Skip to content

Commit e6b67ad

Browse files
authored
feat(aws-codedeploy): Deployment Configuration Construct. (#653)
Part of the work on a AWS Construct Library for CodeDeploy.
1 parent d68b6c3 commit e6b67ad

9 files changed

+365
-18
lines changed

packages/@aws-cdk/aws-codedeploy/README.md

+33-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ To import an already existing Application:
1616

1717
```ts
1818
const application = codedeploy.ServerApplicationRef.import(this, 'ExistingCodeDeployApplication', {
19-
applicationName: new codedeploy.ApplicationName('MyExistingApplication'),
19+
applicationName: 'MyExistingApplication',
2020
});
2121
```
2222

@@ -39,7 +39,38 @@ To import an already existing Deployment Group:
3939
```ts
4040
const deploymentGroup = codedeploy.ServerDeploymentGroupRef.import(this, 'ExistingCodeDeployDeploymentGroup', {
4141
application,
42-
deploymentGroupName: new codedeploy.DeploymentGroupName('MyExistingDeploymentGroup'),
42+
deploymentGroupName: 'MyExistingDeploymentGroup',
43+
});
44+
```
45+
46+
### Deployment Configurations
47+
48+
You can also pass a Deployment Configuration when creating the Deployment Group:
49+
50+
```ts
51+
const deploymentGroup = new codedeploy.ServerDeploymentGroup(this, 'CodeDeployDeploymentGroup', {
52+
deploymentConfig: codedeploy.ServerDeploymentConfig.AllAtOnce,
53+
});
54+
```
55+
56+
The default Deployment Configuration is `ServerDeploymentConfig.OneAtATime`.
57+
58+
You can also create a custom Deployment Configuration:
59+
60+
```ts
61+
const deploymentConfig = new codedeploy.ServerDeploymentConfig(this, 'DeploymentConfiguration', {
62+
deploymentConfigName: 'MyDeploymentConfiguration', // optional property
63+
// one of these is required, but both cannot be specified at the same time
64+
minHealthyHostCount: 2,
65+
minHealthyHostPercentage: 75,
66+
});
67+
```
68+
69+
Or import an existing one:
70+
71+
```ts
72+
const deploymentConfig = codedeploy.ServerDeploymentConfigRef.import(this, 'ExistingDeploymentConfiguration', {
73+
deploymentConfigName: 'MyExistingDeploymentConfiguration',
4374
});
4475
```
4576

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
import cdk = require('@aws-cdk/cdk');
2+
import { cloudformation } from './codedeploy.generated';
3+
4+
/**
5+
* The Deployment Configuration of an EC2/on-premise Deployment Group.
6+
* The default, pre-defined Configurations are available as constants on the {@link ServerDeploymentConfig} class
7+
* (`ServerDeploymentConfig.HalfAtATime`, `ServerDeploymentConfig.AllAtOnce`, etc.).
8+
* To create a custom Deployment Configuration,
9+
* instantiate the {@link ServerDeploymentConfig} Construct.
10+
*/
11+
export interface IServerDeploymentConfig {
12+
readonly deploymentConfigName: string;
13+
readonly deploymentConfigArn: string;
14+
}
15+
16+
/**
17+
* Properties of a reference to a CodeDeploy EC2/on-premise Deployment Configuration.
18+
*
19+
* @see ServerDeploymentConfigRef#import
20+
* @see ServerDeploymentConfigRef#export
21+
*/
22+
export interface ServerDeploymentConfigRefProps {
23+
/**
24+
* The physical, human-readable name of the custom CodeDeploy EC2/on-premise Deployment Configuration
25+
* that we are referencing.
26+
*/
27+
deploymentConfigName: string;
28+
}
29+
30+
/**
31+
* Reference to a custom Deployment Configuration for an EC2/on-premise Deployment Group.
32+
*/
33+
export abstract class ServerDeploymentConfigRef extends cdk.Construct implements IServerDeploymentConfig {
34+
/**
35+
* Import a custom Deployment Configuration for an EC2/on-premise Deployment Group defined either outside the CDK,
36+
* or in a different CDK Stack and exported using the {@link #export} method.
37+
*
38+
* @param parent the parent Construct for this new Construct
39+
* @param id the logical ID of this new Construct
40+
* @param props the properties of the referenced custom Deployment Configuration
41+
* @returns a Construct representing a reference to an existing custom Deployment Configuration
42+
*/
43+
public static import(parent: cdk.Construct, id: string, props: ServerDeploymentConfigRefProps):
44+
ServerDeploymentConfigRef {
45+
return new ImportedServerDeploymentConfigRef(parent, id, props);
46+
}
47+
48+
public abstract readonly deploymentConfigName: string;
49+
public abstract readonly deploymentConfigArn: string;
50+
51+
public export(): ServerDeploymentConfigRefProps {
52+
return {
53+
deploymentConfigName: new cdk.Output(this, 'DeploymentConfigName', {
54+
value: this.deploymentConfigName,
55+
}).makeImportValue().toString(),
56+
};
57+
}
58+
}
59+
60+
class ImportedServerDeploymentConfigRef extends ServerDeploymentConfigRef {
61+
public readonly deploymentConfigName: string;
62+
public readonly deploymentConfigArn: string;
63+
64+
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentConfigRefProps) {
65+
super(parent, id);
66+
67+
this.deploymentConfigName = props.deploymentConfigName;
68+
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName);
69+
}
70+
}
71+
72+
class DefaultServerDeploymentConfig implements IServerDeploymentConfig {
73+
public readonly deploymentConfigName: string;
74+
public readonly deploymentConfigArn: string;
75+
76+
constructor(deploymentConfigName: string) {
77+
this.deploymentConfigName = deploymentConfigName;
78+
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName);
79+
}
80+
}
81+
82+
/**
83+
* Construction properties of {@link ServerDeploymentConfig}.
84+
*/
85+
export interface ServerDeploymentConfigProps {
86+
/**
87+
* The physical, human-readable name of the Deployment Configuration.
88+
*
89+
* @default a name will be auto-generated
90+
*/
91+
deploymentConfigName?: string;
92+
93+
/**
94+
* The minimum healhty hosts threshold expressed as an absolute number.
95+
* If you've specified this value,
96+
* you can't specify {@link #minHealthyHostPercentage},
97+
* however one of this or {@link #minHealthyHostPercentage} is required.
98+
*/
99+
minHealthyHostCount?: number;
100+
101+
/**
102+
* The minmum healhty hosts threshold expressed as a percentage of the fleet.
103+
* If you've specified this value,
104+
* you can't specify {@link #minHealthyHostCount},
105+
* however one of this or {@link #minHealthyHostCount} is required.
106+
*/
107+
minHealthyHostPercentage?: number;
108+
}
109+
110+
/**
111+
* A custom Deployment Configuration for an EC2/on-premise Deployment Group.
112+
*/
113+
export class ServerDeploymentConfig extends ServerDeploymentConfigRef {
114+
public static readonly OneAtATime: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.OneAtATime');
115+
public static readonly HalfAtATime: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.HalfAtATime');
116+
public static readonly AllAtOnce: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.AllAtOnce');
117+
118+
public readonly deploymentConfigName: string;
119+
public readonly deploymentConfigArn: string;
120+
121+
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentConfigProps) {
122+
super(parent, id);
123+
124+
const resource = new cloudformation.DeploymentConfigResource(this, 'Resource', {
125+
deploymentConfigName: props.deploymentConfigName,
126+
minimumHealthyHosts: this.minimumHealthyHosts(props),
127+
});
128+
129+
this.deploymentConfigName = resource.ref.toString();
130+
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName);
131+
}
132+
133+
private minimumHealthyHosts(props: ServerDeploymentConfigProps):
134+
cloudformation.DeploymentConfigResource.MinimumHealthyHostsProperty {
135+
if (props.minHealthyHostCount === undefined && props.minHealthyHostPercentage === undefined) {
136+
throw new Error('At least one of minHealthyHostCount or minHealthyHostPercentage must be specified when creating ' +
137+
'a custom Server DeploymentConfig');
138+
}
139+
if (props.minHealthyHostCount !== undefined && props.minHealthyHostPercentage !== undefined) {
140+
throw new Error('Both minHealthyHostCount and minHealthyHostPercentage cannot be specified when creating ' +
141+
'a custom Server DeploymentConfig');
142+
}
143+
144+
return {
145+
type: props.minHealthyHostCount !== undefined ? 'HOST_COUNT' : 'FLEET_PERCENT',
146+
value: props.minHealthyHostCount !== undefined ? props.minHealthyHostCount : props.minHealthyHostPercentage!,
147+
};
148+
}
149+
}
150+
151+
function arnForDeploymentConfigName(name: string): string {
152+
return cdk.ArnUtils.fromComponents({
153+
service: 'codedeploy',
154+
resource: 'deploymentconfig',
155+
resourceName: name,
156+
sep: ':',
157+
});
158+
}

