Skip to content

Commit d911c58

Browse files
authoredNov 30, 2021
fix(apprunner): startCommand and environment are ignored in imageConfiguration (#16939)
This PR addresses the following issues 1. custom environment variables and start commands should be allowed for `imageConfiguration` 2. buildCommand, environment and startCommand should be allowed for `codeConfigurationValues` Fixes: #16812 - [x] add tests - [x] implementation ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent c62377e commit d911c58

File tree

2 files changed

+204
-9
lines changed

2 files changed

+204
-9
lines changed
 

‎packages/@aws-cdk/aws-apprunner/lib/service.ts

+37-9
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ export class Runtime {
118118
private constructor(public readonly name: string) { }
119119
}
120120

121+
/**
122+
* The environment variable for the service.
123+
*/
124+
interface EnvironmentVariable {
125+
readonly name: string;
126+
readonly value: string;
127+
}
121128

122129
/**
123130
* Result of binding `Source` into a `Service`.
@@ -707,6 +714,10 @@ export class Service extends cdk.Resource {
707714
private readonly props: ServiceProps;
708715
private accessRole?: iam.IRole;
709716
private source: SourceConfig;
717+
/**
718+
* Environment variables for this service
719+
*/
720+
private environment?: { [key: string]: string } = {};
710721

711722
/**
712723
* The ARN of the Service.
@@ -798,22 +809,39 @@ export class Service extends cdk.Resource {
798809

799810
}
800811
private renderCodeConfigurationValues(props: CodeConfigurationValues): any {
812+
this.environment = props.environment;
801813
return {
802-
...props,
814+
port: props.port,
815+
buildCommand: props.buildCommand,
803816
runtime: props.runtime.name,
817+
runtimeEnvironmentVariables: this.renderEnvironmentVariables(),
818+
startCommand: props.startCommand,
804819
};
805820
}
806821
private renderImageRepository(): any {
807822
const repo = this.source.imageRepository!;
808-
if (repo.imageConfiguration?.port) {
809-
// convert port from type number to string
810-
return Object.assign(repo, {
811-
imageConfiguration: {
812-
port: repo.imageConfiguration.port.toString(),
813-
},
814-
});
823+
this.environment = repo.imageConfiguration?.environment;
824+
return Object.assign(repo, {
825+
imageConfiguration: {
826+
port: repo.imageConfiguration?.port?.toString(),
827+
startCommand: repo.imageConfiguration?.startCommand,
828+
runtimeEnvironmentVariables: this.renderEnvironmentVariables(),
829+
},
830+
});
831+
}
832+
833+
private renderEnvironmentVariables(): EnvironmentVariable[] | undefined {
834+
if (this.environment) {
835+
let env: EnvironmentVariable[] = [];
836+
for (const [key, value] of Object.entries(this.environment)) {
837+
if (key.startsWith('AWSAPPRUNNER')) {
838+
throw new Error(`Environment variable key ${key} with a prefix of AWSAPPRUNNER is not allowed`);
839+
}
840+
env.push({ name: key, value: value });
841+
}
842+
return env;
815843
} else {
816-
return repo;
844+
return undefined;
817845
}
818846
}
819847

‎packages/@aws-cdk/aws-apprunner/test/service.test.ts

+167
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as path from 'path';
2+
import '@aws-cdk/assert-internal/jest';
23
import { Template } from '@aws-cdk/assertions';
34
import * as ecr from '@aws-cdk/aws-ecr';
45
import * as ecr_assets from '@aws-cdk/aws-ecr-assets';
@@ -32,6 +33,92 @@ test('create a service with ECR Public(image repository type: ECR_PUBLIC)', () =
3233
});
3334
});
3435

36+
test('custom environment variables and start commands are allowed for imageConfiguration with defined port', () => {
37+
// GIVEN
38+
const app = new cdk.App();
39+
const stack = new cdk.Stack(app, 'demo-stack');
40+
// WHEN
41+
new Service(stack, 'DemoService', {
42+
source: Source.fromEcrPublic({
43+
imageConfiguration: {
44+
port: 8000,
45+
environment: {
46+
foo: 'fooval',
47+
bar: 'barval',
48+
},
49+
startCommand: '/root/start-command.sh',
50+
},
51+
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
52+
}),
53+
});
54+
// we should have the service
55+
Template.fromStack(stack).hasResourceProperties('AWS::AppRunner::Service', {
56+
SourceConfiguration: {
57+
AuthenticationConfiguration: {},
58+
ImageRepository: {
59+
ImageConfiguration: {
60+
Port: '8000',
61+
RuntimeEnvironmentVariables: [
62+
{
63+
Name: 'foo',
64+
Value: 'fooval',
65+
},
66+
{
67+
Name: 'bar',
68+
Value: 'barval',
69+
},
70+
],
71+
StartCommand: '/root/start-command.sh',
72+
},
73+
ImageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
74+
ImageRepositoryType: 'ECR_PUBLIC',
75+
},
76+
},
77+
});
78+
});
79+
80+
test('custom environment variables and start commands are allowed for imageConfiguration with port undefined', () => {
81+
// GIVEN
82+
const app = new cdk.App();
83+
const stack = new cdk.Stack(app, 'demo-stack');
84+
// WHEN
85+
new Service(stack, 'DemoService', {
86+
source: Source.fromEcrPublic({
87+
imageConfiguration: {
88+
environment: {
89+
foo: 'fooval',
90+
bar: 'barval',
91+
},
92+
startCommand: '/root/start-command.sh',
93+
},
94+
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
95+
}),
96+
});
97+
// we should have the service
98+
Template.fromStack(stack).hasResourceProperties('AWS::AppRunner::Service', {
99+
SourceConfiguration: {
100+
AuthenticationConfiguration: {},
101+
ImageRepository: {
102+
ImageConfiguration: {
103+
RuntimeEnvironmentVariables: [
104+
{
105+
Name: 'foo',
106+
Value: 'fooval',
107+
},
108+
{
109+
Name: 'bar',
110+
Value: 'barval',
111+
},
112+
],
113+
StartCommand: '/root/start-command.sh',
114+
},
115+
ImageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
116+
ImageRepositoryType: 'ECR_PUBLIC',
117+
},
118+
},
119+
});
120+
});
121+
35122
test('create a service from existing ECR repository(image repository type: ECR)', () => {
36123
// GIVEN
37124
const app = new cdk.App();
@@ -249,6 +336,66 @@ test('create a service with github repository - undefined branch name is allowed
249336
});
250337
});
251338

339+
test('create a service with github repository - buildCommand, environment and startCommand are allowed', () => {
340+
// GIVEN
341+
const app = new cdk.App();
342+
const stack = new cdk.Stack(app, 'demo-stack');
343+
// WHEN
344+
new Service(stack, 'DemoService', {
345+
source: Source.fromGitHub({
346+
repositoryUrl: 'https://github.com/aws-containers/hello-app-runner',
347+
configurationSource: ConfigurationSourceType.API,
348+
codeConfigurationValues: {
349+
runtime: Runtime.PYTHON_3,
350+
port: '8000',
351+
buildCommand: '/root/build.sh',
352+
environment: {
353+
foo: 'fooval',
354+
bar: 'barval',
355+
},
356+
startCommand: '/root/start.sh',
357+
},
358+
connection: GitHubConnection.fromConnectionArn('MOCK'),
359+
}),
360+
});
361+
362+
// THEN
363+
// we should have the service with the branch value as 'main'
364+
Template.fromStack(stack).hasResourceProperties('AWS::AppRunner::Service', {
365+
SourceConfiguration: {
366+
AuthenticationConfiguration: {
367+
ConnectionArn: 'MOCK',
368+
},
369+
CodeRepository: {
370+
CodeConfiguration: {
371+
CodeConfigurationValues: {
372+
Port: '8000',
373+
Runtime: 'PYTHON_3',
374+
BuildCommand: '/root/build.sh',
375+
RuntimeEnvironmentVariables: [
376+
{
377+
Name: 'foo',
378+
Value: 'fooval',
379+
},
380+
{
381+
Name: 'bar',
382+
Value: 'barval',
383+
},
384+
],
385+
StartCommand: '/root/start.sh',
386+
},
387+
ConfigurationSource: 'API',
388+
},
389+
RepositoryUrl: 'https://github.com/aws-containers/hello-app-runner',
390+
SourceCodeVersion: {
391+
Type: 'BRANCH',
392+
Value: 'main',
393+
},
394+
},
395+
},
396+
});
397+
});
398+
252399

253400
test('import from service name', () => {
254401
// GIVEN
@@ -417,3 +564,23 @@ test('custom cpu and memory units are allowed', () => {
417564
},
418565
});
419566
});
567+
568+
test('environment variable with a prefix of AWSAPPRUNNER should throw an error', () => {
569+
// GIVEN
570+
const app = new cdk.App();
571+
const stack = new cdk.Stack(app, 'demo-stack');
572+
// WHEN
573+
// we should have the service
574+
expect(() => {
575+
new Service(stack, 'DemoService', {
576+
source: Source.fromEcrPublic({
577+
imageConfiguration: {
578+
environment: {
579+
AWSAPPRUNNER_FOO: 'bar',
580+
},
581+
},
582+
imageIdentifier: 'public.ecr.aws/aws-containers/hello-app-runner:latest',
583+
}),
584+
});
585+
}).toThrow('Environment variable key AWSAPPRUNNER_FOO with a prefix of AWSAPPRUNNER is not allowed');
586+
});

0 commit comments

Comments
 (0)
Please sign in to comment.