-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(servicecatalog): Add Product Stack Asset Support #22143
Changes from all commits
86b14f6
e245852
37d12c3
0b84503
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,8 @@ | ||
import { BlockPublicAccess, BucketEncryption, IBucket } from '@aws-cdk/aws-s3'; | ||
import * as cdk from '@aws-cdk/core'; | ||
import { ProductStack } from '../product-stack'; | ||
import { ProductStackAssetBucket } from '../product-stack-asset-bucket'; | ||
import { hashValues } from './util'; | ||
|
||
/** | ||
* Deployment environment for an AWS Service Catalog product stack. | ||
|
@@ -7,6 +11,12 @@ import * as cdk from '@aws-cdk/core'; | |
*/ | ||
export class ProductStackSynthesizer extends cdk.StackSynthesizer { | ||
private stack?: cdk.Stack; | ||
private assetBucket?: IBucket; | ||
|
||
constructor(assetBucket?: IBucket) { | ||
super(); | ||
this.assetBucket = assetBucket; | ||
} | ||
|
||
public bind(stack: cdk.Stack): void { | ||
if (this.stack !== undefined) { | ||
|
@@ -15,8 +25,31 @@ export class ProductStackSynthesizer extends cdk.StackSynthesizer { | |
this.stack = stack; | ||
} | ||
|
||
public addFileAsset(_asset: cdk.FileAssetSource): cdk.FileAssetLocation { | ||
throw new Error('Service Catalog Product Stacks cannot use Assets'); | ||
public addFileAsset(asset: cdk.FileAssetSource): cdk.FileAssetLocation { | ||
if (!this.stack) { | ||
throw new Error('You must call bindStack() first'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this message will reach the user. Do you mean to tell your user to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the error we throw in our |
||
} | ||
|
||
if (!this.assetBucket) { | ||
const parentStack = (this.stack as ProductStack)._getParentStack(); | ||
this.assetBucket = new ProductStackAssetBucket(parentStack, `ProductStackAssetBucket${hashValues(this.stack.stackName)}`, { | ||
bucketName: (this.stack as ProductStack)._generateBucketName(), | ||
blockPublicAccess: BlockPublicAccess.BLOCK_ALL, | ||
encryption: BucketEncryption.KMS, | ||
removalPolicy: cdk.RemovalPolicy.RETAIN, | ||
}); | ||
} | ||
|
||
(this.stack as ProductStack)._setAssetBucket(this.assetBucket); | ||
(this.assetBucket as ProductStackAssetBucket)._addAsset(asset); | ||
|
||
const bucketName = this.assetBucket.bucketName; | ||
const s3Filename = asset.fileName?.split('.')[1] + '.zip'; | ||
const objectKey = `${s3Filename}`; | ||
const s3ObjectUrl = `s3://${bucketName}/${objectKey}`; | ||
const httpUrl = `https://s3.${bucketName}/${objectKey}`; | ||
|
||
return { bucketName, objectKey, httpUrl, s3ObjectUrl, s3Url: httpUrl }; | ||
} | ||
|
||
public addDockerImageAsset(_asset: cdk.DockerImageAssetSource): cdk.DockerImageAssetLocation { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Bucket, BucketProps } from '@aws-cdk/aws-s3'; | ||
import { BucketDeployment, ISource, Source } from '@aws-cdk/aws-s3-deployment'; | ||
import * as cdk from '@aws-cdk/core'; | ||
import { Construct, IConstruct } from 'constructs'; | ||
|
||
/** | ||
* Product stack asset bucket props. | ||
*/ | ||
export interface ProductStackAssetBucketProps extends BucketProps { | ||
} | ||
|
||
/** | ||
* A Service Catalog product stack asset bucket, which is similar in form to an Amazon S3 bucket. | ||
* You can store multiple product stack assets and collectively deploy them to S3. | ||
*/ | ||
export class ProductStackAssetBucket extends Bucket { | ||
private readonly assets: ISource[]; | ||
|
||
constructor(scope: Construct, id: string, props: ProductStackAssetBucketProps = {}) { | ||
super(scope, id, props); | ||
|
||
if (props.bucketName == undefined) { | ||
throw new Error('BucketName must be defined for assetBucket'); | ||
} | ||
|
||
this.assets = []; | ||
|
||
cdk.Aspects.of(this).add({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the reasoning behind using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be done without Aspects I believe, but Aspects fits the use case and allows us to cleanly implement our use case as well as abstract the additional code to the new |
||
visit(c: IConstruct) { | ||
if (c instanceof ProductStackAssetBucket) { | ||
c.deployAssets(); | ||
}; | ||
}, | ||
}); | ||
} | ||
|
||
/** | ||
* Asset are prepared for bulk deployment to S3. | ||
* @internal | ||
*/ | ||
public _addAsset(asset: cdk.FileAssetSource): void { | ||
const assetPath = './cdk.out/' + asset.fileName; | ||
this.assets.push(Source.asset(assetPath)); | ||
} | ||
|
||
/** | ||
* Deploy all assets to S3. | ||
*/ | ||
private deployAssets() { | ||
if (this.assets.length > 0) { | ||
new BucketDeployment(this, 'AssetsBucketDeployment', { | ||
sources: this.assets, | ||
destinationBucket: this, | ||
extract: false, | ||
prune: false, | ||
}); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How are you granting access on the other side? The IAM role that gets from these buckets needs
access to be granted access to the bucket in its princial policy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in my other comment, but there is not much more we can do. We made it as easy as possible but we don't have access to the accounts it is being shared with, it is up to the Admin to configure these spoke accounts.