packages/@aws-cdk/aws-codedeploy/lib/deployment-group.ts

+33-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import cdk = require("@aws-cdk/cdk");
22
import iam = require("../../aws-iam/lib/role");
33
import { ServerApplication, ServerApplicationRef } from "./application";
44
import { cloudformation } from './codedeploy.generated';
5+
import { IServerDeploymentConfig, ServerDeploymentConfig } from "./deployment-config";
56

67
/**
78
* Properties of a reference to a CodeDeploy EC2/on-premise Deployment Group.
@@ -21,6 +22,13 @@ export interface ServerDeploymentGroupRefProps {
2122
* that we are referencing.
2223
*/
2324
deploymentGroupName: string;
25+
26+
/**
27+
* The Deployment Configuration this Deployment Group uses.
28+
*
29+
* @default ServerDeploymentConfig#OneAtATime
30+
*/
31+
deploymentConfig?: IServerDeploymentConfig;
2432
}
2533

2634
/**
@@ -50,11 +58,19 @@ export abstract class ServerDeploymentGroupRef extends cdk.Construct {
5058
public abstract readonly application: ServerApplicationRef;
5159
public abstract readonly deploymentGroupName: string;
5260
public abstract readonly deploymentGroupArn: string;
61+
public readonly deploymentConfig: IServerDeploymentConfig;
62+
63+
constructor(parent: cdk.Construct, id: string, deploymentConfig?: IServerDeploymentConfig) {
64+
super(parent, id);
65+
this.deploymentConfig = deploymentConfig || ServerDeploymentConfig.OneAtATime;
66+
}
5367

5468
public export(): ServerDeploymentGroupRefProps {
5569
return {
5670
application: this.application,
57-
deploymentGroupName: new cdk.Output(this, 'DeploymentGroupName', { value: this.deploymentGroupName }).makeImportValue().toString()
71+
deploymentGroupName: new cdk.Output(this, 'DeploymentGroupName', {
72+
value: this.deploymentGroupName
73+
}).makeImportValue().toString(),
5874
};
5975
}
6076
}
@@ -65,7 +81,7 @@ class ImportedServerDeploymentGroupRef extends ServerDeploymentGroupRef {
6581
public readonly deploymentGroupArn: string;
6682

6783
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentGroupRefProps) {
68-
super(parent, id);
84+
super(parent, id, props.deploymentConfig);
6985

7086
this.application = props.application;
7187
this.deploymentGroupName = props.deploymentGroupName;
@@ -96,6 +112,13 @@ export interface ServerDeploymentGroupProps {
96112
* @default an auto-generated name will be used
97113
*/
98114
deploymentGroupName?: string;
115+
116+
/**
117+
* The EC2/on-premise Deployment Configuration to use for this Deployment Group.
118+
*
119+
* @default ServerDeploymentConfig#OneAtATime
120+
*/
121+
deploymentConfig?: IServerDeploymentConfig;
99122
}
100123

