Open hrko opened 3 weeks ago
Reproducible using customer code.
Error: Enable Execute Command options are not supported for External service
at new ExternalService (/Users/testuser/dev/repros/cdk/cdktest/node_modules/aws-cdk-lib/aws-ecs/lib/external/external-service.js:1:2388)
at new EcsAnywhereStack (/Users/testuser/dev/repros/cdk/cdktest/lib/ecs-anywhere-stack.ts:74:24)
at Object.<anonymous> (/Users/testuser/dev/repros/cdk/cdktest/bin/cdktest.ts:30:1)
at Module._compile (node:internal/modules/cjs/loader:1376:14)
at Module.m._compile (/Users/testuser/dev/repros/cdk/cdktest/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/testuser/dev/repros/cdk/cdktest/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 exception is thrown due to validation check here.
Looking at the commit history, the validation is in place since last 3 years per commit https://github.com/aws/aws-cdk/commit/3592b26c5806cc31cd6ad0ebba32cbf4d09b9abf.
@hrko Good afternoon. Could you please point me to documentation or example which demonstrates that enableExecuteCommand
is supported for ExternalService
(this service essentially uses LaunchType.EXTERNAL
)?
Thanks, Ashish
@ashishdhingra Thank you for your response.
As an example, extract a CfnService from an ExternalService and then enableExecuteCommand can be enabled for that CfnService. The example is shown in the following code:
const ecsService = new ecs.ExternalService(this, 'ExternalService', {
serviceName: "EcsAnywhereService",
cluster: EcsAnywhereCluster,
taskDefinition,
desiredCount: 1,
});
+ const cfnService = ecsService.node.defaultChild as ecs.CfnService;
+ cfnService.enableExecuteCommand = true;
Once the above example code is deployed, you can use aws ecs execute-command
to connect to an container in the external service.
(I did not find either a statement in the documentation that ExternalService
supports enableExecuteCommand
, or that it does not.)
@hrko Thanks for sharing your inputs. I was able to run cdk deploy
successfully after adding the escape hatch as you suggested, thereafter verifying enableExecuteCommand
being set to true
using AWS CLI command aws ecs describe-services --cluster EcsAnywhereCluster --region us-east-2 --services EcsAnywhereService
. Also noticed that documentation at Amazon ECS clusters for the external launch type mentioning ECS Exec is supported on external instances.
. So looks like the validation should be removed.
Thanks, Ashish
Describe the bug
When creating an ExternalService, specifying the
enableExecuteCommand: true
option for the property will result in the following error when runningcdk synth
.However, the
enableExecuteCommand
option is actually supported by the ExternalService as well, and can be manually enabled using the AWS CLI.Regression Issue
Last Known Working CDK Version
No response
Expected Behavior
When creating an ExternalService, the
enableExecuteCommand: true
option can be set for the property.Current Behavior
When creating an ExternalService, setting the
enableExecuteCommand: true
option to the property causes an error when executingcdk synth
.Reproduction Steps
A code snippet that reproduces the problem is like as follows:
Click here to show entire stack code
```ts import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as iam from "aws-cdk-lib/aws-iam"; import { CfnOutput } from 'aws-cdk-lib/core'; export class PocEcsAnywhereStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); // VPC const vpc = new ec2.Vpc(this, "EcsAnywhereVPC", { ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'), natGateways: 0, maxAzs: 2, subnetConfiguration: [ { cidrMask: 24, name: "EcsAnywherePublic", subnetType: ec2.SubnetType.PUBLIC, }, { cidrMask: 24, name: "EcsAnywherePrivate", subnetType: ec2.SubnetType.PRIVATE_ISOLATED, } ] } ) // ECS Cluster const EcsAnywhereCluster = new ecs.Cluster(this, "EcsAnywhereCluster", { vpc: vpc, clusterName: "EcsAnywhereCluster", }) // Task role const taskRole = new iam.Role(this, 'TaskRole', { assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'), }); taskRole.addToPolicy(new iam.PolicyStatement({ actions: [ // for ECS Exec 'ssmmessages:CreateControlChannel', 'ssmmessages:CreateDataChannel', 'ssmmessages:OpenControlChannel', 'ssmmessages:OpenDataChannel', ], resources: ['*'], })); // ECS task definition const taskDefinition = new ecs.ExternalTaskDefinition(this, 'ExternalTaskDefinition', { // executionRole: taskExecutionRole, taskRole: taskRole, }); taskDefinition.addContainer('NginxContainer', { image: ecs.ContainerImage.fromRegistry( "public.ecr.aws/nginx/nginx:latest" ), cpu: 256, memoryLimitMiB: 512, containerName: "EcsAnywhereContainer", // for ECS Exec linuxParameters: new ecs.LinuxParameters(this, 'LinuxParameters', { initProcessEnabled: true, }), }) // ECS service const ecsService = new ecs.ExternalService(this, 'ExternalService', { serviceName: "EcsAnywhereService", cluster: EcsAnywhereCluster, taskDefinition, desiredCount: 1, enableExecuteCommand: true, // for ECS Exec }); // Instance role for ECS Anywhere const instance_iam_role = new iam.Role(this, 'EcsAnywhereInstanceRole', { roleName: "EcsAnywhereInstanceRole", assumedBy: new iam.ServicePrincipal("ssm.amazonaws.com"), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"), iam.ManagedPolicy.fromManagedPolicyArn(this, "EcsAnywhereEC2Policy", "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"), ] }) // Output new CfnOutput(this, "Step1RegisterExternalInstance", { description: "Create an Systems Manager activation pair", value: `aws ssm create-activation --iam-role ${instance_iam_role.roleName}`, exportName: "1-RegisterExternalInstance", }) const ecsAnywhereInstallScriptUrl = "https://amazon-ecs-agent.s3.amazonaws.com/ecs-anywhere-install-latest.sh" new CfnOutput(this, "Step2DownloadInstallationScript", { description: "On your VM, download installation script", value: `curl -o "ecs-anywhere-install.sh" "${ecsAnywhereInstallScriptUrl}" && sudo chmod +x ecs-anywhere-install.sh`, exportName: "2-DownloadInstallationScript", }); new CfnOutput(this, "Step3ExecuteScript", { description: "Run installation script on VM", value: `sudo ./ecs-anywhere-install.sh --region ${this.region} --cluster ${EcsAnywhereCluster.clusterName} --activation-id $ACTIVATION_ID --activation-code $ACTIVATION_CODE`, exportName: "3-ExecuteInstallationScript", }); } } ```
Possible Solution
No response
Additional Information/Context
No response
CDK CLI Version
2.154.0 (build 0fc07f3)
Framework Version
No response
Node.js Version
v20.17.0
OS
Debian GNU/Linux 11 (bullseye)
Language
TypeScript
Language Version
No response
Other information
No response