aws-s3-deployment: BucketDeployment cannot be used as dependency for L1 resources
megakoresh opened this issue · comments
Describe the feature
We should be able to call addDepenedency(bucketDeployment)
on L1 resources that depend on a bucket deployment, but it does not currently work.
Use Case
Right now, e.g. cases where an L1 resource depends on an S3 objects (such as Greengrassv2 ComponentVersions) are unsupported, as the BucketDeployment is some kind of special resource that does not implement the interfaces of the CfnResource
, including also on it's node.defaultChild
property. This makes it impossible to use the BucketDeployment with such resources, as they require the S3 object to already exist before they can be created.
Proposed Solution
I think node.defaultChild
property of the BucketDeployment should implement CfnResource interface because its just a custom resource and those can be used as dependencies in Cloudformation, right?
Other Information
I was able to use this hack as a workaround:
const recipie = this.generateGGv2Recipie();
const depl = new BucketDeployment(this, "GGv2RunScript", {
sources: [
Source.asset(path.join(__dirname, "..", "..", "..", "src"), {
ignoreMode: cdk.IgnoreMode.GIT,
exclude: ["*", "!ggv2-run.sh"],
assetHash: recipie,
})
],
destinationBucket: Bucket.fromBucketName(this, "ComponentsBucket", cfg.componentsBucketName),
// its required to make sure the path to file is predictable because greengrass needs full path to the file in the recipie and the file to exist at the given location before the componentversion can be created
destinationKeyPrefix: "/my/prefix/",
extract: true
});
const componentVersion = new ggv2.CfnComponentVersion(this, "MyComponent", {
inlineRecipe: recipie,
});
Dependable.implement(depl, {dependencyRoots: [depl]})
componentVersion.node.addDependency(depl)
Acknowledgements
- I may be able to implement this feature request
- This feature might incur a breaking change
CDK version used
2.147.0
Environment details (OS name and version, etc.)
Ubuntu 22.04, AMD64
BucketDeployment is actually a L2 Construct, not a L1 resource.
When we cdk synth
in to CFN template, we can't have a CfnResource DependOn a L2 construct.
But it would be possible to have the L1 depend on the custom resource behind the BucketDeployment.
Consider the example
export class DummyStack extends Stack {
readonly cluster: rds.DatabaseCluster;
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const depl = new BucketDeployment(this, 'Deploy', {
sources: [
s3d.Source.asset(path.join(__dirname, '../lambda'), {
exclude: ["*", "!ggv2-run.sh"],
})
],
destinationBucket: s3.Bucket.fromBucketName(this, "ComponentsBucket", 'dummy-bucket-name'),
})
const cr = depl.node.tryFindChild('CustomResource') as CfnCustomResource
const cfnresource = new CfnResource(this, 'dummy-cfnresource', {
type: 'AWS::Foo::Bar',
properties: {
Foo: 'Bar',
},
})
cfnresource.node.addDependency(cr);
}
}
run cdk synth
, you should see the DependsOn like this:
dummycfnresource:
Type: AWS::Foo::Bar
Properties:
Foo: Bar
DependsOn:
- DeployCustomResource218AF6A4
Your workaround seems interesting:
Dependable.implement(depl, {dependencyRoots: [depl]})
componentVersion.node.addDependency(depl)
Can you run cdk synth
and see what resource the componentVersion
would literally depend on?
Can you run
cdk synth
and see what resource thecomponentVersion
would literally depend on?
It produces the following dependencies
"DependsOn": [
"OpcuaEmulatorRunScriptAwsCliLayer53E1CB2F",
"OpcuaEmulatorRunScriptCustomResourceA772EB9D"
]
The second one is the bucket deployment and the first is some kind of layer with aws cli command I guess? Idk... But I think its used by the bucket deployment lambda.