101124
/**
@@ -107,23 +130,25 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef {
107130
public readonly deploymentGroupArn: string;
108131
public readonly deploymentGroupName: string;
109132

110-
constructor(parent: cdk.Construct, id: string, props?: ServerDeploymentGroupProps) {
111-
super(parent, id);
133+
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentGroupProps = {}) {
134+
super(parent, id, props && props.deploymentConfig);
112135

113-
this.application = (props && props.application) || new ServerApplication(this, 'Application');
136+
this.application = props.application || new ServerApplication(this, 'Application');
114137

115-
this.role = (props && props.role) || new iam.Role(this, 'Role', {
138+
this.role = props.role || new iam.Role(this, 'Role', {
116139
assumedBy: new cdk.ServicePrincipal('codedeploy.amazonaws.com'),
117140
managedPolicyArns: ['arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole'],
118141
});
119142

120143
const resource = new cloudformation.DeploymentGroupResource(this, 'Resource', {
121144
applicationName: this.application.applicationName,
122-
deploymentGroupName: props && props.deploymentGroupName,
145+
deploymentGroupName: props.deploymentGroupName,
123146
serviceRoleArn: this.role.roleArn,
147+
deploymentConfigName: props.deploymentConfig &&
148+
props.deploymentConfig.deploymentConfigName,
124149
});
125150

126-
this.deploymentGroupName = resource.ref;
151+
this.deploymentGroupName = resource.deploymentGroupName;
127152
this.deploymentGroupArn = deploymentGroupName2Arn(this.application.applicationName,
128153
this.deploymentGroupName);
129154
}

packages/@aws-cdk/aws-codedeploy/lib/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './application';
2+
export * from './deployment-config';
23
export * from './deployment-group';
34
export * from './pipeline-action';
45

packages/@aws-cdk/aws-codedeploy/test/test.codedeploy.ts

-8
This file was deleted.

0 commit comments

Comments
 (0)