Skip to content

Commit

Permalink
selectively deploy windows fleet
Browse files Browse the repository at this point in the history
  • Loading branch information
tmokmss committed Dec 6, 2023
1 parent 58be1eb commit c2cf520
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 62 deletions.
121 changes: 67 additions & 54 deletions lib/jenkins-unity-build-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ interface JenkinsUnityBuildStackProps extends cdk.StackProps {
*/
readonly macAmiId?: string;

/**
* Set this to true if you use Windows fleetF.
*
* @default No Windows fleet is provisioned.
*/
readonly useWindows?: boolean;

/**
* You can optionally pass a VPC to deploy the stack
*
Expand Down Expand Up @@ -108,62 +115,68 @@ export class JenkinsUnityBuildStack extends cdk.Stack {
// subnet: vpc.privateSubnets[0],
});

const linuxAgent = AgentEC2Fleet.linuxFleet(this, 'JenkinsLinuxAgent', {
vpc,
sshKeyName: keyPair.keyPairName,
artifactBucket,
rootVolumeSize: Size.gibibytes(30),
dataVolumeSize: Size.gibibytes(100),
// You may want to add several instance types to avoid from insufficient Spot capacity.
instanceTypes: [
ec2.InstanceType.of(InstanceClass.C5, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C5A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C5N, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C4, InstanceSize.XLARGE),
],
name: 'linux-fleet',
label: 'linux',
fleetMinSize: 1,
fleetMaxSize: 4,
// You can explicitly set a subnet agents will run in
// subnets: [vpc.privateSubnets[0]],
});
const ec2FleetAgents = [];

ec2FleetAgents.push(
AgentEC2Fleet.linuxFleet(this, 'JenkinsLinuxAgent', {
vpc,
sshKeyName: keyPair.keyPairName,
artifactBucket,
rootVolumeSize: Size.gibibytes(30),
dataVolumeSize: Size.gibibytes(100),
// You may want to add several instance types to avoid from insufficient Spot capacity.
instanceTypes: [
ec2.InstanceType.of(InstanceClass.C5, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C5A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C5N, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.C4, InstanceSize.XLARGE),
],
name: 'linux-fleet',
label: 'linux',
fleetMinSize: 1,
fleetMaxSize: 4,
// You can explicitly set a subnet agents will run in
// subnets: [vpc.privateSubnets[0]],
}),
);

// agents for small tasks
const linuxAgentSmall = AgentEC2Fleet.linuxFleet(this, 'JenkinsLinuxAgentSmall', {
vpc,
sshKeyName: keyPair.keyPairName,
rootVolumeSize: Size.gibibytes(20),
name: 'linux-fleet-small',
label: 'small',
fleetMinSize: 1,
fleetMaxSize: 2,
numExecutors: 5,
instanceTypes: [ec2.InstanceType.of(InstanceClass.T3, InstanceSize.MEDIUM)],
});

const windowsAgent = AgentEC2Fleet.windowsFleet(this, 'JenkinsWindowsAgent', {
vpc,
sshKeyName: keyPair.keyPairName,
artifactBucket,
rootVolumeSize: Size.gibibytes(50),
dataVolumeSize: Size.gibibytes(100),
// You may want to add several instance types to avoid from insufficient Spot capacity.
instanceTypes: [
ec2.InstanceType.of(InstanceClass.M6A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5N, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5, InstanceSize.XLARGE),
],
name: 'windows-fleet',
label: 'windows',
fleetMinSize: 1,
fleetMaxSize: 4,
// You can explicitly set a subnet agents will run in
// subnets: [vpc.privateSubnets[0]],
});

const ec2FleetAgents = [linuxAgent, linuxAgentSmall, windowsAgent];
ec2FleetAgents.push(
AgentEC2Fleet.linuxFleet(this, 'JenkinsLinuxAgentSmall', {
vpc,
sshKeyName: keyPair.keyPairName,
rootVolumeSize: Size.gibibytes(20),
name: 'linux-fleet-small',
label: 'small',
fleetMinSize: 1,
fleetMaxSize: 2,
numExecutors: 5,
instanceTypes: [ec2.InstanceType.of(InstanceClass.T3, InstanceSize.MEDIUM)],
}),
);

if (props.useWindows ?? false) {
ec2FleetAgents.push(
AgentEC2Fleet.windowsFleet(this, 'JenkinsWindowsAgent', {
vpc,
sshKeyName: keyPair.keyPairName,
artifactBucket,
rootVolumeSize: Size.gibibytes(50),
dataVolumeSize: Size.gibibytes(100),
// You may want to add several instance types to avoid from insufficient Spot capacity.
instanceTypes: [
ec2.InstanceType.of(InstanceClass.M6A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5A, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5N, InstanceSize.XLARGE),
ec2.InstanceType.of(InstanceClass.M5, InstanceSize.XLARGE),
],
name: 'windows-fleet',
label: 'windows',
fleetMinSize: 1,
fleetMaxSize: 4,
}),
);
}

const macAgents = [];

Expand Down
40 changes: 32 additions & 8 deletions test/__snapshots__/jenkins-unity-build.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1415,14 +1415,20 @@ TOKEN=\`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-meta
AZ=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .availabilityZone\`
INSTANCE_ID=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id\`
REGION=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/region\`
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=tag:Kind,Values=TestStack-JenkinsLinuxAgent Name=availability-zone,Values=$AZ Name=status,Values=available --query 'Volumes[0].VolumeId' --output text --region $REGION)
# find a volume with the same kind tag as the instance
# choose a random volume to use evenly across all volumes of the same kind
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=tag:Kind,Values=TestStack-JenkinsLinuxAgent Name=availability-zone,Values=$AZ Name=status,Values=available --query 'Volumes[*].[VolumeId]' --output text --region $REGION | shuf | head -1)
if [ "$VOLUME_ID" ];then
echo "found volume \${VOLUME}"
echo "found volume $VOLUME_ID"
DEVICE_NAME="/dev/xvdf"
# There is possibly a race condition between other instances.
# We may want to retry attach-volume according to the return code (currently omitted).
aws ec2 attach-volume --device $DEVICE_NAME --instance-id $INSTANCE_ID --volume-id $VOLUME_ID --region $REGION
if [ $? -ne 0 ]; then
# There is possibly a race condition between other instances (e.g. the volume is occupied by another instance).
# Terminate the instance if attaching volume failed. ASG will retry booting an instance.
shutdown now -h
fi
# we should do polling for the volume status instead, but it usually finishes in a few seconds...
sleep 10
Expand All @@ -1442,6 +1448,12 @@ if [ "$VOLUME_ID" ];then
printf "\\nUUID=\${UUID} \${JENKINS_DIR} xfs defaults,nofail 0 2\\n" >> /etc/fstab
fi
# Set linux parameters to avoid errors when trying to connect an instance via SSM during Unity build
# https://stackoverflow.com/questions/69337154/aws-ec2-terminal-session-terminated-with-plugin-with-name-standard-stream-not-f
echo "fs.file-max=100000" >> /etc/sysctl.conf
echo "fs.inotify.max_user_watches=1048576" >> /etc/sysctl.conf
echo "fs.inotify.max_user_instances=256" >> /etc/sysctl.conf
# install docker
yum install -y docker
systemctl enable docker
Expand Down Expand Up @@ -2054,14 +2066,20 @@ TOKEN=\`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-meta
AZ=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/dynamic/instance-identity/document | jq -r .availabilityZone\`
INSTANCE_ID=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/instance-id\`
REGION=\`curl -H "X-aws-ec2-metadata-token: $TOKEN" -s http://169.254.169.254/latest/meta-data/placement/region\`
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=tag:Kind,Values=TestStack-JenkinsLinuxAgentSmall Name=availability-zone,Values=$AZ Name=status,Values=available --query 'Volumes[0].VolumeId' --output text --region $REGION)
# find a volume with the same kind tag as the instance
# choose a random volume to use evenly across all volumes of the same kind
VOLUME_ID=$(aws ec2 describe-volumes --filters Name=tag:Kind,Values=TestStack-JenkinsLinuxAgentSmall Name=availability-zone,Values=$AZ Name=status,Values=available --query 'Volumes[*].[VolumeId]' --output text --region $REGION | shuf | head -1)
if [ "$VOLUME_ID" ];then
echo "found volume \${VOLUME}"
echo "found volume $VOLUME_ID"
DEVICE_NAME="/dev/xvdf"
# There is possibly a race condition between other instances.
# We may want to retry attach-volume according to the return code (currently omitted).
aws ec2 attach-volume --device $DEVICE_NAME --instance-id $INSTANCE_ID --volume-id $VOLUME_ID --region $REGION
if [ $? -ne 0 ]; then
# There is possibly a race condition between other instances (e.g. the volume is occupied by another instance).
# Terminate the instance if attaching volume failed. ASG will retry booting an instance.
shutdown now -h
fi
# we should do polling for the volume status instead, but it usually finishes in a few seconds...
sleep 10
Expand All @@ -2081,6 +2099,12 @@ if [ "$VOLUME_ID" ];then
printf "\\nUUID=\${UUID} \${JENKINS_DIR} xfs defaults,nofail 0 2\\n" >> /etc/fstab
fi
# Set linux parameters to avoid errors when trying to connect an instance via SSM during Unity build
# https://stackoverflow.com/questions/69337154/aws-ec2-terminal-session-terminated-with-plugin-with-name-standard-stream-not-f
echo "fs.file-max=100000" >> /etc/sysctl.conf
echo "fs.inotify.max_user_watches=1048576" >> /etc/sysctl.conf
echo "fs.inotify.max_user_instances=256" >> /etc/sysctl.conf
# install docker
yum install -y docker
systemctl enable docker
Expand Down
1 change: 1 addition & 0 deletions test/jenkins-unity-build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ test('Snapshot test', () => {
allowedCidrs: ['127.0.0.1/32'],
macAmiId: 'ami-013846afc111c94b0',
licenseServerBaseUrl: 'http://10.0.0.100:8080',
useWindows: true,
});
const template = Template.fromStack(stack);
expect(template).toMatchSnapshot();
Expand Down

0 comments on commit c2cf520

Please sign in to comment.