Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_imagebuilder_pipeline: add support for workflows #37317

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/37317.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_imagebuilder_image_pipeline: Add `execution_role` and `workflow` arguments
```
66 changes: 66 additions & 0 deletions internal/service/imagebuilder/image_pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func ResourceImagePipeline() *schema.Resource {
Optional: true,
Default: true,
},
"execution_role": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidARN,
},
"image_recipe_arn": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -193,6 +198,47 @@ func ResourceImagePipeline() *schema.Resource {
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
"workflow": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"on_failure": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(imagebuilder.OnWorkflowFailure_Values(), false),
},
"parallel_group": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(1, 100),
},
names.AttrParameter: {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
names.AttrName: {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(1, 128),
},
names.AttrValue: {
Type: schema.TypeString,
Required: true,
},
},
},
},
"workflow_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: verify.ValidARN,
},
},
},
},
},

CustomizeDiff: verify.SetTagsDiff,
Expand Down Expand Up @@ -221,6 +267,10 @@ func resourceImagePipelineCreate(ctx context.Context, d *schema.ResourceData, me
input.DistributionConfigurationArn = aws.String(v.(string))
}

if v, ok := d.GetOk("execution_role"); ok {
input.ExecutionRole = aws.String(v.(string))
}

if v, ok := d.GetOk("image_recipe_arn"); ok {
input.ImageRecipeArn = aws.String(v.(string))
}
Expand Down Expand Up @@ -249,6 +299,10 @@ func resourceImagePipelineCreate(ctx context.Context, d *schema.ResourceData, me
input.Status = aws.String(v.(string))
}

if v, ok := d.GetOk("workflow"); ok && len(v.([]interface{})) > 0 {
input.Workflows = expandWorkflowConfigurations(v.([]interface{}))
}

output, err := conn.CreateImagePipelineWithContext(ctx, input)

if err != nil {
Expand Down Expand Up @@ -299,6 +353,7 @@ func resourceImagePipelineRead(ctx context.Context, d *schema.ResourceData, meta
d.Set(names.AttrDescription, imagePipeline.Description)
d.Set("distribution_configuration_arn", imagePipeline.DistributionConfigurationArn)
d.Set("enhanced_image_metadata_enabled", imagePipeline.EnhancedImageMetadataEnabled)
d.Set("execution_role", imagePipeline.ExecutionRole)
d.Set("image_recipe_arn", imagePipeline.ImageRecipeArn)
if imagePipeline.ImageScanningConfiguration != nil {
d.Set("image_scanning_configuration", []interface{}{flattenImageScanningConfiguration(imagePipeline.ImageScanningConfiguration)})
Expand All @@ -319,6 +374,7 @@ func resourceImagePipelineRead(ctx context.Context, d *schema.ResourceData, meta
d.Set(names.AttrSchedule, nil)
}
d.Set(names.AttrStatus, imagePipeline.Status)
d.Set("workflow", flattenWorkflowConfigurations(imagePipeline.Workflows))

setTagsOut(ctx, imagePipeline.Tags)

Expand All @@ -333,11 +389,13 @@ func resourceImagePipelineUpdate(ctx context.Context, d *schema.ResourceData, me
names.AttrDescription,
"distribution_configuration_arn",
"enhanced_image_metadata_enabled",
"execution_role",
"image_scanning_configuration",
"image_tests_configuration",
"infrastructure_configuration_arn",
names.AttrSchedule,
names.AttrStatus,
"workflow",
) {
input := &imagebuilder.UpdateImagePipelineInput{
ClientToken: aws.String(id.UniqueId()),
Expand All @@ -357,6 +415,10 @@ func resourceImagePipelineUpdate(ctx context.Context, d *schema.ResourceData, me
input.DistributionConfigurationArn = aws.String(v.(string))
}

if v, ok := d.GetOk("execution_role"); ok {
input.ExecutionRole = aws.String(v.(string))
}

if v, ok := d.GetOk("image_recipe_arn"); ok {
input.ImageRecipeArn = aws.String(v.(string))
}
Expand All @@ -381,6 +443,10 @@ func resourceImagePipelineUpdate(ctx context.Context, d *schema.ResourceData, me
input.Status = aws.String(v.(string))
}

if v, ok := d.GetOk("workflow"); ok && len(v.([]interface{})) > 0 {
input.Workflows = expandWorkflowConfigurations(v.([]interface{}))
}

_, err := conn.UpdateImagePipelineWithContext(ctx, input)

if err != nil {
Expand Down
177 changes: 177 additions & 0 deletions internal/service/imagebuilder/image_pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,80 @@ func TestAccImageBuilderImagePipeline_tags(t *testing.T) {
})
}

func TestAccImageBuilderImagePipeline_workflow(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_image_pipeline.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ImageBuilderServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckImagePipelineDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccImagePipelineConfig_workflow(rName, imagebuilder.OnWorkflowFailureAbort, "test1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckImagePipelineExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "workflow.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "workflow.0.on_failure", imagebuilder.OnWorkflowFailureAbort),
resource.TestCheckResourceAttr(resourceName, "workflow.0.parallel_group", "test1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccImagePipelineConfig_workflow(rName, imagebuilder.OnWorkflowFailureContinue, "test2"),
Check: resource.ComposeTestCheckFunc(
testAccCheckImagePipelineExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "workflow.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "workflow.0.on_failure", imagebuilder.OnWorkflowFailureContinue),
resource.TestCheckResourceAttr(resourceName, "workflow.0.parallel_group", "test2"),
),
},
},
})
}

func TestAccImageBuilderImagePipeline_workflowParameter(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_image_pipeline.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ImageBuilderServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckImagePipelineDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccImagePipelineConfig_workflowParameter(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckImagePipelineExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "workflow.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "workflow.0.parameter.#", acctest.Ct1),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccImagePipelineConfig_workflowParameter(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckImagePipelineExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "workflow.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "workflow.0.parameter.#", acctest.Ct1),
),
},
},
})
}

func testAccCheckImagePipelineDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).ImageBuilderConn(ctx)
Expand Down Expand Up @@ -705,6 +779,8 @@ data "aws_region" "current" {}

data "aws_partition" "current" {}

data "aws_caller_identity" "current" {}

resource "aws_iam_instance_profile" "test" {
name = aws_iam_role.role.name
role = aws_iam_role.role.name
Expand Down Expand Up @@ -1105,3 +1181,104 @@ resource "aws_imagebuilder_image_pipeline" "test" {
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccImagePipelineConfig_workflow(rName, onFailure, parallelGroup string) string {
return acctest.ConfigCompose(testAccImagePipelineConfig_base(rName), fmt.Sprintf(`
resource "aws_imagebuilder_workflow" "test" {
name = %[1]q
version = "1.0.0"
type = "TEST"

data = <<-EOT
name: test-image
description: Workflow to test an image
schemaVersion: 1.0

steps:
- name: LaunchTestInstance
action: LaunchInstance
onFailure: Abort
inputs:
waitFor: "ssmAgent"

- name: TerminateTestInstance
action: TerminateInstance
onFailure: Continue
inputs:
instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"
EOT
}

