Skip to content

Commit

Permalink
chore: regression suite patch for lambda runtime deprecation (aws#17297)
Browse files Browse the repository at this point in the history
Follow up on aws#17282

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
iliapolo authored and TikiTDO committed Feb 21, 2022
1 parent 15af7e7 commit 3f75c44
Show file tree
Hide file tree
Showing 2 changed files with 382 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
On november 2nd 2021, lambda started deprecating the nodejs10.x runtime. This meant we can no longer create functions with this runtime.
Our integration tests use this runtime for one of its stacks.

This patch brings https://github.com/aws/aws-cdk/pull/17282 into the regression suite.
378 changes: 378 additions & 0 deletions packages/aws-cdk/test/integ/cli-regression-patches/v1.130.0/app/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,378 @@
const path = require('path');

var constructs = require('constructs');
if (process.env.PACKAGE_LAYOUT_VERSION === '1') {
var cdk = require('@aws-cdk/core');
var ec2 = require('@aws-cdk/aws-ec2');
var ssm = require('@aws-cdk/aws-ssm');
var iam = require('@aws-cdk/aws-iam');
var sns = require('@aws-cdk/aws-sns');
var lambda = require('@aws-cdk/aws-lambda');
var docker = require('@aws-cdk/aws-ecr-assets');
} else {
var cdk = require('aws-cdk-lib');
var {
aws_ec2: ec2,
aws_ssm: ssm,
aws_iam: iam,
aws_sns: sns,
aws_lambda: lambda,
aws_ecr_assets: docker
} = require('aws-cdk-lib');
}

const { Annotations } = cdk;
const { StackWithNestedStack, StackWithNestedStackUsingParameters } = require('./nested-stack');

const stackPrefix = process.env.STACK_NAME_PREFIX;
if (!stackPrefix) {
throw new Error(`the STACK_NAME_PREFIX environment variable is required`);
}

class MyStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);
new sns.Topic(this, 'topic');

if (cdk.AvailabilityZoneProvider) { // <= 0.34.0
new cdk.AvailabilityZoneProvider(this).availabilityZones;
} else if (cdk.Context) { // <= 0.35.0
cdk.Context.getAvailabilityZones(this);
} else {
this.availabilityZones;
}

const parameterName = '/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2';
getSsmParameterValue(this, parameterName);
}
}

function getSsmParameterValue(scope, parameterName) {
return ssm.StringParameter.valueFromLookup(scope, parameterName);
}

class YourStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);
new sns.Topic(this, 'topic1');
new sns.Topic(this, 'topic2');
}
}

class StackUsingContext extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);
new cdk.CfnResource(this, 'Handle', {
type: 'AWS::CloudFormation::WaitConditionHandle'
});

new cdk.CfnOutput(this, 'Output', {
value: this.availabilityZones,
});
}
}

class ParameterStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new sns.Topic(this, 'TopicParameter', {
topicName: new cdk.CfnParameter(this, 'TopicNameParam').valueAsString
});
}
}

class OtherParameterStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new sns.Topic(this, 'TopicParameter', {
topicName: new cdk.CfnParameter(this, 'OtherTopicNameParam').valueAsString
});
}
}

class MultiParameterStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new sns.Topic(this, 'TopicParameter', {
displayName: new cdk.CfnParameter(this, 'DisplayNameParam').valueAsString
});
new sns.Topic(this, 'OtherTopicParameter', {
displayName: new cdk.CfnParameter(this, 'OtherDisplayNameParam').valueAsString
});
}
}

class OutputsStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const topic = new sns.Topic(this, 'MyOutput', {
topicName: `${cdk.Stack.of(this).stackName}MyTopic`
});

new cdk.CfnOutput(this, 'TopicName', {
value: topic.topicName
})
}
}

class AnotherOutputsStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const topic = new sns.Topic(this, 'MyOtherOutput', {
topicName: `${cdk.Stack.of(this).stackName}MyOtherTopic`
});

new cdk.CfnOutput(this, 'TopicName', {
value: topic.topicName
});
}
}

class IamStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new iam.Role(this, 'SomeRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')
});
}
}

class ProvidingStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

this.topic = new sns.Topic(this, 'BogusTopic'); // Some filler
}
}

class StackWithError extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

this.topic = new sns.Topic(this, 'BogusTopic'); // Some filler
Annotations.of(this).addError('This is an error');
}
}

class StageWithError extends cdk.Stage {
constructor(parent, id, props) {
super(parent, id, props);

new StackWithError(this, 'Stack');
}
}

class ConsumingStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new sns.Topic(this, 'BogusTopic'); // Some filler
new cdk.CfnOutput(this, 'IConsumedSomething', { value: props.providingStack.topic.topicArn });
}
}

class MissingSSMParameterStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const parameterName = constructs.Node.of(this).tryGetContext('test:ssm-parameter-name');
if (parameterName) {
const param = getSsmParameterValue(this, parameterName);
new iam.Role(this, 'PhonyRole', { assumedBy: new iam.AccountPrincipal(param) });
}
}
}

class LambdaStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const fn = new lambda.Function(this, 'my-function', {
code: lambda.Code.asset(path.join(__dirname, 'lambda')),
runtime: lambda.Runtime.NODEJS_12_X,
handler: 'index.handler'
});

new cdk.CfnOutput(this, 'FunctionArn', { value: fn.functionArn });
}
}

class DockerStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new docker.DockerImageAsset(this, 'image', {
directory: path.join(__dirname, 'docker')
});

