Skip to content
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

Add a way to write properties from resources to a file in S3 #3257

Open
plumdog opened this issue Jul 9, 2019 · 14 comments
Open

Add a way to write properties from resources to a file in S3 #3257

plumdog opened this issue Jul 9, 2019 · 14 comments
Labels
@aws-cdk/aws-s3-deployment effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2

Comments

@plumdog
Copy link
Contributor

plumdog commented Jul 9, 2019

🚀 feature request

Some way of writing some of the values from resources to a file in S3.

Eg, something like:

const myBucket = new s3.Bucket(this, 'MyBucket');
new s3deploy.BucketDeployment(this, 'MyConfigFile', {
    source: s3deploy.Source.fromString(`{"thisBucketArn": "${myBucket.bucketArn}"}`),
    destinationBucket: myBucket,
    destinationKeyPrefix: 'config.json',
});

should deploy the bucket, then write the ARN of the bucket to the json file in the bucket at config.json.

I suspect there's a way to do this already by abusing assets sufficiently, but I haven't been able to make it work. The closest I can get is to write the variables into the source for a lambda and access them using API gateway, but that seems silly.

@plumdog plumdog added the needs-triage This issue or PR still needs to be triaged. label Jul 9, 2019
@plumdog
Copy link
Contributor Author

plumdog commented Jul 9, 2019

Some more digging suggests to me that this might not be possible at present by hacking at assets, as assets are copied to a staging directory (session.assembly.outdir) at synthesize. Is there perhaps instead a way of handling this using Fn.sub?

@fimbulvetr
Copy link

This should help you get some of the way. It doesn't seem to support dynamically writing content, but it does support writing a file you have locally to an s3 bucket of your choice.

https://github.com/awslabs/aws-cdk/blob/master/packages/%40aws-cdk/aws-s3-deployment/README.md

If it were me, I would write the contents to the "Metadata" of a resource, which would give you the feature of allowing the metadata to be Fn::Sub'd (and therefore ${myBucket.bucketArn} would be evaluated). Then I'd have a lambda read from that resource's metadata and put it into an S3 bucket. This is, from a high level, exactly how cfn-init works - it reads the Fn::Sub'd text from a resource's Metadata.

@plumdog
Copy link
Contributor Author

plumdog commented Jul 9, 2019

I did manage to handle this using the rather marvellous AwsCustomResource in @aws-cdk/custom-resources:

const config = {
  myBucketArn = myBucket.bucketArn,
};
new customResources.AwsCustomResource(this, 'WriteS3ConfigFile', {
  onUpdate: {
    service: 'S3',
    action: 'putObject',
    parameters: {
      Body: JSON.stringify(config),
      Bucket: myBucket.bucketName,
      Key: 'config.json',
    },
    physicalResourceId: Date.now().toString(),  // always write this file
  },
  // we need this because we're not doing conventional resource creation
  policyStatements: [
    new iam.PolicyStatement({
       actions: ['s3:PutObject'],
       resources: [`${myBucket.bucketArn}/config.json`],
    }),
  ],
});

Whether the right thing to do is:
a) bundling this up a reusable construct
b) writing something bespoke (I don't know enough about the internal to know what that would be)
c) documenting this a workaround
d) not bothering with either

I'm not sure. I suppose if this is functionality that lots of people might require, then a or b. If only a few, then c. If very very few (or just me), then d.

@rix0rrr
Copy link
Contributor

rix0rrr commented Jul 10, 2019

It's not S3, so I don't know how hard your requirement is on that, but the SSM Parameter Store is intended exactly for storing this kind of configuration data.

@RomainMuller RomainMuller added the feature-request A feature should be added or improved. label Aug 26, 2019
@SomayaB SomayaB added @aws-cdk/aws-s3 Related to Amazon S3 and removed needs-triage This issue or PR still needs to be triaged. labels Oct 1, 2019
@eladb eladb assigned iliapolo and unassigned eladb Jan 23, 2020
@iliapolo iliapolo added the effort/medium Medium work item – several days of effort label Mar 16, 2020
@djorg83
Copy link

djorg83 commented Jun 6, 2020

I created a class that allows you to provide a template for a JSON config file that you would like to be written to S3, for use with static website deployments.

