Aws-cdk: CodePipeline ClusterName & ServiceName deployment using AWS CDK

Created on 4 Oct 2019  路  4Comments  路  Source: aws/aws-cdk

I'm trying to replicate following CloudFormation template using AWS CDK:

      - Name: UpdateDev
        Actions:
        - Name: DeployImage
          InputArtifacts:
            - Name: BuildOutput
          ActionTypeId: {Category: Deploy, Owner: AWS, Version: 1, Provider: ECS}
          RoleArn: !Sub arn:aws:iam::${account}:role/deploy-role
          Configuration:
            ClusterName: cluster-name
            ServiceName: service-name
            FileName: imagedefinitions.json

However, I'm not sure how I should construct ecs.BaseService to achieve the needed functionality. Is there a raw Cfn class that could be used for this?

None of these combinations worked that I tried to use:

            new codepipeline_actions.EcsDeployAction({
                actionName: 'Deploy',
                imageFile: ...,
                service: ecs.FargateService.fromFargateServiceArn(stack, `service`, 'xxxx'), // does not compile
            }),

            new codepipeline_actions.EcsDeployAction({
                actionName: 'Deploy',
                imageFile: ...,
                service: {
                    stack,
                    cluster,
                    serviceName: name,
                    node: stack.node,
                } as ecs.BaseService // does not synth
            }),

Proposed API:

    pipeline.addStage({
        stageName: 'UpdateDev',
        actions: [
            new codepipeline_actions.EcsDeployAction({
                actionName: 'Deploy',
                imageFile: ...,
                service: 'service-name'
            }),
        ]
    });

Other

  • [ ] :wave: I may be able to implement this feature request
  • [ ] :warning: This feature might incur a breaking change

This is a :rocket: Feature Request

@aws-cdaws-codepipeline @aws-cdaws-ecs efformedium feature-request in-progress

Most helpful comment

This is being worked on in https://github.com/aws/aws-cdk/pull/5939

All 4 comments

Thanks for opening the issue @markusl . The problem you're running into is that ecs.FargateService.fromFargateServiceArn does not allow passing the cluster the service is part of, and that's needed information for the action to fill the ClusterName parameter (as you see in CFN).

If you know the cluster name, you can just implement the IAction interface directly:

import codepipeline = require('@aws-cdk/aws-codepipeline');
import events = require('@aws-cdk/aws-events');
import iam = require('@aws-cdk/aws-iam');
import { Construct } from '@aws-cdk/core';

export interface MyEcsDeployActionProps extends codepipeline.CommonAwsActionProps {
  readonly input: codepipeline.Artifact;
  readonly serviceName: string;
  readonly clusterName: string
}

export class MyEcsDeployAction implements codepipeline.IAction {
  public readonly actionProperties: codepipeline.ActionProperties;
  private readonly props: MyEcsDeployActionProps;

  constructor(props: MyEcsDeployActionProps) {
    this.actionProperties = {
      ...props,
      category: codepipeline.ActionCategory.DEPLOY,
      provider: 'ECS',
      artifactBounds: { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 },
      inputs: [props.input],
    };

    this.props = props;
  }

  public bind(_scope: Construct, _stage: codepipeline.IStage, options: codepipeline.ActionBindOptions):
    codepipeline.ActionConfig {
    // you probably need all these permissions
    options.role.addToPolicy(new iam.PolicyStatement({
      actions: [
        'ecs:DescribeServices',
        'ecs:DescribeTaskDefinition',
        'ecs:DescribeTasks',
        'ecs:ListTasks',
        'ecs:RegisterTaskDefinition',
        'ecs:UpdateService',
      ],
      resources: ['*']
    }));

    options.role.addToPolicy(new iam.PolicyStatement({
      actions: ['iam:PassRole'],
      resources: ['*'],
      conditions: {
        StringEqualsIfExists: {
          'iam:PassedToService': [
            'ec2.amazonaws.com',
            'ecs-tasks.amazonaws.com',
          ],
        }
      }
    }));

    options.bucket.grantRead(options.role);

    return {
      configuration: {
        ClusterName: this.props.clusterName,
        ServiceName: this.props.serviceName,
        // FileName is imagedefinitions.json by default
      },
    };
  }

  public onStateChange(name: string, target?: events.IRuleTarget, options?: events.RuleProps): events.Rule {
    throw new Error("Method not implemented.");
  }
}

And you use it like so:

    pipeline.addStage({
        stageName: 'UpdateDev',
        actions: [
            new MyEcsDeployAction({
                actionName: 'Deploy',
                serviceName: 'service-name',
                clusterName: 'cluster-name',
                input: buildOutput,
            }),
        ],
    });

Let me know if that helps!

Thanks,
Adam

@skinny85 thank you for quick response! We will use the provided workaround until this is natively supported in CDK.

Regards,
Markus

This is being worked on in https://github.com/aws/aws-cdk/pull/5939

Done in #6412 :)

Was this page helpful?
0 / 5 - 0 ratings