diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b2025947dd1c..7644c072eb899 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1196,18 +1196,18 @@ Adding a new flag looks as follows: with the name of the context key that enables this new feature (for example, `ENABLE_STACK_NAME_DUPLICATES`). The context key should be in the form `module.Type:feature` (e.g. `@aws-cdk/core:enableStackNameDuplicates`). -2. Add your feature flag to the `FLAGS` map in - [cx-api/lib/features.ts](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/lib/features.ts). - Set `introducedIn.v2` to the literal string `'V2NEXT'`. - Double negatives should be avoided. If you want to add a flag that disables something that was previously enabled, set `default.v2` to `true` and the `recommendedValue` to `false`. You will need to update a test in `features.test.ts` -- this is okay if you have a good reason. - In your description, be sure to cover the following: +2. Use `FeatureFlags.of(construct).isEnabled(cxapi.ENABLE_XXX)` to check if this feature is enabled + in your code. If it is not defined, revert to the legacy behavior. +3. Add your feature flag to the `FLAGS` map in + [cx-api/lib/features.ts](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/lib/features.ts). In + your description, be sure to cover the following: - Consciously pick the type of feature flag. Can the flag be removed in a future major version, or not? - Motivate why the feature flag exists. What is the change to existing infrastructure and why is it not safe? - In case of a "default change flag", describe what the user needs to do to restore the old behavior. -3. Use `FeatureFlags.of(construct).isEnabled(cxapi.ENABLE_XXX)` to check if this feature is enabled - in your code. If it is not defined, revert to the legacy behavior. 4. Add an entry for your feature flag in the [README](https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/cx-api/README.md) file. 5. In your tests, ensure that you test your feature with and without the feature flag enabled. You can do this by passing the feature flag to the `context` property when instantiating an `App`. ```ts diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index 6d6c269f6de48..bbb7d02f34214 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -7,7 +7,7 @@ import { ApplicationTargetGroup, IApplicationLoadBalancerTarget, IApplicationTar import { ListenerCondition } from './conditions'; import * as ec2 from '../../../aws-ec2'; import * as cxschema from '../../../cloud-assembly-schema'; -import { Duration, FeatureFlags, Lazy, Resource, Token } from '../../../core'; +import { Duration, Lazy, Resource, Token } from '../../../core'; import * as cxapi from '../../../cx-api'; import { BaseListener, BaseListenerLookupOptions, IListener } from '../shared/base-listener'; import { HealthCheck } from '../shared/base-target-group'; @@ -664,22 +664,15 @@ abstract class ExternalApplicationListener extends Resource implements IApplicat * It is not possible to add a default action to an imported IApplicationListener. * In order to add actions to an imported IApplicationListener a `priority` * must be provided. - * - * Warning, if you are attempting to migrate an existing `ListenerAction` - * which was declared by the {@link addTargetGroups} method, you will - * need to enable the - * `@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction` - * feature flag. */ public addAction(id: string, props: AddApplicationActionProps): void { checkAddRuleProps(props); if (props.priority !== undefined) { - const idSuffix = FeatureFlags.of(this).isEnabled(cxapi.ALBV2_EXTERNALAPPLICATIONLISTENER_SWITCH_FROM_ADDTARGETGROUP_TO_ADDACTION) ? '' : 'Rule'; // New rule // // TargetGroup.registerListener is called inside ApplicationListenerRule. - new ApplicationListenerRule(this, id + idSuffix, { + new ApplicationListenerRule(this, id + 'Rule', { listener: this, priority: props.priority, ...props, diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts index 4f5f25568cd3d..68be7e820529c 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/alb/application-target-group.ts @@ -60,7 +60,7 @@ export interface ApplicationTargetGroupProps extends BaseTargetGroupProps { * After this period, the cookie is considered stale. The minimum value is * 1 second and the maximum value is 7 days (604800 seconds). * - * @default Duration.days(1) + * @default - Stickiness is disabled */ readonly stickinessCookieDuration?: Duration; diff --git a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts index 0f1f949a2b82b..907cf8a20a683 100644 --- a/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts +++ b/packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/listener.test.ts @@ -6,7 +6,6 @@ import { Metric } from '../../../aws-cloudwatch'; import * as ec2 from '../../../aws-ec2'; import * as cdk from '../../../core'; import { SecretValue } from '../../../core'; -import * as cxapi from '../../../cx-api'; import * as elbv2 from '../../lib'; import { FakeSelfRegisteringTarget } from '../helpers'; @@ -1682,40 +1681,6 @@ describe('tests', () => { }).toThrow(/specify only one/); }); - describe('ExternalApplicationListener logicalId support', () => { - - test('compatibility mode for addAction', () => { - // GIVEN - const context = { [cxapi.ALBV2_EXTERNALAPPLICATIONLISTENER_SWITCH_FROM_ADDTARGETGROUP_TO_ADDACTION]: true }; - const app = new cdk.App({ context }); - const stack = new cdk.Stack(app, 'stack', { - env: { - account: '123456789012', - region: 'us-west-2', - }, - }); - const vpc = new ec2.Vpc(stack, 'Stack'); - const targetGroup = new elbv2.ApplicationTargetGroup(stack, 'TargetGroup', { vpc, port: 80 }); - const listener = elbv2.ApplicationListener.fromLookup(stack, 'a', { - loadBalancerTags: { - some: 'tag', - }, - }); - // WHEN - const identifierToken = 'SuperMagicToken'; - listener.addAction(identifierToken, { - action: elbv2.ListenerAction.weightedForward([{ targetGroup, weight: 1 }]), - conditions: [elbv2.ListenerCondition.pathPatterns(['/fake'])], - priority: 42, - }); - - // THEN - const applicationListenerRule = listener.node.children.find((v)=> v.hasOwnProperty('conditions')); - expect(applicationListenerRule).toBeDefined(); - expect(applicationListenerRule!.node.id).toBe(identifierToken); // Should not have `Rule` suffix - }); - }); - test('not allowed to specify defaultTargetGroups and defaultAction together', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/aws-cdk-lib/aws-lambda/test/code.test.ts b/packages/aws-cdk-lib/aws-lambda/test/code.test.ts index 7fcc937ed7ee3..cdd393c271987 100644 --- a/packages/aws-cdk-lib/aws-lambda/test/code.test.ts +++ b/packages/aws-cdk-lib/aws-lambda/test/code.test.ts @@ -16,6 +16,20 @@ describe('code', () => { }); describe('lambda.Code.fromAsset', () => { + test('fails if path is empty', () => { + // GIVEN + const fileAsset = lambda.Code.fromAsset(''); + + // THEN + expect(() => defineFunction(fileAsset)).toThrow(/Asset path cannot be empty/); + }); + test('fails if path does not exist', () => { + // GIVEN + const fileAsset = lambda.Code.fromAsset('/path/not/found/' + Math.random() * 999999); + + // THEN + expect(() => defineFunction(fileAsset)).toThrow(/Cannot find asset/); + }); test('fails if a non-zip asset is used', () => { // GIVEN const fileAsset = lambda.Code.fromAsset(path.join(__dirname, 'my-lambda-handler', 'index.py')); diff --git a/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts b/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts index d20059505d674..5993a9a2a06e9 100644 --- a/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts +++ b/packages/aws-cdk-lib/aws-s3-assets/lib/asset.ts @@ -137,6 +137,10 @@ export class Asset extends Construct implements cdk.IAsset { constructor(scope: Construct, id: string, props: AssetProps) { super(scope, id); + if (!props.path) { + throw new Error('Asset path cannot be empty'); + } + this.isBundled = props.bundling != null; // stage the asset source (conditionally). diff --git a/packages/aws-cdk-lib/aws-s3-assets/test/asset.test.ts b/packages/aws-cdk-lib/aws-s3-assets/test/asset.test.ts index 4aa70b59bf24d..77d174956393e 100644 --- a/packages/aws-cdk-lib/aws-s3-assets/test/asset.test.ts +++ b/packages/aws-cdk-lib/aws-s3-assets/test/asset.test.ts @@ -143,11 +143,18 @@ test('"readers" or "grantRead" can be used to grant read permissions on the asse }); }); +test('fails if path is empty', () => { + const stack = new cdk.Stack(); + expect(() => new Asset(stack, 'MyDirectory', { + path: '', + })).toThrow(/Asset path cannot be empty/); +}); + test('fails if directory not found', () => { const stack = new cdk.Stack(); expect(() => new Asset(stack, 'MyDirectory', { path: '/path/not/found/' + Math.random() * 999999, - })).toThrow(); + })).toThrow(/Cannot find asset/); }); test('multiple assets under the same parent', () => { diff --git a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md index 4999ca300cef0..e3688ae4b55ae 100644 --- a/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md +++ b/packages/aws-cdk-lib/cx-api/FEATURE_FLAGS.md @@ -67,8 +67,6 @@ Flags come in three types: | [@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse](#aws-cdkaws-codepipelinecrossaccountkeysdefaultvaluetofalse) | Enables Pipeline to set the default value for crossAccountKeys to false. | 2.127.0 | (default) | | [@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2](#aws-cdkaws-codepipelinedefaultpipelinetypetov2) | Enables Pipeline to set the default pipeline type to V2. | 2.133.0 | (default) | | [@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope](#aws-cdkaws-kmsreducecrossaccountregionpolicyscope) | When enabled, IAM Policy created from KMS key grant will reduce the resource scope to this key only. | 2.134.0 | (fix) | -| [@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction](#aws-cdkaws-elasticloadbalancingv2externalapplicationlistener-norulesuffixforaddaction) | When enabled, you can switch from the `addTargetGroups()` method of declaring a `ListenerRule` to the `addAction()` method, -without changing the logicalId and replacing your resource. | V2NEXT | (fix) | @@ -1267,19 +1265,4 @@ When this feature flag is enabled and calling KMS key grant method, the created | 2.134.0 | `false` | `true` | -### @aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction - -*When enabled, you can switch from the `addTargetGroups()` method of declaring a `ListenerRule` to the `addAction()` method, -without changing the logicalId and replacing your resource.* (fix) - -Setting this feature flag will cause the `addAction()` method to not add the `Rule` suffix on the logicalId. -This allows you to switch from the `addTargetGroups()` method without having CloudFormation deadlock while attempting to replace the resource. - - -| Since | Default | Recommended | -| ----- | ----- | ----- | -| (not in v1) | | | -| V2NEXT | `false` | `false` | - - diff --git a/packages/aws-cdk-lib/cx-api/README.md b/packages/aws-cdk-lib/cx-api/README.md index c3ca349b65558..cdbd86f3ae08e 100644 --- a/packages/aws-cdk-lib/cx-api/README.md +++ b/packages/aws-cdk-lib/cx-api/README.md @@ -309,29 +309,3 @@ _cdk.json_ } } ``` - -* `@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction` - -Enable this feature flag if you have deployed a `ListenerRule` using the `addTargetGroups()` -convenience method against an `ExternalApplicationListener` and you need to migrate to -using the `addAction()` method for more complex rule configurations. -This will prevent `Rule` from being added as a suffix to the logicalId so that the logicalId will remain the same. - -Do not enable this if you have already deployed `ListenerRule` resources using the -`addAction()` method. -Instead consider the [cdk-logical-id-mapper](https://github.com/mbonig/cdk-logical-id-mapper), -possibly in conjunction with `@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-addTargetGroupsConsistentLogicalId` (see below). - -* `@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-addTargetGroupsConsistentLogicalId` - -Enable this feature flag to ensure that the logicalIds of `ListenerRule`s created -on a `ExternalApplicationListener` by the `addTargetGroups()` method are consistent -with logicalIds for `ListenerRules` generated by other methods. -This will allow you to migrate between the different methods -without causing a replacement of the `ListenerRule` resource. - -You should enable this on new apps, before creating any resources. -If you have already created resources with the previous behavior, -you may still enable this flag, but will need to use something like the -[cdk-logical-id-mapper](https://github.com/mbonig/cdk-logical-id-mapper). -Alternatively, do not enable this feature flag and instead consider the `@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction` as necessary. diff --git a/packages/aws-cdk-lib/cx-api/lib/features.ts b/packages/aws-cdk-lib/cx-api/lib/features.ts index f3b7b142bd034..3787104072ee5 100644 --- a/packages/aws-cdk-lib/cx-api/lib/features.ts +++ b/packages/aws-cdk-lib/cx-api/lib/features.ts @@ -101,7 +101,6 @@ export const LAMBDA_PERMISSION_LOGICAL_ID_FOR_LAMBDA_ACTION = '@aws-cdk/aws-clou export const CODEPIPELINE_CROSS_ACCOUNT_KEYS_DEFAULT_VALUE_TO_FALSE = '@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse'; export const CODEPIPELINE_DEFAULT_PIPELINE_TYPE_TO_V2 = '@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2'; export const KMS_REDUCE_CROSS_ACCOUNT_REGION_POLICY_SCOPE = '@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope'; -export const ALBV2_EXTERNALAPPLICATIONLISTENER_SWITCH_FROM_ADDTARGETGROUP_TO_ADDACTION = '@aws-cdk/aws-elasticloadbalancingv2:ExternalApplicationListener-noRuleSuffixForAddAction'; export const FLAGS: Record = { ////////////////////////////////////////////////////////////////////// @@ -1035,27 +1034,6 @@ export const FLAGS: Record = { introducedIn: { v2: '2.134.0' }, recommendedValue: true, }, - - ////////////////////////////////////////////////////////////////////// - [ALBV2_EXTERNALAPPLICATIONLISTENER_SWITCH_FROM_ADDTARGETGROUP_TO_ADDACTION]: { - type: FlagType.VisibleContext, - summary: 'When enabled, you can switch from the \`addTargetGroups()\` method of declaring a \`ListenerRule\` to the \`addAction()\` method, without changing the logicalId and replacing your resource.', - detailsMd: ` - When switching from a less complex to a more complex use of ALB, - you will eventually need features not available in the \`addTargetGroups()\` convenience method. - In this case you will want to use the \`addAction()\` method. - Before this feature is enabled, switching over to \`addAction()\` from using \`addTargetGroups()\` - will add a \`Rule\` suffix to the logicalId of your \`ListenerRule\`, - causing CloudFormation to attempt to replace the resource. - Since \`ListenerRule\`s have a unique priority, - CloudFormation will always fail when generating the new \`ListenerRule\`. - - Setting this feature flag will cause the \`addAction()\` method to not add the \`Rule\` suffix on the logicalId. - This allows you to switch from the \`addTargetGroups()\` method without having CloudFormation deadlock while attempting to replace the resource. - `, - introducedIn: { v2: 'V2NEXT' }, - recommendedValue: false, - }, }; const CURRENT_MV = 'v2'; diff --git a/yarn.lock b/yarn.lock index b51c53c485948..ed115bbb559ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13957,16 +13957,7 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.0.1, string-width@^5.1.2: +"string-width-cjs@npm:string-width@^4.2.0", string-width@*, string-width@^1.0.1, "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3, string-width@^5.0.1, string-width@^5.1.2: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14044,7 +14035,7 @@ stringify-package@^1.0.1: resolved "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg== -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -14058,13 +14049,6 @@ strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -14651,9 +14635,9 @@ undici-types@~5.26.4: integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== undici@^5.25.4: - version "5.28.3" - resolved "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz#a731e0eff2c3fcfd41c1169a869062be222d1e5b" - integrity sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA== + version "5.28.4" + resolved "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" + integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== dependencies: "@fastify/busboy" "^2.0.0" @@ -15023,7 +15007,7 @@ workerpool@^6.5.1: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -15041,15 +15025,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"