Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ecs.FargateService: from_service_arn_with_cluster not accepting value from SSM Parameter string #30798

Closed
tisauro opened this issue Jul 9, 2024 · 5 comments · Fixed by #30902 or mannjaro/serverless-bedrock-proxy#2 · May be fixed by NOUIY/aws-solutions-constructs#114 or rwlxxvii/containers#185
Assignees
Labels
@aws-cdk/aws-ecs Related to Amazon Elastic Container bug This issue is a bug. effort/small Small work item – less than a day of effort p1

Comments

@tisauro
Copy link

tisauro commented Jul 9, 2024

Describe the bug

When retrieving a Fargate service arn from the parameter store and passing it to the function from_service_arn_with_cluster it throws the runtime exception: RuntimeError: Error: resource name ${Token[TOKEN.236]} from service ARN: ${Token[TOKEN.226]} is not using the ARN cluster format

Expected Behavior

accept the format

Current Behavior

raises exception RuntimeError: Error: resource name ${Token[TOKEN.236]} from service ARN: ${Token[TOKEN.226]} is not using the ARN cluster format

Reproduction Steps

class TestIacStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here

        alb_ecs_service = ecs_patterns.ApplicationLoadBalancedFargateService(self, 'Service',
                                                                             cluster=ecs.Cluster(self,
                                                                                                 'my_cluster',
                                                                                                 cluster_name="TestCluster"
                                                                                                 ),
                                                                             memory_limit_mib=512,
                                                                             cpu=0.5,
                                                                             task_image_options=ecs_patterns.ApplicationLoadBalancedTaskImageOptions(
                                                                                 image=ecs.ContainerImage.from_registry(
                                                                                     "amazon/amazon-ecs-sample")),
                                                                             public_load_balancer=True,
                                                                             desired_count=1,
                                                                             )

        ssm.StringParameter(self, "ssm_param",
                            parameter_name="ServiceArn",
                            string_value=alb_ecs_service.service.service_arn,
                            )

        ecs_service_arn = ssm.StringParameter.value_for_string_parameter(
            self,
            parameter_name="ServiceArn",
        )
        ecs_service = ecs.FargateService.from_service_arn_with_cluster(self, "FargateServiceArn",
                                                                       service_arn=ecs_service_arn)

        deploy_action = pipelineactions.EcsDeployAction(
            action_name="DeployToStage",
            service=ecs_service,
            image_file=codepipeline.ArtifactPath(codepipeline.Artifact("BuildArtifact"), 'imagedefinitions.json'),
            # deployment_timeout=Duration.minutes(60),
        )

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.148.0 (build e5740c0)

Framework Version

No response

Node.js Version

v18.19.1

OS

Linux

Language

Python

Language Version

3.9.19

Other information

I am trying to retrieve the ecs service from arn in a different module for passing it to a pipeline action as shown in the example above

@tisauro tisauro added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Jul 9, 2024
@github-actions github-actions bot added the @aws-cdk/aws-ecs Related to Amazon Elastic Container label Jul 9, 2024
@ashishdhingra ashishdhingra self-assigned this Jul 9, 2024
@ashishdhingra ashishdhingra added needs-reproduction This issue needs reproduction. and removed needs-triage This issue or PR still needs to be triaged. labels Jul 9, 2024
@ashishdhingra
Copy link
Contributor

Hi @tisauro,

Good morning. Thanks for opening the issue.

Although the issue is reproducible using following TypeScript CDK code:

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ssm from 'aws-cdk-lib/aws-ssm';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as pipelineActions from 'aws-cdk-lib/aws-codepipeline-actions'

export class TypescriptStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const albEcsService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', {
      cluster: new ecs.Cluster(this, 'TestCluster', {
        clusterName: 'TestCluster'
      }),
      memoryLimitMiB: 512,
      cpu: 0.5,
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample')
      },
      publicLoadBalancer: true,
      desiredCount: 1
    });

    new ssm.StringParameter(this, 'ssmParam', {
      parameterName: 'ServiceArn',
      stringValue: albEcsService.service.serviceArn
    });

    const ecsServiceArn = ssm.StringParameter.valueForStringParameter(this, 'ServiceArn');
    const ecsService = ecs.FargateService.fromServiceArnWithCluster(this, 'FargateServiceArn', ecsServiceArn);
    const deployAction = new pipelineActions.EcsDeployAction({
      actionName: 'DeployToStage',
      service: ecsService,
      imageFile: new codepipeline.ArtifactPath(new codepipeline.Artifact('BuildArtifact'), 'imagedefinitions.json')
    });
  }
}