resource "aws_imagebuilder_image_pipeline" "test" {
image_recipe_arn = aws_imagebuilder_image_recipe.test.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
name = %[1]q

execution_role = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/imagebuilder.amazonaws.com/AWSServiceRoleForImageBuilder"

workflow {
on_failure = %[2]q
parallel_group = %[3]q
workflow_arn = aws_imagebuilder_workflow.test.arn
}
}
`, rName, onFailure, parallelGroup))
}

func testAccImagePipelineConfig_workflowParameter(rName string) string {
return acctest.ConfigCompose(testAccImagePipelineConfig_base(rName), fmt.Sprintf(`
resource "aws_imagebuilder_workflow" "test" {
name = %[1]q
version = "1.0.0"
type = "TEST"

data = <<-EOT
name: test-image
description: Workflow to test an image
schemaVersion: 1.0

parameters:
- name: waitForActionAtEnd
type: boolean

steps:
- name: LaunchTestInstance
action: LaunchInstance
onFailure: Abort
inputs:
waitFor: "ssmAgent"

- name: TerminateTestInstance
action: TerminateInstance
onFailure: Continue
inputs:
instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"

- name: WaitForActionAtEnd
action: WaitForAction
if:
booleanEquals: true
value: "$.parameters.waitForActionAtEnd"
EOT
}

resource "aws_imagebuilder_image_pipeline" "test" {
image_recipe_arn = aws_imagebuilder_image_recipe.test.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
name = %[1]q

execution_role = "arn:${data.aws_partition.current.partition}:iam::${data.aws_caller_identity.current.account_id}:role/aws-service-role/imagebuilder.amazonaws.com/AWSServiceRoleForImageBuilder"

workflow {
on_failure = "ABORT"
parallel_group = "test"
workflow_arn = aws_imagebuilder_workflow.test.arn

parameter {
name = "waitForActionAtEnd"
value = "true"
}
}
}
`, rName))
}
21 changes: 21 additions & 0 deletions website/docs/r/imagebuilder_image_pipeline.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ The following arguments are optional:
* `description` - (Optional) Description of the image pipeline.
* `distribution_configuration_arn` - (Optional) Amazon Resource Name (ARN) of the Image Builder Distribution Configuration.
* `enhanced_image_metadata_enabled` - (Optional) Whether additional information about the image being created is collected. Defaults to `true`.
* `execution_role` - (Optional) Amazon Resource Name (ARN) of the service-linked role to be used by Image Builder to [execute workflows](https://docs.aws.amazon.com/imagebuilder/latest/userguide/manage-image-workflows.html).
* `image_recipe_arn` - (Optional) Amazon Resource Name (ARN) of the image recipe.
* `image_scanning_configuration` - (Optional) Configuration block with image scanning configuration. Detailed below.
* `image_tests_configuration` - (Optional) Configuration block with image tests configuration. Detailed below.
* `schedule` - (Optional) Configuration block with schedule settings. Detailed below.
* `status` - (Optional) Status of the image pipeline. Valid values are `DISABLED` and `ENABLED`. Defaults to `ENABLED`.
* `workflow` - (Optional) Configuration block with the workflow configuration. Detailed below.
* `tags` - (Optional) Key-value map of resource tags for the image pipeline. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

### image_scanning_configuration
Expand Down Expand Up @@ -77,6 +79,25 @@ The following arguments are optional:

* `timezone` - (Optional) The timezone that applies to the scheduling expression. For example, "Etc/UTC", "America/Los_Angeles" in the [IANA timezone format](https://www.joda.org/joda-time/timezones.html). If not specified this defaults to UTC.

### workflow

The following arguments are required:

* `workflow_arn` - (Required) Amazon Resource Name (ARN) of the Image Builder Workflow.

The following arguments are optional:

* `on_failure` - (Optional) The action to take if the workflow fails. Must be one of `CONTINUE` or `ABORT`.
* `parallel_group` - (Optional) The parallel group in which to run a test Workflow.
* `parameter` - (Optional) Configuration block for the workflow parameters. Detailed below.

### parameter

The following arguments are required:

* `name` - (Required) The name of the Workflow parameter.
* `value` - (Required) The value of the Workflow parameter.

## Attribute Reference

This resource exports the following attributes in addition to the arguments above:
Expand Down
Loading