Skip to content

Commit

Permalink
feat(aws-constructs-factories): add state machine factory (#1128)
Browse files Browse the repository at this point in the history
* Full Implementation, no docs, first cut

* Docs, test names

* Rename integration tests

* Refresh with CFN suppression

* One more test suppression

* Final Edits

* One More

* Address review comments

* trailing whitespace
  • Loading branch information
biffgaut committed May 31, 2024
1 parent 652cb57 commit d82342c
Show file tree
Hide file tree
Showing 94 changed files with 3,960 additions and 538 deletions.
2 changes: 1 addition & 1 deletion deployment/v2/refresh-multiple-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,4 @@ for construct in $constructs; do
done
cd $constructs_root_dir
echo "Reverting version numbers by getting all package.json files from git"
./deployment/v2/align-version.sh revert
./deployment/v2/align-version.sh revert
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
lib/*.js
test/*.js
test/s3/*.js
*.d.ts
coverage
test/s3/integ.*.js.snapshot/
test/s3/cdk-integ.out.integ.*.snapshot
test/stepfunctions/*.js
test/stepfunctions/integ.*.js.snapshot/
test/stepfunctions/cdk-integ.out.integ.*.snapshot
*.d.ts
coverage
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
lib/*.js
test/*.js
test/s3/*.js
test/stepfunctions/*.js
*.js.map
*.d.ts
node_modules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@

## Overview
This AWS Solutions Construct exposes the same code used to create our underlying resources as factories, so clients can create individual resources that are well-architected.
There are factories to create:

### S3 Buckets
[Amazon S3 buckets](https://docs.aws.amazon.com/solutions/latest/constructs/aws-constructs-factories.html#s3-buckets) - Create a well architected S3 bucket (e.g. - includes an access logging bucket)
[AWS Step Functions state machines](https://docs.aws.amazon.com/solutions/latest/constructs/aws-constructs-factories.html#step-functions-state-machines) - Create a well architected Step Functions state machine and log group (e.g. log group has /aws/vendedlogs/ name prefix to avoid resource policy issues)

## S3 Buckets

Create fully well-architected S3 buckets with as little as one function call. Here is a minimal deployable pattern definition:

Expand Down Expand Up @@ -69,28 +73,28 @@ factories.s3BucketFactory("GoodBucket",
new S3BucketFactoryProps.Builder().build());
```

## S3BucketFactory Function Signature
# S3BucketFactory Function Signature

``` typescript
s3BucketFactory(id: string, props: S3BucketFactoryProps): S3BucketFactoryResponse
```

## S3BucketFactoryProps
# S3BucketFactoryProps

| **Name** | **Type** | **Description** |
|:-------------|:----------------|-----------------|
|bucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Bucket.|
|logS3AccessLogs?|`boolean`|Whether to turn on Access Logging for the S3 bucket. Creates an S3 bucket with associated storage costs for the logs. Enabling Access Logging is a best practice. default - true|
|loggingBucketProps?|[`s3.BucketProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.BucketProps.html)|Optional user provided props to override the default props for the S3 Logging Bucket.|

## S3BucketFactoryResponse
# S3BucketFactoryResponse

| **Name** | **Type** | **Description** |
|:-------------|:----------------|-----------------|
|s3Bucket|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html)|The s3.Bucket created by the factory. |
|s3LoggingBucket?|[`s3.Bucket`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html)|The s3.Bucket created by the construct as the logging bucket for the primary bucket. If the logS3AccessLogs property is false, this value will be undefined.|

## Default settings
# Default settings

Out of the box implementation of the Construct without any override will set the following defaults:

Expand All @@ -113,8 +117,79 @@ Out of the box implementation of the Construct without any override will set the
* Bucket policy granting PutObject privileges to the S3 logging service, from the content bucket in the content bucket account.
* cfn_nag suppression of access logging finding (not logging access to the access log bucket)

## Architecture
# Architecture
![Architecture Diagram](architecture.png)

## Step Functions State Machines

Create fully well-architected Step Functions state machine with log group. The log group name includes the vendedlogs prefix. Here
but is unique to the stack, avoiding naming collions between instances. is a minimal deployable pattern definition:

Typescript
``` typescript
import { App, Stack } from "aws-cdk-lib";
import { ConstructsFactories } from "../../lib";
import { generateIntegStackName, CreateTestStateMachineDefinitionBody } from '@aws-solutions-constructs/core';
import { IntegTest } from '@aws-cdk/integ-tests-alpha';

const placeholderTask = new sftasks.EvaluateExpression(this, 'placeholder', {
expression: '$.argOne + $.argTwo'
});

const factories = new ConstructsFactories(this, 'minimalImplementation');

factories.stateMachineFactory('testsm', {
stateMachineProps: {
definitionBody: sfn.DefinitionBody.fromChainable(placeholderTask)
}
});
```

Python
``` python

# Pending

```

Java
``` java

// Pending

```

# stateMachineFactory Function Signature

``` typescript
stateMachineFactory(id: string, props: StateMachineFactoryProps): StateMachineFactoryResponse
```

# StateMachineFactoryProps

| **Name** | **Type** | **Description** |
|:-------------|:----------------|-----------------|
|stateMachineProps|[`sfn.StateMachineProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions.StateMachineProps.html)|The CDK properties that define the state machine. This property is required and must include a definitionBody or definition (definition is deprecated)|
|logGroup?|[]`logs.LogGroup`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroup.html)|An existing LogGroup to which the new state machine will write log entries. Default: none, the construct will create a new log group.|

# StateMachineFactoryResponse

| **Name** | **Type** | **Description** |
|:-------------|:----------------|-----------------|
|stateMachineProps|[`sfn.StateMachineProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions.StateMachineProps.html)||
|logGroup|[]`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroupProps.html)||

# Default settings

Out of the box implementation of the Construct without any override will set the following defaults:

* An AWS Step Functions State Machine
* Configured to log to the new log group at LogLevel.ERROR
* Amazon CloudWatch Logs Log Group
* Log name is prefaced with /aws/vendedlogs/ to avoid resource policy [issues](https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html#cloudwatch-iam-policy). The Log Group name is still created to be unique to the stack to avoid name collisions.

# Architecture
![Architecture Diagram](sf-architecture.png)

***
© Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
// Note: To ensure CDKv2 compatibility, keep the import statement for Construct separate
import { Construct } from 'constructs';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as sfn from 'aws-cdk-lib/aws-stepfunctions';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as defaults from '@aws-solutions-constructs/core';

export interface S3BucketFactoryProps {
Expand All @@ -28,6 +30,33 @@ export interface S3BucketFactoryResponse {
readonly s3LoggingBucket?: s3.Bucket,
}

export interface StateMachineFactoryProps {
/**
* The CDK properties that define the state machine. This property is required and
* must include a definitionBody or definition (definition is deprecated)
*/
readonly stateMachineProps: sfn.StateMachineProps,
/**
* An existing LogGroup to which the new state machine will write log entries.
*
* Default: none, the construct will create a new log group.
*/
readonly logGroupProps?: logs.LogGroupProps
}