which gives below error:

Error: resource name ${Token[TOKEN.246]} from service ARN: ${Token[TOKEN.236]} is not using the ARN cluster format
    at Function.fromServiceArnWithCluster (/Users/<<REDACTED>>/dev/repros/cdk/issue30798/typescript/node_modules/aws-cdk-lib/aws-ecs/lib/base/base-service.js:1:3823)
    at new TypescriptStack (/Users/<<REDACTED>>/dev/repros/cdk/issue30798/typescript/lib/typescript-stack.ts:32:43)
    at Object.<anonymous> (/Users/<<REDACTED>>/dev/repros/cdk/issue30798/typescript/bin/typescript.ts:7:1)
    at Module._compile (node:internal/modules/cjs/loader:1376:14)
    at Module.m._compile (/Users/<<REDACTED>>/dev/repros/cdk/issue30798/typescript/node_modules/ts-node/src/index.ts:1618:23)
    at Module._extensions..js (node:internal/modules/cjs/loader:1435:10)
    at Object.require.extensions.<computed> [as .ts] (/Users/<<REDACTED>>/dev/repros/cdk/issue30798/typescript/node_modules/ts-node/src/index.ts:1621:12)
    at Module.load (node:internal/modules/cjs/loader:1207:32)
    at Function.Module._load (node:internal/modules/cjs/loader:1023:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)

The reason we are getting the error is because:

  • Per documentation from valueForSecureStringParameter, the function Returns a token that will resolve (during deployment) to the string value of an SSM string parameter.. (also this method is deprecated)
  • Whereas BaseService.fromServiceArnWithCluster() expects exact service Arn (per code).
  • Per Tokens, Tokens represent values that can only be resolved at a later time in the app lifecycle.

For values which are resolved later during deployment, it appears that these cannot be used as such in static helper method BaseService.fromServiceArnWithCluster().

Thanks,
Ashish

@ashishdhingra ashishdhingra added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-reproduction This issue needs reproduction. labels Jul 10, 2024
@pahud
Copy link
Contributor

pahud commented Jul 11, 2024

Yes fromServiceArnWithCluster() does not handle the serviceArn correctly when it is a Token.

public static fromServiceArnWithCluster(scope: Construct, id: string, serviceArn: string): IBaseService {
const stack = Stack.of(scope);
const arn = stack.splitArn(serviceArn, ArnFormat.SLASH_RESOURCE_NAME);
const resourceName = arn.resourceName;
if (!resourceName) {
throw new Error(`Missing resource Name from service ARN: ${serviceArn}`);
}
const resourceNameParts = resourceName.split('/');
if (resourceNameParts.length !== 2) {
throw new Error(`resource name ${resourceName} from service ARN: ${serviceArn} is not using the ARN cluster format`);
}
const clusterName = resourceNameParts[0];
const serviceName = resourceNameParts[1];
const clusterArn = Stack.of(scope).formatArn({
partition: arn.partition,
region: arn.region,
account: arn.account,
service: 'ecs',
resource: 'cluster',
resourceName: clusterName,
});

The bug is at

const resourceName = arn.resourceName;

We should use Arn.extractResourceName() instead, which handles it well with Token support. See more samples here.

Making this a p1 bug and we welcome pull requests.

@pahud pahud added p1 effort/small Small work item – less than a day of effort and removed response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. labels Jul 11, 2024
@ashishdhingra ashishdhingra removed their assignment Jul 11, 2024
@xazhao xazhao self-assigned this Jul 16, 2024
@mergify mergify bot closed this as completed in #30902 Jul 23, 2024
@mergify mergify bot closed this as completed in 0baa573 Jul 23, 2024
Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

1 similar comment
Copy link

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

obraafo pushed a commit to obraafo/aws-cdk that referenced this issue Jul 25, 2024
…meter string (aws#30902)

### Issue # (if applicable)

Closes aws#30798.

### Reason for this change

`fromServiceArnWithCluster()` function can't handle token value correctly. 

### Description of changes
Replace
```
const resourceName = arn.resourceName; 
```
With
```
Arn.extractResourceName()
```
because the function above has the ability to handle token values.

### Description of how you validated changes

- Updated the unit test 
- Manually verified the ECS cluster resource was used in the code pipeline when using the SSM parameter.

### 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*
@aws-cdk-automation
Copy link
Collaborator

Comments on closed issues and PRs are hard for our team to see. If you need help, please open a new issue that references this one.

@aws aws locked as resolved and limited conversation to collaborators Jul 25, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.