Skip to content

Commit

Permalink
Add support for tags
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilturek committed Feb 6, 2022
1 parent 0c778dc commit 0a43e9d
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 6 deletions.
56 changes: 53 additions & 3 deletions internal/service/imagebuilder/container_recipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

func ResourceContainerRecipe() *schema.Resource {
return &schema.Resource{
Create: resourceContainerRecipeCreate,
Read: resourceContainerRecipeRead,
Update: resourceContainerRecipeUpdate,
Delete: resourceContainerRecipeDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
Expand Down Expand Up @@ -92,7 +94,6 @@ func ResourceContainerRecipe() *schema.Resource {
"instance_configuration": {
Type: schema.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Expand Down Expand Up @@ -215,7 +216,8 @@ func ResourceContainerRecipe() *schema.Resource {
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 1024),
},
// tags
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
"target_repository": {
Type: schema.TypeList,
Required: true,
Expand Down Expand Up @@ -248,11 +250,14 @@ func ResourceContainerRecipe() *schema.Resource {
ValidateFunc: validation.StringLenBetween(1, 1024),
},
},
CustomizeDiff: verify.SetTagsDiff,
}
}

func resourceContainerRecipeCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ImageBuilderConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{})))

input := &imagebuilder.CreateContainerRecipeInput{
ClientToken: aws.String(resource.UniqueId()),
Expand Down Expand Up @@ -294,6 +299,10 @@ func resourceContainerRecipeCreate(d *schema.ResourceData, meta interface{}) err
input.ParentImage = aws.String(v.(string))
}

if len(tags) > 0 {
input.Tags = Tags(tags.IgnoreAWS())
}

if v, ok := d.GetOk("target_repository"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.TargetRepository = expandTargetContainerRepository(v.([]interface{})[0].(map[string]interface{}))
}
Expand Down Expand Up @@ -323,6 +332,8 @@ func resourceContainerRecipeCreate(d *schema.ResourceData, meta interface{}) err

func resourceContainerRecipeRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ImageBuilderConn
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*conns.AWSClient).IgnoreTagsConfig

input := &imagebuilder.GetContainerRecipeInput{
ContainerRecipeArn: aws.String(d.Id()),
Expand All @@ -336,24 +347,63 @@ func resourceContainerRecipeRead(d *schema.ResourceData, meta interface{}) error
return nil
}

if err != nil {
return fmt.Errorf("error creating Image Builder Container Recipe: %w", err)
}

if output == nil {
return fmt.Errorf("error creating Image Builder Container Recipe: empty response")
}

containerRecipe := output.ContainerRecipe

d.Set("arn", containerRecipe.Arn)
d.Set("component", flattenComponentConfigurations(containerRecipe.Components))
d.Set("container_type", containerRecipe.ContainerType)
d.Set("description", containerRecipe.Description)
d.Set("dockerfile_template_data", containerRecipe.DockerfileTemplateData)
d.Set("instance_configuration", []interface{}{flattenInstanceConfiguration(containerRecipe.InstanceConfiguration)})

if containerRecipe.InstanceConfiguration != nil {
d.Set("instance_configuration", []interface{}{flattenInstanceConfiguration(containerRecipe.InstanceConfiguration)})
} else {
d.Set("instance_configuration", nil)
}

d.Set("kms_key_id", containerRecipe.KmsKeyId)
d.Set("name", containerRecipe.Name)
d.Set("parent_image", containerRecipe.ParentImage)

tags := KeyValueTags(containerRecipe.Tags).IgnoreAWS().IgnoreConfig(ignoreTagsConfig)

if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return fmt.Errorf("error setting tags_all: %w", err)
}

d.Set("target_repository", []interface{}{flattenTargetContainerRepository(containerRecipe.TargetRepository)})
d.Set("version", containerRecipe.Version)
d.Set("working_directory", containerRecipe.WorkingDirectory)

return nil
}

func resourceContainerRecipeUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ImageBuilderConn

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")

if err := UpdateTags(conn, d.Id(), o, n); err != nil {
return fmt.Errorf("error updating tags for Image Builder Container Recipe (%s): %w", d.Id(), err)
}
}

return resourceContainerRecipeRead(d, meta)
}

func resourceContainerRecipeDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).ImageBuilderConn

