-
Notifications
You must be signed in to change notification settings - Fork 421
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
Extending Copilot with the CDK #4208
Comments
For an alternative proposal that uses simple CloudFormation YAML patches, see #4209! |
I really love this! The only addition I'd have is to take it even further. A lot of the power of the CDK is high level abstractions, so it'd be nice to have a Copilot abstraction that takes care of details like knowing where/how to template include and possibly having opinionated/type-safe ways of getting templated resources. |
Hi @RichiCoder1 👋 Thanks for the feedback! Are you thinking of something along these lines: import * as copilot from 'aws-copilot-lib';
const props = copilot.buildPropsFromManifest('../manifest.yml');
const lbws = new copilot.LoadBalancedWebService(this, 'Web', props);
const service = lbws.getService(); // returns L2 ECS service construct. One benefit that I can think of with this route is that it would allow you to compose CDK apps made out of Copilot abstractions 👍.
For clarification, when running constructor (scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
this.template = new cdk.cloudformation_include.CfnInclude(this, 'Template', {
templateFile: path.join('.build', 'in.yaml'),
}); And everytime
Similarly, Copilot will scaffold the following line: const service = this.template.getResource("Service") as ecs.CfnService; The service variable is now a type-safe L1 CDK construct: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ecs.CfnService.html Do these responses mitigate your concerns? |
I think this is great! I have a few questions/comments:
|
Hello @benjaminpottier! I can probably answer your second question - inviting @efekarakus for the other two!
You should be able to run |
That answers my question. Thank you! And yes, diff would be helpful. |
We are currently planning to use copilot in "compliance environments" (UK Public Sector), where individual development teams have limited access to AWS APIs (i.e. no ability to apply CF from local terminal). What this looks like is using Copilot strategically as a tool as part of a larger "platform offering" from a centralised platform team. I do wonder how these advanced override features will evolve over time and be suitable in those scenarios. My current view is that there would either need to be an abstraction around copilot, or some sort of copilot-managed concept that groups "Applications" into a wider platform, and allows cross-cutting changes to be applied to many teams copilot managed services. |
Hi @bpottier, @craigjbass !
We can happily share a pre-release binary here before submission to get early feedback on the feature, that's a great idea 👍
That's really interesting, we can definitely create a L3 construct that takes the same manifest file as an object as input. Similar to in this comment: const lbws = new copilot.LoadBalancedWebService(this, 'Web', {
http: {
path: '/',
targetPort: 80,
},
image: {
build: './Dockerfile',
},
}); Are you inclined for this abstraction so that you can have all your infrastructure defined in the CDK? Perhaps that would be a better fit for a
|
Yes, although I wonder how we'd enforce that without simply not providing the Copilot CLI to teams. I can see a benefit in giving some but not all of the functionality of the Copilot CLI directly to dev teams. (Mostly around operability)
Unclear yet. Ideally, they would just use the copilot manifest, but if we can't put in the relevant controls - they will probably commit a manifest that a custom tool will read to produce the copilot manifest. Examples of areas where this might be beneficial are for applying security groups without referencing a security group by ID.
Yes but also in restricting the scope of the contract between platform and dev teams. |
That totally makes sense. If we want dev teams to be able to modify infrastructure, but only limited to particular actions and resources, I think we need to put some more thought into it. 💭 |
IAM Role boundaries look good - although it doesn't seem possible to apply that to an existing app? |
In terms of bringing this back on topic to CDK extensions.
Looking at this as a "Platform in a Box" capability of Copilot, what would be ideal is if Copilot allowed a central platform team to define templated "bits of infrastructure" which can be turned on and off inside the manifest yaml with something as simple as a boolean flag. Cross-cutting definitions of infrastructure, rather than giving dev teams the keys to AWS itself. |
That is the case indeed today.
👍 We have plans in the future, using CDK extensions, for platform teams to define their own "Custom" manifests. Something like:
If I'm understanding correctly that seems to fit into the use case you're describing. Our plan is to allow platform engineers to register a custom Side note: have you explored AWS Proton? They're specializing specifically for this usecase. They provide some advanced functionality too for platform teams such as monitoring the version of the services that are deployed across environments. If you have any questions for them, you can post here. |
Hey all! I just added a design proposal to add a |
Apologies for the very late reply, wanted to follow up!
That would be interesting, but would also likely conflict with the pre-existing ECS Patterns and ECS Service Extensions. I could see still creating them as an eject option or slightly better maintained alternative however.
My thought process was that since Copilot (roughly) knows the shape of the template, instead of using raw keys and casting to the correct L1, copilot could expose an abstraction that surfaces these L1's as properties. Something like: constructor (scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// This construct already knows where the template lives, but you can optionally override it.
this.generated = new copilot.GeneratedTemplate(this, "Template" /*, { ... } */);
// template.service is an L1 Service
customTransform(this.genereted.service);
// or to work with the raw bits
this.generated.template
} With that above stated I like the above ideas where while CDK handles the meat of the synth and deployment, Copilot still provides value via developer niceties like log tailing, debug assistance, etc... |
That makes a lot of sense! It reminds me of how Amplify overrides work (example) |
Thanks @PedroAlvarado for the awesome diagram 😍 ! I have a few questions if you don't mind 🙇
This is really interesting, because it makes it sound like you would like to customize the CLI itself, say by changing the UI or commands, (like here) and not just the infrastructure. |
Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
I couldn't find a way to write a unit test that ensures the user-agent will have the extras on new requests. However, I tested the method manually in `copilot app show` and I can see the new extras added on requests. Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Support rendering `overrides/` dir with the CDK on `svc package` Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Update CodeBuild buildspec dependency versions and default project image, so that Copilot overrides with the CDK can be synthesized. Related #4208 By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the Apache 2.0 License.
Hi folks!! I'm really excited to say that AWS Copilot v1.27 is out and CDK extensions is now supported! 🚀
I'll close the issue now! If you have any questions, feedback, or suggestions please feel free to open new GitHub issues 🥳 |
Hi folks! This issue is a design proposal for overriding Copilot abstracted resources using the AWS Cloud Development Kit (CDK). The goal is to provide a "break the glass" mechanism to access and configure functionality that is not surfaced by Copilot manifests by leveraging the expressive power of a programming language.
Problem statement
Clients can describe their application configuration with declarative
manifest.yml
files. Manifests enable users to define their application in terms of “architecture as code” that gets transformed into AWS CloudFormation (CFN) templates by Copilot. Today, customers have the ability to define additional AWS resources with “addons” CFN templates. However, the resources encapsulated by manifests remain unmodifiable by users. We're looking into providing extension solutions for customers to self-unblock themselves and access the internal layers of Copilot.This document proposes a user experience for extending manifests with the CDK.
Proposal
Copilot will introduce a new command
copilot [noun] override
to create a CDK application that overrides Copilot resources, for example:The file structure generated by the
override
command is equivalent tocdk init
output. The only additional file created by Copilot is the hidden.build/
directory.In order to simplify onboarding with the CDK, Copilot will assist clients with installing their dependencies. On macOS and Linux, Copilot can install
npm
for customers on their local machine. On Windows, we won't be able to help customers with installingnpm
and will skip to asking them to follow the README instead. Oncenpm
is present, Copilot will runnpm install
to install the dependencies on behalf of the client.Clients have to edit only
stack.ts
file in order to implement thetransform*
methods for the selected resources. The following content will be present in the file by default:As can be seen above, Copilot will use the clouformation_include module provided by the CDK to help author transformations. This library is the CDK’s recommendation from their “Import or migrate an existing AWS CloudFormation template” guide. It enables accessing the resources hidden by the manifest as L1 constructs and ensures the CDK retains the resources on synthesis. The
CfnInclude
object is initialized from the.build/in.yaml
CFN template. This is how Copilot and the CDK communicates. Copilot writes the manifest generated CFN template under the.build/
directory, which then gets parsed by thecloudformation_include
library into a CDK construct.That's it! From this point forward,
copilot svc package
orcopilot svc deploy
will apply the overrides written instack.ts
. Under the hood, Copilot will invokecdk synth
to synthesize the transformed template and use that to deploy to the existing CFN stack.Feedback
We'd love to hear your feedback on the user experience above:
Appendix: Sample issues
Every new “capability” feature request can be boiled down to having an override functionality. I’ve captured only a sample of these to test the proposal against.
nlb
configuration to assign elastic IPs to the network load balancerReadOnlyRootFS: true
to all containers in the task definition by defaultECS::Service
definitionThe text was updated successfully, but these errors were encountered: