in lib/constructs/jenkins.ts [24:223]
constructor(scope: cdk.Construct, id: string, props: JenkinsPatternProps) {
super(scope, id);
const jenkinsSecurityGroup = new ec2.SecurityGroup(this, "jenkins-sg", {
vpc: props.vpc,
});
props.allowAccessFrom.forEach((p) => {
jenkinsSecurityGroup.addIngressRule(p, ec2.Port.tcp(80));
jenkinsSecurityGroup.addIngressRule(p, ec2.Port.tcp(443));
});
// for build nodes
[80, 443, 50000].forEach((port) => {
jenkinsSecurityGroup.addIngressRule(
ec2.Peer.ipv4(props.vpc.vpcCidrBlock),
ec2.Port.tcp(port)
);
});
const jenkinsRole = new iam.Role(this, "jenkins-role", {
assumedBy: new ServicePrincipal("ec2.amazonaws.com"),
});
jenkinsRole.attachInlinePolicy(
createSSMPolicy(this, props.ssmLoggingBucket)
);
props.backupBucket.grantReadWrite(jenkinsRole);
// to launch instance from Jenkins
jenkinsRole.attachInlinePolicy(
new iam.Policy(scope, "jenkins-ec2-policy", {
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ["*"],
actions: ["iam:ListInstanceProfilesForRole", "iam:PassRole"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ["*"],
actions: [
"ec2:DescribeSpotInstanceRequests",
"ec2:CancelSpotInstanceRequests",
"ec2:GetConsoleOutput",
"ec2:DescribeInstances",
"ec2:DescribeKeyPairs",
"ec2:DescribeRegions",
"ec2:DescribeImages",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:GetPasswordData",
],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ["*"],
actions: [
"ec2:RequestSpotInstances",
"ec2:RunInstances",
"ec2:CreateTags",
"ec2:DeleteTags",
],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: ["*"],
actions: [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:TerminateInstances",
],
conditions: {
StringEquals: {
"ec2:ResourceTag/Purpose": "buildnode",
},
},
}),
],
})
);
/* eslint-disable no-useless-escape */
const userData = ec2.UserData.custom(`
#!/usr/bin/env bash
set -eux
sudo yum update -y
sudo yum install -y python3 java-11-amazon-corretto-headless
sudo pip3 install boto3
sudo alternatives --install /usr/bin/java java /usr/lib/jvm/java-11-amazon-corretto.x86_64/bin/java 20000
sudo update-alternatives --auto java
java -version
sudo amazon-linux-extras install epel -y
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
sudo yum upgrade -y
sudo yum install -y jenkins
rpm -qa | grep jenkins
JENKINS_HOME="/var/lib/jenkins/"
# make backup script
cat << EOF | sudo tee /usr/local/backup-jenkins.sh
#!/usr/bin/env bash
set -eux
BACKUP_FILE="/tmp/jenkins-\\\$(date +"%Y-%m-%d-%H-%M-%S").tar.gz"
# to avoid tar warning (file changed)
set +e
tar -zcvf \\\${BACKUP_FILE} -C $JENKINS_HOME .
code=\\\$?
if [ \\\$code -ne 0 -a \\\$code -ne 1 ]; then
echo "Fatal Error"
exit \\\$code
fi
set -e
aws s3 cp \\\${BACKUP_FILE} s3://${
props.backupBucket.bucketName
}/jenkins-backup/
rm -rf \\\${BACKUP_FILE}
EOF
sudo chmod 755 /usr/local/backup-jenkins.sh
sudo chown jenkins:jenkins /usr/local/backup-jenkins.sh
# environment settings for easy launching
cat << EOF | sudo tee /usr/local/env-vars-for-launching-buildnode.sh
#!/usr/bin/env bash
export BN_SUBNET_ID=${props.vpc.publicSubnets[0].subnetId}
export BN_INSTANCE_PROFILE_ARN=${props.buildNodeInstanceProfile.attrArn}
export BN_SG_ID=${props.buildNodeSecurityGroup.securityGroupId}
export BN_REGION=${cdk.Stack.of(this).region}
export BUILD_ARTIFACT_BUCKET=${props.artifactBucket.bucketName}
EOF
sudo chmod 755 /usr/local/env-vars-for-launching-buildnode.sh
sudo chown jenkins:jenkins /usr/local/env-vars-for-launching-buildnode.sh
# to listen on 80 port
sudo sed -ie 's/^JENKINS_PORT="8080"$/JENKINS_PORT="80"/' /etc/sysconfig/jenkins
sudo sed -ie 's/^JENKINS_USER="jenkins"$/JENKINS_USER="root"/' /etc/sysconfig/jenkins
sudo systemctl enable jenkins
sudo systemctl start jenkins
`);
/* eslint-enable no-useless-escape */
const instanceType = ec2.InstanceType.of(
ec2.InstanceClass.M5,
ec2.InstanceSize.XLARGE
);
const machineImage = ec2.MachineImage.latestAmazonLinux({
generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
});
const ebsSetting = {
volumeSize: 30,
volumeType: autoscaling.EbsDeviceVolumeType.GP3,
};
this.instance = new ec2.Instance(this, "jenkins-instance", {
vpc: props.vpc,
vpcSubnets: { subnetType: ec2.SubnetType.PUBLIC },
instanceType,
machineImage,
userData,
role: jenkinsRole,
securityGroup: jenkinsSecurityGroup,
blockDevices: [
{
deviceName: "/dev/sda1",
volume: {
ebsDevice: ebsSetting,
},
},
],
});
cdk.Tags.of(this.instance).add("Name", "Jenkins");
const jenkinsTmplate = new ec2.LaunchTemplate(this, "jenkins-template", {
launchTemplateName: "jenkins-template",
instanceType,
machineImage,
userData: userData,
role: jenkinsRole,
blockDevices: [
{
deviceName: "/dev/sda1",
volume: {
ebsDevice: ebsSetting,
},
}
],
securityGroup: jenkinsSecurityGroup,
});
cdk.Tags.of(jenkinsTmplate).add("Name", "Jenkins");
}