// Add at least a single resource (WaitConditionHandle), otherwise this stack will never
// be deployed (and its assets never built)
new cdk.CfnResource(this, 'Handle', {
type: 'AWS::CloudFormation::WaitConditionHandle'
});
}
}

class DockerStackWithCustomFile extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

new docker.DockerImageAsset(this, 'image', {
directory: path.join(__dirname, 'docker'),
file: 'Dockerfile.Custom'
});

// Add at least a single resource (WaitConditionHandle), otherwise this stack will never
// be deployed (and its assets never built)
new cdk.CfnResource(this, 'Handle', {
type: 'AWS::CloudFormation::WaitConditionHandle'
});
}
}

class FailedStack extends cdk.Stack {

constructor(parent, id, props) {
super(parent, id, props);

// fails on 'Property PolicyDocument cannot be empty'.
new cdk.CfnResource(this, 'EmptyPolicy', {
type: 'AWS::IAM::Policy'
})

}

}

const VPC_TAG_NAME = 'custom-tag';
const VPC_TAG_VALUE = `${stackPrefix}-bazinga!`;

class DefineVpcStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

const vpc = new ec2.Vpc(this, 'VPC', {
maxAzs: 1,
})
cdk.Aspects.of(vpc).add(new cdk.Tag(VPC_TAG_NAME, VPC_TAG_VALUE));
}
}

class ImportVpcStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

ec2.Vpc.fromLookup(this, 'DefaultVPC', { isDefault: true });
ec2.Vpc.fromLookup(this, 'ByTag', { tags: { [VPC_TAG_NAME]: VPC_TAG_VALUE } });
}
}

class ConditionalResourceStack extends cdk.Stack {
constructor(parent, id, props) {
super(parent, id, props);

if (!process.env.NO_RESOURCE) {
new iam.User(this, 'User');
}
}
}

class SomeStage extends cdk.Stage {
constructor(parent, id, props) {
super(parent, id, props);

new YourStack(this, 'StackInStage');
}
}

class StageUsingContext extends cdk.Stage {
constructor(parent, id, props) {
super(parent, id, props);

new StackUsingContext(this, 'StackInStage');
}
}

const app = new cdk.App();

const defaultEnv = {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
};

// Sometimes we don't want to synthesize all stacks because it will impact the results
const stackSet = process.env.INTEG_STACK_SET || 'default';

switch (stackSet) {
case 'default':
// Deploy all does a wildcard ${stackPrefix}-test-*
new MyStack(app, `${stackPrefix}-test-1`, { env: defaultEnv });
new YourStack(app, `${stackPrefix}-test-2`);
// Deploy wildcard with parameters does ${stackPrefix}-param-test-*
new ParameterStack(app, `${stackPrefix}-param-test-1`);
new OtherParameterStack(app, `${stackPrefix}-param-test-2`);
// Deploy stack with multiple parameters
new MultiParameterStack(app, `${stackPrefix}-param-test-3`);
// Deploy stack with outputs does ${stackPrefix}-outputs-test-*
new OutputsStack(app, `${stackPrefix}-outputs-test-1`);
new AnotherOutputsStack(app, `${stackPrefix}-outputs-test-2`);
// Not included in wildcard
new IamStack(app, `${stackPrefix}-iam-test`, { env: defaultEnv });
const providing = new ProvidingStack(app, `${stackPrefix}-order-providing`);
new ConsumingStack(app, `${stackPrefix}-order-consuming`, { providingStack: providing });

new MissingSSMParameterStack(app, `${stackPrefix}-missing-ssm-parameter`, { env: defaultEnv });

new LambdaStack(app, `${stackPrefix}-lambda`);
new DockerStack(app, `${stackPrefix}-docker`);
new DockerStackWithCustomFile(app, `${stackPrefix}-docker-with-custom-file`);
new FailedStack(app, `${stackPrefix}-failed`)

if (process.env.ENABLE_VPC_TESTING) { // Gating so we don't do context fetching unless that's what we are here for
const env = { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION };
if (process.env.ENABLE_VPC_TESTING === 'DEFINE')
new DefineVpcStack(app, `${stackPrefix}-define-vpc`, { env });
if (process.env.ENABLE_VPC_TESTING === 'IMPORT')
new ImportVpcStack(app, `${stackPrefix}-import-vpc`, { env });
}

new ConditionalResourceStack(app, `${stackPrefix}-conditional-resource`)

new StackWithNestedStack(app, `${stackPrefix}-with-nested-stack`);
new StackWithNestedStackUsingParameters(app, `${stackPrefix}-with-nested-stack-using-parameters`);

new YourStack(app, `${stackPrefix}-termination-protection`, {
terminationProtection: process.env.TERMINATION_PROTECTION !== 'FALSE' ? true : false,
});

new SomeStage(app, `${stackPrefix}-stage`);
break;

case 'stage-using-context':
// Cannot be combined with other test stacks, because we use this to test
// that stage context is propagated up and causes synth to fail when combined
// with '--no-lookups'.

// Needs a dummy stack at the top level because the CLI will fail otherwise
new YourStack(app, `${stackPrefix}-toplevel`, { env: defaultEnv });
new StageUsingContext(app, `${stackPrefix}-stage-using-context`, {
env: defaultEnv,
});
break;

case 'stage-with-errors':
const stage = new StageWithError(app, `${stackPrefix}-stage-with-errors`);
stage.synth({ validateOnSynthesis: true });
break;

default:
throw new Error(`Unrecognized INTEG_STACK_SET: '${stackSet}'`);
}

app.synth();

0 comments on commit 3f75c44

Please sign in to comment.