From 9d1093f133ea38ac7d0e9c5cca7e2ea91e71a754 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Thu, 16 Mar 2023 13:01:41 -0700 Subject: [PATCH 1/6] chore(stepfunctions): remove integ dependency (#24653) Removes a dependency between a unit and integration test by extracting generic code into a separate file. Useful for repo restructure as integ tests are in a separate package. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-stepfunctions/test/fake-task.ts | 37 +++++++++++++++++++ .../test/integ.state-machine-credentials.ts | 36 +----------------- .../aws-stepfunctions/test/state.test.ts | 2 +- 3 files changed, 39 insertions(+), 36 deletions(-) create mode 100644 packages/@aws-cdk/aws-stepfunctions/test/fake-task.ts diff --git a/packages/@aws-cdk/aws-stepfunctions/test/fake-task.ts b/packages/@aws-cdk/aws-stepfunctions/test/fake-task.ts new file mode 100644 index 0000000000000..e21149408141a --- /dev/null +++ b/packages/@aws-cdk/aws-stepfunctions/test/fake-task.ts @@ -0,0 +1,37 @@ +import * as iam from '@aws-cdk/aws-iam'; +import * as constructs from 'constructs'; +import * as sfn from '../lib'; + +export interface FakeTaskProps extends sfn.TaskStateBaseProps { + parameters?: { [key: string]: string }; +} + +/** + * Task extending sfn.TaskStateBase to facilitate integ testing setting credentials + */ +export class FakeTask extends sfn.TaskStateBase { + protected readonly taskMetrics?: sfn.TaskMetricsConfig; + protected readonly taskPolicies?: iam.PolicyStatement[]; + protected readonly parameters?: { [key: string]: string }; + + constructor(scope: constructs.Construct, id: string, props: FakeTaskProps = {}) { + super(scope, id, props); + this.parameters = props.parameters; + } + + protected _renderTask(): any { + return { + Type: 'Task', + Resource: 'arn:aws:states:::dynamodb:putItem', + Parameters: { + TableName: 'my-cool-table', + Item: { + id: { + S: 'my-entry', + }, + }, + ...this.parameters, + }, + }; + } +} diff --git a/packages/@aws-cdk/aws-stepfunctions/test/integ.state-machine-credentials.ts b/packages/@aws-cdk/aws-stepfunctions/test/integ.state-machine-credentials.ts index a5e0b6f584bd1..f76e465581266 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/integ.state-machine-credentials.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/integ.state-machine-credentials.ts @@ -1,43 +1,9 @@ import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import { IntegTest } from '@aws-cdk/integ-tests'; -import * as constructs from 'constructs'; +import { FakeTask } from './fake-task'; import * as sfn from '../lib'; -export interface FakeTaskProps extends sfn.TaskStateBaseProps { - parameters?: { [key: string]: string }; -} - -/** - * Task extending sfn.TaskStateBase to facilitate integ testing setting credentials - */ -export class FakeTask extends sfn.TaskStateBase { - protected readonly taskMetrics?: sfn.TaskMetricsConfig; - protected readonly taskPolicies?: iam.PolicyStatement[]; - protected readonly parameters?: { [key: string]: string }; - - constructor(scope: constructs.Construct, id: string, props: FakeTaskProps = {}) { - super(scope, id, props); - this.parameters = props.parameters; - } - - protected _renderTask(): any { - return { - Type: 'Task', - Resource: 'arn:aws:states:::dynamodb:putItem', - Parameters: { - TableName: 'my-cool-table', - Item: { - id: { - S: 'my-entry', - }, - }, - ...this.parameters, - }, - }; - } -} - /* * Stack verification steps: * diff --git a/packages/@aws-cdk/aws-stepfunctions/test/state.test.ts b/packages/@aws-cdk/aws-stepfunctions/test/state.test.ts index db13dfb573412..0b2157f7526ec 100644 --- a/packages/@aws-cdk/aws-stepfunctions/test/state.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions/test/state.test.ts @@ -1,5 +1,5 @@ import * as cdk from '@aws-cdk/core'; -import { FakeTask } from './integ.state-machine-credentials'; +import { FakeTask } from './fake-task'; import { renderGraph } from './private/render-util'; import { JsonPath } from '../lib'; From 9c94d996009bbe8e7cd85bd0b50bd023aac3474e Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Fri, 17 Mar 2023 02:41:28 -0700 Subject: [PATCH 2/6] docs(cfnspec): update CloudFormation documentation (#24660) --- .../spec-source/cfn-docs/cfn-docs.json | 129 ++++++++++++++---- 1 file changed, 99 insertions(+), 30 deletions(-) diff --git a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json index 9b445cab59878..f5f9f8aa37cdc 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json +++ b/packages/@aws-cdk/cfnspec/spec-source/cfn-docs/cfn-docs.json @@ -382,7 +382,7 @@ }, "AWS::AccessAnalyzer::Analyzer.Filter": { "attributes": {}, - "description": "The criteria that defines the rule.", + "description": "The criteria that defines the rule.\n\nTo learn about filter keys that you can use to create an archive rule, see [filter keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-analyzer-reference-filter-keys.html) in the *User Guide* .", "properties": { "Contains": "A \"contains\" condition to match for the rule.", "Eq": "An \"equals\" condition to match for the rule.", @@ -7271,7 +7271,7 @@ "attributes": { "Ref": "`Ref` returns the name of the keyspace. For example:\n\n`{ \"Ref\": \"MyNewKeyspace\" }`" }, - "description": "The `AWS::Cassandra::Keyspace` resource allows you to create a new keyspace in Amazon Keyspaces (for Apache Cassandra). For more information, see [Create a keyspace and a table](https://docs.aws.amazon.com/keyspaces/latest/devguide/getting-started.ddl.html) in the *Amazon Keyspaces Developer Guide* .", + "description": "You can use the `AWS::Cassandra::Keyspace` resource to create a new keyspace in Amazon Keyspaces (for Apache Cassandra). For more information, see [Create a keyspace and a table](https://docs.aws.amazon.com/keyspaces/latest/devguide/getting-started.ddl.html) in the *Amazon Keyspaces Developer Guide* .", "properties": { "KeyspaceName": "The name of the keyspace to be created. The keyspace name is case sensitive. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID for the keyspace name. For more information, see [Name type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n*Length constraints:* Minimum length of 3. Maximum length of 255.\n\n*Pattern:* `^[a-zA-Z0-9][a-zA-Z0-9_]{1,47}$`", "Tags": "A list of key-value pair tags to be attached to the resource." @@ -7281,23 +7281,24 @@ "attributes": { "Ref": "`Ref` returns the name of the table and the keyspace where the table exists (delimited by '|'). For example:\n\n`{ \"Ref\": \"myKeyspace|myTable\" }`" }, - "description": "The `AWS::Cassandra::Table` resource allows you to create a new table in Amazon Keyspaces (for Apache Cassandra). For more information, see [Create a keyspace and a table](https://docs.aws.amazon.com/keyspaces/latest/devguide/getting-started.ddl.html) in the *Amazon Keyspaces Developer Guide* .", + "description": "You can use the `AWS::Cassandra::Table` resource to create a new table in Amazon Keyspaces (for Apache Cassandra). For more information, see [Create a keyspace and a table](https://docs.aws.amazon.com/keyspaces/latest/devguide/getting-started.ddl.html) in the *Amazon Keyspaces Developer Guide* .", "properties": { "BillingMode": "The billing mode for the table, which determines how you'll be charged for reads and writes:\n\n- *On-demand mode* (default) - You pay based on the actual reads and writes your application performs.\n- *Provisioned mode* - Lets you specify the number of reads and writes per second that you need for your application.\n\nIf you don't specify a value for this property, then the table will use on-demand mode.", + "ClientSideTimestampsEnabled": "Enables client-side timestamps for the table. By default, the setting is disabled. You can enable client-side timestamps with the following option:\n\n- `status: \"enabled\"`\n\nAfter client-side timestamps are enabled for a table, you can't disable this setting.", "ClusteringKeyColumns": "One or more columns that determine how the table data is sorted.", "DefaultTimeToLive": "The default Time To Live (TTL) value for all rows in a table in seconds. The maximum configurable value is 630,720,000 seconds, which is the equivalent of 20 years. By default, the TTL value for a table is 0, which means data does not expire.\n\nFor more information, see [Setting the default TTL value for a table](https://docs.aws.amazon.com/keyspaces/latest/devguide/TTL-how-it-works.html#ttl-howitworks_default_ttl) in the *Amazon Keyspaces Developer Guide* .", "EncryptionSpecification": "The encryption at rest options for the table.\n\n- *AWS owned key* (default) - The key is owned by Amazon Keyspaces.\n- *Customer managed key* - The key is stored in your account and is created, owned, and managed by you.\n\n> If you choose encryption with a customer managed key, you must specify a valid customer managed KMS key with permissions granted to Amazon Keyspaces.\n\nFor more information, see [Encryption at rest in Amazon Keyspaces](https://docs.aws.amazon.com/keyspaces/latest/devguide/EncryptionAtRest.html) in the *Amazon Keyspaces Developer Guide* .", - "KeyspaceName": "The name of the keyspace in which to create the table. The keyspace must already exist.", + "KeyspaceName": "The name of the keyspace to create the table in. The keyspace must already exist.", "PartitionKeyColumns": "One or more columns that uniquely identify every row in the table. Every table must have a partition key.", "PointInTimeRecoveryEnabled": "Specifies if point-in-time recovery is enabled or disabled for the table. The options are `PointInTimeRecoveryEnabled=true` and `PointInTimeRecoveryEnabled=false` . If not specified, the default is `PointInTimeRecoveryEnabled=false` .", "RegularColumns": "One or more columns that are not part of the primary key - that is, columns that are *not* defined as partition key columns or clustering key columns.\n\nYou can add regular columns to existing tables by adding them to the template.", - "TableName": "The name of the table to be created. The table name is case sensitive. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID for the table name. For more information, see [Name type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you cannot perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you must replace the resource, specify a new name. \n\n*Length constraints:* Minimum length of 3. Maximum length of 255.\n\n*Pattern:* `^[a-zA-Z0-9][a-zA-Z0-9_]{1,47}$`", + "TableName": "The name of the table to be created. The table name is case sensitive. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID for the table name. For more information, see [Name type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html) .\n\n> If you specify a name, you can't perform updates that require replacing this resource. You can perform updates that require no interruption or some interruption. If you must replace the resource, specify a new name. \n\n*Length constraints:* Minimum length of 3. Maximum length of 255.\n\n*Pattern:* `^[a-zA-Z0-9][a-zA-Z0-9_]{1,47}$`", "Tags": "A list of key-value pair tags to be attached to the resource." } }, "AWS::Cassandra::Table.BillingMode": { "attributes": {}, - "description": "Determines the billing mode for the table - On-demand or provisioned.", + "description": "Determines the billing mode for the table - on-demand or provisioned.", "properties": { "Mode": "The billing mode for the table:\n\n- On-demand mode - `ON_DEMAND`\n- Provisioned mode - `PROVISIONED`\n\n> If you choose `PROVISIONED` mode, then you also need to specify provisioned throughput (read and write capacity) for the table.\n\nValid values: `ON_DEMAND` | `PROVISIONED`", "ProvisionedThroughput": "The provisioned read capacity and write capacity for the table. For more information, see [Provisioned throughput capacity mode](https://docs.aws.amazon.com/keyspaces/latest/devguide/ReadWriteCapacityMode.html#ReadWriteCapacityMode.Provisioned) in the *Amazon Keyspaces Developer Guide* ." @@ -9047,7 +9048,7 @@ "properties": { "Name": "The name or key of the environment variable.", "Type": "The type of environment variable. Valid values include:\n\n- `PARAMETER_STORE` : An environment variable stored in Systems Manager Parameter Store. To learn how to specify a parameter store environment variable, see [env/parameter-store](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec.env.parameter-store) in the *AWS CodeBuild User Guide* .\n- `PLAINTEXT` : An environment variable in plain text format. This is the default value.\n- `SECRETS_MANAGER` : An environment variable stored in AWS Secrets Manager . To learn how to specify a secrets manager environment variable, see [env/secrets-manager](https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#build-spec.env.secrets-manager) in the *AWS CodeBuild User Guide* .", - "Value": "The value of the environment variable.\n\n> We strongly discourage the use of `PLAINTEXT` environment variables to store sensitive values, especially AWS secret key IDs. `PLAINTEXT` environment variables can be displayed in plain text using the AWS CodeBuild console and the AWS CLI . For sensitive values, we recommend you use an environment variable of type `PARAMETER_STORE` or `SECRETS_MANAGER` ." + "Value": "The value of the environment variable.\n\n> We strongly discourage the use of `PLAINTEXT` environment variables to store sensitive values, especially AWS secret key IDs and secret access keys. `PLAINTEXT` environment variables can be displayed in plain text using the AWS CodeBuild console and the AWS CLI . For sensitive values, we recommend you use an environment variable of type `PARAMETER_STORE` or `SECRETS_MANAGER` ." } }, "AWS::CodeBuild::Project.FilterGroup": { @@ -10397,6 +10398,65 @@ "Username": "The username for the user." } }, + "AWS::Comprehend::Flywheel": { + "attributes": { + "Arn": "The Amazon Resource Name (ARN) of the flywheel.", + "Ref": "`Ref` returns the Amazon Resource Name (ARN) of the flywheel." + }, + "description": "A flywheel is an AWS resource that orchestrates the ongoing training of a model for custom classification or custom entity recognition. You can create a flywheel to start with an existing trained model, or Comprehend can create and train a new model.\n\nWhen you create the flywheel, Comprehend creates a data lake in your account. The data lake holds the training data and test data for all versions of the model.\n\nTo use a flywheel with an existing trained model, you specify the active model version. Comprehend copies the model's training data and test data into the flywheel's data lake.\n\nTo use the flywheel with a new model, you need to provide a dataset for training data (and optional test data) when you create the flywheel.\n\nFor more information about flywheels, see [Flywheel overview](https://docs.aws.amazon.com/comprehend/latest/dg/flywheels-about.html) in the *Amazon Comprehend Developer Guide* .", + "properties": { + "ActiveModelArn": "The Amazon Resource Number (ARN) of the active model version.", + "DataAccessRoleArn": "The Amazon Resource Name (ARN) of the IAM role that grants Amazon Comprehend permission to access the flywheel data.", + "DataLakeS3Uri": "Amazon S3 URI of the data lake location.", + "DataSecurityConfig": "Data security configuration.", + "FlywheelName": "Name for the flywheel.", + "ModelType": "Model type of the flywheel's model.", + "Tags": "Tags associated with the endpoint being created. A tag is a key-value pair that adds metadata to the endpoint. For example, a tag with \"Sales\" as the key might be added to an endpoint to indicate its use by the sales department.", + "TaskConfig": "Configuration about the custom classifier associated with the flywheel." + } + }, + "AWS::Comprehend::Flywheel.DataSecurityConfig": { + "attributes": {}, + "description": "Data security configuration.", + "properties": { + "DataLakeKmsKeyId": "ID for the AWS KMS key that Amazon Comprehend uses to encrypt the data in the data lake.", + "ModelKmsKeyId": "ID for the AWS KMS key that Amazon Comprehend uses to encrypt trained custom models. The ModelKmsKeyId can be either of the following formats:\n\n- KMS Key ID: `\"1234abcd-12ab-34cd-56ef-1234567890ab\"`\n- Amazon Resource Name (ARN) of a KMS Key: `\"arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab\"`", + "VolumeKmsKeyId": "ID for the AWS KMS key that Amazon Comprehend uses to encrypt the volume.", + "VpcConfig": "Configuration parameters for an optional private Virtual Private Cloud (VPC) containing the resources you are using for the job. For more information, see [Amazon VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) ." + } + }, + "AWS::Comprehend::Flywheel.DocumentClassificationConfig": { + "attributes": {}, + "description": "Configuration required for a custom classification model.", + "properties": { + "Labels": "One or more labels to associate with the custom classifier.", + "Mode": "Classification mode indicates whether the documents are `MULTI_CLASS` or `MULTI_LABEL` ." + } + }, + "AWS::Comprehend::Flywheel.EntityRecognitionConfig": { + "attributes": {}, + "description": "Configuration required for an entity recognition model.", + "properties": { + "EntityTypes": "Up to 25 entity types that the model is trained to recognize." + } + }, + "AWS::Comprehend::Flywheel.TaskConfig": { + "attributes": {}, + "description": "Configuration about the custom classifier associated with the flywheel.", + "properties": { + "DocumentClassificationConfig": "Configuration required for a classification model.", + "EntityRecognitionConfig": "Configuration required for an entity recognition model.", + "LanguageCode": "Language code for the language that the model supports." + } + }, + "AWS::Comprehend::Flywheel.VpcConfig": { + "attributes": {}, + "description": "Configuration parameters for an optional private Virtual Private Cloud (VPC) containing the resources you are using for the job. For more information, see [Amazon VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html) .", + "properties": { + "SecurityGroupIds": "The ID number for a security group on an instance of your private VPC. Security groups on your VPC function serve as a virtual firewall to control inbound and outbound traffic and provides security for the resources that you\u2019ll be accessing on the VPC. This ID number is preceded by \"sg-\", for instance: \"sg-03b388029b0a285ea\". For more information, see [Security Groups for your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html) .", + "Subnets": "The ID for each subnet being used in your private VPC. This subnet is a subset of the a range of IPv4 addresses used by the VPC and is specific to a given availability zone in the VPC\u2019s Region. This ID number is preceded by \"subnet-\", for instance: \"subnet-04ccf456919e69055\". For more information, see [VPCs and Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html) ." + } + }, "AWS::Config::AggregationAuthorization": { "attributes": { "AggregationAuthorizationArn": "The Amazon Resource Name (ARN) of the aggregation object.", @@ -13648,7 +13708,7 @@ "description": "Defines settings specific to a single replica of a global table.", "properties": { "ContributorInsightsSpecification": "The settings used to enable or disable CloudWatch Contributor Insights for the specified replica. When not specified, defaults to contributor insights disabled for the replica.", - "DeletionProtectionEnabled": "", + "DeletionProtectionEnabled": "Determines if a replica is protected from deletion. When enabled, the table cannot be deleted by any user or process. This setting is disabled by default. For more information, see [Using deletion protection](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection) in the *Amazon DynamoDB Developer Guide* .", "GlobalSecondaryIndexes": "Defines additional settings for the global secondary indexes of this replica.", "KinesisStreamSpecification": "Defines the Kinesis Data Streams configuration for the specified replica.", "PointInTimeRecoverySpecification": "The settings used to enable point in time recovery. When not specified, defaults to point in time recovery disabled for the replica.", @@ -13710,8 +13770,9 @@ "AttributeDefinitions": "A list of attributes that describe the key schema for the table and indexes.\n\nThis property is required to create a DynamoDB table.\n\nUpdate requires: [Some interruptions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-some-interrupt) . Replacement if you edit an existing AttributeDefinition.", "BillingMode": "Specify how you are charged for read and write throughput and how you manage capacity.\n\nValid values include:\n\n- `PROVISIONED` - We recommend using `PROVISIONED` for predictable workloads. `PROVISIONED` sets the billing mode to [Provisioned Mode](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.ProvisionedThroughput.Manual) .\n- `PAY_PER_REQUEST` - We recommend using `PAY_PER_REQUEST` for unpredictable workloads. `PAY_PER_REQUEST` sets the billing mode to [On-Demand Mode](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html#HowItWorks.OnDemand) .\n\nIf not specified, the default is `PROVISIONED` .", "ContributorInsightsSpecification": "The settings used to enable or disable CloudWatch Contributor Insights for the specified table.", + "DeletionProtectionEnabled": "Determines if a table is protected from deletion. When enabled, the table cannot be deleted by any user or process. This setting is disabled by default. For more information, see [Using deletion protection](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.Basics.html#WorkingWithTables.Basics.DeletionProtection) in the *Amazon DynamoDB Developer Guide* .", "GlobalSecondaryIndexes": "Global secondary indexes to be created on the table. You can create up to 20 global secondary indexes.\n\n> If you update a table to include a new global secondary index, AWS CloudFormation initiates the index creation and then proceeds with the stack update. AWS CloudFormation doesn't wait for the index to complete creation because the backfilling phase can take a long time, depending on the size of the table. You can't use the index or update the table until the index's status is `ACTIVE` . You can track its status by using the DynamoDB [DescribeTable](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/describe-table.html) command.\n> \n> If you add or delete an index during an update, we recommend that you don't update any other resources. If your stack fails to update and is rolled back while adding a new index, you must manually delete the index.\n> \n> Updates are not supported. The following are exceptions:\n> \n> - If you update either the contributor insights specification or the provisioned throughput values of global secondary indexes, you can update the table without interruption.\n> - You can delete or add one global secondary index without interruption. If you do both in the same update (for example, by changing the index's logical ID), the update fails.", - "ImportSourceSpecification": "Specifies the properties of data being imported from the S3 bucket source to the table.\n\n> If you specify the `ImportSourceSpecification` property, and also specify either the `StreamSpecification` or `TableClass` property, the IAM entity creating/updating stack must have `UpdateTable` permission.", + "ImportSourceSpecification": "Specifies the properties of data being imported from the S3 bucket source to the table.\n\n> If you specify the `ImportSourceSpecification` property, and also specify either the `StreamSpecification` , the `TableClass` property, or the `DeletionProtectionEnabled` property, the IAM entity creating/updating stack must have `UpdateTable` permission.", "KeySchema": "Specifies the attributes that make up the primary key for the table. The attributes in the `KeySchema` property must also be defined in the `AttributeDefinitions` property.", "KinesisStreamSpecification": "The Kinesis Data Streams configuration for the specified table.", "LocalSecondaryIndexes": "Local secondary indexes to be created on the table. You can create up to 5 local secondary indexes. Each index is scoped to a given hash key value. The size of each hash key can be up to 10 gigabytes.", @@ -15636,12 +15697,12 @@ }, "description": "Specifies a path to analyze for reachability.\n\nVPC Reachability Analyzer enables you to analyze and debug network reachability between two resources in your virtual private cloud (VPC). For more information, see the [Reachability Analyzer User Guide](https://docs.aws.amazon.com/vpc/latest/reachability/what-is-reachability-analyzer.html) .", "properties": { - "Destination": "The AWS resource that is the destination of the path.", - "DestinationIp": "The IP address of the AWS resource that is the destination of the path.", + "Destination": "The ID or ARN of the destination. If the resource is in another account, you must specify an ARN.", + "DestinationIp": "The IP address of the destination.", "DestinationPort": "The destination port.", "Protocol": "The protocol.", - "Source": "The AWS resource that is the source of the path.", - "SourceIp": "The IP address of the AWS resource that is the source of the path.", + "Source": "The ID or ARN of the source. If the resource is in another account, you must specify an ARN.", + "SourceIp": "The IP address of the source.", "Tags": "The tags to add to the path." } }, @@ -24186,7 +24247,7 @@ "Path": "The path for the virtual MFA device. For more information about paths, see [IAM identifiers](https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) in the *IAM User Guide* .\n\nThis parameter is optional. If it is not included, it defaults to a slash (/).\n\nThis parameter allows (through its [regex pattern](https://docs.aws.amazon.com/http://wikipedia.org/wiki/regex) ) a string of characters consisting of either a forward slash (/) by itself or a string that must begin and end with forward slashes. In addition, it can contain any ASCII character from the ! ( `\\u0021` ) through the DEL character ( `\\u007F` ), including most punctuation characters, digits, and upper and lowercased letters.", "Tags": "A list of tags that you want to attach to the new IAM virtual MFA device. Each tag consists of a key name and an associated value. For more information about tagging, see [Tagging IAM resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_tags.html) in the *IAM User Guide* .\n\n> If any one of the tags is invalid or if you exceed the allowed maximum number of tags, then the entire request fails and the resource is not created.", "Users": "The IAM user associated with this virtual MFA device.", - "VirtualMfaDeviceName": "The name of the virtual MFA device. Use with path to uniquely identify a virtual MFA device.\n\nThis parameter allows (through its [regex pattern](https://docs.aws.amazon.com/http://wikipedia.org/wiki/regex) ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: _+=,.@-" + "VirtualMfaDeviceName": "The name of the virtual MFA device, which must be unique. Use with path to uniquely identify a virtual MFA device.\n\nThis parameter allows (through its [regex pattern](https://docs.aws.amazon.com/http://wikipedia.org/wiki/regex) ) a string of characters consisting of upper and lowercase alphanumeric characters with no spaces. You can also include any of the following characters: _+=,.@-" } }, "AWS::IVS::Channel": { @@ -26113,7 +26174,7 @@ "attributes": {}, "description": "A structure that contains the configuration information of a delta time session window.\n\n[`DeltaTime`](https://docs.aws.amazon.com/iotanalytics/latest/APIReference/API_DeltaTime.html) specifies a time interval. You can use `DeltaTime` to create dataset contents with data that has arrived in the data store since the last execution. For an example of `DeltaTime` , see [Creating a SQL dataset with a delta window (CLI)](https://docs.aws.amazon.com/iotanalytics/latest/userguide/automate-create-dataset.html#automate-example6) in the *AWS IoT Analytics User Guide* .", "properties": { - "TimeoutInMinutes": "A time interval. You can use `timeoutInMinutes` so that AWS IoT Analytics can batch up late data notifications that have been generated since the last execution. AWS IoT Analytics sends one batch of notifications to Amazon CloudWatch Events at one time.\n\nFor more information about how to write a timestamp expression, see [Date and Time Functions and Operators](https://docs.aws.amazon.com/https://prestodb.io/docs/0.172/functions/datetime.html) , in the *Presto 0.172 Documentation* ." + "TimeoutInMinutes": "A time interval. You can use `timeoutInMinutes` so that AWS IoT Analytics can batch up late data notifications that have been generated since the last execution. AWS IoT Analytics sends one batch of notifications to Amazon CloudWatch Events at one time.\n\nFor more information about how to write a timestamp expression, see [Date and Time Functions and Operators](https://docs.aws.amazon.com/https://prestodb.io/docs/current/functions/datetime.html) , in the *Presto 0.172 Documentation* ." } }, "AWS::IoTAnalytics::Dataset.Filter": { @@ -28956,9 +29017,9 @@ "description": "Provides the configuration information required for Amazon Kendra Web Crawler.", "properties": { "AuthenticationConfiguration": "Configuration information required to connect to websites using authentication.\n\nYou can connect to websites using basic authentication of user name and password. You use a secret in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) to store your authentication credentials.\n\nYou must provide the website host name and port number. For example, the host name of https://a.example.com/page1.html is \"a.example.com\" and the port is 443, the standard port for HTTPS.", - "CrawlDepth": "Specifies the number of levels in a website that you want to crawl.\n\nThe first level begins from the website seed or starting point URL. For example, if a website has 3 levels \u2013 index level (i.e. seed in this example), sections level, and subsections level \u2013 and you are only interested in crawling information up to the sections level (i.e. levels 0-1), you can set your depth to 1.\n\nThe default crawl depth is set to 2.", - "MaxContentSizePerPageInMegaBytes": "The maximum size (in MB) of a webpage or attachment to crawl.\n\nFiles larger than this size (in MB) are skipped/not crawled.\n\nThe default maximum size of a webpage or attachment is set to 50 MB.", - "MaxLinksPerPage": "The maximum number of URLs on a webpage to include when crawling a website. This number is per webpage.\n\nAs a website\u2019s webpages are crawled, any URLs the webpages link to are also crawled. URLs on a webpage are crawled in order of appearance.\n\nThe default maximum links per page is 100.", + "CrawlDepth": "Specifies the number of levels in a website that you want to crawl.\n\nThe first level begins from the website seed or starting point URL. For example, if a website has three levels\u2014index level (the seed in this example), sections level, and subsections level\u2014and you are only interested in crawling information up to the sections level (levels 0-1), you can set your depth to 1.\n\nThe default crawl depth is set to 2.", + "MaxContentSizePerPageInMegaBytes": "The maximum size (in MB) of a web page or attachment to crawl.\n\nFiles larger than this size (in MB) are skipped/not crawled.\n\nThe default maximum size of a web page or attachment is set to 50 MB.", + "MaxLinksPerPage": "The maximum number of URLs on a web page to include when crawling a website. This number is per web page.\n\nAs a website\u2019s web pages are crawled, any URLs the web pages link to are also crawled. URLs on a web page are crawled in order of appearance.\n\nThe default maximum links per page is 100.", "MaxUrlsPerMinuteCrawlRate": "The maximum number of URLs crawled per website host per minute.\n\nA minimum of one URL is required.\n\nThe default maximum number of URLs crawled per website host per minute is 300.", "ProxyConfiguration": "Configuration information required to connect to your internal websites via a web proxy.\n\nYou must provide the website host name and port number. For example, the host name of https://a.example.com/page1.html is \"a.example.com\" and the port is 443, the standard port for HTTPS.\n\nWeb proxy credentials are optional and you can use them to connect to a web proxy server that requires basic authentication. To store web proxy credentials, you use a secret in [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) .", "UrlExclusionPatterns": "A list of regular expression patterns to exclude certain URLs to crawl. URLs that match the patterns are excluded from the index. URLs that don't match the patterns are included in the index. If a URL matches both an inclusion and exclusion pattern, the exclusion pattern takes precedence and the URL file isn't included in the index.", @@ -28971,7 +29032,7 @@ "description": "Provides the configuration information of the seed or starting point URLs to crawl.\n\n*When selecting websites to index, you must adhere to the [Amazon Acceptable Use Policy](https://docs.aws.amazon.com/aup/) and all other Amazon terms. Remember that you must only use the Amazon Kendra web crawler to index your own webpages, or webpages that you have authorization to index.*", "properties": { "SeedUrls": "The list of seed or starting point URLs of the websites you want to crawl.\n\nThe list can include a maximum of 100 seed URLs.", - "WebCrawlerMode": "You can choose one of the following modes:\n\n- `HOST_ONLY` \u2013 crawl only the website host names. For example, if the seed URL is \"abc.example.com\", then only URLs with host name \"abc.example.com\" are crawled.\n- `SUBDOMAINS` \u2013 crawl the website host names with subdomains. For example, if the seed URL is \"abc.example.com\", then \"a.abc.example.com\" and \"b.abc.example.com\" are also crawled.\n- `EVERYTHING` \u2013 crawl the website host names with subdomains and other domains that the webpages link to.\n\nThe default mode is set to `HOST_ONLY` ." + "WebCrawlerMode": "You can choose one of the following modes:\n\n- `HOST_ONLY` \u2013 crawl only the website host names. For example, if the seed URL is \"abc.example.com\", then only URLs with host name \"abc.example.com\" are crawled.\n- `SUBDOMAINS` \u2013 crawl the website host names with subdomains. For example, if the seed URL is \"abc.example.com\", then \"a.abc.example.com\" and \"b.abc.example.com\" are also crawled.\n- `EVERYTHING` \u2013 crawl the website host names with subdomains and other domains that the web pages link to.\n\nThe default mode is set to `HOST_ONLY` ." } }, "AWS::Kendra::DataSource.WebCrawlerSiteMapsConfiguration": { @@ -28985,7 +29046,7 @@ "attributes": {}, "description": "Specifies the seed or starting point URLs of the websites or the sitemap URLs of the websites you want to crawl.\n\nYou can include website subdomains. You can list up to 100 seed URLs and up to three sitemap URLs.\n\nYou can only crawl websites that use the secure communication protocol, Hypertext Transfer Protocol Secure (HTTPS). If you receive an error when crawling a website, it could be that the website is blocked from crawling.\n\n*When selecting websites to index, you must adhere to the [Amazon Acceptable Use Policy](https://docs.aws.amazon.com/aup/) and all other Amazon terms. Remember that you must only use the Amazon Kendra web crawler to index your own webpages, or webpages that you have authorization to index.*", "properties": { - "SeedUrlConfiguration": "Configuration of the seed or starting point URLs of the websites you want to crawl.\n\nYou can choose to crawl only the website host names, or the website host names with subdomains, or the website host names with subdomains and other domains that the webpages link to.\n\nYou can list up to 100 seed URLs.", + "SeedUrlConfiguration": "Configuration of the seed or starting point URLs of the websites you want to crawl.\n\nYou can choose to crawl only the website host names, or the website host names with subdomains, or the website host names with subdomains and other domains that the web pages link to.\n\nYou can list up to 100 seed URLs.", "SiteMapsConfiguration": "Configuration of the sitemap URLs of the websites you want to crawl.\n\nOnly URLs belonging to the same website host names are crawled. You can list up to three sitemap URLs." } }, @@ -31605,7 +31666,7 @@ "MaxRetries": "The maximum number of times the bot tries to elicit a response from the user using this prompt.", "MessageGroupsList": "A collection of messages that Amazon Lex can send to the user. Amazon Lex chooses the actual message to send at runtime.", "MessageSelectionStrategy": "Indicates how a message is selected from a message group among retries.", - "PromptAttemptsSpecification": "Specifies the advanced settings on each attempt of the prompt." + "PromptAttemptsSpecification": "Specifies the advanced settings on each attempt of the prompt. The valid keys are `Initial` , `Retry1` , `Retry2` , `Retry3` , `Retry4` , and `Retry5` ." } }, "AWS::Lex::Bot.ResponseSpecification": { @@ -41501,7 +41562,6 @@ }, "AWS::RUM::AppMonitor": { "attributes": { - "Id": "", "Ref": "`Ref` returns the name of the app monitor." }, "description": "Creates a CloudWatch RUM app monitor, which you can use to collect telemetry data from your application and send it to CloudWatch RUM. The data includes performance and reliability information such as page load time, client-side errors, and user behavior.\n\nAfter you create an app monitor, sign in to the CloudWatch RUM console to get the JavaScript code snippet to add to your web application. For more information, see [How do I find a code snippet that I've already generated?](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-find-code-snippet.html)", @@ -41539,11 +41599,12 @@ }, "AWS::RUM::AppMonitor.MetricDefinition": { "attributes": {}, - "description": "Specifies the extended metrics that you want the CloudWatch RUM app monitor to send to a destination. Valid destinations include CloudWatch and Evidently.\n\nBy default, RUM app monitors send some metrics to CloudWatch . These default metrics are listed in [CloudWatch metrics that you can collect with CloudWatch RUM](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html) .\n\nIf you also send extended metrics, you can send metrics to Evidently as well as CloudWatch , and you can also optionally send the metrics with additional dimensions. The valid dimension names for the additional dimensions are `BrowserName` , `CountryCode` , `DeviceType` , `FileType` , `OSName` , and `PageId` . For more information, see [Extended metrics that you can send to CloudWatch and CloudWatch Evidently](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-vended-metrics.html) .\n\nThe maximum number of metric definitions that one destination can contain is 2000.\n\nExtended metrics sent are charged as CloudWatch custom metrics. Each combination of additional dimension name and dimension value counts as a custom metric.\n\nIf some metric definitions that you specify are not valid, then the operation will not modify any metric definitions even if other metric definitions specified are valid.", + "description": "Specifies one custom metric or extended metric that you want the CloudWatch RUM app monitor to send to a destination. Valid destinations include CloudWatch and Evidently.\n\nBy default, RUM app monitors send some metrics to CloudWatch . These default metrics are listed in [CloudWatch metrics that you can collect.](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-metrics.html)\n\nIn addition to these default metrics, you can choose to send extended metrics or custom metrics or both.\n\n- Extended metrics enable you to send metrics with additional dimensions not included in the default metrics. You can also send extended metrics to Evidently as well as CloudWatch . The valid dimension names for the additional dimensions for extended metrics are `BrowserName` , `CountryCode` , `DeviceType` , `FileType` , `OSName` , and `PageId` . For more information, see [Extended metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-RUM-vended-metrics.html) .\n- Custom metrics are metrics that you define. You can send custom metrics to CloudWatch or to CloudWatch Evidently or to both. With custom metrics, you can use any metric name and namespace, and to derive the metrics you can use any custom events, built-in events, custom attributes, or default attributes.\n\nYou can't send custom metrics to the `AWS/RUM` namespace. You must send custom metrics to a custom namespace that you define. The namespace that you use can't start with `AWS/` . CloudWatch RUM prepends `RUM/CustomMetrics/` to the custom namespace that you define, so the final namespace for your metrics in CloudWatch is `RUM/CustomMetrics/ *your-custom-namespace*` .\n\nFor information about syntax rules for specifying custom metrics and extended metrics, see [MetridDefinitionRequest](https://docs.aws.amazon.com/cloudwatchrum/latest/APIReference/API_MetricDefinitionRequest.html) in the *CloudWatch RUM API Reference* .\n\nThe maximum number of metric definitions that one destination can contain is 2000.\n\nExtended metrics sent to CloudWatch and RUM custom metrics are charged as CloudWatch custom metrics. Each combination of additional dimension name and dimension value counts as a custom metric.\n\nIf some metric definitions that you specify are not valid, then the operation will not modify any metric definitions even if other metric definitions specified are valid.", "properties": { - "DimensionKeys": "This field is a map of field paths to dimension names. It defines the dimensions to associate with this metric in CloudWatch The value of this field is used only if the metric destination is `CloudWatch` . If the metric destination is `Evidently` , the value of `DimensionKeys` is ignored.", + "DimensionKeys": "This field is a map of field paths to dimension names. It defines the dimensions to associate with this metric in CloudWatch . The value of this field is used only if the metric destination is `CloudWatch` . If the metric destination is `Evidently` , the value of `DimensionKeys` is ignored.", "EventPattern": "The pattern that defines the metric. RUM checks events that happen in a user's session against the pattern, and events that match the pattern are sent to the metric destination.\n\nIf the metrics destination is `CloudWatch` and the event also matches a value in `DimensionKeys` , then the metric is published with the specified dimensions.", "Name": "The name of the metric that is defined in this structure.", + "Namespace": "If you are creating a custom metric instead of an extended metrics, use this parameter to define the metric namespace for that custom metric. Do not specify this parameter if you are creating an extended metric.\n\nYou can't use any string that starts with `AWS/` for your namespace.", "UnitLabel": "Use this field only if you are sending this metric to CloudWatch . It defines the CloudWatch metric unit that this metric is measured in.", "ValueKey": "The field within the event object that the metric value is sourced from." } @@ -43087,8 +43148,6 @@ "HostVPCId": "The ID of the VPC that you want to create the resolver endpoint in.", "IpAddressCount": "The number of IP addresses that the resolver endpoint can use for DNS queries.", "Name": "The name that you assigned to the resolver endpoint when you created the endpoint.", - "OutpostArn": "", - "PreferredInstanceType": "", "Ref": "`Ref` returns the `ResolverEndpoint` object.", "ResolverEndpointId": "The ID of the resolver endpoint.", "ResolverEndpointType": "" @@ -43098,8 +43157,6 @@ "Direction": "Indicates whether the Resolver endpoint allows inbound or outbound DNS queries:\n\n- `INBOUND` : allows DNS queries to your VPC from your network\n- `OUTBOUND` : allows DNS queries from your VPC to your network", "IpAddresses": "The subnets and IP addresses in your VPC that DNS queries originate from (for outbound endpoints) or that you forward DNS queries to (for inbound endpoints). The subnet ID uniquely identifies a VPC.", "Name": "A friendly name that lets you easily find a configuration in the Resolver dashboard in the Route 53 console.", - "OutpostArn": "", - "PreferredInstanceType": "", "ResolverEndpointType": "The Resolver endpoint IP address type.", "SecurityGroupIds": "The ID of one or more security groups that control access to this VPC. The security group must include one or more inbound rules (for inbound endpoints) or outbound rules (for outbound endpoints). Inbound and outbound rules must allow TCP and UDP access. For inbound access, open port 53. For outbound access, open the port that you're using for DNS queries on your network.", "Tags": "Route 53 Resolver doesn't support updating tags through CloudFormation." @@ -43790,7 +43847,8 @@ "attributes": {}, "description": "A bucket associated with a specific Region when creating Multi-Region Access Points.", "properties": { - "Bucket": "The name of the associated bucket for the Region." + "Bucket": "The name of the associated bucket for the Region.", + "BucketAccountId": "The AWS account ID that owns the Amazon S3 bucket that's associated with this Multi-Region Access Point." } }, "AWS::S3::MultiRegionAccessPointPolicy": { @@ -43968,6 +44026,9 @@ }, "AWS::S3ObjectLambda::AccessPoint": { "attributes": { + "Alias": "", + "Alias.Status": "", + "Alias.Value": "", "Arn": "Specifies the ARN for the Object Lambda Access Point.", "CreationDate": "The date and time when the specified Object Lambda Access Point was created.", "PolicyStatus": "", @@ -43985,6 +44046,14 @@ "ObjectLambdaConfiguration": "A configuration used when creating an Object Lambda Access Point." } }, + "AWS::S3ObjectLambda::AccessPoint.Alias": { + "attributes": {}, + "description": "", + "properties": { + "Status": "", + "Value": "" + } + }, "AWS::S3ObjectLambda::AccessPoint.AwsLambda": { "attributes": {}, "description": "", @@ -46012,7 +46081,7 @@ "attributes": {}, "description": "The security configuration for `OnlineStore` .", "properties": { - "KmsKeyId": "The AWS Key Management Service (KMS) key ARN that SageMaker Feature Store uses to encrypt the Amazon S3 objects at rest using Amazon S3 server-side encryption.\n\nThe caller (either IAM user or IAM role) of `CreateFeatureGroup` must have below permissions to the `OnlineStore` `KmsKeyId` :\n\n- `\"kms:Encrypt\"`\n- `\"kms:Decrypt\"`\n- `\"kms:DescribeKey\"`\n- `\"kms:CreateGrant\"`\n- `\"kms:RetireGrant\"`\n- `\"kms:ReEncryptFrom\"`\n- `\"kms:ReEncryptTo\"`\n- `\"kms:GenerateDataKey\"`\n- `\"kms:ListAliases\"`\n- `\"kms:ListGrants\"`\n- `\"kms:RevokeGrant\"`\n\nThe caller (either user or IAM role) to all DataPlane operations ( `PutRecord` , `GetRecord` , `DeleteRecord` ) must have the following permissions to the `KmsKeyId` :\n\n- `\"kms:Decrypt\"`" + "KmsKeyId": "The AWS Key Management Service (KMS) key ARN that SageMaker Feature Store uses to encrypt the Amazon S3 objects at rest using Amazon S3 server-side encryption.\n\nThe caller (either user or IAM role) of `CreateFeatureGroup` must have below permissions to the `OnlineStore` `KmsKeyId` :\n\n- `\"kms:Encrypt\"`\n- `\"kms:Decrypt\"`\n- `\"kms:DescribeKey\"`\n- `\"kms:CreateGrant\"`\n- `\"kms:RetireGrant\"`\n- `\"kms:ReEncryptFrom\"`\n- `\"kms:ReEncryptTo\"`\n- `\"kms:GenerateDataKey\"`\n- `\"kms:ListAliases\"`\n- `\"kms:ListGrants\"`\n- `\"kms:RevokeGrant\"`\n\nThe caller (either user or IAM role) to all DataPlane operations ( `PutRecord` , `GetRecord` , `DeleteRecord` ) must have the following permissions to the `KmsKeyId` :\n\n- `\"kms:Decrypt\"`" } }, "AWS::SageMaker::FeatureGroup.S3StorageConfig": { From 25b6edd9d83e4766a2cb064b8eb8e3c6198b4f53 Mon Sep 17 00:00:00 2001 From: pattasai <121061922+pattasai@users.noreply.github.com> Date: Fri, 17 Mar 2023 06:30:47 -0400 Subject: [PATCH 3/6] feat(elasticloadbalancing): classic load balancer supports ec2 instances (#24353) Introducing the `InstanceTarget` class: an EC2 instance that serves as the target for load balancing. This class allows to register an instance to a load balancer. `InstanceTarget ` takes an instance to register as the target for the load balancer. For example, ```ts const target = new elb.InstanceTarget(instance); elb.addTarget(target); ``` creates an InstanceTarget object with the specified instance and then adds it to the load balancer. > [CONTRIBUTING GUIDE]: https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md > [DESIGN GUIDELINES]: https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md Closes #23500. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-elasticloadbalancing/README.md | 17 + .../lib/load-balancer.ts | 32 +- .../aws-elasticloadbalancing/package.json | 1 + ...efaultTestDeployAssertAF607556.assets.json | 19 + ...aultTestDeployAssertAF607556.template.json | 36 + ...-cdk-elb-instance-target-integ.assets.json | 19 + ...dk-elb-instance-target-integ.template.json | 447 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 255 ++++++ .../tree.json | 784 ++++++++++++++++++ .../test/integ.instanceTarget.elb.ts | 36 + .../test/loadbalancer.test.ts | 108 ++- 13 files changed, 1763 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.assets.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.template.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.assets.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.template.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.ts diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/README.md b/packages/@aws-cdk/aws-elasticloadbalancing/README.md index 45ec1828bb466..676646f8efa6c 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/README.md +++ b/packages/@aws-cdk/aws-elasticloadbalancing/README.md @@ -48,3 +48,20 @@ lb.addListener({ allowConnectionsFrom: [mySecurityGroup], }); ``` + +### Adding Ec2 Instance as a target for the load balancer + +You can add an EC2 instance to the load balancer by calling using `new InstanceTarget` as the argument to `addTarget()`: + +```ts +const lb = new elb.LoadBalancer(this, 'LB', { + vpc, +}); +// instance to add as the target for load balancer. +const instance = new Instance(stack, 'targetInstance', { + vpc: vpc, + instanceType: InstanceType.of(InstanceClass.BURSTABLE2, InstanceSize.MICRO), + machineImage: new AmazonLinuxImage(), +}); +lb.addTarget(elb.InstanceTarget(instance)); +``` diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts index e64d631ddf242..4fec4bad91fa3 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts @@ -1,5 +1,5 @@ import { - Connections, IConnectable, ISecurityGroup, IVpc, Peer, Port, + Connections, IConnectable, Instance, ISecurityGroup, IVpc, Peer, Port, SecurityGroup, SelectedSubnets, SubnetSelection, SubnetType, } from '@aws-cdk/aws-ec2'; import { Duration, Lazy, Resource } from '@aws-cdk/core'; @@ -251,13 +251,13 @@ export class LoadBalancer extends Resource implements IConnectable { private readonly instancePorts: number[] = []; private readonly targets: ILoadBalancerTarget[] = []; + private readonly instanceIds: string[] = []; constructor(scope: Construct, id: string, props: LoadBalancerProps) { super(scope, id); this.securityGroup = new SecurityGroup(this, 'SecurityGroup', { vpc: props.vpc, allowAllOutbound: false }); this.connections = new Connections({ securityGroups: [this.securityGroup] }); - // Depending on whether the ELB has public or internal IPs, pick the right backend subnets const selectedSubnets: SelectedSubnets = loadBalancerSubnets(props); @@ -265,6 +265,7 @@ export class LoadBalancer extends Resource implements IConnectable { securityGroups: [this.securityGroup.securityGroupId], subnets: selectedSubnets.subnetIds, listeners: Lazy.any({ produce: () => this.listeners }), + instances: Lazy.list({ produce: () => this.instanceIds }, { omitEmpty: true }), scheme: props.internetFacing ? 'internet-facing' : 'internal', healthCheck: props.healthCheck && healthCheckToJSON(props.healthCheck), crossZone: props.crossZone ?? true, @@ -398,6 +399,33 @@ export class LoadBalancer extends Resource implements IConnectable { Port.tcp(instancePort), `Port ${instancePort} LB to fleet`); } + + /** + * Add instance to the load balancer. + * @internal + */ + public _addInstanceId(instanceId: string) { + this.instanceIds.push(instanceId); + } +} + +/** + * An EC2 instance that is the target for load balancing + */ +export class InstanceTarget implements ILoadBalancerTarget { + readonly connections: Connections; + /** + * Create a new Instance target. + * + * @param instance Instance to register to. + */ + constructor(public readonly instance: Instance) { + this.connections = instance.connections; + } + + public attachToClassicLB(loadBalancer: LoadBalancer): void { + loadBalancer._addInstanceId(this.instance.instanceId); + } } /** diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/package.json b/packages/@aws-cdk/aws-elasticloadbalancing/package.json index a8fcc72027323..f3b4e13aacb23 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/package.json +++ b/packages/@aws-cdk/aws-elasticloadbalancing/package.json @@ -83,6 +83,7 @@ "@aws-cdk/assertions": "0.0.0", "@aws-cdk/cdk-build-tools": "0.0.0", "@aws-cdk/integ-runner": "0.0.0", + "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/cfn2ts": "0.0.0", "@aws-cdk/pkglint": "0.0.0", "@types/jest": "^27.5.2" diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.assets.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.assets.json new file mode 100644 index 0000000000000..3493f6a48b43c --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.assets.json @@ -0,0 +1,19 @@ +{ + "version": "29.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "InstanceTargetTestDefaultTestDeployAssertAF607556.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.template.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/InstanceTargetTestDefaultTestDeployAssertAF607556.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.assets.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.assets.json new file mode 100644 index 0000000000000..1d178796401c7 --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.assets.json @@ -0,0 +1,19 @@ +{ + "version": "29.0.0", + "files": { + "11ca0111a871a53be970c5db0c5a24d4146213fd59f6d172b6fc1bc3de206cf9": { + "source": { + "path": "aws-cdk-elb-instance-target-integ.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "11ca0111a871a53be970c5db0c5a24d4146213fd59f6d172b6fc1bc3de206cf9.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.template.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.template.json new file mode 100644 index 0000000000000..07931ccc284e9 --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/aws-cdk-elb-instance-target-integ.template.json @@ -0,0 +1,447 @@ +{ + "Resources": { + "VPCB9E5F0B4": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "10.0.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "InstanceTenancy": "default", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC" + } + ] + } + }, + "VPCPublicSubnet1SubnetB4246D30": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.0.0/17", + "MapPublicIpOnLaunch": true, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Public" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Public" + }, + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableFEE4B781": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1RouteTableAssociation0B0896DC": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "VPCPublicSubnet1DefaultRoute91CEF279": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "GatewayId": { + "Ref": "VPCIGWB7E252D3" + } + }, + "DependsOn": [ + "VPCVPCGW99B986DC" + ] + }, + "VPCPublicSubnet1EIP6AD938E8": { + "Type": "AWS::EC2::EIP", + "Properties": { + "Domain": "vpc", + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "VPCPublicSubnet1NATGatewayE0556630": { + "Type": "AWS::EC2::NatGateway", + "Properties": { + "SubnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "AllocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + }, + "DependsOn": [ + "VPCPublicSubnet1DefaultRoute91CEF279", + "VPCPublicSubnet1RouteTableAssociation0B0896DC" + ] + }, + "VPCPrivateSubnet1Subnet8BCA10E0": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "CidrBlock": "10.0.128.0/17", + "MapPublicIpOnLaunch": false, + "Tags": [ + { + "Key": "aws-cdk:subnet-name", + "Value": "Private" + }, + { + "Key": "aws-cdk:subnet-type", + "Value": "Private" + }, + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableBE8A6027": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "VPCPrivateSubnet1RouteTableAssociation347902D1": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "VPCPrivateSubnet1DefaultRouteAE1D6490": { + "Type": "AWS::EC2::Route", + "Properties": { + "RouteTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "DestinationCidrBlock": "0.0.0.0/0", + "NatGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "VPCIGWB7E252D3": { + "Type": "AWS::EC2::InternetGateway", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/VPC" + } + ] + } + }, + "VPCVPCGW99B986DC": { + "Type": "AWS::EC2::VPCGatewayAttachment", + "Properties": { + "VpcId": { + "Ref": "VPCB9E5F0B4" + }, + "InternetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "targetInstanceInstanceSecurityGroupF268BD07": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup", + "SecurityGroupEgress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Allow all outbound traffic by default", + "IpProtocol": "-1" + } + ], + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "targetInstanceInstanceSecurityGroupfromawscdkelbinstancetargetintegLBSecurityGroup395870CC8080DF6C0658": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "IpProtocol": "tcp", + "Description": "Port 8080 LB to fleet", + "FromPort": 8080, + "GroupId": { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + }, + "SourceSecurityGroupId": { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + }, + "ToPort": 8080 + } + }, + "targetInstanceInstanceRole3F8EC526": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ] + } + }, + "targetInstanceInstanceProfile0A012423": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "targetInstanceInstanceRole3F8EC526" + } + ] + } + }, + "targetInstance603C5817": { + "Type": "AWS::EC2::Instance", + "Properties": { + "AvailabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "IamInstanceProfile": { + "Ref": "targetInstanceInstanceProfile0A012423" + }, + "ImageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "InstanceType": "t2.micro", + "SecurityGroupIds": [ + { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + } + ], + "SubnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + "Tags": [ + { + "Key": "Name", + "Value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ], + "UserData": { + "Fn::Base64": "#!/bin/bash" + } + }, + "DependsOn": [ + "targetInstanceInstanceRole3F8EC526" + ] + }, + "LBSecurityGroup8A41EA2B": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "aws-cdk-elb-instance-target-integ/LB/SecurityGroup", + "SecurityGroupIngress": [ + { + "CidrIp": "0.0.0.0/0", + "Description": "Default rule allow on 80", + "FromPort": 80, + "IpProtocol": "tcp", + "ToPort": 80 + } + ], + "VpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "LBSecurityGrouptoawscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E8080E1991644": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + }, + "IpProtocol": "tcp", + "Description": "Port 8080 LB to fleet", + "DestinationSecurityGroupId": { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + }, + "FromPort": 8080, + "ToPort": 8080 + } + }, + "LB8A12904C": { + "Type": "AWS::ElasticLoadBalancing::LoadBalancer", + "Properties": { + "Listeners": [ + { + "InstancePort": "8080", + "InstanceProtocol": "http", + "LoadBalancerPort": "80", + "Protocol": "http" + } + ], + "CrossZone": true, + "Instances": [ + { + "Ref": "targetInstance603C5817" + } + ], + "Scheme": "internal", + "SecurityGroups": [ + { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + } + ], + "Subnets": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ] + } + } + }, + "Parameters": { + "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2" + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/cdk.out b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/cdk.out new file mode 100644 index 0000000000000..d8b441d447f8a --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"29.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/integ.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/integ.json new file mode 100644 index 0000000000000..23c31182b8fce --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "29.0.0", + "testCases": { + "InstanceTargetTest/DefaultTest": { + "stacks": [ + "aws-cdk-elb-instance-target-integ" + ], + "assertionStack": "InstanceTargetTest/DefaultTest/DeployAssert", + "assertionStackName": "InstanceTargetTestDefaultTestDeployAssertAF607556" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/manifest.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/manifest.json new file mode 100644 index 0000000000000..f0e7e3434a175 --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/manifest.json @@ -0,0 +1,255 @@ +{ + "version": "29.0.0", + "artifacts": { + "aws-cdk-elb-instance-target-integ.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-elb-instance-target-integ.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-elb-instance-target-integ": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-elb-instance-target-integ.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/11ca0111a871a53be970c5db0c5a24d4146213fd59f6d172b6fc1bc3de206cf9.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-elb-instance-target-integ.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "aws-cdk-elb-instance-target-integ.assets" + ], + "metadata": { + "/aws-cdk-elb-instance-target-integ/VPC/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCB9E5F0B4" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1SubnetB4246D30" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableFEE4B781" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1RouteTableAssociation0B0896DC" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1DefaultRoute91CEF279" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/EIP": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1EIP6AD938E8" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/NATGateway": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPublicSubnet1NATGatewayE0556630" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/Subnet": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/RouteTable": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableBE8A6027" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/RouteTableAssociation": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1RouteTableAssociation347902D1" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/DefaultRoute": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCPrivateSubnet1DefaultRouteAE1D6490" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/IGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCIGWB7E252D3" + } + ], + "/aws-cdk-elb-instance-target-integ/VPC/VPCGW": [ + { + "type": "aws:cdk:logicalId", + "data": "VPCVPCGW99B986DC" + } + ], + "/aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstanceInstanceSecurityGroupF268BD07" + } + ], + "/aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup/from awscdkelbinstancetargetintegLBSecurityGroup395870CC:8080": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstanceInstanceSecurityGroupfromawscdkelbinstancetargetintegLBSecurityGroup395870CC8080DF6C0658" + } + ], + "/aws-cdk-elb-instance-target-integ/targetInstance/InstanceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstanceInstanceRole3F8EC526" + } + ], + "/aws-cdk-elb-instance-target-integ/targetInstance/InstanceProfile": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstanceInstanceProfile0A012423" + } + ], + "/aws-cdk-elb-instance-target-integ/targetInstance/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstance603C5817" + } + ], + "/aws-cdk-elb-instance-target-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": [ + { + "type": "aws:cdk:logicalId", + "data": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + } + ], + "/aws-cdk-elb-instance-target-integ/LB/SecurityGroup/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LBSecurityGroup8A41EA2B" + } + ], + "/aws-cdk-elb-instance-target-integ/LB/SecurityGroup/to awscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E:8080": [ + { + "type": "aws:cdk:logicalId", + "data": "LBSecurityGrouptoawscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E8080E1991644" + } + ], + "/aws-cdk-elb-instance-target-integ/LB/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "LB8A12904C" + } + ], + "/aws-cdk-elb-instance-target-integ/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-elb-instance-target-integ/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ], + "targetInstanceInstanceSecurityGroupfromawscdkelbinstancetargetintegLBSecurityGroup395870CC80E053AA6C": [ + { + "type": "aws:cdk:logicalId", + "data": "targetInstanceInstanceSecurityGroupfromawscdkelbinstancetargetintegLBSecurityGroup395870CC80E053AA6C", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ], + "LBSecurityGrouptoawscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E80A95A3BE8": [ + { + "type": "aws:cdk:logicalId", + "data": "LBSecurityGrouptoawscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E80A95A3BE8", + "trace": [ + "!!DESTRUCTIVE_CHANGES: WILL_DESTROY" + ] + } + ] + }, + "displayName": "aws-cdk-elb-instance-target-integ" + }, + "InstanceTargetTestDefaultTestDeployAssertAF607556.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "InstanceTargetTestDefaultTestDeployAssertAF607556.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "InstanceTargetTestDefaultTestDeployAssertAF607556": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "InstanceTargetTestDefaultTestDeployAssertAF607556.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "InstanceTargetTestDefaultTestDeployAssertAF607556.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "InstanceTargetTestDefaultTestDeployAssertAF607556.assets" + ], + "metadata": { + "/InstanceTargetTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/InstanceTargetTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "InstanceTargetTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/tree.json b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/tree.json new file mode 100644 index 0000000000000..6d4e4af19f1eb --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.js.snapshot/tree.json @@ -0,0 +1,784 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-elb-instance-target-integ": { + "id": "aws-cdk-elb-instance-target-integ", + "path": "aws-cdk-elb-instance-target-integ", + "children": { + "VPC": { + "id": "VPC", + "path": "aws-cdk-elb-instance-target-integ/VPC", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/VPC/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPC", + "aws:cdk:cloudformation:props": { + "cidrBlock": "10.0.0.0/16", + "enableDnsHostnames": true, + "enableDnsSupport": true, + "instanceTenancy": "default", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnVPC", + "version": "0.0.0" + } + }, + "PublicSubnet1": { + "id": "PublicSubnet1", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.0.0/17", + "mapPublicIpOnLaunch": true, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Public" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Public" + }, + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPublicSubnet1RouteTableFEE4B781" + }, + "destinationCidrBlock": "0.0.0.0/0", + "gatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + }, + "EIP": { + "id": "EIP", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/EIP", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::EIP", + "aws:cdk:cloudformation:props": { + "domain": "vpc", + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnEIP", + "version": "0.0.0" + } + }, + "NATGateway": { + "id": "NATGateway", + "path": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1/NATGateway", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::NatGateway", + "aws:cdk:cloudformation:props": { + "subnetId": { + "Ref": "VPCPublicSubnet1SubnetB4246D30" + }, + "allocationId": { + "Fn::GetAtt": [ + "VPCPublicSubnet1EIP6AD938E8", + "AllocationId" + ] + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PublicSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnNatGateway", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PublicSubnet", + "version": "0.0.0" + } + }, + "PrivateSubnet1": { + "id": "PrivateSubnet1", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1", + "children": { + "Subnet": { + "id": "Subnet", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/Subnet", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Subnet", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "cidrBlock": "10.0.128.0/17", + "mapPublicIpOnLaunch": false, + "tags": [ + { + "key": "aws-cdk:subnet-name", + "value": "Private" + }, + { + "key": "aws-cdk:subnet-type", + "value": "Private" + }, + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnet", + "version": "0.0.0" + } + }, + "Acl": { + "id": "Acl", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/Acl", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "RouteTable": { + "id": "RouteTable", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/RouteTable", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::RouteTable", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRouteTable", + "version": "0.0.0" + } + }, + "RouteTableAssociation": { + "id": "RouteTableAssociation", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/RouteTableAssociation", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SubnetRouteTableAssociation", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "subnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSubnetRouteTableAssociation", + "version": "0.0.0" + } + }, + "DefaultRoute": { + "id": "DefaultRoute", + "path": "aws-cdk-elb-instance-target-integ/VPC/PrivateSubnet1/DefaultRoute", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Route", + "aws:cdk:cloudformation:props": { + "routeTableId": { + "Ref": "VPCPrivateSubnet1RouteTableBE8A6027" + }, + "destinationCidrBlock": "0.0.0.0/0", + "natGatewayId": { + "Ref": "VPCPublicSubnet1NATGatewayE0556630" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnRoute", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.PrivateSubnet", + "version": "0.0.0" + } + }, + "IGW": { + "id": "IGW", + "path": "aws-cdk-elb-instance-target-integ/VPC/IGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::InternetGateway", + "aws:cdk:cloudformation:props": { + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/VPC" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnInternetGateway", + "version": "0.0.0" + } + }, + "VPCGW": { + "id": "VPCGW", + "path": "aws-cdk-elb-instance-target-integ/VPC/VPCGW", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::VPCGatewayAttachment", + "aws:cdk:cloudformation:props": { + "vpcId": { + "Ref": "VPCB9E5F0B4" + }, + "internetGatewayId": { + "Ref": "VPCIGWB7E252D3" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnVPCGatewayAttachment", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.Vpc", + "version": "0.0.0" + } + }, + "targetInstance": { + "id": "targetInstance", + "path": "aws-cdk-elb-instance-target-integ/targetInstance", + "children": { + "InstanceSecurityGroup": { + "id": "InstanceSecurityGroup", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup", + "securityGroupEgress": [ + { + "cidrIp": "0.0.0.0/0", + "description": "Allow all outbound traffic by default", + "ipProtocol": "-1" + } + ], + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "from awscdkelbinstancetargetintegLBSecurityGroup395870CC:8080": { + "id": "from awscdkelbinstancetargetintegLBSecurityGroup395870CC:8080", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceSecurityGroup/from awscdkelbinstancetargetintegLBSecurityGroup395870CC:8080", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupIngress", + "aws:cdk:cloudformation:props": { + "ipProtocol": "tcp", + "description": "Port 8080 LB to fleet", + "fromPort": 8080, + "groupId": { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + }, + "sourceSecurityGroupId": { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + }, + "toPort": 8080 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupIngress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "InstanceRole": { + "id": "InstanceRole", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceRole", + "children": { + "ImportInstanceRole": { + "id": "ImportInstanceRole", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceRole/ImportInstanceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "InstanceProfile": { + "id": "InstanceProfile", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/InstanceProfile", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::InstanceProfile", + "aws:cdk:cloudformation:props": { + "roles": [ + { + "Ref": "targetInstanceInstanceRole3F8EC526" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnInstanceProfile", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/targetInstance/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::Instance", + "aws:cdk:cloudformation:props": { + "availabilityZone": { + "Fn::Select": [ + 0, + { + "Fn::GetAZs": "" + } + ] + }, + "iamInstanceProfile": { + "Ref": "targetInstanceInstanceProfile0A012423" + }, + "imageId": { + "Ref": "SsmParameterValueawsserviceamiamazonlinuxlatestamzn2amihvmx8664gp2C96584B6F00A464EAD1953AFF4B05118Parameter" + }, + "instanceType": "t2.micro", + "securityGroupIds": [ + { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + } + ], + "subnetId": { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + }, + "tags": [ + { + "key": "Name", + "value": "aws-cdk-elb-instance-target-integ/targetInstance" + } + ], + "userData": { + "Fn::Base64": "#!/bin/bash" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnInstance", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.Instance", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "path": "aws-cdk-elb-instance-target-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118.Parameter", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118": { + "id": "SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "path": "aws-cdk-elb-instance-target-integ/SsmParameterValue:--aws--service--ami-amazon-linux-latest--amzn2-ami-hvm-x86_64-gp2:C96584B6-F00A-464E-AD19-53AFF4B05118", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "LB": { + "id": "LB", + "path": "aws-cdk-elb-instance-target-integ/LB", + "children": { + "SecurityGroup": { + "id": "SecurityGroup", + "path": "aws-cdk-elb-instance-target-integ/LB/SecurityGroup", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/LB/SecurityGroup/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroup", + "aws:cdk:cloudformation:props": { + "groupDescription": "aws-cdk-elb-instance-target-integ/LB/SecurityGroup", + "securityGroupIngress": [ + { + "cidrIp": "0.0.0.0/0", + "ipProtocol": "tcp", + "fromPort": 80, + "toPort": 80, + "description": "Default rule allow on 80" + } + ], + "vpcId": { + "Ref": "VPCB9E5F0B4" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroup", + "version": "0.0.0" + } + }, + "to awscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E:8080": { + "id": "to awscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E:8080", + "path": "aws-cdk-elb-instance-target-integ/LB/SecurityGroup/to awscdkelbinstancetargetintegtargetInstanceInstanceSecurityGroup4B82664E:8080", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::EC2::SecurityGroupEgress", + "aws:cdk:cloudformation:props": { + "groupId": { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + }, + "ipProtocol": "tcp", + "description": "Port 8080 LB to fleet", + "destinationSecurityGroupId": { + "Fn::GetAtt": [ + "targetInstanceInstanceSecurityGroupF268BD07", + "GroupId" + ] + }, + "fromPort": 8080, + "toPort": 8080 + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.CfnSecurityGroupEgress", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-ec2.SecurityGroup", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-elb-instance-target-integ/LB/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::ElasticLoadBalancing::LoadBalancer", + "aws:cdk:cloudformation:props": { + "listeners": [ + { + "loadBalancerPort": "80", + "protocol": "http", + "instancePort": "8080", + "instanceProtocol": "http" + } + ], + "crossZone": true, + "instances": [ + { + "Ref": "targetInstance603C5817" + } + ], + "scheme": "internal", + "securityGroups": [ + { + "Fn::GetAtt": [ + "LBSecurityGroup8A41EA2B", + "GroupId" + ] + } + ], + "subnets": [ + { + "Ref": "VPCPrivateSubnet1Subnet8BCA10E0" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancing.CfnLoadBalancer", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-elasticloadbalancing.LoadBalancer", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-elb-instance-target-integ/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-elb-instance-target-integ/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "InstanceTargetTest": { + "id": "InstanceTargetTest", + "path": "InstanceTargetTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "InstanceTargetTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "InstanceTargetTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.237" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "InstanceTargetTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "InstanceTargetTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "InstanceTargetTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.237" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.ts b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.ts new file mode 100644 index 0000000000000..57ab3f1371ff0 --- /dev/null +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/integ.instanceTarget.elb.ts @@ -0,0 +1,36 @@ +#!/usr/bin/env node +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import * as elb from '../lib'; + +const app = new cdk.App(); +const stack = new cdk.Stack(app, 'aws-cdk-elb-instance-target-integ'); + +const vpc = new ec2.Vpc(stack, 'VPC', { + maxAzs: 1, +}); + +const instance = new ec2.Instance(stack, 'targetInstance', { + vpc: vpc, + instanceType: ec2.InstanceType.of( // t2.micro has free tier usage in aws + ec2.InstanceClass.T2, + ec2.InstanceSize.MICRO, + ), + machineImage: ec2.MachineImage.latestAmazonLinux({ + generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, + }), +}); + +const elbalancer = new elb.LoadBalancer(stack, 'LB', { + vpc, +}); + +elbalancer.addTarget(new elb.InstanceTarget(instance)); +elbalancer.addListener({ externalPort: 80, internalPort: 8080 }); + +new integ.IntegTest(app, 'InstanceTargetTest', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-elasticloadbalancing/test/loadbalancer.test.ts b/packages/@aws-cdk/aws-elasticloadbalancing/test/loadbalancer.test.ts index 14003c49cf36e..8eabd5ffb1407 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancing/test/loadbalancer.test.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancing/test/loadbalancer.test.ts @@ -1,8 +1,8 @@ import { Template } from '@aws-cdk/assertions'; -import { Connections, Peer, SubnetType, Vpc } from '@aws-cdk/aws-ec2'; +import { AmazonLinuxGeneration, Connections, Instance, InstanceClass, InstanceSize, InstanceType, MachineImage, Peer, SubnetType, Vpc } from '@aws-cdk/aws-ec2'; import { testDeprecated } from '@aws-cdk/cdk-build-tools'; import { Duration, Stack } from '@aws-cdk/core'; -import { ILoadBalancerTarget, LoadBalancer, LoadBalancingProtocol } from '../lib'; +import { ILoadBalancerTarget, InstanceTarget, LoadBalancer, LoadBalancingProtocol } from '../lib'; describe('tests', () => { test('test specifying nonstandard port works', () => { @@ -89,6 +89,110 @@ describe('tests', () => { }); }); + test('add an Instance as a load balancing target', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VCP'); + const instance = new Instance(stack, 'targetInstance', { + vpc: vpc, + instanceType: InstanceType.of( // t2.micro has free tier usage in aws + InstanceClass.T2, + InstanceSize.MICRO, + ), + machineImage: MachineImage.latestAmazonLinux({ + generation: AmazonLinuxGeneration.AMAZON_LINUX_2, + }), + }); + const elb = new LoadBalancer(stack, 'LB', { + vpc, + }); + + // WHEN + elb.addListener({ externalPort: 80, internalPort: 8080 }); + elb.addTarget(new InstanceTarget(instance)); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancing::LoadBalancer', { + CrossZone: true, + Instances: [ + { + Ref: 'targetInstance603C5817', + }, + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { + Description: 'Port 8080 LB to fleet', + FromPort: 8080, + IpProtocol: 'tcp', + ToPort: 8080, + GroupId: { + 'Fn::GetAtt': [ + 'LBSecurityGroup8A41EA2B', + 'GroupId', + ], + }, + DestinationSecurityGroupId: { + 'Fn::GetAtt': [ + 'targetInstanceInstanceSecurityGroupF268BD07', + 'GroupId', + ], + }, + }); + }); + + test('order test for addTarget and addListener', () => { + // GIVEN + const stack = new Stack(); + const vpc = new Vpc(stack, 'VCP'); + const instance = new Instance(stack, 'targetInstance', { + vpc: vpc, + instanceType: InstanceType.of( // t2.micro has free tier usage in aws + InstanceClass.T2, + InstanceSize.MICRO, + ), + machineImage: MachineImage.latestAmazonLinux({ + generation: AmazonLinuxGeneration.AMAZON_LINUX_2, + }), + }); + const elb = new LoadBalancer(stack, 'LB', { + vpc, + }); + + // WHEN + elb.addTarget(new InstanceTarget(instance)); + elb.addListener({ externalPort: 80, internalPort: 8080 }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancing::LoadBalancer', { + CrossZone: true, + Instances: [ + { + Ref: 'targetInstance603C5817', + }, + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroupEgress', { + Description: 'Port 8080 LB to fleet', + FromPort: 8080, + IpProtocol: 'tcp', + ToPort: 8080, + GroupId: { + 'Fn::GetAtt': [ + 'LBSecurityGroup8A41EA2B', + 'GroupId', + ], + }, + DestinationSecurityGroupId: { + 'Fn::GetAtt': [ + 'targetInstanceInstanceSecurityGroupF268BD07', + 'GroupId', + ], + }, + }); + }); + test('enable cross zone load balancing', () => { // GIVEN const stack = new Stack(); From 160ac48b8b9da5451ae01d09f303a845f7f80cf6 Mon Sep 17 00:00:00 2001 From: Otavio Macedo <288203+otaviomacedo@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:30:14 +0000 Subject: [PATCH 4/6] chore(logs): add new supported value of 3 years (#24664) New value (1096) added to the list of valid retention periods: https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutRetentionPolicy.html#API_PutRetentionPolicy_RequestSyntax ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-logs/lib/log-group.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/@aws-cdk/aws-logs/lib/log-group.ts b/packages/@aws-cdk/aws-logs/lib/log-group.ts index a675c9f7dc701..5db7a29ed3ac0 100644 --- a/packages/@aws-cdk/aws-logs/lib/log-group.ts +++ b/packages/@aws-cdk/aws-logs/lib/log-group.ts @@ -326,6 +326,11 @@ export enum RetentionDays { */ TWO_YEARS = 731, + /** + * 3 years + */ + THREE_YEARS = 1096, + /** * 5 years */ From 3e8d8d8e1b9a88376a6460094dea0c08ce19742e Mon Sep 17 00:00:00 2001 From: Rico Hermans Date: Fri, 17 Mar 2023 13:48:48 +0100 Subject: [PATCH 5/6] fix(cli): user agent is reported as `undefined/undefined` (#24663) Our CLI's user agent is reported as `undefined/undefined`. This is because we are reading the package name and version from the CLI's `package.json` by using a relative path to the source file (using `__dirname`). However, since a good long while, our production CLI is being bundled using `esbuild` into a single JavaScript file. This means that at runtime, `__dirname` points to a completely different directory than the one it's been coded against, and so reading the `package.json` fails. Account for this by using a function that searches for `package.json`; still do it defensively so that if some other condition we didn't predict causes the search to fail, our CLI doesn't fail. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk/lib/api/aws-auth/sdk-provider.ts | 19 +++++++++++++++--- packages/aws-cdk/lib/util/directories.ts | 20 +++++++++++++++---- .../aws-cdk/test/api/sdk-provider.test.ts | 6 +++++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/packages/aws-cdk/lib/api/aws-auth/sdk-provider.ts b/packages/aws-cdk/lib/api/aws-auth/sdk-provider.ts index 567900f6326fc..739bfc1473503 100644 --- a/packages/aws-cdk/lib/api/aws-auth/sdk-provider.ts +++ b/packages/aws-cdk/lib/api/aws-auth/sdk-provider.ts @@ -10,6 +10,7 @@ import { cached } from './cached'; import { CredentialPlugins } from './credential-plugins'; import { Mode } from './credentials'; import { ISDK, SDK, isUnrecoverableAwsError } from './sdk'; +import { rootDir } from '../../util/directories'; import { traceMethods } from '../../util/tracing'; @@ -417,9 +418,7 @@ function parseHttpOptions(options: SdkHttpOptions) { let userAgent = options.userAgent; if (userAgent == null) { - // Find the package.json from the main toolkit - const pkg = JSON.parse(readIfPossible(path.join(__dirname, '..', '..', '..', 'package.json')) ?? '{}'); - userAgent = `${pkg.name}/${pkg.version}`; + userAgent = defaultCliUserAgent(); } config.customUserAgent = userAgent; @@ -444,6 +443,20 @@ function parseHttpOptions(options: SdkHttpOptions) { return config; } +/** + * Find the package.json from the main toolkit. + * + * If we can't read it for some reason, try to do something reasonable anyway. + * Fall back to argv[1], or a standard string if that is undefined for some reason. + */ +export function defaultCliUserAgent() { + const root = rootDir(false); + const pkg = JSON.parse((root ? readIfPossible(path.join(root, 'package.json')) : undefined) ?? '{}'); + const name = pkg.name ?? path.basename(process.argv[1] ?? 'cdk-cli'); + const version = pkg.version ?? ''; + return `${name}/${version}`; +} + /** * Find and return a CA certificate bundle path to be passed into the SDK. */ diff --git a/packages/aws-cdk/lib/util/directories.ts b/packages/aws-cdk/lib/util/directories.ts index a2327f5d292bc..20be45f47926f 100644 --- a/packages/aws-cdk/lib/util/directories.ts +++ b/packages/aws-cdk/lib/util/directories.ts @@ -28,15 +28,27 @@ export function cdkCacheDir() { return path.join(cdkHomeDir(), 'cache'); } -export function rootDir() { - - function _rootDir(dirname: string): string { +/** + * From the current file, find the directory that contains the CLI's package.json + * + * Can't use `__dirname` in production code, as the CLI will get bundled as it's + * released and `__dirname` will refer to a different location in the `.ts` form + * as it will in the final executing form. + */ +export function rootDir(): string; +export function rootDir(fail: true): string; +export function rootDir(fail: false): string | undefined; +export function rootDir(fail?: boolean) { + function _rootDir(dirname: string): string | undefined { const manifestPath = path.join(dirname, 'package.json'); if (fs.existsSync(manifestPath)) { return dirname; } if (path.dirname(dirname) === dirname) { - throw new Error('Unable to find package manifest'); + if (fail ?? true) { + throw new Error('Unable to find package manifest'); + } + return undefined; } return _rootDir(path.dirname(dirname)); } diff --git a/packages/aws-cdk/test/api/sdk-provider.test.ts b/packages/aws-cdk/test/api/sdk-provider.test.ts index d66b631686ac2..bd2c19bc6e321 100644 --- a/packages/aws-cdk/test/api/sdk-provider.test.ts +++ b/packages/aws-cdk/test/api/sdk-provider.test.ts @@ -5,7 +5,7 @@ import type { ConfigurationOptions } from 'aws-sdk/lib/config-base'; import * as promptly from 'promptly'; import * as uuid from 'uuid'; import { FakeSts, RegisterRoleOptions, RegisterUserOptions } from './fake-sts'; -import { ISDK, Mode, SDK, SdkProvider } from '../../lib/api/aws-auth'; +import { ISDK, Mode, SDK, SdkProvider, defaultCliUserAgent } from '../../lib/api/aws-auth'; import { PluginHost } from '../../lib/api/plugin'; import * as logging from '../../lib/logging'; import * as bockfs from '../bockfs'; @@ -623,6 +623,10 @@ test('even when using a profile to assume another profile, STS calls goes throug expect(called).toEqual(true); }); +test('default useragent is reasonable', () => { + expect(defaultCliUserAgent()).toContain('aws-cdk/'); +}); + /** * Use object hackery to get the credentials out of the SDK object */ From 1ba85fee418fc79ccf5d5a36c12f2a83422f92e5 Mon Sep 17 00:00:00 2001 From: Rico Hermans Date: Fri, 17 Mar 2023 14:27:34 +0100 Subject: [PATCH 6/6] chore(cli-integ): retry throttled Maven uploads (#24665) Maven uploads can fail with the following error, which indicates throttling: ``` [ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:3.0.0:deploy-file (default-cli) on project standalone-pom: Failed to deploy artifacts: Could not transfer artifact software.amazon.awscdk:batch-alpha:jar:2.70.0-alpha.999 from/to codeartifact (https://xxxxx.d.codeartifact.us-east-1.amazonaws.com/maven/test-0ek4hpd8q2tm/): status code: 429, reason phrase: Too Many Requests (429) -> [Help 1] ``` Catch these errors and retry them. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk-testing/cli-integ/lib/staging/maven.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/@aws-cdk-testing/cli-integ/lib/staging/maven.ts b/packages/@aws-cdk-testing/cli-integ/lib/staging/maven.ts index 4a7412f58304e..8da08ad1d6f15 100644 --- a/packages/@aws-cdk-testing/cli-integ/lib/staging/maven.ts +++ b/packages/@aws-cdk-testing/cli-integ/lib/staging/maven.ts @@ -52,6 +52,10 @@ export async function uploadJavaPackages(packages: string[], login: LoginInforma console.log(`❌ ${pkg}: already exists. Skipped.`); return 'skip'; } + if (output.toString().includes('Too Many Requests')) { + console.log(`♻️ ${pkg}: Too many requests. Retrying.`); + return 'retry'; + } return 'fail'; }); }