aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code

Home Page:https://aws.amazon.com/cdk

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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 the componentVersion 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.