Skip to content

Commit 8f7e5b4

Browse files
authored
Merge pull request #33005 from stromp/f-add-image-scanning-to-imagebuilder-image-pipeline-resource
Add image scanning to imagebuilder image pipeline resource
2 parents c5f7376 + 67c93c6 commit 8f7e5b4

10 files changed

+394
-127
lines changed

.changelog/33005.txt

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:enhancement
2+
resource/aws_imagebuilder_image_pipeline: Add `image_scanning_configuration` configuration block
3+
```
4+
5+
```release-note:enhancement
6+
data-source/aws_imagebuilder_image_pipeline: Add `image_scanning_configuration` attribute
7+
```

internal/service/imagebuilder/distribution_configuration_data_source_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ resource "aws_imagebuilder_distribution_configuration" "test" {
102102
launch_template_version = "1"
103103
}
104104
105-
max_parallel_launches = 1
105+
max_parallel_launches = 6
106106
107107
snapshot_configuration {
108108
target_resource_count = 1

internal/service/imagebuilder/distribution_configuration_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func init() {
2626
func testAccErrorCheckSkip(t *testing.T) resource.ErrorCheckFunc {
2727
return acctest.ErrorCheckSkipMessagesContaining(t,
2828
"You have reached the maximum allowed number of license configurations created in one day",
29+
"Amazon Inspector is not enabled",
2930
)
3031
}
3132

@@ -703,12 +704,12 @@ func TestAccImageBuilderDistributionConfiguration_DistributionFastLaunchConfigur
703704
CheckDestroy: testAccCheckDistributionConfigurationDestroy(ctx),
704705
Steps: []resource.TestStep{
705706
{
706-
Config: testAccDistributionConfigurationConfig_fastLaunchMaxParallelLaunches(rName, 5),
707+
Config: testAccDistributionConfigurationConfig_fastLaunchMaxParallelLaunches(rName, 7),
707708
Check: resource.ComposeTestCheckFunc(
708709
testAccCheckDistributionConfigurationExists(ctx, resourceName),
709710
resource.TestCheckResourceAttr(resourceName, "distribution.#", "1"),
710711
resource.TestCheckResourceAttr(resourceName, "distribution.0.fast_launch_configuration.#", "1"),
711-
resource.TestCheckResourceAttr(resourceName, "distribution.0.fast_launch_configuration.0.max_parallel_launches", "5"),
712+
resource.TestCheckResourceAttr(resourceName, "distribution.0.fast_launch_configuration.0.max_parallel_launches", "7"),
712713
),
713714
},
714715
{

internal/service/imagebuilder/image_pipeline.go

+123-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1818
"github.com/hashicorp/terraform-provider-aws/internal/conns"
1919
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
20+
"github.com/hashicorp/terraform-provider-aws/internal/flex"
2021
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
2122
"github.com/hashicorp/terraform-provider-aws/internal/verify"
2223
"github.com/hashicorp/terraform-provider-aws/names"
@@ -84,6 +85,42 @@ func ResourceImagePipeline() *schema.Resource {
8485
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^arn:aws[^:]*:imagebuilder:[^:]+:(?:\d{12}|aws):image-recipe/[a-z0-9-_]+/\d+\.\d+\.\d+$`), "valid image recipe ARN must be provided"),
8586
ExactlyOneOf: []string{"container_recipe_arn", "image_recipe_arn"},
8687
},
88+
"image_scanning_configuration": {
89+
Type: schema.TypeList,
90+
Optional: true,
91+
Computed: true,
92+
MaxItems: 1,
93+
Elem: &schema.Resource{
94+
Schema: map[string]*schema.Schema{
95+
"ecr_configuration": {
96+
Type: schema.TypeList,
97+
Optional: true,
98+
Computed: true,
99+
MaxItems: 1,
100+
Elem: &schema.Resource{
101+
Schema: map[string]*schema.Schema{
102+
"container_tags": {
103+
Type: schema.TypeSet,
104+
Optional: true,
105+
Elem: &schema.Schema{
106+
Type: schema.TypeString,
107+
},
108+
},
109+
"repository_name": {
110+
Type: schema.TypeString,
111+
Optional: true,
112+
},
113+
},
114+
},
115+
},
116+
"image_scanning_enabled": {
117+
Type: schema.TypeBool,
118+
Optional: true,
119+
Default: false,
120+
},
121+
},
122+
},
123+
},
87124
"image_tests_configuration": {
88125
Type: schema.TypeList,
89126
Optional: true,
@@ -188,6 +225,10 @@ func resourceImagePipelineCreate(ctx context.Context, d *schema.ResourceData, me
188225
input.ImageRecipeArn = aws.String(v.(string))
189226
}
190227

228+
if v, ok := d.GetOk("image_scanning_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
229+
input.ImageScanningConfiguration = expandImageScanningConfiguration(v.([]interface{})[0].(map[string]interface{}))
230+
}
231+
191232
if v, ok := d.GetOk("image_tests_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
192233
input.ImageTestsConfiguration = expandImageTestConfiguration(v.([]interface{})[0].(map[string]interface{}))
193234
}
@@ -259,23 +300,24 @@ func resourceImagePipelineRead(ctx context.Context, d *schema.ResourceData, meta
259300
d.Set("distribution_configuration_arn", imagePipeline.DistributionConfigurationArn)
260301
d.Set("enhanced_image_metadata_enabled", imagePipeline.EnhancedImageMetadataEnabled)
261302
d.Set("image_recipe_arn", imagePipeline.ImageRecipeArn)
262-
303+
if imagePipeline.ImageScanningConfiguration != nil {
304+
d.Set("image_scanning_configuration", []interface{}{flattenImageScanningConfiguration(imagePipeline.ImageScanningConfiguration)})
305+
} else {
306+
d.Set("image_scanning_configuration", nil)
307+
}
263308
if imagePipeline.ImageTestsConfiguration != nil {
264309
d.Set("image_tests_configuration", []interface{}{flattenImageTestsConfiguration(imagePipeline.ImageTestsConfiguration)})
265310
} else {
266311
d.Set("image_tests_configuration", nil)
267312
}
268-
269313
d.Set("infrastructure_configuration_arn", imagePipeline.InfrastructureConfigurationArn)
270314
d.Set("name", imagePipeline.Name)
271315
d.Set("platform", imagePipeline.Platform)
272-
273316
if imagePipeline.Schedule != nil {
274317
d.Set("schedule", []interface{}{flattenSchedule(imagePipeline.Schedule)})
275318
} else {
276319
d.Set("schedule", nil)
277320
}
278-
279321
d.Set("status", imagePipeline.Status)
280322

281323
setTagsOut(ctx, imagePipeline.Tags)
@@ -291,6 +333,7 @@ func resourceImagePipelineUpdate(ctx context.Context, d *schema.ResourceData, me
291333
"description",
292334
"distribution_configuration_arn",
293335
"enhanced_image_metadata_enabled",
336+
"image_scanning_configuration",
294337
"image_tests_configuration",
295338
"infrastructure_configuration_arn",
296339
"schedule",
@@ -318,6 +361,10 @@ func resourceImagePipelineUpdate(ctx context.Context, d *schema.ResourceData, me
318361
input.ImageRecipeArn = aws.String(v.(string))
319362
}
320363

364+
if v, ok := d.GetOk("image_scanning_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
365+
input.ImageScanningConfiguration = expandImageScanningConfiguration(v.([]interface{})[0].(map[string]interface{}))
366+
}
367+
321368
if v, ok := d.GetOk("image_tests_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
322369
input.ImageTestsConfiguration = expandImageTestConfiguration(v.([]interface{})[0].(map[string]interface{}))
323370
}
@@ -365,6 +412,42 @@ func resourceImagePipelineDelete(ctx context.Context, d *schema.ResourceData, me
365412
return diags
366413
}
367414

415+
func expandImageScanningConfiguration(tfMap map[string]interface{}) *imagebuilder.ImageScanningConfiguration {
416+
if tfMap == nil {
417+
return nil
418+
}
419+
420+
apiObject := &imagebuilder.ImageScanningConfiguration{}
421+
422+
if v, ok := tfMap["image_scanning_enabled"].(bool); ok {
423+
apiObject.ImageScanningEnabled = aws.Bool(v)
424+
}
425+
426+
if v, ok := tfMap["ecr_configuration"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
427+
apiObject.EcrConfiguration = expandECRConfiguration(v[0].(map[string]interface{}))
428+
}
429+
430+
return apiObject
431+
}
432+
433+
func expandECRConfiguration(tfMap map[string]interface{}) *imagebuilder.EcrConfiguration {
434+
if tfMap == nil {
435+
return nil
436+
}
437+
438+
apiObject := &imagebuilder.EcrConfiguration{}
439+
440+
if v, ok := tfMap["container_tags"].(*schema.Set); ok {
441+
apiObject.ContainerTags = flex.ExpandStringSet(v)
442+
}
443+
444+
if v, ok := tfMap["repository_name"].(string); ok {
445+
apiObject.RepositoryName = aws.String(v)
446+
}
447+
448+
return apiObject
449+
}
450+
368451
func expandImageTestConfiguration(tfMap map[string]interface{}) *imagebuilder.ImageTestsConfiguration {
369452
if tfMap == nil {
370453
return nil
@@ -405,6 +488,42 @@ func expandPipelineSchedule(tfMap map[string]interface{}) *imagebuilder.Schedule
405488
return apiObject
406489
}
407490

491+
func flattenImageScanningConfiguration(apiObject *imagebuilder.ImageScanningConfiguration) map[string]interface{} {
492+
if apiObject == nil {
493+
return nil
494+
}
495+
496+
tfMap := map[string]interface{}{}
497+
498+
if v := apiObject.ImageScanningEnabled; v != nil {
499+
tfMap["image_scanning_enabled"] = aws.BoolValue(v)
500+
}
501+
502+
if v := apiObject.EcrConfiguration; v != nil {
503+
tfMap["ecr_configuration"] = []interface{}{flattenECRConfiguration(v)}
504+
}
505+
506+
return tfMap
507+
}
508+
509+
func flattenECRConfiguration(apiObject *imagebuilder.EcrConfiguration) map[string]interface{} {
510+
if apiObject == nil {
511+
return nil
512+
}
513+
514+
tfMap := map[string]interface{}{}
515+
516+
if v := apiObject.RepositoryName; v != nil {
517+
tfMap["repository_name"] = aws.StringValue(v)
518+
}
519+
520+
if v := apiObject.ContainerTags; v != nil {
521+
tfMap["container_tags"] = aws.StringValueSlice(v)
522+
}
523+
524+
return tfMap
525+
}
526+
408527
func flattenImageTestsConfiguration(apiObject *imagebuilder.ImageTestsConfiguration) map[string]interface{} {
409528
if apiObject == nil {
410529
return nil

internal/service/imagebuilder/image_pipeline_data_source.go

+36-3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,37 @@ func DataSourceImagePipeline() *schema.Resource {
6363
Type: schema.TypeString,
6464
Computed: true,
6565
},
66+
"image_scanning_configuration": {
67+
Type: schema.TypeList,
68+
Computed: true,
69+
Elem: &schema.Resource{
70+
Schema: map[string]*schema.Schema{
71+
"ecr_configuration": {
72+
Type: schema.TypeList,
73+
Computed: true,
74+
Elem: &schema.Resource{
75+
Schema: map[string]*schema.Schema{
76+
"container_tags": {
77+
Type: schema.TypeSet,
78+
Computed: true,
79+
Elem: &schema.Schema{
80+
Type: schema.TypeString,
81+
},
82+
},
83+
"repository_name": {
84+
Type: schema.TypeString,
85+
Computed: true,
86+
},
87+
},
88+
},
89+
},
90+
"image_scanning_enabled": {
91+
Type: schema.TypeBool,
92+
Computed: true,
93+
},
94+
},
95+
},
96+
},
6697
"image_tests_configuration": {
6798
Type: schema.TypeList,
6899
Computed: true,
@@ -149,17 +180,19 @@ func dataSourceImagePipelineRead(ctx context.Context, d *schema.ResourceData, me
149180
d.Set("distribution_configuration_arn", imagePipeline.DistributionConfigurationArn)
150181
d.Set("enhanced_image_metadata_enabled", imagePipeline.EnhancedImageMetadataEnabled)
151182
d.Set("image_recipe_arn", imagePipeline.ImageRecipeArn)
152-
183+
if imagePipeline.ImageScanningConfiguration != nil {
184+
d.Set("image_scanning_configuration", []interface{}{flattenImageScanningConfiguration(imagePipeline.ImageScanningConfiguration)})
185+
} else {
186+
d.Set("image_scanning_configuration", nil)
187+
}
153188
if imagePipeline.ImageTestsConfiguration != nil {
154189
d.Set("image_tests_configuration", []interface{}{flattenImageTestsConfiguration(imagePipeline.ImageTestsConfiguration)})
155190
} else {
156191
d.Set("image_tests_configuration", nil)
157192
}
158-
159193
d.Set("infrastructure_configuration_arn", imagePipeline.InfrastructureConfigurationArn)
160194
d.Set("name", imagePipeline.Name)
161195
d.Set("platform", imagePipeline.Platform)
162-
163196
if imagePipeline.Schedule != nil {
164197
d.Set("schedule", []interface{}{flattenSchedule(imagePipeline.Schedule)})
165198
} else {

internal/service/imagebuilder/image_pipeline_data_source_test.go

+16-9
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func TestAccImageBuilderImagePipelineDataSource_arn(t *testing.T) {
2727
Steps: []resource.TestStep{
2828
{
2929
Config: testAccImagePipelineDataSourceConfig_arn(rName),
30-
Check: resource.ComposeTestCheckFunc(
30+
Check: resource.ComposeAggregateTestCheckFunc(
3131
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
3232
resource.TestCheckResourceAttrPair(dataSourceName, "container_recipe_arn", resourceName, "container_recipe_arn"),
3333
resource.TestCheckResourceAttrPair(dataSourceName, "date_created", resourceName, "date_created"),
@@ -38,6 +38,7 @@ func TestAccImageBuilderImagePipelineDataSource_arn(t *testing.T) {
3838
resource.TestCheckResourceAttrPair(dataSourceName, "distribution_configuration_arn", resourceName, "distribution_configuration_arn"),
3939
resource.TestCheckResourceAttrPair(dataSourceName, "enhanced_image_metadata_enabled", resourceName, "enhanced_image_metadata_enabled"),
4040
resource.TestCheckResourceAttrPair(dataSourceName, "image_recipe_arn", resourceName, "image_recipe_arn"),
41+
resource.TestCheckResourceAttrPair(dataSourceName, "image_scanning_configuration.#", resourceName, "image_scanning_configuration.#"),
4142
resource.TestCheckResourceAttrPair(dataSourceName, "image_tests_configuration.#", resourceName, "image_tests_configuration.#"),
4243
resource.TestCheckResourceAttrPair(dataSourceName, "infrastructure_configuration_arn", resourceName, "infrastructure_configuration_arn"),
4344
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
@@ -65,16 +66,17 @@ func TestAccImageBuilderImagePipelineDataSource_containerRecipeARN(t *testing.T)
6566
Steps: []resource.TestStep{
6667
{
6768
Config: testAccImagePipelineDataSourceConfig_containerRecipeARN(rName),
68-
Check: resource.ComposeTestCheckFunc(
69+
Check: resource.ComposeAggregateTestCheckFunc(
6970
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
7071
resource.TestCheckResourceAttrPair(dataSourceName, "container_recipe_arn", resourceName, "container_recipe_arn"),
72+
resource.TestCheckResourceAttrPair(dataSourceName, "image_scanning_configuration.#", resourceName, "image_scanning_configuration.#"),
7173
),
7274
},
7375
},
7476
})
7577
}
7678

77-
func testAccImagePipelineBaseDataSourceConfig(rName string) string {
79+
func testAccImagePipelineDataSourceConfig_base(rName string) string {
7880
return fmt.Sprintf(`
7981
data "aws_region" "current" {}
8082
@@ -128,9 +130,7 @@ resource "aws_imagebuilder_infrastructure_configuration" "test" {
128130
}
129131

130132
func testAccImagePipelineDataSourceConfig_arn(rName string) string {
131-
return acctest.ConfigCompose(
132-
testAccImagePipelineBaseDataSourceConfig(rName),
133-
fmt.Sprintf(`
133+
return acctest.ConfigCompose(testAccImagePipelineDataSourceConfig_base(rName), fmt.Sprintf(`
134134
resource "aws_imagebuilder_image_recipe" "test" {
135135
component {
136136
component_arn = aws_imagebuilder_component.test.arn
@@ -154,9 +154,7 @@ data "aws_imagebuilder_image_pipeline" "test" {
154154
}
155155

156156
func testAccImagePipelineDataSourceConfig_containerRecipeARN(rName string) string {
157-
return acctest.ConfigCompose(
158-
testAccImagePipelineBaseDataSourceConfig(rName),
159-
fmt.Sprintf(`
157+
return acctest.ConfigCompose(testAccImagePipelineDataSourceConfig_base(rName), fmt.Sprintf(`
160158
resource "aws_ecr_repository" "test" {
161159
name = %[1]q
162160
}
@@ -187,6 +185,15 @@ resource "aws_imagebuilder_image_pipeline" "test" {
187185
container_recipe_arn = aws_imagebuilder_container_recipe.test.arn
188186
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
189187
name = %[1]q
188+
189+
image_scanning_configuration {
190+
image_scanning_enabled = true
191+
192+
ecr_configuration {
193+
container_tags = ["a", "b"]
194+
repository_name = aws_ecr_repository.test.name
195+
}
196+
}
190197
}
191198
192199
data "aws_imagebuilder_image_pipeline" "test" {

0 commit comments

Comments
 (0)