Skip to content

Commit 616d32a

Browse files
authored
feat(imagebuilder-alpha): add support for Workflow Construct (#36007)
### Issue # aws/aws-cdk-rfcs#789 ### Reason for this change This change adds a new alpha module for EC2 Image Builder L2 Constructs (`@aws-cdk/aws-imagebuilder-alpha`), as outlined in aws/aws-cdk-rfcs#789. This PR specifically implements the `Workflow` construct. ### Description of changes This change implements the `Workflow` construct, which is a higher-level construct of [`CfnWorkflow`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_imagebuilder.CfnWorkflow.html). #### Example ```ts const workflow = new imagebuilder.Workflow(this, 'Workflow', { workflowName: 'custom-build-workflow', workflowType: imagebuilder.WorkflowType.BUILD, workflowVersion: '1.0.0', description: 'A test workflow', changeDescription: 'Initial version', kmsKey: kms.Key.fromLookup(this, 'WorkflowKey', { aliasName: 'alias/workflow-encryption-key' }), // Workflow to create an AMI from an existing EC2 instance data: imagebuilder.WorkflowData.fromJsonObject({ name: 'custom-build-workflow', description: 'Workflow to build an AMI from an EC2 instance', schemaVersion: imagebuilder.WorkflowSchemaVersion.V1_0, parameters: [ { name: 'instanceId', type: imagebuilder.WorkflowParameterType.STRING } ], steps: [ { name: 'CreateOutputAMI', action: imagebuilder.WorkflowAction.CREATE_IMAGE, onFailure: imagebuilder.WorkflowOnFailure.ABORT, inputs: { 'instanceId': 'i-123' } }, { name: 'TerminateBuildInstance', action: imagebuilder.WorkflowAction.TERMINATE_INSTANCE, onFailure: imagebuilder.WorkflowOnFailure.CONTINUE, inputs: { 'instanceId': 'i-123' } } ], outputs: [{ name: 'ImageId', value: 'ami-123' }] }) }); ``` ### Describe any new or updated permissions being added N/A - new L2 construct in alpha module ### Description of how you validated changes Validated with unit tests and integration tests. Manually verified generated CFN templates as well. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 72d3e6f commit 616d32a

File tree

44 files changed

+5574
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+5574
-9
lines changed

packages/@aws-cdk/aws-imagebuilder-alpha/README.md

Lines changed: 232 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ EC2 Image Builder supports AWS-managed components for common tasks, AWS Marketpl
222222
that you create. Components run during specific workflow phases: build and validate phases during the build stage, and
223223
test phase during the test stage.
224224

225-
#### Basic Usage
225+
#### Basic Component Usage
226226

227227
Create a component with the required properties: platform and component data.
228228

@@ -407,13 +407,13 @@ const component = new imagebuilder.Component(this, 'EncryptedComponent', {
407407
name: 'secure-setup',
408408
action: imagebuilder.ComponentAction.EXECUTE_BASH,
409409
inputs: {
410-
commands: ['echo "This component data is encrypted with KMS"'],
411-
},
412-
},
413-
],
414-
},
415-
],
416-
}),
410+
commands: ['echo "This component data is encrypted with KMS"']
411+
}
412+
}
413+
]
414+
}
415+
]
416+
})
417417
});
418418
```
419419

@@ -654,3 +654,227 @@ containerDistributionConfiguration.addContainerDistributions({
654654
containerTags: ['latest', 'latest-1.0']
655655
});
656656
```
657+
658+
### Workflow
659+
660+
Workflows define the sequence of steps that Image Builder performs during image creation. There are three workflow types: BUILD (image building), TEST (testing images), and DISTRIBUTION (distributing container images).
661+
662+
#### Basic Workflow Usage
663+
664+
Create a workflow with the required properties: workflow type and workflow data.
665+
666+
```ts
667+
const workflow = new imagebuilder.Workflow(this, 'MyWorkflow', {
668+
workflowType: imagebuilder.WorkflowType.BUILD,
669+
data: imagebuilder.WorkflowData.fromJsonObject({
670+
schemaVersion: imagebuilder.WorkflowSchemaVersion.V1_0,
671+
steps: [
672+
{
673+
name: 'LaunchBuildInstance',
674+
action: imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
675+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
676+
inputs: {
677+
waitFor: 'ssmAgent',
678+
},
679+
},
680+
{
681+
name: 'ExecuteComponents',
682+
action: imagebuilder.WorkflowAction.EXECUTE_COMPONENTS,
683+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
684+
inputs: {
685+
'instanceId': 'i-123',
686+
},
687+
},
688+
{
689+
name: 'CreateImage',
690+
action: imagebuilder.WorkflowAction.CREATE_IMAGE,
691+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
692+
inputs: {
693+
'instanceId': 'i-123',
694+
},
695+
},
696+
{
697+
name: 'TerminateInstance',
698+
action: imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
699+
onFailure: imagebuilder.WorkflowOnFailure.CONTINUE,
700+
inputs: {
701+
'instanceId': 'i-123',
702+
},
703+
},
704+
],
705+
outputs: [
706+
{
707+
name: 'ImageId',
708+
value: '$.stepOutputs.CreateImage.imageId',
709+
},
710+
],
711+
}),
712+
});
713+
```
714+
715+
#### Workflow Data Sources
716+
717+
##### Inline Workflow Data
718+
719+
Use `WorkflowData.fromInline()` for existing YAML/JSON definitions:
720+
721+
```ts
722+
const workflow = new imagebuilder.Workflow(this, 'InlineWorkflow', {
723+
workflowType: imagebuilder.WorkflowType.TEST,
724+
data: imagebuilder.WorkflowData.fromInline(`
725+
schemaVersion: 1.0
726+
steps:
727+
- name: LaunchTestInstance
728+
action: LaunchInstance
729+
onFailure: Abort
730+
inputs:
731+
waitFor: ssmAgent
732+
- name: RunTests
733+
action: RunCommand
734+
onFailure: Abort
735+
inputs:
736+
instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"
737+
commands: ['./run-tests.sh']
738+
- name: TerminateTestInstance
739+
action: TerminateInstance
740+
onFailure: Continue
741+
inputs:
742+
instanceId.$: "$.stepOutputs.LaunchTestInstance.instanceId"
743+
`),
744+
});
745+
```
746+
747+
##### JSON Object Workflow Data
748+
749+
Most developer-friendly approach using JavaScript objects:
750+
751+
```ts
752+
const workflow = new imagebuilder.Workflow(this, 'JsonWorkflow', {
753+
workflowType: imagebuilder.WorkflowType.BUILD,
754+
data: imagebuilder.WorkflowData.fromJsonObject({
755+
schemaVersion: imagebuilder.WorkflowSchemaVersion.V1_0,
756+
steps: [
757+
{
758+
name: 'LaunchBuildInstance',
759+
action: imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
760+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
761+
inputs: {
762+
waitFor: 'ssmAgent'
763+
}
764+
},
765+
{
766+
name: 'ExecuteComponents',
767+
action: imagebuilder.WorkflowAction.EXECUTE_COMPONENTS,
768+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
769+
inputs: {
770+
'instanceId': 'i-123'
771+
}
772+
},
773+
{
774+
name: 'CreateImage',
775+
action: imagebuilder.WorkflowAction.CREATE_IMAGE,
776+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
777+
inputs: {
778+
'instanceId': 'i-123'
779+
}
780+
},
781+
{
782+
name: 'TerminateInstance',
783+
action: imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
784+
onFailure: imagebuilder.WorkflowOnFailure.CONTINUE,
785+
inputs: {
786+
'instanceId': 'i-123'
787+
}
788+
}
789+
],
790+
outputs: [
791+
{
792+
name: 'ImageId',
793+
value: '$.stepOutputs.CreateImage.imageId'
794+
}
795+
]
796+
})
797+
});
798+
```
799+
800+
##### S3 Workflow Data
801+
802+
For those workflows you want to upload or have uploaded to S3:
803+
804+
```ts
805+
// Upload a local file
806+
const workflowFromAsset = new imagebuilder.Workflow(this, 'AssetWorkflow', {
807+
workflowType: imagebuilder.WorkflowType.BUILD,
808+
data: imagebuilder.WorkflowData.fromAsset(this, 'WorkflowAsset', './my-workflow.yml'),
809+
});
810+
811+
// Reference an existing S3 object
812+
const bucket = s3.Bucket.fromBucketName(this, 'WorkflowBucket', 'my-workflows-bucket');
813+
const workflowFromS3 = new imagebuilder.Workflow(this, 'S3Workflow', {
814+
workflowType: imagebuilder.WorkflowType.BUILD,
815+
data: imagebuilder.WorkflowData.fromS3(bucket, 'workflows/my-workflow.yml'),
816+
});
817+
```
818+
819+
#### Encrypt workflow data with a KMS key
820+
821+
You can encrypt workflow data with a KMS key, so that only principals with access to decrypt with the key are able to access the workflow data.
822+
823+
```ts
824+
const workflow = new imagebuilder.Workflow(this, 'EncryptedWorkflow', {
825+
workflowType: imagebuilder.WorkflowType.BUILD,
826+
kmsKey: new kms.Key(this, 'WorkflowKey'),
827+
data: imagebuilder.WorkflowData.fromJsonObject({
828+
schemaVersion: imagebuilder.WorkflowSchemaVersion.V1_0,
829+
steps: [
830+
{
831+
name: 'LaunchBuildInstance',
832+
action: imagebuilder.WorkflowAction.LAUNCH_INSTANCE,
833+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
834+
inputs: {
835+
waitFor: 'ssmAgent',
836+
},
837+
},
838+
{
839+
name: 'CreateImage',
840+
action: imagebuilder.WorkflowAction.CREATE_IMAGE,
841+
onFailure: imagebuilder.WorkflowOnFailure.ABORT,
842+
inputs: {
843+
'instanceId': 'i-123',
844+
},
845+
},
846+
{
847+
name: 'TerminateInstance',
848+
action: imagebuilder.WorkflowAction.TERMINATE_INSTANCE,
849+
onFailure: imagebuilder.WorkflowOnFailure.CONTINUE,
850+
inputs: {
851+
'instanceId': 'i-123',
852+
},
853+
},
854+
],
855+
outputs: [
856+
{
857+
name: 'ImageId',
858+
value: '$.stepOutputs.CreateImage.imageId',
859+
},
860+
],
861+
}),
862+
});
863+
```
864+
865+
#### AWS-Managed Workflows
866+
867+
AWS provides a collection of workflows for common scenarios:
868+
869+
```ts
870+
// Build workflows
871+
const buildImageWorkflow = imagebuilder.AwsManagedWorkflow.buildImage(this, 'BuildImage');
872+
const buildContainerWorkflow = imagebuilder.AwsManagedWorkflow.buildContainer(this, 'BuildContainer');
873+
874+
// Test workflows
875+
const testImageWorkflow = imagebuilder.AwsManagedWorkflow.testImage(this, 'TestImage');
876+
const testContainerWorkflow = imagebuilder.AwsManagedWorkflow.testContainer(this, 'TestContainer');
877+
878+
// Distribution workflows
879+
const distributeContainerWorkflow = imagebuilder.AwsManagedWorkflow.distributeContainer(this, 'DistributeContainer');
880+
```
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
{
22
"exclude": [
33
"props-no-arn-refs:@aws-cdk/aws-imagebuilder-alpha.InfrastructureConfigurationProps.ec2InstanceHostResourceGroupArn",
4-
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.ContainerType"
4+
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.ContainerType",
5+
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.WorkflowAction",
6+
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.WorkflowOnFailure",
7+
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.WorkflowParameterType",
8+
"no-unused-type:@aws-cdk/aws-imagebuilder-alpha.WorkflowSchemaVersion"
59
]
610
}

packages/@aws-cdk/aws-imagebuilder-alpha/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from './component';
44
export * from './container-recipe';
55
export * from './distribution-configuration';
66
export * from './infrastructure-configuration';
7+
export * from './workflow';
78

89
export * from './base-image';
910
export * from './os-version';

0 commit comments

Comments
 (0)