@aws-cdk/aws-ecs
Version:
The CDK Construct Library for AWS::ECS
669 lines • 105 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.AsgCapacityProvider = exports.ExecuteCommandLogging = exports.Cluster = exports.MachineImageType = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const autoscaling = require("@aws-cdk/aws-autoscaling");
const cloudwatch = require("@aws-cdk/aws-cloudwatch");
const ec2 = require("@aws-cdk/aws-ec2");
const iam = require("@aws-cdk/aws-iam");
const cloudmap = require("@aws-cdk/aws-servicediscovery");
const core_1 = require("@aws-cdk/core");
const amis_1 = require("./amis");
const instance_drain_hook_1 = require("./drain-hook/instance-drain-hook");
const ecs_canned_metrics_generated_1 = require("./ecs-canned-metrics.generated");
const ecs_generated_1 = require("./ecs.generated");
// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
// eslint-disable-next-line
const core_2 = require("@aws-cdk/core");
/**
* The machine image type
*/
var MachineImageType;
(function (MachineImageType) {
/**
* Amazon ECS-optimized Amazon Linux 2 AMI
*/
MachineImageType[MachineImageType["AMAZON_LINUX_2"] = 0] = "AMAZON_LINUX_2";
/**
* Bottlerocket AMI
*/
MachineImageType[MachineImageType["BOTTLEROCKET"] = 1] = "BOTTLEROCKET";
})(MachineImageType = exports.MachineImageType || (exports.MachineImageType = {}));
/**
* A regional grouping of one or more container instances on which you can run tasks and services.
*/
class Cluster extends core_1.Resource {
/**
* Constructs a new instance of the Cluster class.
*/
constructor(scope, id, props = {}) {
super(scope, id, {
physicalName: props.clusterName,
});
/**
* Manage the allowed network connections for the cluster with Security Groups.
*/
this.connections = new ec2.Connections();
/**
* The names of both ASG and Fargate capacity providers associated with the cluster.
*/
this._capacityProviderNames = [];
/**
* Specifies whether the cluster has EC2 instance capacity.
*/
this._hasEc2Capacity = false;
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ClusterProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Cluster);
}
throw error;
}
/**
* clusterSettings needs to be undefined if containerInsights is not explicitly set in order to allow any
* containerInsights settings on the account to apply. See:
* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clustersettings.html#cfn-ecs-cluster-clustersettings-value
*/
let clusterSettings = undefined;
if (props.containerInsights !== undefined) {
clusterSettings = [{ name: 'containerInsights', value: props.containerInsights ? ContainerInsights.ENABLED : ContainerInsights.DISABLED }];
}
this._capacityProviderNames = props.capacityProviders ?? [];
if (props.enableFargateCapacityProviders) {
this.enableFargateCapacityProviders();
}
if (props.executeCommandConfiguration) {
if ((props.executeCommandConfiguration.logging === ExecuteCommandLogging.OVERRIDE) !==
(props.executeCommandConfiguration.logConfiguration !== undefined)) {
throw new Error('Execute command log configuration must only be specified when logging is OVERRIDE.');
}
this._executeCommandConfiguration = props.executeCommandConfiguration;
}
const cluster = new ecs_generated_1.CfnCluster(this, 'Resource', {
clusterName: this.physicalName,
clusterSettings,
configuration: this._executeCommandConfiguration && this.renderExecuteCommandConfiguration(),
});
this.clusterArn = this.getResourceArnAttribute(cluster.attrArn, {
service: 'ecs',
resource: 'cluster',
resourceName: this.physicalName,
});
this.clusterName = this.getResourceNameAttribute(cluster.ref);
this.vpc = props.vpc || new ec2.Vpc(this, 'Vpc', { maxAzs: 2 });
this._defaultCloudMapNamespace = props.defaultCloudMapNamespace !== undefined
? this.addDefaultCloudMapNamespace(props.defaultCloudMapNamespace)
: undefined;
this._autoscalingGroup = props.capacity !== undefined
? this.addCapacity('DefaultAutoScalingGroup', props.capacity)
: undefined;
// Only create cluster capacity provider associations if there are any EC2
// capacity providers. Ordinarily we'd just add the construct to the tree
// since it's harmless, but we'd prefer not to add unexpected new
// resources to the stack which could surprise users working with
// brown-field CDK apps and stacks.
core_1.Aspects.of(this).add(new MaybeCreateCapacityProviderAssociations(this, id, this._capacityProviderNames));
}
/**
* Import an existing cluster to the stack from its attributes.
*/
static fromClusterAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ClusterAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromClusterAttributes);
}
throw error;
}
return new ImportedCluster(scope, id, attrs);
}
/**
* Import an existing cluster to the stack from the cluster ARN.
* This does not provide access to the vpc, hasEc2Capacity, or connections -
* use the `fromClusterAttributes` method to access those properties.
*/
static fromClusterArn(scope, id, clusterArn) {
const stack = core_1.Stack.of(scope);
const arn = stack.splitArn(clusterArn, core_1.ArnFormat.SLASH_RESOURCE_NAME);
const clusterName = arn.resourceName;
if (!clusterName) {
throw new Error(`Missing required Cluster Name from Cluster ARN: ${clusterArn}`);
}
const errorSuffix = 'is not available for a Cluster imported using fromClusterArn(), please use fromClusterAttributes() instead.';
class Import extends core_1.Resource {
constructor() {
super(...arguments);
this.clusterArn = clusterArn;
this.clusterName = clusterName;
}
get hasEc2Capacity() {
throw new Error(`hasEc2Capacity ${errorSuffix}`);
}
get connections() {
throw new Error(`connections ${errorSuffix}`);
}
get vpc() {
throw new Error(`vpc ${errorSuffix}`);
}
}
return new Import(scope, id, {
environmentFromArn: clusterArn,
});
}
/**
* Enable the Fargate capacity providers for this cluster.
*/
enableFargateCapacityProviders() {
for (const provider of ['FARGATE', 'FARGATE_SPOT']) {
if (!this._capacityProviderNames.includes(provider)) {
this._capacityProviderNames.push(provider);
}
}
}
renderExecuteCommandConfiguration() {
return {
executeCommandConfiguration: {
kmsKeyId: this._executeCommandConfiguration?.kmsKey?.keyArn,
logConfiguration: this._executeCommandConfiguration?.logConfiguration && this.renderExecuteCommandLogConfiguration(),
logging: this._executeCommandConfiguration?.logging,
},
};
}
renderExecuteCommandLogConfiguration() {
const logConfiguration = this._executeCommandConfiguration?.logConfiguration;
if (logConfiguration?.s3EncryptionEnabled && !logConfiguration?.s3Bucket) {
throw new Error('You must specify an S3 bucket name in the execute command log configuration to enable S3 encryption.');
}
if (logConfiguration?.cloudWatchEncryptionEnabled && !logConfiguration?.cloudWatchLogGroup) {
throw new Error('You must specify a CloudWatch log group in the execute command log configuration to enable CloudWatch encryption.');
}
return {
cloudWatchEncryptionEnabled: logConfiguration?.cloudWatchEncryptionEnabled,
cloudWatchLogGroupName: logConfiguration?.cloudWatchLogGroup?.logGroupName,
s3BucketName: logConfiguration?.s3Bucket?.bucketName,
s3EncryptionEnabled: logConfiguration?.s3EncryptionEnabled,
s3KeyPrefix: logConfiguration?.s3KeyPrefix,
};
}
/**
* Add an AWS Cloud Map DNS namespace for this cluster.
* NOTE: HttpNamespaces are not supported, as ECS always requires a DNSConfig when registering an instance to a Cloud
* Map service.
*/
addDefaultCloudMapNamespace(options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_CloudMapNamespaceOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addDefaultCloudMapNamespace);
}
throw error;
}
if (this._defaultCloudMapNamespace !== undefined) {
throw new Error('Can only add default namespace once.');
}
const namespaceType = options.type !== undefined
? options.type
: cloudmap.NamespaceType.DNS_PRIVATE;
const sdNamespace = namespaceType === cloudmap.NamespaceType.DNS_PRIVATE ?
new cloudmap.PrivateDnsNamespace(this, 'DefaultServiceDiscoveryNamespace', {
name: options.name,
vpc: this.vpc,
}) :
new cloudmap.PublicDnsNamespace(this, 'DefaultServiceDiscoveryNamespace', {
name: options.name,
});
this._defaultCloudMapNamespace = sdNamespace;
return sdNamespace;
}
/**
* Getter for namespace added to cluster
*/
get defaultCloudMapNamespace() {
return this._defaultCloudMapNamespace;
}
/**
* It is highly recommended to use {@link Cluster.addAsgCapacityProvider} instead of this method.
*
* This method adds compute capacity to a cluster by creating an AutoScalingGroup with the specified options.
*
* Returns the AutoScalingGroup so you can add autoscaling settings to it.
*/
addCapacity(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddCapacityOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addCapacity);
}
throw error;
}
// Do 2-way defaulting here: if the machineImageType is BOTTLEROCKET, pick the right AMI.
// Otherwise, determine the machineImageType from the given AMI.
const machineImage = options.machineImage ??
(options.machineImageType === MachineImageType.BOTTLEROCKET ? new amis_1.BottleRocketImage({
architecture: options.instanceType.architecture,
}) : new amis_1.EcsOptimizedAmi());
const machineImageType = options.machineImageType ??
(isBottleRocketImage(machineImage) ? MachineImageType.BOTTLEROCKET : MachineImageType.AMAZON_LINUX_2);
const autoScalingGroup = new autoscaling.AutoScalingGroup(this, id, {
vpc: this.vpc,
machineImage,
updateType: options.updateType || autoscaling.UpdateType.REPLACING_UPDATE,
...options,
});
this.addAutoScalingGroup(autoScalingGroup, {
machineImageType: machineImageType,
...options,
});
return autoScalingGroup;
}
/**
* This method adds an Auto Scaling Group Capacity Provider to a cluster.
*
* @param provider the capacity provider to add to this cluster.
*/
addAsgCapacityProvider(provider, options = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_AsgCapacityProvider(provider);
jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddAutoScalingGroupCapacityOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addAsgCapacityProvider);
}
throw error;
}
// Don't add the same capacity provider more than once.
if (this._capacityProviderNames.includes(provider.capacityProviderName)) {
return;
}
this._hasEc2Capacity = true;
this.configureAutoScalingGroup(provider.autoScalingGroup, {
...options,
machineImageType: provider.machineImageType,
// Don't enable the instance-draining lifecycle hook if managed termination protection is enabled
taskDrainTime: provider.enableManagedTerminationProtection ? core_1.Duration.seconds(0) : options.taskDrainTime,
canContainersAccessInstanceRole: options.canContainersAccessInstanceRole ?? provider.canContainersAccessInstanceRole,
});
this._capacityProviderNames.push(provider.capacityProviderName);
}
/**
* This method adds compute capacity to a cluster using the specified AutoScalingGroup.
*
* @deprecated Use {@link Cluster.addAsgCapacityProvider} instead.
* @param autoScalingGroup the ASG to add to this cluster.
* [disable-awslint:ref-via-interface] is needed in order to install the ECS
* agent by updating the ASGs user data.
*/
addAutoScalingGroup(autoScalingGroup, options = {}) {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-ecs.Cluster#addAutoScalingGroup", "Use {@link Cluster.addAsgCapacityProvider} instead.");
jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddAutoScalingGroupCapacityOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addAutoScalingGroup);
}
throw error;
}
this._hasEc2Capacity = true;
this.connections.connections.addSecurityGroup(...autoScalingGroup.connections.securityGroups);
this.configureAutoScalingGroup(autoScalingGroup, options);
}
configureAutoScalingGroup(autoScalingGroup, options = {}) {
if (autoScalingGroup.osType === ec2.OperatingSystemType.WINDOWS) {
this.configureWindowsAutoScalingGroup(autoScalingGroup, options);
}
else {
// Tie instances to cluster
switch (options.machineImageType) {
// Bottlerocket AMI
case MachineImageType.BOTTLEROCKET: {
autoScalingGroup.addUserData(
// Connect to the cluster
// Source: https://github.com/bottlerocket-os/bottlerocket/blob/develop/QUICKSTART-ECS.md#connecting-to-your-cluster
'[settings.ecs]', `cluster = "${this.clusterName}"`);
// Enabling SSM
// Source: https://github.com/bottlerocket-os/bottlerocket/blob/develop/QUICKSTART-ECS.md#enabling-ssm
autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
// required managed policy
autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role'));
break;
}
default:
// Amazon ECS-optimized AMI for Amazon Linux 2
autoScalingGroup.addUserData(`echo ECS_CLUSTER=${this.clusterName} >> /etc/ecs/ecs.config`);
if (!options.canContainersAccessInstanceRole) {
// Deny containers access to instance metadata service
// Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
autoScalingGroup.addUserData('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
autoScalingGroup.addUserData('sudo service iptables save');
// The following is only for AwsVpc networking mode, but doesn't hurt for the other modes.
autoScalingGroup.addUserData('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
}
if (autoScalingGroup.spotPrice && options.spotInstanceDraining) {
autoScalingGroup.addUserData('echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config');
}
}
}
// ECS instances must be able to do these things
// Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
// But, scoped down to minimal permissions required.
// Notes:
// - 'ecs:CreateCluster' removed. The cluster already exists.
autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
actions: [
'ecs:DeregisterContainerInstance',
'ecs:RegisterContainerInstance',
'ecs:Submit*',
],
resources: [
this.clusterArn,
],
}));
autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
actions: [
// These act on a cluster instance, and the instance doesn't exist until the service starts.
// Thus, scope to the cluster using a condition.
// See: https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonelasticcontainerservice.html
'ecs:Poll',
'ecs:StartTelemetrySession',
],
resources: ['*'],
conditions: {
ArnEquals: { 'ecs:cluster': this.clusterArn },
},
}));
autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
actions: [
// These do not support resource constraints, and must be resource '*'
'ecs:DiscoverPollEndpoint',
'ecr:GetAuthorizationToken',
// Preserved for backwards compatibility.
// Users are able to enable cloudwatch agent using CDK. Existing
// customers might be installing CW agent as part of user-data so if we
// remove these permissions we will break that customer use cases.
'logs:CreateLogStream',
'logs:PutLogEvents',
],
resources: ['*'],
}));
// 0 disables, otherwise forward to underlying implementation which picks the sane default
if (!options.taskDrainTime || options.taskDrainTime.toSeconds() !== 0) {
new instance_drain_hook_1.InstanceDrainHook(autoScalingGroup, 'DrainECSHook', {
autoScalingGroup,
cluster: this,
drainTime: options.taskDrainTime,
topicEncryptionKey: options.topicEncryptionKey,
});
}
}
/**
* This method enables the Fargate or Fargate Spot capacity providers on the cluster.
*
* @param provider the capacity provider to add to this cluster.
* @deprecated Use {@link enableFargateCapacityProviders} instead.
* @see {@link addAsgCapacityProvider} to add an Auto Scaling Group capacity provider to the cluster.
*/
addCapacityProvider(provider) {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-ecs.Cluster#addCapacityProvider", "Use {@link enableFargateCapacityProviders} instead.");
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addCapacityProvider);
}
throw error;
}
if (!(provider === 'FARGATE' || provider === 'FARGATE_SPOT')) {
throw new Error('CapacityProvider not supported');
}
if (!this._capacityProviderNames.includes(provider)) {
this._capacityProviderNames.push(provider);
}
}
configureWindowsAutoScalingGroup(autoScalingGroup, options = {}) {
// clear the cache of the agent
autoScalingGroup.addUserData('Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache');
// pull the latest ECS Tools
autoScalingGroup.addUserData('Import-Module ECSTools');
// set the cluster name environment variable
autoScalingGroup.addUserData(`[Environment]::SetEnvironmentVariable("ECS_CLUSTER", "${this.clusterName}", "Machine")`);
autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE", "true", "Machine")');
// tslint:disable-next-line: max-line-length
autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_AVAILABLE_LOGGING_DRIVERS", \'["json-file","awslogs"]\', "Machine")');
// enable instance draining
if (autoScalingGroup.spotPrice && options.spotInstanceDraining) {
autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_SPOT_INSTANCE_DRAINING", "true", "Machine")');
}
// enable task iam role
if (!options.canContainersAccessInstanceRole) {
autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_TASK_IAM_ROLE", "true", "Machine")');
autoScalingGroup.addUserData(`Initialize-ECSAgent -Cluster '${this.clusterName}' -EnableTaskIAMRole`);
}
else {
autoScalingGroup.addUserData(`Initialize-ECSAgent -Cluster '${this.clusterName}'`);
}
}
/**
* Getter for autoscaling group added to cluster
*/
get autoscalingGroup() {
return this._autoscalingGroup;
}
/**
* Whether the cluster has EC2 capacity associated with it
*/
get hasEc2Capacity() {
return this._hasEc2Capacity;
}
/**
* Getter for execute command configuration associated with the cluster.
*/
get executeCommandConfiguration() {
return this._executeCommandConfiguration;
}
/**
* This method returns the CloudWatch metric for this clusters CPU reservation.
*
* @default average over 5 minutes
*/
metricCpuReservation(props) {
return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.cpuReservationAverage, props);
}
/**
* This method returns the CloudWatch metric for this clusters CPU utilization.
*
* @default average over 5 minutes
*/
metricCpuUtilization(props) {
return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.cpuUtilizationAverage, props);
}
/**
* This method returns the CloudWatch metric for this clusters memory reservation.
*
* @default average over 5 minutes
*/
metricMemoryReservation(props) {
return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.memoryReservationAverage, props);
}
/**
* This method returns the CloudWatch metric for this clusters memory utilization.
*
* @default average over 5 minutes
*/
metricMemoryUtilization(props) {
return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.memoryUtilizationAverage, props);
}
/**
* This method returns the specifed CloudWatch metric for this cluster.
*/
metric(metricName, props) {
return new cloudwatch.Metric({
namespace: 'AWS/ECS',
metricName,
dimensionsMap: { ClusterName: this.clusterName },
...props,
}).attachTo(this);
}
cannedMetric(fn, props) {
return new cloudwatch.Metric({
...fn({ ClusterName: this.clusterName }),
...props,
}).attachTo(this);
}
}
exports.Cluster = Cluster;
_a = JSII_RTTI_SYMBOL_1;
Cluster[_a] = { fqn: "@aws-cdk/aws-ecs.Cluster", version: "1.204.0" };
/**
* An Cluster that has been imported
*/
class ImportedCluster extends core_1.Resource {
/**
* Constructs a new instance of the ImportedCluster class.
*/
constructor(scope, id, props) {
super(scope, id);
/**
* Security group of the cluster instances
*/
this.connections = new ec2.Connections();
this.clusterName = props.clusterName;
this.vpc = props.vpc;
this.hasEc2Capacity = props.hasEc2Capacity !== false;
this._defaultCloudMapNamespace = props.defaultCloudMapNamespace;
this._executeCommandConfiguration = props.executeCommandConfiguration;
this.clusterArn = props.clusterArn ?? core_1.Stack.of(this).formatArn({
service: 'ecs',
resource: 'cluster',
resourceName: props.clusterName,
});
this.connections = new ec2.Connections({
securityGroups: props.securityGroups,
});
}
get defaultCloudMapNamespace() {
return this._defaultCloudMapNamespace;
}
get executeCommandConfiguration() {
return this._executeCommandConfiguration;
}
}
var ContainerInsights;
(function (ContainerInsights) {
/**
* Enable CloudWatch Container Insights for the cluster
*/
ContainerInsights["ENABLED"] = "enabled";
/**
* Disable CloudWatch Container Insights for the cluster
*/
ContainerInsights["DISABLED"] = "disabled";
})(ContainerInsights || (ContainerInsights = {}));
/**
* The log settings to use to for logging the execute command session. For more information, see
* [Logging] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html#cfn-ecs-cluster-executecommandconfiguration-logging
*/
var ExecuteCommandLogging;
(function (ExecuteCommandLogging) {
/**
* The execute command session is not logged.
*/
ExecuteCommandLogging["NONE"] = "NONE";
/**
* The awslogs configuration in the task definition is used. If no logging parameter is specified, it defaults to this value. If no awslogs log driver is configured in the task definition, the output won't be logged.
*/
ExecuteCommandLogging["DEFAULT"] = "DEFAULT";
/**
* Specify the logging details as a part of logConfiguration.
*/
ExecuteCommandLogging["OVERRIDE"] = "OVERRIDE";
})(ExecuteCommandLogging = exports.ExecuteCommandLogging || (exports.ExecuteCommandLogging = {}));
/**
* An Auto Scaling Group Capacity Provider. This allows an ECS cluster to target
* a specific EC2 Auto Scaling Group for the placement of tasks. Optionally (and
* recommended), ECS can manage the number of instances in the ASG to fit the
* tasks, and can ensure that instances are not prematurely terminated while
* there are still tasks running on them.
*/
class AsgCapacityProvider extends core_2.Construct {
constructor(scope, id, props) {
super(scope, id);
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_AsgCapacityProviderProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, AsgCapacityProvider);
}
throw error;
}
this.autoScalingGroup = props.autoScalingGroup;
this.machineImageType = props.machineImageType ?? MachineImageType.AMAZON_LINUX_2;
this.canContainersAccessInstanceRole = props.canContainersAccessInstanceRole;
this.enableManagedTerminationProtection =
props.enableManagedTerminationProtection === undefined ? true : props.enableManagedTerminationProtection;
if (this.enableManagedTerminationProtection) {
this.autoScalingGroup.protectNewInstancesFromScaleIn();
}
if (props.capacityProviderName) {
if (!(/^(?!aws|ecs|fargate).+/gm.test(props.capacityProviderName))) {
throw new Error(`Invalid Capacity Provider Name: ${props.capacityProviderName}, If a name is specified, it cannot start with aws, ecs, or fargate.`);
}
}
const capacityProvider = new ecs_generated_1.CfnCapacityProvider(this, id, {
name: props.capacityProviderName,
autoScalingGroupProvider: {
autoScalingGroupArn: this.autoScalingGroup.autoScalingGroupName,
managedScaling: props.enableManagedScaling === false ? undefined : {
status: 'ENABLED',
targetCapacity: props.targetCapacityPercent || 100,
maximumScalingStepSize: props.maximumScalingStepSize,
minimumScalingStepSize: props.minimumScalingStepSize,
},
managedTerminationProtection: this.enableManagedTerminationProtection ? 'ENABLED' : 'DISABLED',
},
});
this.capacityProviderName = capacityProvider.ref;
}
}
exports.AsgCapacityProvider = AsgCapacityProvider;
_b = JSII_RTTI_SYMBOL_1;
AsgCapacityProvider[_b] = { fqn: "@aws-cdk/aws-ecs.AsgCapacityProvider", version: "1.204.0" };
/**
* A visitor that adds a capacity provider association to a Cluster only if
* the caller created any EC2 Capacity Providers.
*/
class MaybeCreateCapacityProviderAssociations {
constructor(scope, id, capacityProviders) {
this.scope = scope;
this.id = id;
this.capacityProviders = capacityProviders;
}
visit(node) {
if (node instanceof Cluster) {
if (this.capacityProviders.length > 0 && !this.resource) {
const resource = new ecs_generated_1.CfnClusterCapacityProviderAssociations(this.scope, this.id, {
cluster: node.clusterName,
defaultCapacityProviderStrategy: [],
capacityProviders: core_1.Lazy.list({ produce: () => this.capacityProviders }),
});
this.resource = resource;
}
}
}
}
function isBottleRocketImage(image) {
return image instanceof amis_1.BottleRocketImage;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsd0RBQXdEO0FBQ3hELHNEQUFzRDtBQUN0RCx3Q0FBd0M7QUFDeEMsd0NBQXdDO0FBSXhDLDBEQUEwRDtBQUMxRCx3Q0FBb0g7QUFFcEgsaUNBQTREO0FBQzVELDBFQUFxRTtBQUNyRSxpRkFBNEQ7QUFDNUQsbURBQTBHO0FBRTFHLGdIQUFnSDtBQUNoSCwyQkFBMkI7QUFDM0Isd0NBQTJEO0FBaUUzRDs7R0FFRztBQUNILElBQVksZ0JBU1g7QUFURCxXQUFZLGdCQUFnQjtJQUMxQjs7T0FFRztJQUNILDJFQUFjLENBQUE7SUFDZDs7T0FFRztJQUNILHVFQUFZLENBQUE7QUFDZCxDQUFDLEVBVFcsZ0JBQWdCLEdBQWhCLHdCQUFnQixLQUFoQix3QkFBZ0IsUUFTM0I7QUFFRDs7R0FFRztBQUNILE1BQWEsT0FBUSxTQUFRLGVBQVE7SUF3Rm5DOztPQUVHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxRQUFzQixFQUFFO1FBQ2hFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsWUFBWSxFQUFFLEtBQUssQ0FBQyxXQUFXO1NBQ2hDLENBQUMsQ0FBQztRQW5ETDs7V0FFRztRQUNhLGdCQUFXLEdBQW9CLElBQUksR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBaUJyRTs7V0FFRztRQUNLLDJCQUFzQixHQUFhLEVBQUUsQ0FBQztRQU85Qzs7V0FFRztRQUNLLG9CQUFlLEdBQVksS0FBSyxDQUFDOzs7Ozs7K0NBNUU5QixPQUFPOzs7O1FBZ0doQjs7OztVQUlFO1FBQ0YsSUFBSSxlQUFlLEdBQUcsU0FBUyxDQUFDO1FBQ2hDLElBQUksS0FBSyxDQUFDLGlCQUFpQixLQUFLLFNBQVMsRUFBRTtZQUN6QyxlQUFlLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxLQUFLLEVB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LEVBQUU7b0JBQy9FLE9BQU8sRUFBRSxJQUFJLENBQUMsV0FBVztvQkFDekIsK0JBQStCLEVBQUUsRUFBRTtvQkFDbkMsaUJBQWlCLEVBQUUsV0FBSSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztpQkFDeEUsQ0FBQyxDQUFDO2dCQUNILElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO2FBQzFCO1NBQ0Y7S0FDRjtDQUNGO0FBR0QsU0FBUyxtQkFBbUIsQ0FBQyxLQUF3QjtJQUNuRCxPQUFPLEtBQUssWUFBWSx3QkFBaUIsQ0FBQztBQUM1QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXV0b3NjYWxpbmcgZnJvbSAnQGF3cy1jZGsvYXdzLWF1dG9zY2FsaW5nJztcbmltcG9ydCAqIGFzIGNsb3Vkd2F0Y2ggZnJvbSAnQGF3cy1jZGsvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ0Bhd3MtY2RrL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ0Bhd3MtY2RrL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMga21zIGZyb20gJ0Bhd3MtY2RrL2F3cy1rbXMnO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdAYXdzLWNkay9hd3MtbG9ncyc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdAYXdzLWNkay9hd3MtczMnO1xuaW1wb3J0ICogYXMgY2xvdWRtYXAgZnJvbSAnQGF3cy1jZGsvYXdzLXNlcnZpY2VkaXNjb3ZlcnknO1xuaW1wb3J0IHsgRHVyYXRpb24sIExhenksIElSZXNvdXJjZSwgUmVzb3VyY2UsIFN0YWNrLCBBc3BlY3RzLCBJQXNwZWN0LCBJQ29uc3RydWN0LCBBcm5Gb3JtYXQgfSBmcm9t