aws-cloudformation / aws-cloudformation/cloudformation-coverage-roadmap
[AWS::ECS::Service] - [Enhancement] - Expose Cloud Map service ARN for an ECS service using Service Connect
- Dominant language
- No language data
- Stars
- 1.1k
- Forks
- 62
- PR merge metrics
- No merged PRs in 30d
Description
### Name of the resource
AWS::ECS::Service
### Resource name
_No response_
### Description
When using ECS Service Connect, SC implicitly creates a Cloud Map service. We need the Cloud Map serivce ARN when integrating it with other AWS services like API Gateway ([CloudMap integration](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-private.html)). It would be great if CFn directly exposes the ARN as a resource attribute.
### Other Details
Current workaround: use a custom resource to get the ARN. CDK example is the following:
```ts
const cluster = new Cluster(this, 'Cluster', {
defaultCloudMapNamespace: {
name: 'foo',
useForServiceConnect: true,
type: NamespaceType.HTTP,
},
});
const serviceName = 'foo-service';
const service = new ecs.FargateService(this, 'FargateService', {
cluster,
taskDefinition,
serviceConnectConfiguration: {
services: [
{
portMappingName: serviceName,
},
],
},
});
service.node.addDependency(cluster.defaultCloudMapNamespace!);
const handler = new Function(this, 'GetCloudMapServiceArn', {
runtime: Runtime.NODEJS_20_X,
handler: 'index.handler',
timeout: Duration.seconds(30),
code: Code.fromInline(`
const response = require('cfn-response');
const sdk = require('@aws-sdk/client-servicediscovery');
const client = new sdk.ServiceDiscoveryClient();
exports.handler = async function (event, context) {
try {
console.log(event);
if (event.RequestType == 'Delete') {
return await response.send(event, context, response.SUCCESS);
}
// https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/servicediscovery/command/ListServicesCommand/
const namespaceId = event.ResourceProperties.NamespaceId;
const serviceName = event.ResourceProperties.ServiceName;
const command = new sdk.ListServicesCommand({
Filters: [
{
Name: "NAMESPACE_ID",
Values: [
namespaceId,
],
Condition: "EQ",
},
],
});
const res = await client.send(command);
const service = res.Services.find(service => service.Name == serviceName);
if (service == null) {
throw new Error('Service not found.');
}
await response.send(event, context, response.SUCCESS, { serviceArn: service.Arn }, service.Id);
} catch (e) {
console.log(e);
await response.send(event, context, response.FAILED);
}
};
`),
});
handler.addToRolePolicy(
new PolicyStatement({
actions: ['servicediscovery:ListServices'],
resources: ['*'],
})
);
const resource = new CustomResource(this, `GetServiceArnResult-${serviceName}`, {
serviceToken: handler.functionArn,
resourceType: 'Custom::GetServiceArn',
properties: { NamespaceId: cluster.defaultCloudMapNamespace!.namespaceId, ServiceName: serviceName },
});
resource.node.addDependency(ecsService);
const serviceArn = resource.getAttString('serviceArn');
```
Contributor guide
Assessment
This issue has not been assessed yet.