-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deployment Configuration Construct for CodeDeploy L2 #653
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import { cloudformation } from './codedeploy.generated'; | ||
|
||
/** | ||
* The Deployment Configuration of an EC2/on-premise Deployment Group. | ||
* The default, pre-defined Configurations are available as constants on the {@link ServerDeploymentConfig} class | ||
* (`ServerDeploymentConfig.HalfAtATime`, `ServerDeploymentConfig.AllAtOnce`, etc.). | ||
* To create a custom Deployment Configuration, | ||
* instantiate the {@link ServerDeploymentConfig} Construct. | ||
*/ | ||
export interface IServerDeploymentConfig { | ||
readonly deploymentConfigName: string; | ||
readonly deploymentConfigArn: string; | ||
} | ||
|
||
/** | ||
* Properties of a reference to a CodeDeploy EC2/on-premise Deployment Configuration. | ||
* | ||
* @see ServerDeploymentConfigRef#import | ||
* @see ServerDeploymentConfigRef#export | ||
*/ | ||
export interface ServerDeploymentConfigRefProps { | ||
/** | ||
* The physical, human-readable name of the custom CodeDeploy EC2/on-premise Deployment Configuration | ||
* that we are referencing. | ||
*/ | ||
deploymentConfigName: string; | ||
} | ||
|
||
/** | ||
* Reference to a custom Deployment Configuration for an EC2/on-premise Deployment Group. | ||
*/ | ||
export abstract class ServerDeploymentConfigRef extends cdk.Construct implements IServerDeploymentConfig { | ||
/** | ||
* Import a custom Deployment Configuration for an EC2/on-premise Deployment Group defined either outside the CDK, | ||
* or in a different CDK Stack and exported using the {@link #export} method. | ||
* | ||
* @param parent the parent Construct for this new Construct | ||
* @param id the logical ID of this new Construct | ||
* @param props the properties of the referenced custom Deployment Configuration | ||
* @returns a Construct representing a reference to an existing custom Deployment Configuration | ||
*/ | ||
public static import(parent: cdk.Construct, id: string, props: ServerDeploymentConfigRefProps): | ||
ServerDeploymentConfigRef { | ||
return new ImportedServerDeploymentConfigRef(parent, id, props); | ||
} | ||
|
||
public abstract readonly deploymentConfigName: string; | ||
public abstract readonly deploymentConfigArn: string; | ||
|
||
public export(): ServerDeploymentConfigRefProps { | ||
return { | ||
deploymentConfigName: new cdk.Output(this, 'DeploymentConfigName', { | ||
value: this.deploymentConfigName, | ||
}).makeImportValue().toString(), | ||
}; | ||
} | ||
} | ||
|
||
class ImportedServerDeploymentConfigRef extends ServerDeploymentConfigRef { | ||
public readonly deploymentConfigName: string; | ||
public readonly deploymentConfigArn: string; | ||
|
||
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentConfigRefProps) { | ||
super(parent, id); | ||
|
||
this.deploymentConfigName = props.deploymentConfigName; | ||
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName); | ||
} | ||
} | ||
|
||
class DefaultServerDeploymentConfig implements IServerDeploymentConfig { | ||
public readonly deploymentConfigName: string; | ||
public readonly deploymentConfigArn: string; | ||
|
||
constructor(deploymentConfigName: string) { | ||
this.deploymentConfigName = deploymentConfigName; | ||
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName); | ||
} | ||
} | ||
|
||
/** | ||
* Construction properties of {@link ServerDeploymentConfig}. | ||
*/ | ||
export interface ServerDeploymentConfigProps { | ||
/** | ||
* The physical, human-readable name of the Deployment Configuration. | ||
* | ||
* @default a name will be auto-generated | ||
*/ | ||
deploymentConfigName?: string; | ||
|
||
/** | ||
* The minimum healhty hosts threshold expressed as an absolute number. | ||
* If you've specified this value, | ||
* you can't specify {@link #minHealthyHostPercentage}, | ||
* however one of this or {@link #minHealthyHostPercentage} is required. | ||
*/ | ||
minHealthyHostCount?: number; | ||
|
||
/** | ||
* The minmum healhty hosts threshold expressed as a percentage of the fleet. | ||
* If you've specified this value, | ||
* you can't specify {@link #minHealthyHostCount}, | ||
* however one of this or {@link #minHealthyHostCount} is required. | ||
*/ | ||
minHealthyHostPercentage?: number; | ||
} | ||
|
||
/** | ||
* A custom Deployment Configuration for an EC2/on-premise Deployment Group. | ||
*/ | ||
export class ServerDeploymentConfig extends ServerDeploymentConfigRef { | ||
public static readonly OneAtATime: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.OneAtATime'); | ||
public static readonly HalfAtATime: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.HalfAtATime'); | ||
public static readonly AllAtOnce: IServerDeploymentConfig = new DefaultServerDeploymentConfig('CodeDeployDefault.AllAtOnce'); | ||
|
||
public readonly deploymentConfigName: string; | ||
public readonly deploymentConfigArn: string; | ||
|
||
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentConfigProps) { | ||
super(parent, id); | ||
|
||
const resource = new cloudformation.DeploymentConfigResource(this, 'Resource', { | ||
deploymentConfigName: props.deploymentConfigName, | ||
minimumHealthyHosts: this.minimumHealthyHosts(props), | ||
}); | ||
|
||
this.deploymentConfigName = resource.ref.toString(); | ||
this.deploymentConfigArn = arnForDeploymentConfigName(this.deploymentConfigName); | ||
} | ||
|
||
private minimumHealthyHosts(props: ServerDeploymentConfigProps): | ||
cloudformation.DeploymentConfigResource.MinimumHealthyHostsProperty { | ||
if (props.minHealthyHostCount === undefined && props.minHealthyHostPercentage === undefined) { | ||
throw new Error('At least one of minHealthyHostCount or minHealthyHostPercentage must be specified when creating ' + | ||
'a custom Server DeploymentConfig'); | ||
} | ||
if (props.minHealthyHostCount !== undefined && props.minHealthyHostPercentage !== undefined) { | ||
throw new Error('Both minHealthyHostCount and minHealthyHostPercentage cannot be specified when creating ' + | ||
'a custom Server DeploymentConfig'); | ||
} | ||
|
||
return { | ||
type: props.minHealthyHostCount !== undefined ? 'HOST_COUNT' : 'FLEET_PERCENT', | ||
value: props.minHealthyHostCount !== undefined ? props.minHealthyHostCount : props.minHealthyHostPercentage!, | ||
}; | ||
} | ||
} | ||
|
||
function arnForDeploymentConfigName(name: string): string { | ||
return cdk.ArnUtils.fromComponents({ | ||
service: 'codedeploy', | ||
resource: 'deploymentconfig', | ||
resourceName: name, | ||
sep: ':', | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ import cdk = require("@aws-cdk/cdk"); | |
import iam = require("../../aws-iam/lib/role"); | ||
import { ServerApplication, ServerApplicationRef } from "./application"; | ||
import { cloudformation } from './codedeploy.generated'; | ||
import { IServerDeploymentConfig, ServerDeploymentConfig } from "./deployment-config"; | ||
|
||
/** | ||
* Properties of a reference to a CodeDeploy EC2/on-premise Deployment Group. | ||
|
@@ -21,6 +22,13 @@ export interface ServerDeploymentGroupRefProps { | |
* that we are referencing. | ||
*/ | ||
deploymentGroupName: string; | ||
|
||
/** | ||
* The Deployment Configuration this Deployment Group uses. | ||
* | ||
* @default ServerDeploymentConfig#OneAtATime | ||
*/ | ||
deploymentConfig?: IServerDeploymentConfig; | ||
} | ||
|
||
/** | ||
|
@@ -50,11 +58,19 @@ export abstract class ServerDeploymentGroupRef extends cdk.Construct { | |
public abstract readonly application: ServerApplicationRef; | ||
public abstract readonly deploymentGroupName: string; | ||
public abstract readonly deploymentGroupArn: string; | ||
public readonly deploymentConfig: IServerDeploymentConfig; | ||
|
||
constructor(parent: cdk.Construct, id: string, deploymentConfig?: IServerDeploymentConfig) { | ||
super(parent, id); | ||
this.deploymentConfig = deploymentConfig || ServerDeploymentConfig.OneAtATime; | ||
} | ||
|
||
public export(): ServerDeploymentGroupRefProps { | ||
return { | ||
application: this.application, | ||
deploymentGroupName: new cdk.Output(this, 'DeploymentGroupName', { value: this.deploymentGroupName }).makeImportValue().toString() | ||
deploymentGroupName: new cdk.Output(this, 'DeploymentGroupName', { | ||
value: this.deploymentGroupName | ||
}).makeImportValue().toString(), | ||
}; | ||
} | ||
} | ||
|
@@ -65,7 +81,7 @@ class ImportedServerDeploymentGroupRef extends ServerDeploymentGroupRef { | |
public readonly deploymentGroupArn: string; | ||
|
||
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentGroupRefProps) { | ||
super(parent, id); | ||
super(parent, id, props.deploymentConfig); | ||
|
||
this.application = props.application; | ||
this.deploymentGroupName = props.deploymentGroupName; | ||
|
@@ -96,6 +112,13 @@ export interface ServerDeploymentGroupProps { | |
* @default an auto-generated name will be used | ||
*/ | ||
deploymentGroupName?: string; | ||
|
||
/** | ||
* The EC2/on-premise Deployment Configuration to use for this Deployment Group. | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is an interface. Provide some pointers/example on how to use a predefined one and how to define a custom one There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Will fix. |
||
* @default ServerDeploymentConfig#OneAtATime | ||
*/ | ||
deploymentConfig?: IServerDeploymentConfig; | ||
} | ||
|
||
/** | ||
|
@@ -107,23 +130,25 @@ export class ServerDeploymentGroup extends ServerDeploymentGroupRef { | |
public readonly deploymentGroupArn: string; | ||
public readonly deploymentGroupName: string; | ||
|
||
constructor(parent: cdk.Construct, id: string, props?: ServerDeploymentGroupProps) { | ||
super(parent, id); | ||
constructor(parent: cdk.Construct, id: string, props: ServerDeploymentGroupProps = {}) { | ||
super(parent, id, props && props.deploymentConfig); | ||
|
||
this.application = (props && props.application) || new ServerApplication(this, 'Application'); | ||
this.application = props.application || new ServerApplication(this, 'Application'); | ||
|
||
this.role = (props && props.role) || new iam.Role(this, 'Role', { | ||
this.role = props.role || new iam.Role(this, 'Role', { | ||
assumedBy: new cdk.ServicePrincipal('codedeploy.amazonaws.com'), | ||
managedPolicyArns: ['arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole'], | ||
}); | ||
|
||
const resource = new cloudformation.DeploymentGroupResource(this, 'Resource', { | ||
applicationName: this.application.applicationName, | ||
deploymentGroupName: props && props.deploymentGroupName, | ||
deploymentGroupName: props.deploymentGroupName, | ||
serviceRoleArn: this.role.roleArn, | ||
deploymentConfigName: props.deploymentConfig && | ||
props.deploymentConfig.deploymentConfigName, | ||
}); | ||
|
||
this.deploymentGroupName = resource.ref; | ||
this.deploymentGroupName = resource.deploymentGroupName; | ||
this.deploymentGroupArn = deploymentGroupName2Arn(this.application.applicationName, | ||
this.deploymentGroupName); | ||
} | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe in a subsequent commit, but can we provide a sugar that allows me to do this:
It will be the natural thing for people to look for when they are “browsing” the options.
The challenge would be how to propagate the parent construct. I think that the construct id can be just DeploymentConfig if you attach this to the DeploymentGroup because a deployment group can only have one deployment config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I don't see an easy way of allowing both that form, and
deploymentConfig: new ServerDeploymentConfig(this, 'id', { minHealthyHostCount: 5 })
...