UNPKG

@aws-cdk/aws-ecs

Version:

The CDK Construct Library for AWS::ECS

769 lines 109 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.PropagatedTagSource = exports.DeploymentControllerType = exports.LaunchType = exports.BaseService = exports.ListenerConfig = void 0; const jsiiDeprecationWarnings = require("../../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const appscaling = require("@aws-cdk/aws-applicationautoscaling"); const cloudwatch = require("@aws-cdk/aws-cloudwatch"); const ec2 = require("@aws-cdk/aws-ec2"); const elbv2 = require("@aws-cdk/aws-elasticloadbalancingv2"); const iam = require("@aws-cdk/aws-iam"); const cloudmap = require("@aws-cdk/aws-servicediscovery"); const core_1 = require("@aws-cdk/core"); const task_definition_1 = require("../base/task-definition"); const cluster_1 = require("../cluster"); const ecs_generated_1 = require("../ecs.generated"); const scalable_task_count_1 = require("./scalable-task-count"); /** * Base class for configuring listener when registering targets. */ class ListenerConfig { /** * Create a config for adding target group to ALB listener. */ static applicationListener(listener, props) { return new ApplicationListenerConfig(listener, props); } /** * Create a config for adding target group to NLB listener. */ static networkListener(listener, props) { return new NetworkListenerConfig(listener, props); } } exports.ListenerConfig = ListenerConfig; _a = JSII_RTTI_SYMBOL_1; ListenerConfig[_a] = { fqn: "@aws-cdk/aws-ecs.ListenerConfig", version: "1.204.0" }; /** * Class for configuring application load balancer listener when registering targets. */ class ApplicationListenerConfig extends ListenerConfig { constructor(listener, props) { super(); this.listener = listener; this.props = props; } /** * Create and attach a target group to listener. */ addTargets(id, target, service) { const props = this.props || {}; const protocol = props.protocol; const port = props.port ?? (protocol === elbv2.ApplicationProtocol.HTTPS ? 443 : 80); this.listener.addTargets(id, { ...props, targets: [ service.loadBalancerTarget({ ...target, }), ], port, }); } } /** * Class for configuring network load balancer listener when registering targets. */ class NetworkListenerConfig extends ListenerConfig { constructor(listener, props) { super(); this.listener = listener; this.props = props; } /** * Create and attach a target group to listener. */ addTargets(id, target, service) { const port = this.props?.port ?? 80; this.listener.addTargets(id, { ...this.props, targets: [ service.loadBalancerTarget({ ...target, }), ], port, }); } } /** * The base class for Ec2Service and FargateService services. */ class BaseService extends core_1.Resource { /** * Constructs a new instance of the BaseService class. */ constructor(scope, id, props, additionalProps, taskDefinition) { super(scope, id, { physicalName: props.serviceName, }); /** * The security groups which manage the allowed network traffic for the service. */ this.connections = new ec2.Connections(); /** * A list of Elastic Load Balancing load balancer objects, containing the load balancer name, the container * name (as it appears in a container definition), and the container port to access from the load balancer. */ this.loadBalancers = new Array(); /** * The details of the service discovery registries to assign to this service. * For more information, see Service Discovery. */ this.serviceRegistries = new Array(); try { jsiiDeprecationWarnings._aws_cdk_aws_ecs_BaseServiceProps(props); jsiiDeprecationWarnings._aws_cdk_aws_ecs_TaskDefinition(taskDefinition); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, BaseService); } throw error; } if (props.propagateTags && props.propagateTaskTagsFrom) { throw new Error('You can only specify either propagateTags or propagateTaskTagsFrom. Alternatively, you can leave both blank'); } this.taskDefinition = taskDefinition; // launchType will set to undefined if using external DeploymentController or capacityProviderStrategies const launchType = props.deploymentController?.type === DeploymentControllerType.EXTERNAL || props.capacityProviderStrategies !== undefined ? undefined : props.launchType; const propagateTagsFromSource = props.propagateTaskTagsFrom ?? props.propagateTags ?? PropagatedTagSource.NONE; this.resource = new ecs_generated_1.CfnService(this, 'Service', { desiredCount: props.desiredCount, serviceName: this.physicalName, loadBalancers: core_1.Lazy.any({ produce: () => this.loadBalancers }, { omitEmptyArray: true }), deploymentConfiguration: { maximumPercent: props.maxHealthyPercent || 200, minimumHealthyPercent: props.minHealthyPercent === undefined ? 50 : props.minHealthyPercent, deploymentCircuitBreaker: props.circuitBreaker ? { enable: true, rollback: props.circuitBreaker.rollback ?? false, } : undefined, }, propagateTags: propagateTagsFromSource === PropagatedTagSource.NONE ? undefined : props.propagateTags, enableEcsManagedTags: props.enableECSManagedTags ?? false, deploymentController: props.circuitBreaker ? { type: DeploymentControllerType.ECS, } : props.deploymentController, launchType: launchType, enableExecuteCommand: props.enableExecuteCommand, capacityProviderStrategy: props.capacityProviderStrategies, healthCheckGracePeriodSeconds: this.evaluateHealthGracePeriod(props.healthCheckGracePeriod), /* role: never specified, supplanted by Service Linked Role */ networkConfiguration: core_1.Lazy.any({ produce: () => this.networkConfiguration }, { omitEmptyArray: true }), serviceRegistries: core_1.Lazy.any({ produce: () => this.serviceRegistries }, { omitEmptyArray: true }), ...additionalProps, }); if (props.deploymentController?.type === DeploymentControllerType.EXTERNAL) { core_1.Annotations.of(this).addWarning('taskDefinition and launchType are blanked out when using external deployment controller.'); } this.serviceArn = this.getResourceArnAttribute(this.resource.ref, { service: 'ecs', resource: 'service', resourceName: `${props.cluster.clusterName}/${this.physicalName}`, }); this.serviceName = this.getResourceNameAttribute(this.resource.attrName); this.cluster = props.cluster; if (props.cloudMapOptions) { this.enableCloudMap(props.cloudMapOptions); } if (props.enableExecuteCommand) { this.enableExecuteCommand(); const logging = this.cluster.executeCommandConfiguration?.logging ?? cluster_1.ExecuteCommandLogging.DEFAULT; if (this.cluster.executeCommandConfiguration?.kmsKey) { this.enableExecuteCommandEncryption(logging); } if (logging !== cluster_1.ExecuteCommandLogging.NONE) { this.executeCommandLogConfiguration(); } } this.node.defaultChild = this.resource; } /** * Import an existing ECS/Fargate Service using the service cluster format. * The format is the "new" format "arn:aws:ecs:region:aws_account_id:service/cluster-name/service-name". * @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-account-settings.html#ecs-resource-ids */ static fromServiceArnWithCluster(scope, id, serviceArn) { const stack = core_1.Stack.of(scope); const arn = stack.splitArn(serviceArn, core_1.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 = core_1.Stack.of(scope).formatArn({ partition: arn.partition, region: arn.region, account: arn.account, service: 'ecs', resource: 'cluster', resourceName: clusterName, }); const cluster = cluster_1.Cluster.fromClusterArn(scope, `${id}Cluster`, clusterArn); class Import extends core_1.Resource { constructor() { super(...arguments); this.serviceArn = serviceArn; this.serviceName = serviceName; this.cluster = cluster; } } return new Import(scope, id, { environmentFromArn: serviceArn, }); } /** * The CloudMap service created for this service, if any. */ get cloudMapService() { return this.cloudmapService; } executeCommandLogConfiguration() { const logConfiguration = this.cluster.executeCommandConfiguration?.logConfiguration; this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 'logs:DescribeLogGroups', ], resources: ['*'], })); const logGroupArn = logConfiguration?.cloudWatchLogGroup ? `arn:${this.stack.partition}:logs:${this.env.region}:${this.env.account}:log-group:${logConfiguration.cloudWatchLogGroup.logGroupName}:*` : '*'; this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 'logs:CreateLogStream', 'logs:DescribeLogStreams', 'logs:PutLogEvents', ], resources: [logGroupArn], })); if (logConfiguration?.s3Bucket?.bucketName) { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 's3:GetBucketLocation', ], resources: ['*'], })); this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 's3:PutObject', ], resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketName}/*`], })); if (logConfiguration.s3EncryptionEnabled) { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 's3:GetEncryptionConfiguration', ], resources: [`arn:${this.stack.partition}:s3:::${logConfiguration.s3Bucket.bucketName}`], })); } } } enableExecuteCommandEncryption(logging) { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 'kms:Decrypt', 'kms:GenerateDataKey', ], resources: [`${this.cluster.executeCommandConfiguration?.kmsKey?.keyArn}`], })); this.cluster.executeCommandConfiguration?.kmsKey?.addToResourcePolicy(new iam.PolicyStatement({ actions: [ 'kms:*', ], resources: ['*'], principals: [new iam.ArnPrincipal(`arn:${this.stack.partition}:iam::${this.env.account}:root`)], })); if (logging === cluster_1.ExecuteCommandLogging.DEFAULT || this.cluster.executeCommandConfiguration?.logConfiguration?.cloudWatchEncryptionEnabled) { this.cluster.executeCommandConfiguration?.kmsKey?.addToResourcePolicy(new iam.PolicyStatement({ actions: [ 'kms:Encrypt*', 'kms:Decrypt*', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:Describe*', ], resources: ['*'], principals: [new iam.ServicePrincipal(`logs.${this.env.region}.amazonaws.com`)], conditions: { ArnLike: { 'kms:EncryptionContext:aws:logs:arn': `arn:${this.stack.partition}:logs:${this.env.region}:${this.env.account}:*` }, }, })); } } /** * This method is called to attach this service to an Application Load Balancer. * * Don't call this function directly. Instead, call `listener.addTargets()` * to add this service to a load balancer. */ attachToApplicationTargetGroup(targetGroup) { return this.defaultLoadBalancerTarget.attachToApplicationTargetGroup(targetGroup); } /** * Registers the service as a target of a Classic Load Balancer (CLB). * * Don't call this. Call `loadBalancer.addTarget()` instead. */ attachToClassicLB(loadBalancer) { return this.defaultLoadBalancerTarget.attachToClassicLB(loadBalancer); } /** * Return a load balancing target for a specific container and port. * * Use this function to create a load balancer target if you want to load balance to * another container than the first essential container or the first mapped port on * the container. * * Use the return value of this function where you would normally use a load balancer * target, instead of the `Service` object itself. * * @example * * declare const listener: elbv2.ApplicationListener; * declare const service: ecs.BaseService; * listener.addTargets('ECS', { * port: 80, * targets: [service.loadBalancerTarget({ * containerName: 'MyContainer', * containerPort: 1234, * })], * }); */ loadBalancerTarget(options) { try { jsiiDeprecationWarnings._aws_cdk_aws_ecs_LoadBalancerTargetOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.loadBalancerTarget); } throw error; } const self = this; const target = this.taskDefinition._validateTarget(options); const connections = self.connections; return { attachToApplicationTargetGroup(targetGroup) { targetGroup.registerConnectable(self, self.taskDefinition._portRangeFromPortMapping(target.portMapping)); return self.attachToELBv2(targetGroup, target.containerName, target.portMapping.containerPort); }, attachToNetworkTargetGroup(targetGroup) { return self.attachToELBv2(targetGroup, target.containerName, target.portMapping.containerPort); }, connections, attachToClassicLB(loadBalancer) { return self.attachToELB(loadBalancer, target.containerName, target.portMapping.containerPort); }, }; } /** * Use this function to create all load balancer targets to be registered in this service, add them to * target groups, and attach target groups to listeners accordingly. * * Alternatively, you can use `listener.addTargets()` to create targets and add them to target groups. * * @example * * declare const listener: elbv2.ApplicationListener; * declare const service: ecs.BaseService; * service.registerLoadBalancerTargets( * { * containerName: 'web', * containerPort: 80, * newTargetGroupId: 'ECS', * listener: ecs.ListenerConfig.applicationListener(listener, { * protocol: elbv2.ApplicationProtocol.HTTPS * }), * }, * ) */ registerLoadBalancerTargets(...targets) { try { jsiiDeprecationWarnings._aws_cdk_aws_ecs_EcsTarget(targets); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.registerLoadBalancerTargets); } throw error; } for (const target of targets) { target.listener.addTargets(target.newTargetGroupId, { containerName: target.containerName, containerPort: target.containerPort, protocol: target.protocol, }, this); } } /** * This method is called to attach this service to a Network Load Balancer. * * Don't call this function directly. Instead, call `listener.addTargets()` * to add this service to a load balancer. */ attachToNetworkTargetGroup(targetGroup) { return this.defaultLoadBalancerTarget.attachToNetworkTargetGroup(targetGroup); } /** * An attribute representing the minimum and maximum task count for an AutoScalingGroup. */ autoScaleTaskCount(props) { if (this.scalableTaskCount) { throw new Error('AutoScaling of task count already enabled for this service'); } return this.scalableTaskCount = new scalable_task_count_1.ScalableTaskCount(this, 'TaskCount', { serviceNamespace: appscaling.ServiceNamespace.ECS, resourceId: `service/${this.cluster.clusterName}/${this.serviceName}`, dimension: 'ecs:service:DesiredCount', role: this.makeAutoScalingRole(), ...props, }); } /** * Enable CloudMap service discovery for the service * * @returns The created CloudMap service */ enableCloudMap(options) { try { jsiiDeprecationWarnings._aws_cdk_aws_ecs_CloudMapOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.enableCloudMap); } throw error; } const sdNamespace = options.cloudMapNamespace ?? this.cluster.defaultCloudMapNamespace; if (sdNamespace === undefined) { throw new Error('Cannot enable service discovery if a Cloudmap Namespace has not been created in the cluster.'); } // Determine DNS type based on network mode const networkMode = this.taskDefinition.networkMode; if (networkMode === task_definition_1.NetworkMode.NONE) { throw new Error('Cannot use a service discovery if NetworkMode is None. Use Bridge, Host or AwsVpc instead.'); } // Bridge or host network mode requires SRV records let dnsRecordType = options.dnsRecordType; if (networkMode === task_definition_1.NetworkMode.BRIDGE || networkMode === task_definition_1.NetworkMode.HOST) { if (dnsRecordType === undefined) { dnsRecordType = cloudmap.DnsRecordType.SRV; } if (dnsRecordType !== cloudmap.DnsRecordType.SRV) { throw new Error('SRV records must be used when network mode is Bridge or Host.'); } } // Default DNS record type for AwsVpc network mode is A Records if (networkMode === task_definition_1.NetworkMode.AWS_VPC) { if (dnsRecordType === undefined) { dnsRecordType = cloudmap.DnsRecordType.A; } } const { containerName, containerPort } = determineContainerNameAndPort({ taskDefinition: this.taskDefinition, dnsRecordType: dnsRecordType, container: options.container, containerPort: options.containerPort, }); const cloudmapService = new cloudmap.Service(this, 'CloudmapService', { namespace: sdNamespace, name: options.name, dnsRecordType: dnsRecordType, customHealthCheck: { failureThreshold: options.failureThreshold || 1 }, dnsTtl: options.dnsTtl, }); const serviceArn = cloudmapService.serviceArn; // add Cloudmap service to the ECS Service's serviceRegistry this.addServiceRegistry({ arn: serviceArn, containerName, containerPort, }); this.cloudmapService = cloudmapService; return cloudmapService; } /** * Associates this service with a CloudMap service */ associateCloudMapService(options) { try { jsiiDeprecationWarnings._aws_cdk_aws_ecs_AssociateCloudMapServiceOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.associateCloudMapService); } throw error; } const service = options.service; const { containerName, containerPort } = determineContainerNameAndPort({ taskDefinition: this.taskDefinition, dnsRecordType: service.dnsRecordType, container: options.container, containerPort: options.containerPort, }); // add Cloudmap service to the ECS Service's serviceRegistry this.addServiceRegistry({ arn: service.serviceArn, containerName, containerPort, }); } /** * This method returns the specified CloudWatch metric name for this service. */ metric(metricName, props) { return new cloudwatch.Metric({ namespace: 'AWS/ECS', metricName, dimensionsMap: { ClusterName: this.cluster.clusterName, ServiceName: this.serviceName }, ...props, }).attachTo(this); } /** * This method returns the CloudWatch metric for this service's memory utilization. * * @default average over 5 minutes */ metricMemoryUtilization(props) { return this.metric('MemoryUtilization', props); } /** * This method returns the CloudWatch metric for this service's CPU utilization. * * @default average over 5 minutes */ metricCpuUtilization(props) { return this.metric('CPUUtilization', props); } /** * This method is called to create a networkConfiguration. * @deprecated use configureAwsVpcNetworkingWithSecurityGroups instead. */ // eslint-disable-next-line max-len configureAwsVpcNetworking(vpc, assignPublicIp, vpcSubnets, securityGroup) { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-ecs.BaseService#configureAwsVpcNetworking", "use configureAwsVpcNetworkingWithSecurityGroups instead."); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.configureAwsVpcNetworking); } throw error; } if (vpcSubnets === undefined) { vpcSubnets = assignPublicIp ? { subnetType: ec2.SubnetType.PUBLIC } : {}; } if (securityGroup === undefined) { securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', { vpc }); } this.connections.addSecurityGroup(securityGroup); this.networkConfiguration = { awsvpcConfiguration: { assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED', subnets: vpc.selectSubnets(vpcSubnets).subnetIds, securityGroups: core_1.Lazy.list({ produce: () => [securityGroup.securityGroupId] }), }, }; } /** * This method is called to create a networkConfiguration. */ // eslint-disable-next-line max-len configureAwsVpcNetworkingWithSecurityGroups(vpc, assignPublicIp, vpcSubnets, securityGroups) { if (vpcSubnets === undefined) { vpcSubnets = assignPublicIp ? { subnetType: ec2.SubnetType.PUBLIC } : {}; } if (securityGroups === undefined || securityGroups.length === 0) { securityGroups = [new ec2.SecurityGroup(this, 'SecurityGroup', { vpc })]; } securityGroups.forEach((sg) => { this.connections.addSecurityGroup(sg); }, this); this.networkConfiguration = { awsvpcConfiguration: { assignPublicIp: assignPublicIp ? 'ENABLED' : 'DISABLED', subnets: vpc.selectSubnets(vpcSubnets).subnetIds, securityGroups: securityGroups.map((sg) => sg.securityGroupId), }, }; } renderServiceRegistry(registry) { return { registryArn: registry.arn, containerName: registry.containerName, containerPort: registry.containerPort, }; } /** * Shared logic for attaching to an ELB */ attachToELB(loadBalancer, containerName, containerPort) { if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.AWS_VPC) { throw new Error('Cannot use a Classic Load Balancer if NetworkMode is AwsVpc. Use Host or Bridge instead.'); } if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.NONE) { throw new Error('Cannot use a Classic Load Balancer if NetworkMode is None. Use Host or Bridge instead.'); } this.loadBalancers.push({ loadBalancerName: loadBalancer.loadBalancerName, containerName, containerPort, }); } /** * Shared logic for attaching to an ELBv2 */ attachToELBv2(targetGroup, containerName, containerPort) { if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.NONE) { throw new Error('Cannot use a load balancer if NetworkMode is None. Use Bridge, Host or AwsVpc instead.'); } this.loadBalancers.push({ targetGroupArn: targetGroup.targetGroupArn, containerName, containerPort, }); // Service creation can only happen after the load balancer has // been associated with our target group(s), so add ordering dependency. this.resource.node.addDependency(targetGroup.loadBalancerAttached); const targetType = this.taskDefinition.networkMode === task_definition_1.NetworkMode.AWS_VPC ? elbv2.TargetType.IP : elbv2.TargetType.INSTANCE; return { targetType }; } get defaultLoadBalancerTarget() { return this.loadBalancerTarget({ containerName: this.taskDefinition.defaultContainer.containerName, }); } /** * Generate the role that will be used for autoscaling this service */ makeAutoScalingRole() { // Use a Service Linked Role. return iam.Role.fromRoleArn(this, 'ScalingRole', core_1.Stack.of(this).formatArn({ region: '', service: 'iam', resource: 'role/aws-service-role/ecs.application-autoscaling.amazonaws.com', resourceName: 'AWSServiceRoleForApplicationAutoScaling_ECSService', })); } /** * Associate Service Discovery (Cloud Map) service */ addServiceRegistry(registry) { if (this.serviceRegistries.length >= 1) { throw new Error('Cannot associate with the given service discovery registry. ECS supports at most one service registry per service.'); } const sr = this.renderServiceRegistry(registry); this.serviceRegistries.push(sr); } /** * Return the default grace period when load balancers are configured and * healthCheckGracePeriod is not already set */ evaluateHealthGracePeriod(providedHealthCheckGracePeriod) { return core_1.Lazy.any({ produce: () => providedHealthCheckGracePeriod?.toSeconds() ?? (this.loadBalancers.length > 0 ? 60 : undefined), }); } enableExecuteCommand() { this.taskDefinition.addToTaskRolePolicy(new iam.PolicyStatement({ actions: [ 'ssmmessages:CreateControlChannel', 'ssmmessages:CreateDataChannel', 'ssmmessages:OpenControlChannel', 'ssmmessages:OpenDataChannel', ], resources: ['*'], })); } } exports.BaseService = BaseService; _b = JSII_RTTI_SYMBOL_1; BaseService[_b] = { fqn: "@aws-cdk/aws-ecs.BaseService", version: "1.204.0" }; /** * The launch type of an ECS service */ var LaunchType; (function (LaunchType) { /** * The service will be launched using the EC2 launch type */ LaunchType["EC2"] = "EC2"; /** * The service will be launched using the FARGATE launch type */ LaunchType["FARGATE"] = "FARGATE"; /** * The service will be launched using the EXTERNAL launch type */ LaunchType["EXTERNAL"] = "EXTERNAL"; })(LaunchType = exports.LaunchType || (exports.LaunchType = {})); /** * The deployment controller type to use for the service. */ var DeploymentControllerType; (function (DeploymentControllerType) { /** * The rolling update (ECS) deployment type involves replacing the current * running version of the container with the latest version. */ DeploymentControllerType["ECS"] = "ECS"; /** * The blue/green (CODE_DEPLOY) deployment type uses the blue/green deployment model powered by AWS CodeDeploy */ DeploymentControllerType["CODE_DEPLOY"] = "CODE_DEPLOY"; /** * The external (EXTERNAL) deployment type enables you to use any third-party deployment controller */ DeploymentControllerType["EXTERNAL"] = "EXTERNAL"; })(DeploymentControllerType = exports.DeploymentControllerType || (exports.DeploymentControllerType = {})); /** * Propagate tags from either service or task definition */ var PropagatedTagSource; (function (PropagatedTagSource) { /** * Propagate tags from service */ PropagatedTagSource["SERVICE"] = "SERVICE"; /** * Propagate tags from task definition */ PropagatedTagSource["TASK_DEFINITION"] = "TASK_DEFINITION"; /** * Do not propagate */ PropagatedTagSource["NONE"] = "NONE"; })(PropagatedTagSource = exports.PropagatedTagSource || (exports.PropagatedTagSource = {})); /** * Determine the name of the container and port to target for the service registry. */ function determineContainerNameAndPort(options) { // If the record type is SRV, then provide the containerName and containerPort to target. // We use the name of the default container and the default port of the default container // unless the user specifies otherwise. if (options.dnsRecordType === cloudmap.DnsRecordType.SRV) { // Ensure the user-provided container is from the right task definition. if (options.container && options.container.taskDefinition != options.taskDefinition) { throw new Error('Cannot add discovery for a container from another task definition'); } const container = options.container ?? options.taskDefinition.defaultContainer; // Ensure that any port given by the user is mapped. if (options.containerPort && !container.portMappings.some(mapping => mapping.containerPort === options.containerPort)) { throw new Error('Cannot add discovery for a container port that has not been mapped'); } return { containerName: container.containerName, containerPort: options.containerPort ?? options.taskDefinition.defaultContainer.containerPort, }; } return {}; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYmFzZS1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGtFQUFrRTtBQUNsRSxzREFBc0Q7QUFDdEQsd0NBQXdDO0FBRXhDLDZEQUE2RDtBQUM3RCx3Q0FBd0M7QUFDeEMsMERBQTBEO0FBQzFELHdDQUFnSDtBQUVoSCw2REFBaUc7QUFDakcsd0NBQWdHO0FBRWhHLG9EQUE4QztBQUM5QywrREFBMEQ7QUFxTjFEOztHQUVHO0FBQ0gsTUFBc0IsY0FBYztJQUNsQzs7T0FFRztJQUNJLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxRQUFtQyxFQUFFLEtBQXdDO1FBQzdHLE9BQU8sSUFBSSx5QkFBeUIsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7S0FDdkQ7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxlQUFlLENBQUMsUUFBK0IsRUFBRSxLQUFvQztRQUNqRyxPQUFPLElBQUkscUJBQXFCLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ25EOztBQWJILHdDQW1CQzs7O0FBRUQ7O0dBRUc7QUFDSCxNQUFNLHlCQUEwQixTQUFRLGNBQWM7SUFDcEQsWUFBNkIsUUFBbUMsRUFBbUIsS0FBd0M7UUFDekgsS0FBSyxFQUFFLENBQUM7UUFEbUIsYUFBUSxHQUFSLFFBQVEsQ0FBMkI7UUFBbUIsVUFBSyxHQUFMLEtBQUssQ0FBbUM7S0FFMUg7SUFFRDs7T0FFRztJQUNJLFVBQVUsQ0FBQyxFQUFVLEVBQUUsTUFBaUMsRUFBRSxPQUFvQjtRQUNuRixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztRQUMvQixNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSyxDQUFDLG1CQUFtQixDQUFDLEtB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