How it works...

  1. You provide it a template that can include placeholders for SSM parameters.
{
  apiUrl: '{{ssm:yourParameterName}}'
}
  1. You provide it the source for the lambda function that produces the JSON config. You can find a working example here

  2. It creates the CDK constructs for the lambda function, role, and policy. Grants permission to access the required ssm parameters. Grants permission to write the JSON file to S3. Grants permission to create a new invalidation in CloudFront. Then creates a custom resource to orchestrate the deployment.

  3. When the stack is deployed, the lambda function is invoked. The SSM parameters are retrieved and substituted into the provided template. The resulting JSON is written to S3. A new invalidation for the created file is made to CloudFront.

Basic Example
new StaticWebsiteAppConfig(
  this,
  'UiAppConfig',
  {
    accountId,
    stage,
    region,
    providerFunctionCodePath: join(__dirname, '/lambda/app-config-producer'),
    bucketName: yourStaticWebsiteBucket.bucketName,
    distributionId: yourCloudFrontDistribution.distributionId,
    configTemplate: {
      apiUrl: '{{ssm:yourParameterName}}'
    },
  }
);

Full working example and source code for lambda function

https://gist.github.com/djorg83/11fc8cba5c37c9c7d89b108f9e42d2db

@iliapolo
Copy link
Contributor

iliapolo commented Jul 7, 2020

@djorg83 The StaticWebsiteAppConfig construct looks cool. I'm having second thoughts though about the place of such functionality in the core modules. The only module I feel might include this is @aws-cdk/aws-cloudfront, but even then, it seems a little too specific and involves a lot of moving parts.

We are currently actively working on redesigning (which we would love feedback on) the CloudFront module. As part of that work, we are considering vending an L3 library that makes it super easy to implement the StaticWebsite use-case. I think this construct will fit nicely in that library.

Until then, I suggest you publish this as a third-party reusable library. You already have the code ready, and it should be fairly easy to setup the publishing scaffolding, see Publishing Modules.

I'll also be happy to offer a review on that code and help in any way I can.

Thoughts?

@iliapolo iliapolo added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. guidance Question that needs advice or information. and removed effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. labels Jul 7, 2020
@github-actions
Copy link

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added the closing-soon This issue will automatically close in 4 days unless further comments are made. label Jul 15, 2020
@iliapolo
Copy link
Contributor

Don't close

@github-actions github-actions bot removed closing-soon This issue will automatically close in 4 days unless further comments are made. response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. labels Jul 16, 2020
@SomayaB
Copy link
Contributor

SomayaB commented Aug 6, 2020

Closing this for now as there doesn't seem to be any more actionable steps. Here's a link to the Cloudfront tracking issue and redesign RFC. Feel free to reopen.

@SomayaB SomayaB closed this as completed Aug 6, 2020
@rix0rrr
Copy link
Contributor

rix0rrr commented Dec 2, 2020

Reopening. I've just ran into the need for this as well, and I actually feel that the @aws-cdk/aws-s3-deployment module would be a good location for it.

@rix0rrr rix0rrr reopened this Dec 2, 2020
@iliapolo iliapolo added the needs-triage This issue or PR still needs to be triaged. label Dec 3, 2020
@SomayaB SomayaB added feature-request A feature should be added or improved. @aws-cdk/aws-s3-deployment and removed guidance Question that needs advice or information. @aws-cdk/aws-s3 Related to Amazon S3 labels Dec 7, 2020
@iliapolo iliapolo added effort/medium Medium work item – several days of effort p2 and removed needs-triage This issue or PR still needs to be triaged. labels Dec 29, 2020
@iliapolo iliapolo removed their assignment Jun 27, 2021
@jagregory
Copy link

+1 I think the s3 deployment would be a good place for this too. I'm uploading a bunch of files with a deployment, but I'd like one of them to be templated with information from the deployment (think environment name, S3 bucket URL etc).

@eladb
Copy link
Contributor

eladb commented Aug 29, 2021

I've been experimenting with something like this. Will report back in the coming weeks with some ideas.

@fjmacagno
Copy link

I have a similar use case, local directory of template files i want to substitute configs into and upload to S3.

There is also this ticket, but it is for a subtly different thing: #12903

@moltar
Copy link
Contributor

moltar commented Oct 16, 2021

I like the idea of s3deploy.Source.fromString( pattern, and that is what I was expecting to find in the intellisense.

And I think this sort-a exists already, but it's not a published package, just an example:

https://docs.aws.amazon.com/cdk/api/latest/docs/custom-resources-readme.html#provider-framework-examples

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-s3-deployment effort/medium Medium work item – several days of effort feature-request A feature should be added or improved. p2
Projects
None yet
Development

No branches or pull requests