Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
24 changes: 24 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions-tasks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aw
- [Cancel Step](#cancel-step)
- [Modify Instance Fleet](#modify-instance-fleet)
- [Modify Instance Group](#modify-instance-group)
- [EKS](#eks)
- [Call](#call)
- [Glue](#glue)
- [Glue DataBrew](#glue-databrew)
- [Lambda](#lambda)
Expand Down Expand Up @@ -664,6 +666,28 @@ new tasks.EmrModifyInstanceGroupByName(stack, 'Task', {
});
```

## EKS

Step Functions supports Amazon EKS through the service integration pattern.
The service integration APIs correspond to Amazon EKS APIs.

[Read more](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) about the differences when using these service integrations.

### Call

Read and write Kubernetes resource objects via a Kubernetes API endpoint.
Corresponds to the [`call`](https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html) API in Step Functions Connector.

```ts
new tasks.EksCall(stack, 'Call a EKS Endpoint', {
clusterName: 'clusterName',
certificateAuthority: 'certificateAuthority',
endpoint: 'https://apiid.gr7.us-east-1.eks.amazonaws.com',
httpMethod: MethodType.GET,
path: '/api/v1/namespaces/default/pods',
});
```

## Glue

Step Functions supports [AWS Glue](https://docs.aws.amazon.com/step-functions/latest/dg/connect-glue.html) through the service integration pattern.
Expand Down
125 changes: 125 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions-tasks/lib/eks/call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import * as iam from '@aws-cdk/aws-iam';
import * as sfn from '@aws-cdk/aws-stepfunctions';
import { Construct } from 'constructs';
import { integrationResourceArn, validatePatternSupported } from '../private/task-utils';

/**
* Properties for calling a EKS endpoint with EksCall
*/
export interface EksCallProps extends sfn.TaskStateBaseProps {

/**
* Name of the cluster
*/
readonly clusterName: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not take in an ICluster and take properties out of it?
question: are step functions executions of EKS restricted to the account in which the state machine resides?

this is available as clusterName in an ICluster

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will use EKS L2 Construct instead in next commit.


/**
* Base 64 encoded certificate data required to communicate with your cluster
*/
readonly certificateAuthority: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is available as clusterCertificateAuthorityData from an ICluster

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will use EKS L2 Construct instead in next commit.


/**
* API endpoint to communicate with your cluster
*/
readonly endpoint: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is clusterEndpoint from an ICluster

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will use EKS L2 Construct instead in next commit.


/**
* HTTP method ("GET", "POST", "PUT", ...) part of HTTP request
*/
readonly httpMethod: MethodType;

/**
* Path of cluster
*/
readonly path: string;

/**
* Query Parameters part of HTTP request
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would be helpful to include doc links and or purpose of query parameters. the current doc strings don't add much information from the parameter names

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query parameters would look something like this: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#-strong-write-operations-cronjob-v1beta1-batch-strong- I'm not sure if it would be helpful to include an example such as this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotcha, I agree. maybe using it in the readme example would be helpful for users though.

* @default - no query parameters
*/
readonly queryParameters?: { [key: string]: string[] };

/**
* Request body part of HTTP request
* @default - No request body
*/
readonly requestBody?: { [key: string]: any };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not support paths: i.e. how could you supply $.blah
please change the type to sfn.TaskInput and also add a test for it.

the same applies to any parameters that support state input json path.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to sfn.TaskInput and added more coverage tests

}

/**
* Call a EKS endpoint as a Task
*
* @see https://docs.aws.amazon.com/step-functions/latest/dg/connect-eks.html
*/
export class EksCall extends sfn.TaskStateBase {

private static readonly SUPPORTED_INTEGRATION_PATTERNS: sfn.IntegrationPattern[] = [
sfn.IntegrationPattern.REQUEST_RESPONSE,
];

protected readonly taskMetrics?: sfn.TaskMetricsConfig;
protected readonly taskPolicies?: iam.PolicyStatement[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably worth a comment why task policies are not being set in this integration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment in latest commit.


private readonly integrationPattern: sfn.IntegrationPattern;

constructor(scope: Construct, id: string, private readonly props: EksCallProps) {
super(scope, id, props);
this.integrationPattern = props.integrationPattern ?? sfn.IntegrationPattern.REQUEST_RESPONSE;

validatePatternSupported(this.integrationPattern, EksCall.SUPPORTED_INTEGRATION_PATTERNS);
}

/**
* Provides the EKS Call service integration task configuration
* @internal
*/
protected _renderTask(): any {
return {
Resource: integrationResourceArn('eks', 'call', this.integrationPattern),
Parameters: sfn.FieldUtils.renderObject({
ClusterName: this.props.clusterName,
CertificateAuthority: this.props.certificateAuthority,
Endpoint: this.props.endpoint,
Method: this.props.httpMethod,
Path: this.props.path,
QueryParameters: this.props.queryParameters,
RequestBody: this.props.requestBody,
}),
};
}
}

/**
* Method type of a EKS call
*/
export enum MethodType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

choose a more specific name. It doesn't quite communicate the intent of the enum... maybe something like HttpMethods or some appropriate qualifier that is less general from a naming perspective

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will Change to HttpMethods in next commit.

/**
* Retrieve data from a server at the specified resource
*/
GET = 'GET',

/**
* Send data to the API endpoint to create or update a resource
*/
POST = 'POST',

/**
* Send data to the API endpoint to update or create a resource
*/
PUT = 'PUT',

/**
* Delete the resource at the specified endpoint
*/
DELETE = 'DELETE',

/**
* Apply partial modifications to the resource
*/
PATCH = 'PATCH',

/**
* Retrieve data from a server at the specified resource without the response body
*/
HEAD = 'HEAD'
}
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions-tasks/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ export * from './dynamodb/update-item';
export * from './dynamodb/delete-item';
export * from './dynamodb/shared-types';
export * from './codebuild/start-build';
export * from './eks/call';
export * from './athena/start-query-execution';
export * from './athena/stop-query-execution';
export * from './athena/get-query-execution';
export * from './athena/get-query-results';
export * from './databrew/start-job-run';
export * from './eks/call';
54 changes: 54 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/call.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as cdk from '@aws-cdk/core';
import { EksCall, MethodType } from '../../lib/eks/call';

describe('Call an EKS endpoint', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing tests for invalid service integration pattern (i.e. an error is thrown if RUN_JOB is selected)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add tests for run a job pattern in next commit.


test('default settings', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
const task = new EksCall(stack, 'Call', {
clusterName: 'clusterName',
certificateAuthority: 'certificateAuthority',
endpoint: 'endpoint',
httpMethod: MethodType.GET,
path: 'path',
requestBody: sfn.TaskInput.fromObject({
RequestBody: 'requestBody',
}),
});

// THEN
expect(stack.resolve(task.toStateJson())).toEqual({
Type: 'Task',
Resource: {
'Fn::Join': [
'',
[
'arn:',
{
Ref: 'AWS::Partition',
},
':states:::eks:call',
],
],
},
End: true,
Parameters: {
ClusterName: 'clusterName',
CertificateAuthority: 'certificateAuthority',
Endpoint: 'endpoint',
Method: 'GET',
Path: 'path',
RequestBody: {
type: 1,
value: {
RequestBody: 'requestBody',
},
},
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{
"Resources": {
"StateMachineRoleB840431D": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": {
"Fn::Join": [
"",
[
"states.",
{
"Ref": "AWS::Region"
},
".amazonaws.com"
]
]
}
}
}
],
"Version": "2012-10-17"
}
}
},
"StateMachine2E01A3A5": {
"Type": "AWS::StepFunctions::StateMachine",
"Properties": {
"RoleArn": {
"Fn::GetAtt": [
"StateMachineRoleB840431D",
"Arn"
]
},
"DefinitionString": {
"Fn::Join": [
"",
[
"{\"StartAt\":\"Call a EKS Endpoint\",\"States\":{\"Call a EKS Endpoint\":{\"End\":true,\"Type\":\"Task\",\"Resource\":\"arn:",
{
"Ref": "AWS::Partition"
},
":states:::eks:call\",\"Parameters\":{\"ClusterName\":\"clusterName\",\"CertificateAuthority\":\"certificateAuthority\",\"Endpoint\":\"https://apiid.gr7.us-east-1.eks.amazonaws.com\",\"Method\":\"GET\",\"Path\":\"/api/v1/namespaces/default/pods\"}}},\"TimeoutSeconds\":30}"
]
]
}
},
"DependsOn": [
"StateMachineRoleB840431D"
]
}
},
"Outputs": {
"stateMachineArn": {
"Value": {
"Ref": "StateMachine2E01A3A5"
}
}
}
}
28 changes: 28 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions-tasks/test/eks/integ.call.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as cdk from '@aws-cdk/core';
import { EksCall, MethodType } from '../../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-stepfunctions-tasks-eks-call-integ');
Comment on lines +18 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test is not self contained. Please include verification steps, but more importantly create the EKS cluster as a part of the integration test.

The test should create a state machine that can be executed successfully. Right now it has a dependency that an EKS job already exists called clusterName, but this is not self-contained.

Verification steps should look something like this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified integ test in the latest commit


const callJob = new EksCall(stack, 'Call a EKS Endpoint', {
clusterName: 'clusterName',
certificateAuthority: 'certificateAuthority',
endpoint: 'https://apiid.gr7.us-east-1.eks.amazonaws.com',
httpMethod: MethodType.GET,
path: '/api/v1/namespaces/default/pods',
});

const chain = sfn.Chain.start(callJob);

const sm = new sfn.StateMachine(stack, 'StateMachine', {
definition: chain,
timeout: cdk.Duration.seconds(30),
});

new cdk.CfnOutput(stack, 'stateMachineArn', {
value: sm.stateMachineArn,
});


app.synth();