// Create a response specifically for the interface to avoid coupling client with internal implementation
export interface StateMachineFactoryResponse {
/**
* The state machine created by the factory (the state machine role is
* available as a property on this resource)
*/
readonly stateMachine: sfn.StateMachine,
/**
* The log group that will receive log messages from the state maching
*/
readonly logGroup: logs.ILogGroup
}

export class ConstructsFactories extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
Expand All @@ -49,4 +78,13 @@ export class ConstructsFactories extends Construct {
s3LoggingBucket: buildS3BucketResponse.loggingBucket
};
}

public stateMachineFactory(id: string, props: StateMachineFactoryProps): StateMachineFactoryResponse {
const buildStateMachineResponse = defaults.buildStateMachine(this, id, props.stateMachineProps, props.logGroupProps);
return {
stateMachine: buildStateMachineResponse.stateMachine,
logGroup: buildStateMachineResponse.logGroup
};
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
{
"version": "36.0.0",
"files": {
"6c1e9b465fa4b2d651dbc9ce3e732d8702a7b19137327684a71d89f1d355f1a2": {
"2eb6a831b107939f63cfebf68e6316e1a40f79fc99cae0fee9b333bac8d29bc4": {
"source": {
"path": "asset.6c1e9b465fa4b2d651dbc9ce3e732d8702a7b19137327684a71d89f1d355f1a2",
"path": "asset.2eb6a831b107939f63cfebf68e6316e1a40f79fc99cae0fee9b333bac8d29bc4",
"packaging": "zip"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "6c1e9b465fa4b2d651dbc9ce3e732d8702a7b19137327684a71d89f1d355f1a2.zip",
"objectKey": "2eb6a831b107939f63cfebf68e6316e1a40f79fc99cae0fee9b333bac8d29bc4.zip",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
},
"2161142d5baee33bf29b5438c80e578a67773313c3407242b4229224aa35b9aa": {
"1e17b90810968629b1054d57627dec33416d760d218b930f17bf30a9de550ecb": {
"source": {
"path": "defaults.template.json",
"path": "facs3-defaults.template.json",
"packaging": "file"
},
"destinations": {
"current_account-current_region": {
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
"objectKey": "2161142d5baee33bf29b5438c80e578a67773313c3407242b4229224aa35b9aa.json",
"objectKey": "1e17b90810968629b1054d57627dec33416d760d218b930f17bf30a9de550ecb.json",
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@
"S3Bucket": {
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
},
"S3Key": "6c1e9b465fa4b2d651dbc9ce3e732d8702a7b19137327684a71d89f1d355f1a2.zip"
"S3Key": "2eb6a831b107939f63cfebf68e6316e1a40f79fc99cae0fee9b333bac8d29bc4.zip"
},
"Timeout": 900,
"MemorySize": 128,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": {
"21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": {
"source": {
"path": "nologgingIntegDefaultTestDeployAssert09C268F5.template.json",
"path": "facs3defaultsIntegDefaultTestDeployAssert304B3A68.template.json",
"packaging": "file"
},
"destinations": {
Expand Down
Loading

0 comments on commit d82342c

Please sign in to comment.