diff --git a/.github/ISSUE_TEMPLATE/tracking.md b/.github/ISSUE_TEMPLATE/tracking.md index 0b7af0fdc1547..f01cf2969bb9a 100644 --- a/.github/ISSUE_TEMPLATE/tracking.md +++ b/.github/ISSUE_TEMPLATE/tracking.md @@ -21,7 +21,13 @@ service’s CDK Construct Library API reference page. [AWS Docs](url) -[CDK API Reference](url) + +### Maturity: CloudFormation Resources Only + + +See the [AWS Construct Library Module Lifecycle doc](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0107-construct-library-module-lifecycle.md) for more information about maturity levels. ### Implementation: @@ -31,6 +37,7 @@ Checklist of use cases, constructs, features (such as grant methods) that will s - [ ] - [ ] --> +[CDK API Reference](url) diff --git a/README.md b/README.md index 34fdaf211c532..d3cab200be3b9 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ The CDK is available in the following languages: [API Reference](https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html) | [Examples](https://github.com/aws-samples/aws-cdk-examples) | [Getting Help](#getting-help) | -[RFCs](https://github.com/aws/aws-cdk-rfcs) +[RFCs](https://github.com/aws/aws-cdk-rfcs) | +[Roadmap](https://github.com/aws/aws-cdk/ROADMAP.md) Developers use the [CDK framework] in one of the supported programming languages to define reusable cloud components called [constructs], which @@ -122,6 +123,13 @@ We welcome community contributions and pull requests. See [CONTRIBUTING](./CONTRIBUTING.md) for information on how to set up a development environment and submit code. +## Roadmap + +The [AWS CDK Roadmap project board] lets developers know about our upcoming features and priorities to help them plan how to best leverage the CDK and identify opportunities to contribute to the project. See [ROADMAP] for more information and FAQs. + +[AWS CDK Roadmap project board]: https://github.com/orgs/aws/projects/7 +[Roadmap]: (https://github.com/aws/aws-cdk/ROADMAP.md) + ## License The AWS CDK is distributed under the [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000000000..8a8a1f18c6181 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,86 @@ +# AWS CDK Roadmap + +The [AWS CDK Roadmap] lets developers know about our upcoming features and priorities to help them plan how to best leverage the CDK and identify opportunities to contribute to the project. The roadmap provides a high-level view of our work in progress across the [aws-cdk], [aws-cdk-rfcs], and [jsii] repositories, and creates an opportunity for customers to engage in a conversation with AWS CDK engineers to give us direct feedback. + +[AWS CDK Roadmap]: https://github.com/orgs/aws/projects/7 +[aws-cdk]: https://github.com/aws/aws-cdk +[aws-cdk-rfcs]: https://github.com/aws/aws-cdk-rfcs +[jsii]: https://github.com/aws/jsii + +## Roadmap FAQs + +**Q: How do you manage the roadmap?** + +A: We know that our customers are making decisions and plans based on what we +are developing, and we want to provide the information they need to be successful. Our roadmap management tenets are: + +* **Be transparent** with customers about the AWS CDK team’s work in progress +* **Listen to customers,** allowing them to participate in design decisions and to vote on and propose new AWS CDK + features. We will periodically re-prioritize the roadmap based on customer feedback +* **Stay up-to-date,** or we will lose customer trust +* **Provide the right level of detail** so customers can easily see what we’re working on at a glance, without being + overwhelmed by minutiae +* **Guide the community** on what AWS CDK constructs or features to contribute without the risk of conflicting with work + already in progress + +**Q: What do the roadmap project board columns mean?** + +A: There are four columns on the roadmap project board: + +* **Researching** - We’re thinking about it, but cannot commit if, or when, we will work on items in this list. + This means we are still designing the feature and evaluating how it might work. This is the phase when we collect + customer use cases and feedback on how they want to see something implemented. There is no firm commitment to deliver + functionality listed in the Researching column, and there might be situations that require us to move items from the + roadmap back to the backlog. +* **We’re working on it** - In progress, but further out. We have made an implied commitment to work on items in this + bucket, they have some level of design spec’ed out, and a developer assigned to them. Items might linger in this + bucket as we work through the implementation details, or scope stuff out. Think several months out until a developer + preview release, give or take. +* **Developer preview** - It’s available now as a release candidate. Items will spend extended periods of time in + developer preview as we conduct user acceptance testing and accumulate sufficient usage to declare the API stable and + ready for general availability. We will only make breaking changes to developer preview modules when we need to address unforeseen use cases or issues. Not all + features, such as enhancements to the CDK CLI, will have a developer preview phase. In these cases the tracking issue + is moved directly to the Shipped bucket when released. +* **Shipped** - It’s available now, fully supported by AWS, and we guarantee the API is stable and safe to use in + production. + +**Q: How do items on the roadmap move across the project board?** + +A: The [AWS Construct Library module lifecycle +document](https://github.com/aws/aws-cdk-rfcs/blob/master/text/0107-construct-library-module-lifecycle.md) describes how +we graduate packages from experimental, to developer preview, to generally available. + +**Q: Why are there no dates on this roadmap?** + +A: Security and operational stability are our main priority and we will not ship a feature until these criteria are met, +therefore we generally don’t provide specific target dates for releases. + +**Q: Is every feature on the roadmap?** + +A: The AWS Cloud Development Kit roadmap provides transparency on our priority for adding new programming languages, +developer experience improvements, and service coverage in the AWS Construct Library. The AWS CDK toolkit and AWS +Construct Library are such a large surface areas we are intentionally keeping the roadmap at a high-level, so not every +CDK feature request will appear on the roadmap. Instead, the roadmap will include a tracking issue +for each deliverable that provides a feature overview and contains links to relevant, more granular issues and pull +requests. If you want to track the status of a specific issue or pull request, you can do so by monitoring that work +item in the [aws-cdk] GitHub repository. + +**Q: What is a tracking issue?** + +A: We create a tracking issue for each CDK feature, AWS Construct Library module, and jsii-supported programming language. Tracking issues provide a brief summary of the feature and a consolidated view of the work scoped for the release. They include links to design documentation, implementation details, and relevant issues. Tracking issues are living documents that start from a basic template and grow more robust over time as we experiment and learn. You can easily find tracking issues by filtering on the [management/tracking label](https://github.com/aws/aws-cdk/labels/management%2Ftracking). + +**Q: How can I provide feedback on the roadmap or ask for more information about a feature?** + +A: Please open an issue! + +**Q: How can I request a feature be added to the roadmap?** + +A: Please open an issue! Community submitted issues will be tagged “feature-request” and will be reviewed by the team. + +**Q: Can I “+1” tracking issues and feature requests?** + +A: We strongly encourage you to do so, as it helps us understand which issues will have the broadest impact. You can navigate to the issue details page and add a reaction. There are six types of reactions (thumbs up “+1”, thumbs down “-1”, confused, heart, watching, laugh, and hooray) you can use to help us decide which items will benefit you most. + +**Q: Will you accept a pull request to the aws-cdk repo?** + +A: Yes! We take PRs very seriously and will review for inclusion. You can read how to contribute to the CDK [here](https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md). diff --git a/design/aws-guidelines.md b/design/aws-guidelines.md index 2f24f59eca01a..56d0516417505 100644 --- a/design/aws-guidelines.md +++ b/design/aws-guidelines.md @@ -437,7 +437,7 @@ class ImportedFoo extends FooBase { - [ ] Metrics (`metricXxx`) - [ ] Events (`onXxx`) - [ ] Security Groups (`connections`) -- [ ] Pipeline Actions (`addToPipline`) +- [ ] Pipeline Actions (`addToPipeline`) - [ ] SNS Targets - [ ] `_asFooTarget` - [ ] TODO: other cross AWS patterns diff --git a/design/cloud-assembly.md b/design/cloud-assembly.md index 63d8d808ceda1..a1f2854abc833 100644 --- a/design/cloud-assembly.md +++ b/design/cloud-assembly.md @@ -62,7 +62,7 @@ In other words, *Logical IDs* are expected to match the following regular expres ``` ### Droplet -Clouds are made of Droplets. Thet are the building blocks of *Cloud Assemblies*. They model a part of the +Clouds are made of Droplets. They are the building blocks of *Cloud Assemblies*. They model a part of the *cloud application* that can be deployed independently, provided its dependencies are fulfilled. Droplets are specified using [JSON] objects that **MUST** conform to the following schema: @@ -197,7 +197,7 @@ Key |Type |Description Here is a schematic example: ```js { - // When this attestation doucment was created + // When this attestation document was created "timestamp": "2018-11-15T11:08:52", // The hashing algorithm for the attestation is SHA256 "algorithm": "SHA256", @@ -216,7 +216,7 @@ Here is a schematic example: ``` Once the attestation is ready, it is digitally *signed* using the configured [PGP][RFC 4880] key. The key **MUST** be -valid as of the `timestamp` field included in the attestation. The siganture **MUST** not be detached, and is +valid as of the `timestamp` field included in the attestation. The signature **MUST** not be detached, and is **RECOMMENDED** to use the *cleartext signature framework* described in section 7 of [RFC 4880] so the attestation can be read by a human. @@ -229,7 +229,7 @@ Deployment systems that support verifying signed *Cloud Assemblies*: be returned when attempting to deploy an un-signed *Cloud Assembly*. * **MUST** verify the integrity and authenticity of signed *Cloud Assemblies* prior to attempting to load any file included in it, except for `signature.asc`. - * An error **MUST** be raised if the *Cloud Assembly*'s integirty is not verified by the signature. + * An error **MUST** be raised if the *Cloud Assembly*'s integrity is not verified by the signature. * An error **MUST** be raised if the [PGP][RFC 4880] key has expired according to the signature timestamp. * An error **MUST** be raised if the [PGP][RFC 4880] key is known to have been revoked. Deployment systems **MAY** trust locally available information pertaining to the key's validity. @@ -470,4 +470,4 @@ Hash: SHA256 [ISO/IEC 21320-1:2015]: https://www.iso.org/standard/60101.html [JSON]: https://www.json.org [RFC 4880]: https://tools.ietf.org/html/rfc4880 -[ISO 8601]: https://www.iso.org/standard/40874.html \ No newline at end of file +[ISO 8601]: https://www.iso.org/standard/40874.html diff --git a/design/code-asset-metadata.md b/design/code-asset-metadata.md index 1e771754dc169..9c6366bb33af0 100644 --- a/design/code-asset-metadata.md +++ b/design/code-asset-metadata.md @@ -56,8 +56,8 @@ well as through the key `assetMetadata` in `cdk.json`. Very similar design to ho We considered alternatives that will "enforce" the embedding of metadata when an asset is referenced by a resource. Since a single asset can be referenced by multiple resources, it means that the _relationship_ is what should trigger the -metadata addition. There currently isn't support in the framework for such hooks, but there is a possiblility that -the changes in [#1436](https://github.com/aws/aws-cdk/pull/1436) might enable hooking into the relationnship, and then we might be able to use this mechanism to produce the metadata. +metadata addition. There currently isn't support in the framework for such hooks, but there is a possibility that +the changes in [#1436](https://github.com/aws/aws-cdk/pull/1436) might enable hooking into the relationship, and then we might be able to use this mechanism to produce the metadata. Having said that, the need to embed asset metadata on resources is mainly confined to authors of L2 constructs, and not applicable for the general user population, so the value of automation is not high. diff --git a/packages/@aws-cdk/aws-batch/lib/compute-environment.ts b/packages/@aws-cdk/aws-batch/lib/compute-environment.ts index 663d806f0fff7..39054245acb5c 100644 --- a/packages/@aws-cdk/aws-batch/lib/compute-environment.ts +++ b/packages/@aws-cdk/aws-batch/lib/compute-environment.ts @@ -51,11 +51,33 @@ export enum AllocationStrategy { */ export interface ComputeResources { /** - * The IAM role applied to EC2 resources in the compute environment. + * The allocation strategy to use for the compute resource in case not enough instances of the best + * fitting instance type can be allocated. This could be due to availability of the instance type in + * the region or Amazon EC2 service limits. If this is not specified, the default for the EC2 + * ComputeResourceType is BEST_FIT, which will use only the best fitting instance type, waiting for + * additional capacity if it's not available. This allocation strategy keeps costs lower but can limit + * scaling. If you are using Spot Fleets with BEST_FIT then the Spot Fleet IAM Role must be specified. + * BEST_FIT_PROGRESSIVE will select an additional instance type that is large enough to meet the + * requirements of the jobs in the queue, with a preference for an instance type with a lower cost. + * The default value for the SPOT instance type is SPOT_CAPACITY_OPTIMIZED, which is only available for + * for this type of compute resources and will select an additional instance type that is large enough + * to meet the requirements of the jobs in the queue, with a preference for an instance type that is + * less likely to be interrupted. + * + * @default AllocationStrategy.BEST_FIT + */ + readonly allocationStrategy?: AllocationStrategy; + + /** + * The Amazon ECS instance profile applied to Amazon EC2 instances in a compute environment. You can specify + * the short name or full Amazon Resource Name (ARN) of an instance profile. For example, ecsInstanceRole or + * arn:aws:iam:::instance-profile/ecsInstanceRole . For more information, see Amazon ECS + * Instance Role in the AWS Batch User Guide. * * @default - a new role will be created. + * @link https://docs.aws.amazon.com/batch/latest/userguide/instance_IAM_role.html */ - readonly instanceRole?: iam.IRole; + readonly instanceRole?: string; /** * The types of EC2 instances that may be launched in the compute environment. You can specify instance @@ -70,7 +92,7 @@ export interface ComputeResources { /** * The EC2 security group(s) associated with instances launched in the compute environment. * - * @default AWS default security group. + * @default - AWS default security group. */ readonly securityGroups?: ec2.ISecurityGroup[]; @@ -133,7 +155,7 @@ export interface ComputeResources { * The EC2 key pair that is used for instances launched in the compute environment. * If no key is defined, then SSH access is not allowed to provisioned compute resources. * - * @default - No SSH access will be possible. + * @default - no SSH access will be possible. */ readonly ec2KeyPair?: string; @@ -169,40 +191,25 @@ export interface ComputeResources { * Properties for creating a new Compute Environment */ export interface ComputeEnvironmentProps { - /** - * The allocation strategy to use for the compute resource in case not enough instances ofthe best - * fitting instance type can be allocated. This could be due to availability of the instance type in - * the region or Amazon EC2 service limits. If this is not specified, the default is BEST_FIT, which - * will use only the best fitting instance type, waiting for additional capacity if it's not available. - * This allocation strategy keeps costs lower but can limit scaling. If you are using Spot Fleets with - * BEST_FIT then the Spot Fleet IAM Role must be specified. BEST_FIT_PROGRESSIVE will select an additional - * instance type that is large enough to meet the requirements of the jobs in the queue, with a preference - * for an instance type with a lower cost. SPOT_CAPACITY_OPTIMIZED is only available for Spot Instance - * compute resources and will select an additional instance type that is large enough to meet the requirements - * of the jobs in the queue, with a preference for an instance type that is less likely to be interrupted. - * - * @default AllocationStrategy.BEST_FIT - */ - readonly allocationStrategy?: AllocationStrategy; - /** * A name for the compute environment. * * Up to 128 letters (uppercase and lowercase), numbers, hyphens, and underscores are allowed. * - * @default Cloudformation-generated name + * @default - CloudFormation-generated name */ readonly computeEnvironmentName?: string; /** - * The details of the compute resources managed by this environment. + * The details of the required compute resources for the managed compute environment. * - * If specified, and this is an managed compute environment, the property will be ignored. + * If specified, and this is an unmanaged compute environment, will throw an error. * * By default, AWS Batch managed compute environments use a recent, approved version of the * Amazon ECS-optimized AMI for compute resources. * - * @default - AWS-managed compute resources + * @default - CloudFormation defaults + * @link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-computeresources.html */ readonly computeResources?: ComputeResources; @@ -302,19 +309,29 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment const spotFleetRole = this.getSpotFleetRole(props); let computeResources: CfnComputeEnvironment.ComputeResourcesProperty | undefined; - // Only allow compute resources to be set when using UNMANAGED type - if (props.computeResources && !this.isManaged(props)) { + // Only allow compute resources to be set when using MANAGED type + if (props.computeResources && this.isManaged(props)) { computeResources = { - allocationStrategy: props.allocationStrategy || AllocationStrategy.BEST_FIT, + allocationStrategy: props.computeResources.allocationStrategy + || ( + props.computeResources.type === ComputeResourceType.SPOT + ? AllocationStrategy.SPOT_CAPACITY_OPTIMIZED + : AllocationStrategy.BEST_FIT + ), bidPercentage: props.computeResources.bidPercentage, desiredvCpus: props.computeResources.desiredvCpus, ec2KeyPair: props.computeResources.ec2KeyPair, imageId: props.computeResources.image && props.computeResources.image.getImage(this).imageId, instanceRole: props.computeResources.instanceRole - ? props.computeResources.instanceRole.roleArn - : new iam.Role(this, 'Resource-Instance-Role', { - assumedBy: new iam.ServicePrincipal('batch.amazonaws.com'), - }).roleArn, + ? props.computeResources.instanceRole + : new iam.CfnInstanceProfile(this, 'Instance-Profile', { + roles: [ new iam.Role(this, 'Ecs-Instance-Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), + managedPolicies: [ + iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role') + ] + }).roleName] + }).attrArn, instanceTypes: this.buildInstanceTypes(props.computeResources.instanceTypes), maxvCpus: props.computeResources.maxvCpus || 256, minvCpus: props.computeResources.minvCpus || 0, @@ -338,7 +355,7 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment assumedBy: new iam.ServicePrincipal('batch.amazonaws.com'), }).roleArn, state: props.enabled === undefined ? 'ENABLED' : (props.enabled ? 'ENABLED' : 'DISABLED'), - type: this.isManaged(props) ? 'UNMANAGED' : 'MANAGED', + type: this.isManaged(props) ? 'MANAGED' : 'UNMANAGED', }); if (props.computeResources && props.computeResources.vpc) { @@ -365,12 +382,12 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment return; } - if (this.isManaged(props) && props.computeResources !== undefined) { - throw new Error('It is not allowed to set computeResources on an AWS managed compute environment'); + if (!this.isManaged(props) && props.computeResources !== undefined) { + throw new Error('It is not allowed to set computeResources on an AWS unmanaged compute environment'); } - if (!this.isManaged(props) && props.computeResources === undefined) { - throw new Error('computeResources is missing but required on an unmanaged compute environment'); + if (this.isManaged(props) && props.computeResources === undefined) { + throw new Error('computeResources is missing but required on a managed compute environment'); } // Setting a bid percentage is only allowed on SPOT resources + @@ -385,7 +402,7 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment } // SPOT_CAPACITY_OPTIMIZED allocation is not allowed - if (props.allocationStrategy && props.allocationStrategy === AllocationStrategy.SPOT_CAPACITY_OPTIMIZED) { + if (props.computeResources.allocationStrategy && props.computeResources.allocationStrategy === AllocationStrategy.SPOT_CAPACITY_OPTIMIZED) { throw new Error('The SPOT_CAPACITY_OPTIMIZED allocation strategy is only allowed if the environment is a SPOT type compute environment'); } } else { @@ -440,7 +457,7 @@ export class ComputeEnvironment extends Resource implements IComputeEnvironment * @param props - the compute environment construct properties */ private getSpotFleetRole(props: ComputeEnvironmentProps): iam.IRole | undefined { - if (props.allocationStrategy && props.allocationStrategy !== AllocationStrategy.BEST_FIT) { + if (props.computeResources?.allocationStrategy && props.computeResources.allocationStrategy !== AllocationStrategy.BEST_FIT) { return undefined; } diff --git a/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts b/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts index 18cd77e5f3b15..fcee90c1ef92f 100644 --- a/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts +++ b/packages/@aws-cdk/aws-batch/test/compute-environment.test.ts @@ -1,11 +1,11 @@ -import { expect, haveResource, haveResourceLike, ResourcePart } from '@aws-cdk/assert'; +import {expect, haveResource, haveResourceLike, ResourcePart} from '@aws-cdk/assert'; import '@aws-cdk/assert/jest'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; -import { throws } from 'assert'; -import * as batch from '../lib'; +import {throws} from 'assert'; +import * as batch from "../lib"; describe('Batch Compute Evironment', () => { let expectedManagedDefaultComputeProps: any; @@ -34,7 +34,7 @@ describe('Batch Compute Evironment', () => { AllocationStrategy: batch.AllocationStrategy.BEST_FIT, InstanceRole: { 'Fn::GetAtt': [ - 'testcomputeenvResourceInstanceRole7FD819B9', + 'testcomputeenvInstanceProfileCBD87EAB', 'Arn' ] }, @@ -59,37 +59,39 @@ describe('Batch Compute Evironment', () => { }); describe('when validating props', () => { - test('should deny setting compute resources when using type managed', () => { + test('should deny setting compute resources when using type unmanaged', () => { // THEN throws(() => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { + managed: false, computeResources: { - vpc, + vpc }, }); }); }); - test('should deny if creating an unmanged environment with no provided compute resource props', () => { + test('should deny if creating a managed environment with no provided compute resource props', () => { // THEN throws(() => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, }); }); }); }); describe('using spot resources', () => { - test('should provide a spotfleet role if one is not given', () => { + test('should provide a spot fleet role if one is not given and allocationStrategy is BEST_FIT', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { type: batch.ComputeResourceType.SPOT, - vpc, + allocationStrategy: batch.AllocationStrategy.BEST_FIT, + vpc }, }); @@ -124,7 +126,7 @@ describe('Batch Compute Evironment', () => { throws(() => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, type: batch.ComputeResourceType.SPOT, @@ -139,7 +141,7 @@ describe('Batch Compute Evironment', () => { throws(() => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, type: batch.ComputeResourceType.SPOT, @@ -155,9 +157,9 @@ describe('Batch Compute Evironment', () => { test('renders the correct cloudformation properties', () => { // WHEN const props = { - allocationStrategy: batch.AllocationStrategy.BEST_FIT, computeEnvironmentName: 'my-test-compute-env', computeResources: { + allocationStrategy: batch.AllocationStrategy.BEST_FIT, vpc, computeResourcesTags: new cdk.Tag('foo', 'bar'), desiredvCpus: 1, @@ -166,9 +168,14 @@ describe('Batch Compute Evironment', () => { generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, hardwareType: ecs.AmiHardwareType.STANDARD, }), - instanceRole: new iam.Role(stack, 'test-compute-env-instance-role', { - assumedBy: new iam.ServicePrincipal('batch.amazonaws.com'), - }), + instanceRole: new iam.CfnInstanceProfile(stack, 'Instance-Profile', { + roles: [ new iam.Role(stack, 'Ecs-Instance-Role', { + assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), + managedPolicies: [ + iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role') + ] + }).roleName] + }).attrArn, instanceTypes: [ ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO), ], @@ -186,7 +193,7 @@ describe('Batch Compute Evironment', () => { }, } as batch.ComputeResources, enabled: false, - managed: false, + managed: true, }; new batch.ComputeEnvironment(stack, 'test-compute-env', props); @@ -211,7 +218,7 @@ describe('Batch Compute Evironment', () => { }, InstanceRole: { 'Fn::GetAtt': [ - props.computeResources.instanceRole ? `${props.computeResources.instanceRole.node.uniqueId}F3B86D94` : '', + props.computeResources.instanceRole ? "InstanceProfile" : '', 'Arn' ] }, @@ -251,7 +258,7 @@ describe('Batch Compute Evironment', () => { test('should default to a best_fit strategy', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, @@ -303,7 +310,7 @@ describe('Batch Compute Evironment', () => { test('should default to 0', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, @@ -323,7 +330,7 @@ describe('Batch Compute Evironment', () => { test('should default to 256', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, @@ -342,7 +349,7 @@ describe('Batch Compute Evironment', () => { test('should generate a role for me', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, @@ -358,7 +365,7 @@ describe('Batch Compute Evironment', () => { test('should default to optimal matching', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, @@ -377,7 +384,7 @@ describe('Batch Compute Evironment', () => { test('should default to EC2', () => { // WHEN new batch.ComputeEnvironment(stack, 'test-compute-env', { - managed: false, + managed: true, computeResources: { vpc, }, diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch.expected.json b/packages/@aws-cdk/aws-batch/test/integ.batch.expected.json index 7c367e0d37a08..936888ce29321 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch.expected.json +++ b/packages/@aws-cdk/aws-batch/test/integ.batch.expected.json @@ -514,7 +514,7 @@ } } }, - "batchmanagedcomputeenvResourceServiceInstanceRole3A9DC7D6": { + "batchunmanagedcomputeenvResourceServiceInstanceRoleCA40AF77": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -545,12 +545,12 @@ ] } }, - "batchmanagedcomputeenv1AA975A9": { + "batchunmanagedcomputeenvED550298": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { "ServiceRole": { "Fn::GetAtt": [ - "batchmanagedcomputeenvResourceServiceInstanceRole3A9DC7D6", + "batchunmanagedcomputeenvResourceServiceInstanceRoleCA40AF77", "Arn" ] }, @@ -558,7 +558,7 @@ "State": "ENABLED" } }, - "batchdemandcomputeenvResourceInstanceRole8989496E": { + "batchdemandcomputeenvlaunchtemplateEcsInstanceRole24D4E799": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -567,12 +567,36 @@ "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { - "Service": "batch.amazonaws.com" + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } } } ], "Version": "2012-10-17" - } + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" + ] + ] + } + ] }, "DependsOn": [ "vpcIGWE57CBDCA", @@ -610,10 +634,55 @@ "vpcVPCGW7984C166" ] }, - "batchdemandcomputeenvResourceSecurityGroup64711D4D": { + "batchdemandcomputeenvlaunchtemplateInstanceProfile2DEC3A97": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "batchdemandcomputeenvlaunchtemplateEcsInstanceRole24D4E799" + } + ] + }, + "DependsOn": [ + "vpcIGWE57CBDCA", + "vpcPrivateSubnet1DefaultRoute1AA8E2E5", + "vpcPrivateSubnet1RouteTableB41A48CC", + "vpcPrivateSubnet1RouteTableAssociation67945127", + "vpcPrivateSubnet1Subnet934893E8", + "vpcPrivateSubnet2DefaultRouteB0E07F99", + "vpcPrivateSubnet2RouteTable7280F23E", + "vpcPrivateSubnet2RouteTableAssociation007E94D3", + "vpcPrivateSubnet2Subnet7031C2BA", + "vpcPrivateSubnet3DefaultRoute30C45F47", + "vpcPrivateSubnet3RouteTable24DA79A0", + "vpcPrivateSubnet3RouteTableAssociationC58B3C2C", + "vpcPrivateSubnet3Subnet985AC459", + "vpcPublicSubnet1DefaultRoute10708846", + "vpcPublicSubnet1EIPDA49DCBE", + "vpcPublicSubnet1NATGateway9C16659E", + "vpcPublicSubnet1RouteTable48A2DF9B", + "vpcPublicSubnet1RouteTableAssociation5D3F4579", + "vpcPublicSubnet1Subnet2E65531E", + "vpcPublicSubnet2DefaultRouteA1EC0F60", + "vpcPublicSubnet2EIP9B3743B1", + "vpcPublicSubnet2NATGateway9B8AE11A", + "vpcPublicSubnet2RouteTableEB40D4CB", + "vpcPublicSubnet2RouteTableAssociation21F81B59", + "vpcPublicSubnet2Subnet009B674F", + "vpcPublicSubnet3DefaultRoute3F356A11", + "vpcPublicSubnet3EIP2C3B9D91", + "vpcPublicSubnet3NATGateway82F6CA9E", + "vpcPublicSubnet3RouteTableA3C00665", + "vpcPublicSubnet3RouteTableAssociationD102D1C4", + "vpcPublicSubnet3Subnet11B92D7C", + "vpcA2121C38", + "vpcVPCGW7984C166" + ] + }, + "batchdemandcomputeenvlaunchtemplateResourceSecurityGroup23599B84": { "Type": "AWS::EC2::SecurityGroup", "Properties": { - "GroupDescription": "batch-stack/batch-demand-compute-env/Resource-Security-Group", + "GroupDescription": "batch-stack/batch-demand-compute-env-launch-template/Resource-Security-Group", "SecurityGroupEgress": [ { "CidrIp": "0.0.0.0/0", @@ -661,7 +730,7 @@ "vpcVPCGW7984C166" ] }, - "batchdemandcomputeenvResourceServiceInstanceRole8DF7CB96": { + "batchdemandcomputeenvlaunchtemplateResourceServiceInstanceRole76AD99CC": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -727,12 +796,12 @@ "vpcVPCGW7984C166" ] }, - "batchdemandcomputeenv6131030A": { + "batchdemandcomputeenvlaunchtemplateF8A5B233": { "Type": "AWS::Batch::ComputeEnvironment", "Properties": { "ServiceRole": { "Fn::GetAtt": [ - "batchdemandcomputeenvResourceServiceInstanceRole8DF7CB96", + "batchdemandcomputeenvlaunchtemplateResourceServiceInstanceRole76AD99CC", "Arn" ] }, @@ -741,7 +810,7 @@ "AllocationStrategy": "BEST_FIT", "InstanceRole": { "Fn::GetAtt": [ - "batchdemandcomputeenvResourceInstanceRole8989496E", + "batchdemandcomputeenvlaunchtemplateInstanceProfile2DEC3A97", "Arn" ] }, @@ -753,7 +822,7 @@ "SecurityGroupIds": [ { "Fn::GetAtt": [ - "batchdemandcomputeenvResourceSecurityGroup64711D4D", + "batchdemandcomputeenvlaunchtemplateResourceSecurityGroup23599B84", "GroupId" ] } @@ -809,7 +878,7 @@ "vpcVPCGW7984C166" ] }, - "batchspotcomputeenvResourceInstanceRoleF6188F15": { + "batchspotcomputeenvEcsInstanceRoleE976826B": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { @@ -818,12 +887,81 @@ "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { - "Service": "batch.amazonaws.com" + "Service": { + "Fn::Join": [ + "", + [ + "ec2.", + { + "Ref": "AWS::URLSuffix" + } + ] + ] + } } } ], "Version": "2012-10-17" - } + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role" + ] + ] + } + ] + }, + "DependsOn": [ + "vpcIGWE57CBDCA", + "vpcPrivateSubnet1DefaultRoute1AA8E2E5", + "vpcPrivateSubnet1RouteTableB41A48CC", + "vpcPrivateSubnet1RouteTableAssociation67945127", + "vpcPrivateSubnet1Subnet934893E8", + "vpcPrivateSubnet2DefaultRouteB0E07F99", + "vpcPrivateSubnet2RouteTable7280F23E", + "vpcPrivateSubnet2RouteTableAssociation007E94D3", + "vpcPrivateSubnet2Subnet7031C2BA", + "vpcPrivateSubnet3DefaultRoute30C45F47", + "vpcPrivateSubnet3RouteTable24DA79A0", + "vpcPrivateSubnet3RouteTableAssociationC58B3C2C", + "vpcPrivateSubnet3Subnet985AC459", + "vpcPublicSubnet1DefaultRoute10708846", + "vpcPublicSubnet1EIPDA49DCBE", + "vpcPublicSubnet1NATGateway9C16659E", + "vpcPublicSubnet1RouteTable48A2DF9B", + "vpcPublicSubnet1RouteTableAssociation5D3F4579", + "vpcPublicSubnet1Subnet2E65531E", + "vpcPublicSubnet2DefaultRouteA1EC0F60", + "vpcPublicSubnet2EIP9B3743B1", + "vpcPublicSubnet2NATGateway9B8AE11A", + "vpcPublicSubnet2RouteTableEB40D4CB", + "vpcPublicSubnet2RouteTableAssociation21F81B59", + "vpcPublicSubnet2Subnet009B674F", + "vpcPublicSubnet3DefaultRoute3F356A11", + "vpcPublicSubnet3EIP2C3B9D91", + "vpcPublicSubnet3NATGateway82F6CA9E", + "vpcPublicSubnet3RouteTableA3C00665", + "vpcPublicSubnet3RouteTableAssociationD102D1C4", + "vpcPublicSubnet3Subnet11B92D7C", + "vpcA2121C38", + "vpcVPCGW7984C166" + ] + }, + "batchspotcomputeenvInstanceProfileFA613AC2": { + "Type": "AWS::IAM::InstanceProfile", + "Properties": { + "Roles": [ + { + "Ref": "batchspotcomputeenvEcsInstanceRoleE976826B" + } + ] }, "DependsOn": [ "vpcIGWE57CBDCA", @@ -989,11 +1127,11 @@ }, "Type": "MANAGED", "ComputeResources": { - "AllocationStrategy": "BEST_FIT", + "AllocationStrategy": "SPOT_CAPACITY_OPTIMIZED", "BidPercentage": 80, "InstanceRole": { "Fn::GetAtt": [ - "batchspotcomputeenvResourceInstanceRoleF6188F15", + "batchspotcomputeenvInstanceProfileFA613AC2", "Arn" ] }, @@ -1083,13 +1221,13 @@ "ComputeEnvironmentOrder": [ { "ComputeEnvironment": { - "Ref": "batchmanagedcomputeenv1AA975A9" + "Ref": "batchunmanagedcomputeenvED550298" }, "Order": 1 }, { "ComputeEnvironment": { - "Ref": "batchdemandcomputeenv6131030A" + "Ref": "batchdemandcomputeenvlaunchtemplateF8A5B233" }, "Order": 2 }, diff --git a/packages/@aws-cdk/aws-batch/test/integ.batch.ts b/packages/@aws-cdk/aws-batch/test/integ.batch.ts index c28d7d4f2e159..174e0bd5e5ba2 100644 --- a/packages/@aws-cdk/aws-batch/test/integ.batch.ts +++ b/packages/@aws-cdk/aws-batch/test/integ.batch.ts @@ -13,12 +13,14 @@ const vpc = new ec2.Vpc(stack, 'vpc'); new batch.JobQueue(stack, 'batch-job-queue', { computeEnvironments: [ { - computeEnvironment: new batch.ComputeEnvironment(stack, 'batch-managed-compute-env'), + computeEnvironment: new batch.ComputeEnvironment(stack, 'batch-unmanaged-compute-env', { + managed: false + }), order: 1, }, { - computeEnvironment: new batch.ComputeEnvironment(stack, 'batch-demand-compute-env', { - managed: false, + computeEnvironment: new batch.ComputeEnvironment(stack, 'batch-demand-compute-env-launch-template', { + managed: true, computeResources: { type: batch.ComputeResourceType.ON_DEMAND, vpc, @@ -28,7 +30,7 @@ new batch.JobQueue(stack, 'batch-job-queue', { }, { computeEnvironment: new batch.ComputeEnvironment(stack, 'batch-spot-compute-env', { - managed: false, + managed: true, computeResources: { type: batch.ComputeResourceType.SPOT, vpc, diff --git a/packages/@aws-cdk/aws-batch/test/job-queue.test.ts b/packages/@aws-cdk/aws-batch/test/job-queue.test.ts index d99a6ad82e8fe..9a20f0334a8ce 100644 --- a/packages/@aws-cdk/aws-batch/test/job-queue.test.ts +++ b/packages/@aws-cdk/aws-batch/test/job-queue.test.ts @@ -9,7 +9,9 @@ describe('Batch Job Queue', () => { beforeEach(() => { stack = new cdk.Stack(); - computeEnvironment = new batch.ComputeEnvironment(stack, 'test-compute-env'); + computeEnvironment = new batch.ComputeEnvironment(stack, 'test-compute-env', { + managed: false + }); }); it('can be imported from an ARN', () => { diff --git a/packages/@aws-cdk/aws-cloudfront/package.json b/packages/@aws-cdk/aws-cloudfront/package.json index 3f2286857b2c4..9d5e62c7f4194 100644 --- a/packages/@aws-cdk/aws-cloudfront/package.json +++ b/packages/@aws-cdk/aws-cloudfront/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-cloudtrail/package.json b/packages/@aws-cdk/aws-cloudtrail/package.json index 19eebb6179e6f..8dc324a789c65 100644 --- a/packages/@aws-cdk/aws-cloudtrail/package.json +++ b/packages/@aws-cdk/aws-cloudtrail/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index 2c0d5f565455f..9cc6a90e66e13 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -70,7 +70,7 @@ "@aws-cdk/aws-sns": "0.0.0", "@aws-cdk/aws-sqs": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index cb63fe15a0dc6..15a8ed670e9f4 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -70,7 +70,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-sns": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-dynamodb/package.json b/packages/@aws-cdk/aws-dynamodb/package.json index 9be9c2acab9cf..ad1e6435cd970 100644 --- a/packages/@aws-cdk/aws-dynamodb/package.json +++ b/packages/@aws-cdk/aws-dynamodb/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "aws-sdk-mock": "^5.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-efs/README.md b/packages/@aws-cdk/aws-efs/README.md index 6b9958d570161..c743f78786eee 100644 --- a/packages/@aws-cdk/aws-efs/README.md +++ b/packages/@aws-cdk/aws-efs/README.md @@ -17,4 +17,67 @@ --- +This construct library allows you to set up AWS Elastic File System (EFS). + +```ts +import efs = require('@aws-cdk/aws-efs'); + +const myVpc = new ec2.Vpc(this, 'VPC'); +const fileSystem = new efs.EfsFileSystem(this, 'MyEfsFileSystem', { + vpc: myVpc, + encrypted: true, + lifecyclePolicy: EfsLifecyclePolicyProperty.AFTER_14_DAYS, + performanceMode: EfsPerformanceMode.GENERAL_PURPOSE, + throughputMode: EfsThroughputMode.BURSTING +}); +``` + +### Connecting + +To control who can access the EFS, use the `.connections` attribute. EFS has +a fixed default port, so you don't need to specify the port: + +```ts +fileSystem.connections.allowDefaultPortFrom(instance); +``` +### Mounting the file system using User Data + +In order to automatically mount this file system during instance launch, +following code can be used as reference: +``` +const vpc = new ec2.Vpc(this, 'VPC'); + +const fileSystem = new efs.EfsFileSystem(this, 'EfsFileSystem', { + vpc, + encrypted: true, + lifecyclePolicy: efs.EfsLifecyclePolicyProperty.AFTER_14_DAYS, + performanceMode: efs.EfsPerformanceMode.GENERAL_PURPOSE, + throughputMode: efs.EfsThroughputMode.BURSTING +}); + +const inst = new Instance(this, 'inst', { + instanceType: InstanceType.of(InstanceClass.T2, InstanceSize.LARGE), + machineImage: new AmazonLinuxImage({ + generation: AmazonLinuxGeneration.AMAZON_LINUX_2 + }), + vpc, + vpcSubnets: { + subnetType: SubnetType.PUBLIC, + } +}); + +fileSystem.connections.allowDefaultPortFrom(inst); + +inst.userData.addCommands("yum check-update -y", // Ubuntu: apt-get -y update + "yum upgrade -y", // Ubuntu: apt-get -y upgrade + "yum install -y amazon-efs-utils", // Ubuntu: apt-get -y install amazon-efs-utils + "yum install -y nfs-utils", // Ubuntu: apt-get -y install nfs-common + "file_system_id_1=" + fileSystem.fileSystemId, + "efs_mount_point_1=/mnt/efs/fs1", + "mkdir -p \"${efs_mount_point_1}\"", + "test -f \"/sbin/mount.efs\" && echo \"${file_system_id_1}:/ ${efs_mount_point_1} efs defaults,_netdev\" >> /etc/fstab || " + + "echo \"${file_system_id_1}.efs." + cdk.Stack.of(this).region + ".amazonaws.com:/ ${efs_mount_point_1} nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport,_netdev 0 0\" >> /etc/fstab", + "mount -a -t efs,nfs4 defaults"); +``` + This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project. diff --git a/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts new file mode 100644 index 0000000000000..bf83de7d8f217 --- /dev/null +++ b/packages/@aws-cdk/aws-efs/lib/efs-file-system.ts @@ -0,0 +1,282 @@ +import * as ec2 from '@aws-cdk/aws-ec2'; +import * as kms from '@aws-cdk/aws-kms'; +import {Construct, Resource} from "@aws-cdk/core"; +import {CfnFileSystem, CfnMountTarget} from "./efs.generated"; + +// tslint:disable: max-line-length +/** + * EFS Lifecycle Policy, if a file is not accessed for given days, it will move to EFS Infrequent Access. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-elasticfilesystem-filesystem-lifecyclepolicies + */ +export enum EfsLifecyclePolicyProperty { + /** + * After 7 days of not being accessed. + */ + AFTER_7_DAYS, + + /** + * After 14 days of not being accessed. + */ + AFTER_14_DAYS, + + /** + * After 30 days of not being accessed. + */ + AFTER_30_DAYS, + + /** + * After 60 days of not being accessed. + */ + AFTER_60_DAYS, + + /** + * After 90 days of not being accessed. + */ + AFTER_90_DAYS +} + +/** + * EFS Performance mode. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-efs-filesystem-performancemode + */ +export enum EfsPerformanceMode { + /** + * This is the general purpose performance mode for most file systems. + */ + GENERAL_PURPOSE = "generalPurpose", + + /** + * This performance mode can scale to higher levels of aggregate throughput and operations per second with a + * tradeoff of slightly higher latencies. + */ + MAX_IO = "maxIO" +} + +/** + * EFS Throughput mode. + * + * @see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html#cfn-elasticfilesystem-filesystem-throughputmode + */ +export enum EfsThroughputMode { + /** + * This mode on Amazon EFS scales as the size of the file system in the standard storage class grows. + */ + BURSTING = "bursting", + + /** + * This mode can instantly provision the throughput of the file system (in MiB/s) independent of the amount of data stored. + */ + PROVISIONED = "provisioned" +} + +/** + * Interface to implement AWS File Systems. + */ +export interface IEfsFileSystem extends ec2.IConnectable { + /** + * The ID of the file system, assigned by Amazon EFS. + * + * @attribute + */ + readonly fileSystemId: string; +} + +/** + * Properties of EFS FileSystem. + */ +export interface EfsFileSystemProps { + + /** + * VPC to launch the file system in. + */ + readonly vpc: ec2.IVpc; + + /** + * Security Group to assign to this file system. + * + * @default - creates new security group which allow all out bound traffic + */ + readonly securityGroup?: ec2.ISecurityGroup; + + /** + * Where to place the mount target within the VPC. + * + * @default - Private subnets + */ + readonly vpcSubnets?: ec2.SubnetSelection; + + /** + * Defines if the data at rest in the file system is encrypted or not. + * + * @default - false + */ + readonly encrypted?: boolean; + + /** + * The KMS key used for encryption. This is required to encrypt the data at rest if @encrypted is set to true. + * + * @default - if @encrypted is true, the default key for EFS (/aws/elasticfilesystem) is used + */ + readonly kmsKey?: kms.IKey; + + /** + * A policy used by EFS lifecycle management to transition files to the Infrequent Access (IA) storage class. + * + * @default - none + */ + readonly lifecyclePolicy?: EfsLifecyclePolicyProperty; + + /** + * Enum to mention the performance mode of the file system. + * + * @default - GENERAL_PURPOSE + */ + readonly performanceMode?: EfsPerformanceMode; + + /** + * Enum to mention the throughput mode of the file system. + * + * @default - BURSTING + */ + readonly throughputMode?: EfsThroughputMode; + + /** + * Provisioned throughput for the file system. This is a required property if the throughput mode is set to PROVISIONED. + * Valid values are 1-1024. + * + * @default - None, errors out + */ + readonly provisionedThroughputInMibps?: number; +} + +/** + * A new or imported EFS File System. + */ +abstract class EfsFileSystemBase extends Resource implements IEfsFileSystem { + + /** + * The security groups/rules used to allow network connections to the file system. + */ + public abstract readonly connections: ec2.Connections; + + /** + * @attribute + */ + public abstract readonly fileSystemId: string; +} + +/** + * Properties that describe an existing EFS file system. + */ +export interface EfsFileSystemAttributes { + /** + * The security group of the file system + */ + readonly securityGroup: ec2.ISecurityGroup; + + /** + * The File System's ID. + */ + readonly fileSystemID: string; +} + +/** + * The Elastic File System implementation of IFileSystem. + * It creates a new, empty file system in Amazon Elastic File System (Amazon EFS). + * It also creates mount target (AWS::EFS::MountTarget) implicitly to mount the + * EFS file system on an Amazon Elastic Compute Cloud (Amazon EC2) instance or another resource. + * + * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-efs-filesystem.html + * + * @resource AWS::EFS::FileSystem + */ +export class EfsFileSystem extends EfsFileSystemBase { + + /** + * Import an existing File System from the given properties. + */ + public static fromEfsFileSystemAttributes(scope: Construct, id: string, attrs: EfsFileSystemAttributes): IEfsFileSystem { + class Import extends EfsFileSystemBase implements IEfsFileSystem { + public readonly fileSystemId = attrs.fileSystemID; + public readonly connections = new ec2.Connections({ + securityGroups: [attrs.securityGroup], + defaultPort: ec2.Port.tcp(EfsFileSystem.DEFAULT_PORT) + }); + } + + return new Import(scope, id); + } + + /** + * The default port File System listens on. + */ + private static readonly DEFAULT_PORT: number = 2049; + + /** + * The security groups/rules used to allow network connections to the file system. + */ + public readonly connections: ec2.Connections; + + /** + * @attribute + */ + public readonly fileSystemId: string; + + private readonly efsFileSystem: CfnFileSystem; + + /** + * Constructor for creating a new EFS FileSystem. + */ + constructor(scope: Construct, id: string, props: EfsFileSystemProps) { + super(scope, id); + + if (props.throughputMode === EfsThroughputMode.PROVISIONED) { + if (props.provisionedThroughputInMibps === undefined) { + throw new Error('Property provisionedThroughputInMibps is required when throughputMode is PROVISIONED'); + } else if (!Number.isInteger(props.provisionedThroughputInMibps)) { + throw new Error("Invalid input for provisionedThroughputInMibps"); + } else if (props.provisionedThroughputInMibps < 1 || props.provisionedThroughputInMibps > 1024) { + this.node.addWarning("Valid values for throughput are 1-1024 MiB/s. You can get this limit increased by contacting AWS Support."); + } + } + + this.efsFileSystem = new CfnFileSystem(this, "Resource", { + encrypted: props.encrypted, + kmsKeyId: (props.kmsKey ? props.kmsKey.keyId : undefined), + lifecyclePolicies: (props.lifecyclePolicy ? Array.of({ + transitionToIa: EfsLifecyclePolicyProperty[props.lifecyclePolicy] + } as CfnFileSystem.LifecyclePolicyProperty) : undefined), + performanceMode: props.performanceMode, + throughputMode: props.throughputMode, + provisionedThroughputInMibps: props.provisionedThroughputInMibps + }); + + this.fileSystemId = this.efsFileSystem.ref; + this.node.defaultChild = this.efsFileSystem; + + const securityGroup = (props.securityGroup || new ec2.SecurityGroup(this, 'EfsSecurityGroup', { + vpc: props.vpc + })); + + this.connections = new ec2.Connections({ + securityGroups: [securityGroup], + defaultPort: ec2.Port.tcp(EfsFileSystem.DEFAULT_PORT) + }); + + const subnets = props.vpc.selectSubnets(props.vpcSubnets); + + // We now have to create the mount target for each of the mentioned subnet + let mountTargetCount = 0; + subnets.subnetIds.forEach((subnetId: string) => { + new CfnMountTarget(this, + "EfsMountTarget" + (++mountTargetCount), + { + fileSystemId: this.fileSystemId, + securityGroups: Array.of(securityGroup.securityGroupId), + subnetId + }); + }); + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-efs/lib/index.ts b/packages/@aws-cdk/aws-efs/lib/index.ts index 0f93e4419ab6b..808b7a1162e5f 100644 --- a/packages/@aws-cdk/aws-efs/lib/index.ts +++ b/packages/@aws-cdk/aws-efs/lib/index.ts @@ -1,2 +1,3 @@ // AWS::EFS CloudFormation Resources: +export * from './efs-file-system'; export * from './efs.generated'; diff --git a/packages/@aws-cdk/aws-efs/package.json b/packages/@aws-cdk/aws-efs/package.json index 04dbf74368339..9c71b82dc5875 100644 --- a/packages/@aws-cdk/aws-efs/package.json +++ b/packages/@aws-cdk/aws-efs/package.json @@ -85,14 +85,28 @@ "pkglint": "0.0.0" }, "dependencies": { - "@aws-cdk/core": "0.0.0" + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/cx-api": "0.0.0" }, "homepage": "https://github.com/aws/aws-cdk", "peerDependencies": { - "@aws-cdk/core": "0.0.0" + "@aws-cdk/core": "0.0.0", + "@aws-cdk/aws-ec2": "0.0.0", + "@aws-cdk/aws-kms": "0.0.0", + "@aws-cdk/cx-api": "0.0.0" }, "engines": { "node": ">= 10.3.0" }, + "awslint": { + "exclude": [ + "props-physical-name:@aws-cdk/aws-efs.EfsFileSystemProps", + "resource-interface:@aws-cdk/aws-efs.EfsFileSystem", + "construct-interface-extends-iconstruct:@aws-cdk/aws-efs.IEfsFileSystem", + "resource-interface-extends-resource:@aws-cdk/aws-efs.IEfsFileSystem" + ] + }, "stability": "experimental" } diff --git a/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts new file mode 100644 index 0000000000000..51efbc95d97b5 --- /dev/null +++ b/packages/@aws-cdk/aws-efs/test/efs-file-system.test.ts @@ -0,0 +1,190 @@ +import {expect as expectCDK, haveResource} from '@aws-cdk/assert'; +import * as ec2 from "@aws-cdk/aws-ec2"; +import * as kms from "@aws-cdk/aws-kms"; +import {Stack} from "@aws-cdk/core"; +import {WARNING_METADATA_KEY} from "@aws-cdk/cx-api"; +import {EfsFileSystem, EfsLifecyclePolicyProperty, EfsPerformanceMode, EfsThroughputMode} from "../lib/efs-file-system"; + +let stack = new Stack(); +let vpc = new ec2.Vpc(stack, 'VPC'); + +beforeEach( () => { + stack = new Stack(); + vpc = new ec2.Vpc(stack, 'VPC'); +}); + +test('default file system is created correctly', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem')); + expectCDK(stack).to(haveResource('AWS::EFS::MountTarget')); + expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroup')); +}); + +test('unencrypted file system is created correctly with default KMS', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + encrypted: false + }); + // THEN + expectCDK(stack).notTo(haveResource('AWS::EFS::FileSystem', { + Encrypted: true, + })); +}); + +test('encrypted file system is created correctly with default KMS', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + encrypted: true + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + Encrypted: true, + })); +}); + +test('encrypted file system is created correctly with custom KMS', () => { + const key = new kms.Key(stack, 'customKeyFS'); + + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + encrypted: true, + kmsKey: key + }); + // THEN + + /** + * CDK appends 8-digit MD5 hash of the resource path to the logical Id of the resource in order to make sure + * that the id is unique across multiple stacks. There isnt a direct way to identify the exact name of the resource + * in generated CDK, hence hardcoding the MD5 hash here for assertion. Assumption is that the path of the Key wont + * change in this UT. Checked the unique id by generating the cloud formation stack. + */ + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + Encrypted: true, + KmsKeyId: { + Ref: 'customKeyFSDDB87C6D' + } + })); +}); + +test('file system is created correctly with life cycle property', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + lifecyclePolicy: EfsLifecyclePolicyProperty.AFTER_14_DAYS + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + LifecyclePolicies: [{ + TransitionToIA: "AFTER_14_DAYS" + }] + })); +}); + +test('file system is created correctly with performance mode', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + performanceMode: EfsPerformanceMode.MAX_IO + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + PerformanceMode: "maxIO" + })); +}); + +test('file system is created correctly with bursting throughput mode', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + throughputMode: EfsThroughputMode.BURSTING + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + ThroughputMode: "bursting" + })); +}); + +test('Exception when throughput mode is set to PROVISIONED, but provisioned throughput is not set', () => { + expect(() => { + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + throughputMode: EfsThroughputMode.PROVISIONED + }); + }).toThrowError(/Property provisionedThroughputInMibps is required when throughputMode is PROVISIONED/); +}); + +test('Warning when provisioned throughput is less than the valid range', () => { + const fileSystem = new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + throughputMode: EfsThroughputMode.PROVISIONED, + provisionedThroughputInMibps: 0 + }); + + expect(fileSystem.node.metadata[0].type).toMatch(WARNING_METADATA_KEY); + expect(fileSystem.node.metadata[0].data).toContain("Valid values for throughput are 1-1024 MiB/s"); + expect(fileSystem.node.metadata[0].data).toContain("You can get this limit increased by contacting AWS Support"); + + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem')); +}); + +test('Warning when provisioned throughput is above than the valid range', () => { + const fileSystem = new EfsFileSystem(stack, 'EfsFileSystem1', { + vpc, + throughputMode: EfsThroughputMode.PROVISIONED, + provisionedThroughputInMibps: 1025 + }); + + expect(fileSystem.node.metadata[0].type).toMatch(WARNING_METADATA_KEY); + expect(fileSystem.node.metadata[0].data).toContain("Valid values for throughput are 1-1024 MiB/s"); + expect(fileSystem.node.metadata[0].data).toContain("You can get this limit increased by contacting AWS Support"); + + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem')); +}); + +test('Error when provisioned throughput is invalid number', () => { + expect(() => { + new EfsFileSystem(stack, 'EfsFileSystem2', { + vpc, + throughputMode: EfsThroughputMode.PROVISIONED, + provisionedThroughputInMibps: 1.5 + }); + }).toThrowError(/Invalid input for provisionedThroughputInMibps/); +}); + +test('file system is created correctly with provisioned throughput mode', () => { + // WHEN + new EfsFileSystem(stack, 'EfsFileSystem', { + vpc, + throughputMode: EfsThroughputMode.PROVISIONED, + provisionedThroughputInMibps: 5 + }); + // THEN + expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', { + ThroughputMode: "provisioned", + ProvisionedThroughputInMibps: 5 + })); +}); + +test('existing file system is imported correctly', () => { + // WHEN + const fs = EfsFileSystem.fromEfsFileSystemAttributes(stack, "existingFS", { + fileSystemID: "fs123", + securityGroup: ec2.SecurityGroup.fromSecurityGroupId(stack, 'SG', 'sg-123456789', { + allowAllOutbound: false + }) + }); + + fs.connections.allowToAnyIpv4(ec2.Port.tcp(443)); + + // THEN + expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroupEgress', { + GroupId: 'sg-123456789', + })); +}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-efs/test/efs.test.ts b/packages/@aws-cdk/aws-efs/test/efs.test.ts deleted file mode 100644 index e394ef336bfb4..0000000000000 --- a/packages/@aws-cdk/aws-efs/test/efs.test.ts +++ /dev/null @@ -1,6 +0,0 @@ -import '@aws-cdk/assert/jest'; -import {} from '../lib'; - -test('No tests are specified for this package', () => { - expect(true).toBe(true); -}); diff --git a/packages/@aws-cdk/aws-eks/package.json b/packages/@aws-cdk/aws-eks/package.json index f16dc3017211e..97de559591bd2 100644 --- a/packages/@aws-cdk/aws-eks/package.json +++ b/packages/@aws-cdk/aws-eks/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-events-targets/package.json b/packages/@aws-cdk/aws-events-targets/package.json index e4fcd21da00df..5b6de1712e8fe 100644 --- a/packages/@aws-cdk/aws-events-targets/package.json +++ b/packages/@aws-cdk/aws-events-targets/package.json @@ -86,7 +86,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-codecommit": "0.0.0", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "aws-sdk-mock": "^5.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index 16d3ad42e8daf..33cbac5981a42 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -71,7 +71,7 @@ "@types/lodash": "^4.14.149", "@types/nodeunit": "^0.0.30", "@types/sinon": "^7.5.2", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "aws-sdk-mock": "^5.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/@aws-cdk/aws-route53/package.json b/packages/@aws-cdk/aws-route53/package.json index e804aa8a2ed98..cc500cdb9e753 100644 --- a/packages/@aws-cdk/aws-route53/package.json +++ b/packages/@aws-cdk/aws-route53/package.json @@ -64,7 +64,7 @@ "devDependencies": { "@aws-cdk/assert": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/aws-sqs/package.json b/packages/@aws-cdk/aws-sqs/package.json index 71a9a34217d58..31ae40fb2b228 100644 --- a/packages/@aws-cdk/aws-sqs/package.json +++ b/packages/@aws-cdk/aws-sqs/package.json @@ -65,7 +65,7 @@ "@aws-cdk/assert": "0.0.0", "@aws-cdk/aws-s3": "0.0.0", "@types/nodeunit": "^0.0.30", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", "cfn2ts": "0.0.0", diff --git a/packages/@aws-cdk/cfnspec/CHANGELOG.md b/packages/@aws-cdk/cfnspec/CHANGELOG.md index 22bc1db55fe29..7f7739c0490f4 100644 --- a/packages/@aws-cdk/cfnspec/CHANGELOG.md +++ b/packages/@aws-cdk/cfnspec/CHANGELOG.md @@ -1,3 +1,65 @@ +# CloudFormation Resource Specification v11.3.0 + +## New Resource Types + +* AWS::CloudWatch::CompositeAlarm + +## Attribute Changes + +* AWS::AppMesh::Mesh MeshOwner (__added__) +* AWS::AppMesh::Mesh ResourceOwner (__added__) +* AWS::AppMesh::Route MeshOwner (__added__) +* AWS::AppMesh::Route ResourceOwner (__added__) +* AWS::AppMesh::VirtualNode MeshOwner (__added__) +* AWS::AppMesh::VirtualNode ResourceOwner (__added__) +* AWS::AppMesh::VirtualRouter MeshOwner (__added__) +* AWS::AppMesh::VirtualRouter ResourceOwner (__added__) +* AWS::AppMesh::VirtualService MeshOwner (__added__) +* AWS::AppMesh::VirtualService ResourceOwner (__added__) + +## Property Changes + + +## Property Type Changes + +* AWS::AppMesh::VirtualNode.BackendDefaults (__added__) +* AWS::AppMesh::VirtualNode.ClientPolicy (__added__) +* AWS::AppMesh::VirtualNode.ClientPolicyTls (__added__) +* AWS::AppMesh::VirtualNode.ListenerTls (__added__) +* AWS::AppMesh::VirtualNode.ListenerTlsAcmCertificate (__added__) +* AWS::AppMesh::VirtualNode.ListenerTlsCertificate (__added__) +* AWS::AppMesh::VirtualNode.ListenerTlsFileCertificate (__added__) +* AWS::AppMesh::VirtualNode.TlsValidationContext (__added__) +* AWS::AppMesh::VirtualNode.TlsValidationContextAcmTrust (__added__) +* AWS::AppMesh::VirtualNode.TlsValidationContextFileTrust (__added__) +* AWS::AppMesh::VirtualNode.TlsValidationContextTrust (__added__) +* AWS::Greengrass::ResourceDefinition.ResourceDownloadOwnerSetting (__added__) +* AWS::Greengrass::ResourceDefinitionVersion.ResourceDownloadOwnerSetting (__added__) +* AWS::AppMesh::VirtualNode.Listener TLS (__added__) +* AWS::AppMesh::VirtualNode.VirtualNodeSpec BackendDefaults (__added__) +* AWS::AppMesh::VirtualNode.VirtualServiceBackend ClientPolicy (__added__) +* AWS::Greengrass::ResourceDefinition.S3MachineLearningModelResourceData OwnerSetting (__added__) +* AWS::Greengrass::ResourceDefinition.SageMakerMachineLearningModelResourceData OwnerSetting (__added__) +* AWS::Greengrass::ResourceDefinitionVersion.S3MachineLearningModelResourceData OwnerSetting (__added__) +* AWS::Greengrass::ResourceDefinitionVersion.SageMakerMachineLearningModelResourceData OwnerSetting (__added__) + +# Serverless Application Model (SAM) Resource Specification v2016-10-31 + +## New Resource Types + + +## Attribute Changes + + +## Property Changes + + +## Property Type Changes + +* AWS::Serverless::Function.CloudWatchLogsEvent (__added__) +* AWS::Serverless::Function.EventSource Properties.Types (__changed__) + * Added CloudWatchLogsEvent + # CloudFormation Resource Specification v11.1.0 ## New Resource Types diff --git a/packages/@aws-cdk/cfnspec/build-tools/build.ts b/packages/@aws-cdk/cfnspec/build-tools/build.ts index d65f2f53fe6a4..5b2910f12d7c4 100644 --- a/packages/@aws-cdk/cfnspec/build-tools/build.ts +++ b/packages/@aws-cdk/cfnspec/build-tools/build.ts @@ -26,8 +26,7 @@ async function main() { } } - detectScrutinyTypes(spec); - replaceIncompleteTypes(spec); + massageSpec(spec); spec.Fingerprint = md5(JSON.stringify(normalize(spec))); @@ -36,6 +35,12 @@ async function main() { await fs.writeJson(path.join(outDir, 'specification.json'), spec, { spaces: 2 }); } +export function massageSpec(spec: schema.Specification) { + detectScrutinyTypes(spec); + replaceIncompleteTypes(spec); + dropTypelessAttributes(spec); +} + function forEachSection(spec: schema.Specification, data: any, cb: (spec: any, fragment: any, path: string[]) => void) { cb(spec.PropertyTypes, data.PropertyTypes, ['PropertyTypes']); cb(spec.ResourceTypes, data.ResourceTypes, ['ResourceTypes']); @@ -74,6 +79,23 @@ function replaceIncompleteTypes(spec: schema.Specification) { } } +/** + * Drop Attributes specified with the different ResourceTypes that have + * no type specified. + */ +function dropTypelessAttributes(spec: schema.Specification) { + const resourceTypes = spec.ResourceTypes; + Object.values(resourceTypes).forEach((resourceType) => { + const attributes = resourceType.Attributes ?? {}; + Object.keys(attributes).forEach((attrKey) => { + const attrVal = attributes[attrKey]; + if (Object.keys(attrVal).length === 0) { + delete attributes[attrKey]; + } + }); + }); +} + function merge(spec: any, fragment: any, jsonPath: string[]) { if (!fragment) { return; } for (const key of Object.keys(fragment)) { diff --git a/packages/@aws-cdk/cfnspec/cfn.version b/packages/@aws-cdk/cfnspec/cfn.version index 68d8f15e23cf5..f628d2eafc5e5 100644 --- a/packages/@aws-cdk/cfnspec/cfn.version +++ b/packages/@aws-cdk/cfnspec/cfn.version @@ -1 +1 @@ -11.1.0 +11.3.0 diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json index 00eda8574624a..2284434892c24 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_CloudFormationResourceSpecification.json @@ -2068,6 +2068,52 @@ } } }, + "AWS::AppMesh::VirtualNode.BackendDefaults": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-backenddefaults.html", + "Properties": { + "ClientPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-backenddefaults.html#cfn-appmesh-virtualnode-backenddefaults-clientpolicy", + "Required": false, + "Type": "ClientPolicy", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ClientPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicy.html", + "Properties": { + "TLS": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicy.html#cfn-appmesh-virtualnode-clientpolicy-tls", + "Required": false, + "Type": "ClientPolicyTls", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ClientPolicyTls": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicytls.html", + "Properties": { + "Enforce": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicytls.html#cfn-appmesh-virtualnode-clientpolicytls-enforce", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "Ports": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicytls.html#cfn-appmesh-virtualnode-clientpolicytls-ports", + "PrimitiveItemType": "Integer", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "Validation": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-clientpolicytls.html#cfn-appmesh-virtualnode-clientpolicytls-validation", + "Required": true, + "Type": "TlsValidationContext", + "UpdateType": "Mutable" + } + } + }, "AWS::AppMesh::VirtualNode.DnsServiceDiscovery": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-dnsservicediscovery.html", "Properties": { @@ -2151,6 +2197,74 @@ "Required": true, "Type": "PortMapping", "UpdateType": "Mutable" + }, + "TLS": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listener.html#cfn-appmesh-virtualnode-listener-tls", + "Required": false, + "Type": "ListenerTls", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ListenerTls": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertls.html", + "Properties": { + "Certificate": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertls.html#cfn-appmesh-virtualnode-listenertls-certificate", + "Required": true, + "Type": "ListenerTlsCertificate", + "UpdateType": "Mutable" + }, + "Mode": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertls.html#cfn-appmesh-virtualnode-listenertls-mode", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ListenerTlsAcmCertificate": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlsacmcertificate.html", + "Properties": { + "CertificateArn": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlsacmcertificate.html#cfn-appmesh-virtualnode-listenertlsacmcertificate-certificatearn", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ListenerTlsCertificate": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlscertificate.html", + "Properties": { + "ACM": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlscertificate.html#cfn-appmesh-virtualnode-listenertlscertificate-acm", + "Required": false, + "Type": "ListenerTlsAcmCertificate", + "UpdateType": "Mutable" + }, + "File": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlscertificate.html#cfn-appmesh-virtualnode-listenertlscertificate-file", + "Required": false, + "Type": "ListenerTlsFileCertificate", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.ListenerTlsFileCertificate": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlsfilecertificate.html", + "Properties": { + "CertificateChain": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlsfilecertificate.html#cfn-appmesh-virtualnode-listenertlsfilecertificate-certificatechain", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "PrivateKey": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-listenertlsfilecertificate.html#cfn-appmesh-virtualnode-listenertlsfilecertificate-privatekey", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" } } }, @@ -2199,9 +2313,66 @@ } } }, + "AWS::AppMesh::VirtualNode.TlsValidationContext": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontext.html", + "Properties": { + "Trust": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontext.html#cfn-appmesh-virtualnode-tlsvalidationcontext-trust", + "Required": true, + "Type": "TlsValidationContextTrust", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.TlsValidationContextAcmTrust": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontextacmtrust.html", + "Properties": { + "CertificateAuthorityArns": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontextacmtrust.html#cfn-appmesh-virtualnode-tlsvalidationcontextacmtrust-certificateauthorityarns", + "PrimitiveItemType": "String", + "Required": true, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.TlsValidationContextFileTrust": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontextfiletrust.html", + "Properties": { + "CertificateChain": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontextfiletrust.html#cfn-appmesh-virtualnode-tlsvalidationcontextfiletrust-certificatechain", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + } + } + }, + "AWS::AppMesh::VirtualNode.TlsValidationContextTrust": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontexttrust.html", + "Properties": { + "ACM": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontexttrust.html#cfn-appmesh-virtualnode-tlsvalidationcontexttrust-acm", + "Required": false, + "Type": "TlsValidationContextAcmTrust", + "UpdateType": "Mutable" + }, + "File": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-tlsvalidationcontexttrust.html#cfn-appmesh-virtualnode-tlsvalidationcontexttrust-file", + "Required": false, + "Type": "TlsValidationContextFileTrust", + "UpdateType": "Mutable" + } + } + }, "AWS::AppMesh::VirtualNode.VirtualNodeSpec": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualnodespec.html", "Properties": { + "BackendDefaults": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualnodespec.html#cfn-appmesh-virtualnode-virtualnodespec-backenddefaults", + "Required": false, + "Type": "BackendDefaults", + "UpdateType": "Mutable" + }, "Backends": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualnodespec.html#cfn-appmesh-virtualnode-virtualnodespec-backends", "ItemType": "Backend", @@ -2233,6 +2404,12 @@ "AWS::AppMesh::VirtualNode.VirtualServiceBackend": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualservicebackend.html", "Properties": { + "ClientPolicy": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualservicebackend.html#cfn-appmesh-virtualnode-virtualservicebackend-clientpolicy", + "Required": false, + "Type": "ClientPolicy", + "UpdateType": "Mutable" + }, "VirtualServiceName": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appmesh-virtualnode-virtualservicebackend.html#cfn-appmesh-virtualnode-virtualservicebackend-virtualservicename", "PrimitiveType": "String", @@ -17649,6 +17826,23 @@ } } }, + "AWS::Greengrass::ResourceDefinition.ResourceDownloadOwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-resourcedownloadownersetting.html", + "Properties": { + "GroupOwner": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-resourcedownloadownersetting.html#cfn-greengrass-resourcedefinition-resourcedownloadownersetting-groupowner", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "GroupPermission": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-resourcedownloadownersetting.html#cfn-greengrass-resourcedefinition-resourcedownloadownersetting-grouppermission", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::Greengrass::ResourceDefinition.ResourceInstance": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-resourceinstance.html", "Properties": { @@ -17681,6 +17875,12 @@ "Required": true, "UpdateType": "Immutable" }, + "OwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-s3machinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinition-s3machinelearningmodelresourcedata-ownersetting", + "Required": false, + "Type": "ResourceDownloadOwnerSetting", + "UpdateType": "Immutable" + }, "S3Uri": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-s3machinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinition-s3machinelearningmodelresourcedata-s3uri", "PrimitiveType": "String", @@ -17698,6 +17898,12 @@ "Required": true, "UpdateType": "Immutable" }, + "OwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-sagemakermachinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinition-sagemakermachinelearningmodelresourcedata-ownersetting", + "Required": false, + "Type": "ResourceDownloadOwnerSetting", + "UpdateType": "Immutable" + }, "SageMakerJobArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinition-sagemakermachinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinition-sagemakermachinelearningmodelresourcedata-sagemakerjobarn", "PrimitiveType": "String", @@ -17816,6 +18022,23 @@ } } }, + "AWS::Greengrass::ResourceDefinitionVersion.ResourceDownloadOwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-resourcedownloadownersetting.html", + "Properties": { + "GroupOwner": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-resourcedownloadownersetting.html#cfn-greengrass-resourcedefinitionversion-resourcedownloadownersetting-groupowner", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "GroupPermission": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-resourcedownloadownersetting.html#cfn-greengrass-resourcedefinitionversion-resourcedownloadownersetting-grouppermission", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::Greengrass::ResourceDefinitionVersion.ResourceInstance": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-resourceinstance.html", "Properties": { @@ -17848,6 +18071,12 @@ "Required": true, "UpdateType": "Immutable" }, + "OwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-s3machinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinitionversion-s3machinelearningmodelresourcedata-ownersetting", + "Required": false, + "Type": "ResourceDownloadOwnerSetting", + "UpdateType": "Immutable" + }, "S3Uri": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-s3machinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinitionversion-s3machinelearningmodelresourcedata-s3uri", "PrimitiveType": "String", @@ -17865,6 +18094,12 @@ "Required": true, "UpdateType": "Immutable" }, + "OwnerSetting": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-sagemakermachinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinitionversion-sagemakermachinelearningmodelresourcedata-ownersetting", + "Required": false, + "Type": "ResourceDownloadOwnerSetting", + "UpdateType": "Immutable" + }, "SageMakerJobArn": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-greengrass-resourcedefinitionversion-sagemakermachinelearningmodelresourcedata.html#cfn-greengrass-resourcedefinitionversion-sagemakermachinelearningmodelresourcedata-sagemakerjobarn", "PrimitiveType": "String", @@ -29912,7 +30147,7 @@ } } }, - "ResourceSpecificationVersion": "11.1.0", + "ResourceSpecificationVersion": "11.3.0", "ResourceTypes": { "AWS::ACMPCA::Certificate": { "Attributes": { @@ -32149,6 +32384,8 @@ "MeshName": { "PrimitiveType": "String" }, + "MeshOwner": {}, + "ResourceOwner": {}, "Uid": { "PrimitiveType": "String" } @@ -32184,6 +32421,8 @@ "MeshName": { "PrimitiveType": "String" }, + "MeshOwner": {}, + "ResourceOwner": {}, "RouteName": { "PrimitiveType": "String" }, @@ -32237,6 +32476,8 @@ "MeshName": { "PrimitiveType": "String" }, + "MeshOwner": {}, + "ResourceOwner": {}, "Uid": { "PrimitiveType": "String" }, @@ -32281,6 +32522,8 @@ "MeshName": { "PrimitiveType": "String" }, + "MeshOwner": {}, + "ResourceOwner": {}, "Uid": { "PrimitiveType": "String" }, @@ -32325,6 +32568,8 @@ "MeshName": { "PrimitiveType": "String" }, + "MeshOwner": {}, + "ResourceOwner": {}, "Uid": { "PrimitiveType": "String" }, @@ -34521,6 +34766,61 @@ } } }, + "AWS::CloudWatch::CompositeAlarm": { + "Attributes": { + "Arn": { + "PrimitiveType": "String" + } + }, + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html", + "Properties": { + "ActionsEnabled": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-actionsenabled", + "PrimitiveType": "Boolean", + "Required": false, + "UpdateType": "Mutable" + }, + "AlarmActions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-alarmactions", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "AlarmDescription": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-alarmdescription", + "PrimitiveType": "String", + "Required": false, + "UpdateType": "Mutable" + }, + "AlarmName": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-alarmname", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "AlarmRule": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-alarmrule", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Mutable" + }, + "InsufficientDataActions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-insufficientdataactions", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + }, + "OKActions": { + "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-compositealarm.html#cfn-cloudwatch-compositealarm-okactions", + "PrimitiveItemType": "String", + "Required": false, + "Type": "List", + "UpdateType": "Mutable" + } + } + }, "AWS::CloudWatch::Dashboard": { "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-dashboard.html", "Properties": { diff --git a/packages/@aws-cdk/cfnspec/spec-source/000_sam.spec.json b/packages/@aws-cdk/cfnspec/spec-source/000_sam.spec.json index 4605ed2151a38..2dd18618067a8 100644 --- a/packages/@aws-cdk/cfnspec/spec-source/000_sam.spec.json +++ b/packages/@aws-cdk/cfnspec/spec-source/000_sam.spec.json @@ -178,6 +178,23 @@ } } }, + "AWS::Serverless::Function.CloudWatchLogsEvent": { + "Documentation": "https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchevent", + "Properties": { + "FilterPattern": { + "Documentation": "https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchlogs", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + }, + "LogGroupName": { + "Documentation": "https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#cloudwatchlogs", + "PrimitiveType": "String", + "Required": true, + "UpdateType": "Immutable" + } + } + }, "AWS::Serverless::Function.CollectionSAMPT": { "Documentation": "https://github.com/awslabs/serverless-application-model/blob/master/docs/policy_templates.rst", "Properties": { @@ -302,6 +319,7 @@ "ApiEvent", "ScheduleEvent", "CloudWatchEventEvent", + "CloudWatchLogsEvent", "IoTRuleEvent", "AlexaSkillEvent" ], diff --git a/packages/@aws-cdk/cfnspec/test/spec-validators.ts b/packages/@aws-cdk/cfnspec/test/spec-validators.ts index 04fd388210fba..7506d5e1da77d 100644 --- a/packages/@aws-cdk/cfnspec/test/spec-validators.ts +++ b/packages/@aws-cdk/cfnspec/test/spec-validators.ts @@ -120,7 +120,7 @@ function validateAttributes(typeName: string, specification: schema.Specification) { for (const name of Object.keys(attributes)) { const attribute = attributes[name]; - test.ok(('Type' in attribute) !== ('PrimitiveType' in attribute)); + test.ok(('Type' in attribute) !== ('PrimitiveType' in attribute), 'One of, and only one of, Type or PrimitiveType must be present'); if (schema.isPrimitiveAttribute(attribute)) { test.ok(!schema.isListAttribute(attribute), `${typeName}.Attributes.${name} is only a Primitive type`); test.ok(schema.isPrimitiveType(attribute.PrimitiveType), `${typeName}.Attributes.${name} has a valid PrimitiveType`); diff --git a/packages/@aws-cdk/cfnspec/test/test.build.ts b/packages/@aws-cdk/cfnspec/test/test.build.ts new file mode 100644 index 0000000000000..ba7364b7075d8 --- /dev/null +++ b/packages/@aws-cdk/cfnspec/test/test.build.ts @@ -0,0 +1,68 @@ +import { Test } from 'nodeunit'; +import { massageSpec } from '../build-tools/build'; +import { schema } from '../lib'; + +export = { + 'dropTypelessAttributes works correctly'(test: Test) { + const spec: schema.Specification = { + Fingerprint: 'some-fingerprint', + PropertyTypes: { + 'CDK::Test::Property': { + Properties: { + Type: ({ + PrimitiveType: "String", + } as schema.ScalarProperty), // ts is being weird and doesn't correctly match the type + }, + } + }, + ResourceTypes: { + 'CDK::Test::Resource': { + Attributes: { + Attribute1: ({ + PrimitiveType: 'String' + } as schema.PrimitiveAttribute), // ts is being weird and doesn't correctly match the type + Attribute2: ({} as schema.PrimitiveAttribute), + }, + Documentation: "https://documentation-url/cdk/test/resource", + Properties: { + ResourceArn: ({ + PrimitiveType: "String", + } as schema.PrimitiveProperty), // ts is being weird and doesn't correctly match the type + } + } + } + }; + + massageSpec(spec); + + test.deepEqual(spec, { + Fingerprint: 'some-fingerprint', + PropertyTypes: { + 'CDK::Test::Property': { + Properties: { + Type: ({ + PrimitiveType: "String", + } as schema.ScalarProperty), // ts is being weird and doesn't correctly match the type + }, + } + }, + ResourceTypes: { + 'CDK::Test::Resource': { + Attributes: { + Attribute1: ({ + PrimitiveType: 'String' + }), + }, + Documentation: "https://documentation-url/cdk/test/resource", + Properties: { + ResourceArn: { + PrimitiveType: "String", + }, + } + } + } + }); + + test.done(); + } +}; diff --git a/packages/@aws-cdk/custom-resources/package.json b/packages/@aws-cdk/custom-resources/package.json index 7ded8beac3ef4..73a998d65fbb1 100644 --- a/packages/@aws-cdk/custom-resources/package.json +++ b/packages/@aws-cdk/custom-resources/package.json @@ -73,7 +73,7 @@ "@types/aws-lambda": "^8.10.39", "@types/fs-extra": "^8.1.0", "@types/sinon": "^7.5.2", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "aws-sdk-mock": "^5.0.0", "cdk-build-tools": "0.0.0", "cdk-integ-tools": "0.0.0", diff --git a/packages/aws-cdk/package.json b/packages/aws-cdk/package.json index c1ef0880c55c7..8cf79ed4ac0af 100644 --- a/packages/aws-cdk/package.json +++ b/packages/aws-cdk/package.json @@ -71,7 +71,7 @@ "@aws-cdk/cx-api": "0.0.0", "@aws-cdk/region-info": "0.0.0", "archiver": "^3.1.1", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "camelcase": "^5.3.1", "colors": "^1.4.0", "decamelize": "^4.0.0", diff --git a/packages/cdk-assets/package.json b/packages/cdk-assets/package.json index f6e8565aa6d89..783d669defae9 100644 --- a/packages/cdk-assets/package.json +++ b/packages/cdk-assets/package.json @@ -42,7 +42,7 @@ "dependencies": { "@aws-cdk/cdk-assets-schema": "0.0.0", "archiver": "^3.1.1", - "aws-sdk": "^2.633.0", + "aws-sdk": "^2.634.0", "glob": "^7.1.6", "yargs": "^15.2.0" }, diff --git a/packages/decdk/package.json b/packages/decdk/package.json index 67557c0f9ab45..310ed6c10618e 100644 --- a/packages/decdk/package.json +++ b/packages/decdk/package.json @@ -185,4 +185,4 @@ "engines": { "node": ">= 8.10.0" } -} \ No newline at end of file +} diff --git a/packages/monocdk-experiment/package.json b/packages/monocdk-experiment/package.json index 905fc3009d753..b2c4fb659b230 100644 --- a/packages/monocdk-experiment/package.json +++ b/packages/monocdk-experiment/package.json @@ -164,4 +164,4 @@ "engines": { "node": ">= 10.3.0" } -} \ No newline at end of file +} diff --git a/tools/prlint/index.js b/tools/prlint/index.js index 2db9b2a547ea4..7e4212d1ef9ea 100755 --- a/tools/prlint/index.js +++ b/tools/prlint/index.js @@ -22,6 +22,10 @@ function createGitHubClient() { return new GitHub({'token': token}); } +function isPkgCfnspec(issue) { + return issue.title.indexOf("(cfnspec)") > -1; +} + function isFeature(issue) { return issue.title.startsWith("feat") } @@ -39,7 +43,7 @@ function readmeChanged(files) { } function featureContainsReadme(issue, files) { - if (isFeature(issue) && !readmeChanged(files)) { + if (isFeature(issue) && !readmeChanged(files) && !isPkgCfnspec(issue)) { throw new LinterError("Features must contain a change to a README file"); }; }; diff --git a/yarn.lock b/yarn.lock index 01cf1f4f0fa85..86a450009c537 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2646,10 +2646,10 @@ aws-sdk-mock@^5.0.0: sinon "^8.0.1" traverse "^0.6.6" -aws-sdk@^2.596.0, aws-sdk@^2.633.0: - version "2.633.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.633.0.tgz#3bdb8ec2671884025e9f64fdfa2c0af3cc663118" - integrity sha512-C28/GefIQ+Dk1hjPQrpG1Yt9RdvqeFMP4nb6iActanoGq5JTSJU9103ukpBzrHz96fvjhIRogrvfOhDKubbcjw== +aws-sdk@^2.596.0, aws-sdk@^2.634.0: + version "2.634.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.634.0.tgz#95077c191107b9cb696e922b06e79949dcd13434" + integrity sha512-cZfRD7bcKBHOLoHUJuqB9xaLs/z1/xsc9zfGLIzyuxKLJa7Z0pxy8Y/0GrhWO98yXLBvLLET7btj2iDI2oWWhQ== dependencies: buffer "4.9.1" events "1.1.1"