diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.product.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.product.ts index 445fb6c994f54..7ff087bfadbdb 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.product.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/integ.product.ts @@ -83,7 +83,7 @@ const portfolio = new servicecatalog.Portfolio(stack, 'TestPortfolio', { messageLanguage: servicecatalog.MessageLanguage.EN, }); -class TestAssetProductStack extends servicecatalog.ProductStack { +class TestAssetProductOneStack extends servicecatalog.ProductStack { constructor(scope: any, id: string, props?: ProductStackProps) { super(scope, id, props); @@ -101,7 +101,25 @@ class TestAssetProductStack extends servicecatalog.ProductStack { } } -const productStackHistory = new ProductStackHistory(stack, 'ProductStackHistory', { +class TestAssetProductTwoStack extends servicecatalog.ProductStack { + constructor(scope: any, id: string, props?: ProductStackProps) { + super(scope, id, props); + + new lambda.Function(this, 'HelloHandler', { + runtime: lambda.Runtime.PYTHON_3_9, + code: lambda.Code.fromAsset('./assets'), + handler: 'index.handler', + }); + + new lambda.Function(this, 'HelloHandler2', { + runtime: lambda.Runtime.PYTHON_3_9, + code: lambda.Code.fromAsset('./assetsv2'), + handler: 'index.handler', + }); + } +} + +const productStackHistory = new ProductStackHistory(stack, 'ProductStackOneHistory', { productStack: new TestProductStack(stack, 'SNSTopicProduct3'), currentVersionName: 'v1', currentVersionLocked: false, @@ -135,9 +153,16 @@ const product = new servicecatalog.CloudFormationProduct(stack, 'TestProduct', { cloudFormationTemplate: servicecatalog.CloudFormationTemplate.fromProductStack(new TestProductStack(stack, 'SNSTopicProduct2')), }, { - productVersionName: 'testAssetProduct', + productVersionName: 'testAssetProductOne', + validateTemplate: false, + cloudFormationTemplate: servicecatalog.CloudFormationTemplate.fromProductStack(new TestAssetProductOneStack(stack, 'S3AssetProductOne', { + assetBucket: testAssetBucket, + })), + }, + { + productVersionName: 'testAssetProductTwo', validateTemplate: false, - cloudFormationTemplate: servicecatalog.CloudFormationTemplate.fromProductStack(new TestAssetProductStack(stack, 'S3AssetProduct', { + cloudFormationTemplate: servicecatalog.CloudFormationTemplate.fromProductStack(new TestAssetProductTwoStack(stack, 'S3AssetProductTwo', { assetBucket: testAssetBucket, })), }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/product-stack-snapshots/integservicecatalogproductProductStackOneHistory5099C4DD.integservicecatalogproductSNSTopicProduct3B51CF591.v1.product.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/product-stack-snapshots/integservicecatalogproductProductStackOneHistory5099C4DD.integservicecatalogproductSNSTopicProduct3B51CF591.v1.product.template.json new file mode 100644 index 0000000000000..2f2f4704a22ad --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-servicecatalog/test/product-stack-snapshots/integservicecatalogproductProductStackOneHistory5099C4DD.integservicecatalogproductSNSTopicProduct3B51CF591.v1.product.template.json @@ -0,0 +1,7 @@ +{ + "Resources": { + "TopicProductD757E287": { + "Type": "AWS::SNS::Topic" + } + } +} \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-servicecatalog/lib/private/product-stack-synthesizer.ts b/packages/aws-cdk-lib/aws-servicecatalog/lib/private/product-stack-synthesizer.ts index 2971c6c0fceff..19d0aaeee9be3 100644 --- a/packages/aws-cdk-lib/aws-servicecatalog/lib/private/product-stack-synthesizer.ts +++ b/packages/aws-cdk-lib/aws-servicecatalog/lib/private/product-stack-synthesizer.ts @@ -30,7 +30,7 @@ export class ProductStackSynthesizer extends cdk.StackSynthesizer { cdk.Annotations.of(parentStack).addWarning('[WARNING] Bucket Policy Permissions cannot be added to' + ' referenced Bucket. Please make sure your bucket has the correct permissions'); } - this.bucketDeployment = new BucketDeployment(parentStack, 'AssetsBucketDeployment', { + this.bucketDeployment = (parentStack.node.findChild('AssetsBucketDeployment') as BucketDeployment) ?? new BucketDeployment(parentStack, `${cdk.Names.uniqueId(this.boundStack)}-AssetsBucketDeployment`, { sources: [Source.asset(assetPath)], destinationBucket: this.assetBucket, extract: false, diff --git a/packages/aws-cdk-lib/aws-servicecatalog/test/product-stack.test.ts b/packages/aws-cdk-lib/aws-servicecatalog/test/product-stack.test.ts index 60d24e527c629..0f74c58f493d6 100644 --- a/packages/aws-cdk-lib/aws-servicecatalog/test/product-stack.test.ts +++ b/packages/aws-cdk-lib/aws-servicecatalog/test/product-stack.test.ts @@ -145,6 +145,45 @@ describe('ProductStack', () => { }).toThrow('A bucketName must be provided to use Assets'); }); + test('can be deployed with multiple assets bucket', () => { + // GIVEN + const app = new cdk.App( + { outdir: 'cdk.out' }, + ); + const mainStack = new cdk.Stack(app, 'MyStack'); + const testAssetBucket = new s3.Bucket(mainStack, 'TestAssetBucket', { + bucketName: 'test-asset-bucket', + }); + const productStack = new servicecatalog.ProductStack(mainStack, 'MyProductStack', { + assetBucket: testAssetBucket, + }); + + new lambda.Function(productStack, 'HelloHandler', { + runtime: lambda.Runtime.PYTHON_3_9, + code: lambda.Code.fromAsset(path.join(__dirname, 'assets')), + handler: 'index.handler', + }); + + const productStack2 = new servicecatalog.ProductStack(mainStack, 'MyProductStack2', { + assetBucket: testAssetBucket, + }); + + new lambda.Function(productStack2, 'HelloHandler2', { + runtime: lambda.Runtime.PYTHON_3_9, + code: lambda.Code.fromAsset(path.join(__dirname, 'assetsv2')), + handler: 'index.handler', + }); + + // WHEN + const whenAction = () => { + app.synth(); + }; + + // THEN + expect(whenAction).not.toThrow(/There is already a Construct with name/); + Template.fromStack(mainStack).resourcePropertiesCountIs('Custom::CDKBucketDeployment', {}, 2); + }); + test('fails if Asset bucket is not defined in product stack with assets', () => { // GIVEN const app = new cdk.App();