Skip to content

Commit

Permalink
feat(codepipeline-actions): add elastic beanstalk deploy action (aws#…
Browse files Browse the repository at this point in the history
…22135)

Add  ElasticBeanstalk Deploy action for CodePipeline.

closes aws#2516


----

### All Submissions:

* [ ] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
TheRealAmazonKendra authored and madeline-k committed Oct 10, 2022
1 parent cd45f77 commit edffeba
Show file tree
Hide file tree
Showing 15 changed files with 2,908 additions and 0 deletions.
22 changes: 22 additions & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,28 @@ new codepipeline.Pipeline(this, 'Pipeline', {
});
```

### Elastic Beanstalk Deployment

To deploy an Elastic Beanstalk Application in CodePipeline:

```ts
const sourceOutput = new codepipeline.Artifact();
const targetBucket = new s3.Bucket(this, 'MyBucket');

const pipeline = new codepipeline.Pipeline(this, 'MyPipeline');
const deployAction = new codepipeline_actions.ElasticBeanstalkDeployAction({
actionName: 'ElasticBeanstalkDeploy',
input: sourceOutput,
environmentName: 'envName',
applicationName: 'appName',
});

const deployStage = pipeline.addStage({
stageName: 'Deploy',
actions: [deployAction],
});
```

### Alexa Skill

You can deploy to Alexa using CodePipeline with the following Action:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import { Construct } from 'constructs';
import { Action } from '../action';
import { deployArtifactBounds } from '../common';

/**
* Construction properties of the {@link ElasticBeanstalkDeployAction Elastic Beanstalk deploy CodePipeline Action}.
*/
export interface ElasticBeanstalkDeployActionProps extends codepipeline.CommonAwsActionProps {
/**
* The source to use as input for deployment.
*/
readonly input: codepipeline.Artifact;

/**
* The name of the AWS Elastic Beanstalk application to deploy.
*/
readonly applicationName: string;

/**
* The name of the AWS Elastic Beanstalk environment to deploy to.
*/
readonly environmentName: string;
}

/**
* CodePipeline action to deploy an AWS ElasticBeanstalk Application.
*/
export class ElasticBeanstalkDeployAction extends Action {
private readonly applicationName: string;
private readonly environmentName: string;

constructor(props: ElasticBeanstalkDeployActionProps) {
super({
...props,
category: codepipeline.ActionCategory.DEPLOY,
provider: 'ElasticBeanstalk',
artifactBounds: deployArtifactBounds(),
inputs: [props.input],
});

this.applicationName = props.applicationName;
this.environmentName = props.environmentName;
}

protected bound(
_scope: Construct,
_stage: codepipeline.IStage,
options: codepipeline.ActionBindOptions,
): codepipeline.ActionConfig {

// Per https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.iam.managed-policies.html
// it doesn't seem we can scope this down further for the codepipeline action.
options.role.addManagedPolicy({ managedPolicyArn: 'arn:aws:iam::aws:policy/AdministratorAccess-AWSElasticBeanstalk' });

// the Action's Role needs to read from the Bucket to get artifacts
options.bucket.grantRead(options.role);

return {
configuration: {
ApplicationName: this.applicationName,
EnvironmentName: this.environmentName,
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export * from './codedeploy/ecs-deploy-action';
export * from './codedeploy/server-deploy-action';
export * from './ecr/source-action';
export * from './ecs/deploy-action';
export * from './elastic-beanstalk/deploy-action';
export * from './github/source-action';
export * from './jenkins/jenkins-action';
export * from './jenkins/jenkins-provider';
Expand Down
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@aws-cdk/aws-cloudtrail": "0.0.0",
"@aws-cdk/aws-codestarnotifications": "0.0.0",
"@aws-cdk/aws-s3-assets": "0.0.0",
"@aws-cdk/aws-s3-deployment": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/integ-runner": "0.0.0",
"@aws-cdk/integ-tests": "0.0.0",
Expand All @@ -99,6 +100,7 @@
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-ecr": "0.0.0",
"@aws-cdk/aws-ecs": "0.0.0",
"@aws-cdk/aws-elasticbeanstalk": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
"@aws-cdk/aws-events-targets": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
Expand All @@ -122,6 +124,7 @@
"@aws-cdk/aws-ec2": "0.0.0",
"@aws-cdk/aws-ecr": "0.0.0",
"@aws-cdk/aws-ecs": "0.0.0",
"@aws-cdk/aws-elasticbeanstalk": "0.0.0",
"@aws-cdk/aws-events": "0.0.0",
"@aws-cdk/aws-events-targets": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Template } from '@aws-cdk/assertions';
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import { Bucket } from '@aws-cdk/aws-s3';
import { App, Stack } from '@aws-cdk/core';
import { ElasticBeanstalkDeployAction, S3SourceAction, S3Trigger } from '../../lib';

describe('elastic beanstalk deploy action tests', () => {
test('region and account are action region and account when set', () => {
const stack = buildPipelineStack();
Template.fromStack(stack).hasResourceProperties('AWS::CodePipeline::Pipeline', {
Stages: [
{
Actions: [
{
ActionTypeId: {
Category: 'Source',
Owner: 'AWS',
Provider: 'S3',
Version: '1',
},
Configuration: {
S3Bucket: {
Ref: 'MyBucketF68F3FF0',
},
S3ObjectKey: 'some/path/to',
PollForSourceChanges: true,
},
Name: 'Source',
OutputArtifacts: [
{
Name: 'Artifact_Source_Source',
},
],
RoleArn: {
'Fn::GetAtt': [
'MyPipelineSourceCodePipelineActionRoleAA05D76F',
'Arn',
],
},
RunOrder: 1,
},
],
Name: 'Source',
},
{
Actions: [
{
ActionTypeId: {
Category: 'Deploy',
Owner: 'AWS',
Provider: 'ElasticBeanstalk',
Version: '1',
},
Configuration: {
ApplicationName: 'testApplication',
EnvironmentName: 'env-testApplication',
},
InputArtifacts: [
{
Name: 'Artifact_Source_Source',
},
],
Name: 'Deploy',
RoleArn: {
'Fn::GetAtt': [
'MyPipelineDeployCodePipelineActionRole742BD48A',
'Arn',
],
},
RunOrder: 1,
},
],
Name: 'Deploy',
},
],
ArtifactStore: {
EncryptionKey: {
Id: {
'Fn::GetAtt': [
'MyPipelineArtifactsBucketEncryptionKey8BF0A7F3',
'Arn',
],
},
Type: 'KMS',
},
Location: {
Ref: 'MyPipelineArtifactsBucket727923DD',
},
Type: 'S3',
},
});
});
});

function buildPipelineStack(): Stack {
const app = new App();
const stack = new Stack(app);
const sourceOutput = new codepipeline.Artifact();
const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline');
pipeline.addStage({
stageName: 'Source',
actions: [
new S3SourceAction({
actionName: 'Source',
bucket: new Bucket(stack, 'MyBucket'),
bucketKey: 'some/path/to',
output: sourceOutput,
trigger: S3Trigger.POLL,
}),
],
});

pipeline.addStage({
stageName: 'Deploy',
actions: [
new ElasticBeanstalkDeployAction({
actionName: 'Deploy',
applicationName: 'testApplication',
environmentName: 'env-testApplication',
input: sourceOutput,
}),
],
});

return stack;
}
Loading

0 comments on commit edffeba

Please sign in to comment.