Expand Down
116 changes: 113 additions & 3 deletions internal/service/imagebuilder/container_recipe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,11 @@ func TestAccImageBuilderContainerRecipe_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "container_type", "DOCKER"),
resource.TestCheckResourceAttr(resourceName, "description", ""),
resource.TestCheckResourceAttrSet(resourceName, "dockerfile_template_data"),
// template uri
// resource.TestCheckResourceAttr(resourceName, "instance_configuration.#", "1"),
// resource.TestCheckResourceAttr(resourceName, "instance_configuration.0.block_device_mapping.#", "0"),
resource.TestCheckResourceAttr(resourceName, "instance_configuration.#", "0"),
resource.TestCheckResourceAttr(resourceName, "kms_key_id", ""),
resource.TestCheckResourceAttr(resourceName, "name", rName),
acctest.CheckResourceAttrRegionalARNAccountID(resourceName, "parent_image", "imagebuilder", "aws", "image/amazon-linux-x86-2/x.x.x"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
resource.TestCheckResourceAttr(resourceName, "target_repository.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "target_repository.0.repository_name", "aws_ecr_repository.test", "name"),
resource.TestCheckResourceAttr(resourceName, "target_repository.0.service", "ECR"),
Expand Down Expand Up @@ -537,6 +536,50 @@ func TestAccImageBuilderContainerRecipe_kmsKeyID(t *testing.T) {
})
}

func TestAccImageBuilderContainerRecipe_tags(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_container_recipe.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, imagebuilder.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckContainerRecipeDestroy,
Steps: []resource.TestStep{
{
Config: testAccContainerRecipeTags1Config(rName, "key1", "value1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerRecipeExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerRecipeTags2Config(rName, "key1", "value1updated", "key2", "value2"),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerRecipeExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"),
resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
),
},
{
Config: testAccContainerRecipeTags1Config(rName, "key2", "value2"),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerRecipeExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
),
},
},
})
}

func TestAccImageBuilderContainerRecipe_workingDirectory(t *testing.T) {
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_container_recipe.test"
Expand Down Expand Up @@ -1281,6 +1324,73 @@ EOF
`, rName))
}

func testAccContainerRecipeTags1Config(rName string, tagKey1 string, tagValue1 string) string {
return acctest.ConfigCompose(
testAccContainerRecipeBaseConfig(rName),
fmt.Sprintf(`
resource "aws_imagebuilder_container_recipe" "test" {
name = %[1]q
container_type = "DOCKER"
parent_image = "arn:${data.aws_partition.current.partition}:imagebuilder:${data.aws_region.current.name}:aws:image/amazon-linux-x86-2/x.x.x"
version = "1.0.0"
component {
component_arn = "arn:${data.aws_partition.current.partition}:imagebuilder:${data.aws_region.current.name}:aws:component/update-linux/x.x.x"
}
dockerfile_template_data = <<EOF
FROM {{{ imagebuilder:parentImage }}}
{{{ imagebuilder:environments }}}
{{{ imagebuilder:components }}}
EOF
target_repository {
repository_name = aws_ecr_repository.test.name
service = "ECR"
}
tags = {
%[2]q = %[3]q
}
}
`, rName, tagKey1, tagValue1))
}

func testAccContainerRecipeTags2Config(rName string, tagKey1 string, tagValue1, tagKey2 string, tagValue2 string) string {
return acctest.ConfigCompose(
testAccContainerRecipeBaseConfig(rName),
fmt.Sprintf(`
resource "aws_imagebuilder_container_recipe" "test" {
name = %[1]q
container_type = "DOCKER"
parent_image = "arn:${data.aws_partition.current.partition}:imagebuilder:${data.aws_region.current.name}:aws:image/amazon-linux-x86-2/x.x.x"
version = "1.0.0"
component {
component_arn = "arn:${data.aws_partition.current.partition}:imagebuilder:${data.aws_region.current.name}:aws:component/update-linux/x.x.x"
}
dockerfile_template_data = <<EOF
FROM {{{ imagebuilder:parentImage }}}
{{{ imagebuilder:environments }}}
{{{ imagebuilder:components }}}
EOF
target_repository {
repository_name = aws_ecr_repository.test.name
service = "ECR"
}
tags = {
%[2]q = %[3]q
%[4]q = %[5]q
}
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccContainerRecipeWorkingDirectoryConfig(rName string) string {
return acctest.ConfigCompose(
testAccContainerRecipeBaseConfig(rName),
Expand Down

0 comments on commit 0a43e9d

Please sign in to comment.