Last active
August 21, 2021 21:54
-
-
Save enriquemanuel/faf28a5c50105b90731d9cc435bbb488 to your computer and use it in GitHub Desktop.
this is a serverless project that is used to launch an EC2 instance and configure Jenkins using JCASC plugin that is stored in a repo so its cloned and it gets copied to the EC2 accordingly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[DEFAULT] | |
instance_type = t3.xlarge | |
security_groups = sg-1234 | |
iam_role = iam-role | |
subnet_id = subnet-id | |
target_group_arn = arn:<aws>:elasticloadbalancing:<region>:<accountid>:targetgroup/<id> | |
[ebs] | |
device_name = /dev/xvda | |
delete_on_termination = True | |
volume_size = 200 | |
volume_type = gp2 | |
volume_kms_key = aws/ebs | |
[github] | |
admins = <ids> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
# Defaults | |
aws_default_region="us-gov-west-1" | |
debug=true | |
jenkins_url="url" | |
tz="America/New_York" | |
echo "Update and install Jenkins..." | |
# Update system and install Jenkins | |
sudo yum -y update | |
sudo yum -y install java-1.8.0 java-1.8.0-openjdk-devel git jq | |
sudo yum -y remove java-1.7.0-openjdk | |
sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo | |
sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key | |
# Install EFS | |
sudo yum install -y amazon-efs-utils | |
echo "Configuring AWS default for Jenkins" | |
# Configure awscli | |
sudo mkdir -p ~/.aws/ | |
sudo cat >~/.aws/config <<EOL | |
[default] | |
region = $aws_default_region | |
output = json | |
EOL | |
# Insert secrets here | |
client_id=replace_client_id | |
client_secret=replace_client_secret | |
github_org_name=replace_github_org_name | |
github_admins='replace_github_admins' | |
admin_email=replace_admin_email | |
# Credentials | |
## Channels have # at the start, so we are escaping it here | |
slack_team_domain='replace_slack_team_domain' | |
slack_token='replace_slack_token' | |
slack_channel='\replace_slack_channel' | |
deploy_channel='\replace_deploy_channel' | |
alert_channel='\replace_alert_channel' | |
test_channel='\replace_test_channel' | |
github_api_token='replace_github_api_token' | |
new_relic_api_key='replace_new_relic_api_key' | |
echo "Installing and configuring Jenkins..." | |
# Jenkins key exists on our base image so it is already there | |
sudo yum -y install jenkins | |
# Configure timezone and other jenkins catches | |
sudo sed -i "s#-Djava.awt.headless=true#-Djava.awt.headless=true -Djenkins.install.runSetupWizard=false -Duser.timezone=$tz#" /etc/sysconfig/jenkins | |
# Install Jenkins Configuration as Code repo | |
git clone https://github.com/something/jcasc.git /tmp/jac/ | |
sudo cp /tmp/jac/jcasc/* /var/lib/jenkins/ | |
echo "Getting Availability Zone..." | |
# Get the az of the instance | |
az=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone) | |
if [[ $az == "us-gov-west-1a" ]]; then | |
nfsip="1a-nfs-ip" | |
elif [[ $az == "us-gov-west-1b" ]]; then | |
nfsip="1b-nfs-ip" | |
fi | |
# Configure the JCaC | |
sudo sed -i "s#<client_id>#$client_id#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<client_secret>#$client_secret#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<ip>#$jenkins_url/#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<admins>#$github_admins#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<github_org_name>#$github_org_name#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<admin_email>#$admin_email#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<aws_region>#$aws_default_region#" /var/lib/jenkins/jenkins.yaml | |
# Credentials | |
sudo sed -i "s#<jenkins.slack_team_domain>#$slack_team_domain#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<jenkins.slack_token>#$slack_token#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<jenkins.slack_channel>#$slack_channel#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<jenkins.deploy_channel>#$deploy_channel#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<jenkins.alert_channel>#$alert_channel#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<jenkins.test_channel>#$test_channel#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<devops.new_relic_api_key>#$new_relic_api_key#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<devops.github_api_token>#$github_api_token#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<devops.pd_api_token>#$pd_api_token#" /var/lib/jenkins/jenkins.yaml | |
sudo sed -i "s#<devops.vault_pass>#$vault_pass#" /var/lib/jenkins/jenkins.yaml | |
# Reset ownership and permissions | |
chown jenkins:jenkins /var/lib/jenkins | |
chown -R jenkins:jenkins /var/lib/jenkins/* | |
chmod 700 /var/lib/jenkins/install_plugins.sh | |
chmod 700 /var/lib/jenkins/jenkins.yaml | |
chmod 700 /var/lib/jenkins/plugins.txt | |
# Add Jenkins to the docker group | |
usermod -a -G docker jenkins | |
echo "Copy Jenkins private key and set permissions" | |
private_key_file_name="/home/jenkins/.ssh/kp.pem" | |
cat > $private_key_file_name <<- EOM | |
'replace_jenkins_private_key' | |
EOM | |
chown jenkins:jenkins $private_key_file_name | |
chmod 600 $private_key_file_name | |
echo "Mounting EFS..." | |
# Mount the EFS (this only is for the jobs directory in jenkins) | |
mkdir /var/lib/jenkins/jobs | |
chown -R jenkins:jenkins /var/lib/jenkins/jobs | |
mount -t efs -o tls,accesspoint=id id.efs.us-gov-west-1.amazonaws.com:/ /var/lib/jenkins/jobs | |
echo "" | |
echo "Copying the Seed Job & Init Scripts" | |
# Create workspace folder | |
seed_job_workspace="/var/lib/jenkins/jobs/seed-job/workspace" | |
[[ -d $seed_job_workspace ]] || mkdir -p $seed_job_workspace | |
# Copy seed job to the workspace | |
cp /var/lib/jenkins/seedJob.groovy $seed_job_workspace/seedJob.groovy | |
chown -R jenkins:jenkins /var/lib/jenkins/jobs/* | |
# Create the init.groovy.d folder for Jenkins | |
init_dir="/var/lib/jenkins/init.groovy.d" | |
[[ -d $init_dir ]] || mkdir -p $init_dir | |
cp /var/lib/jenkins/seedJobPreApproval.groovy $init_dir/seedJobPreApproval.groovy | |
cp /var/lib/jenkins/startSeedJob.groovy $init_dir/startSeedJob.groovy | |
chown -R jenkins:jenkins /var/lib/jenkins/init.groovy.d/ | |
# Install plugins | |
for plugin in `cat /var/lib/jenkins/plugins.txt`; do | |
/var/lib/jenkins/install_plugins.sh $plugin; | |
done | |
sudo pip install boto3 | |
sudo pip install virtualenv | |
# Auto start if server gets restarted | |
sudo chkconfig --add jenkins | |
echo "Starting Jenkins..." | |
# Start jenkins | |
sudo service jenkins start |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import boto3 | |
from dateutil import parser | |
import credstash | |
import os | |
from datetime import datetime | |
import configparser | |
import logging | |
import time | |
from botocore.exceptions import WaiterError | |
import sys | |
def automate(event, context): | |
logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s', | |
level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S') | |
# find base AMI | |
base_ami = find_base_ami() | |
config = configparser.ConfigParser() | |
config.read('files/config.ini') | |
instance_type = config['DEFAULT']['instance_type'] | |
sgs = config['DEFAULT']['security_groups'].split(',') | |
subnet_id = config['DEFAULT']['subnet_id'] | |
iam_role = config['DEFAULT']['iam_role'] | |
target_group_arn = config['DEFAULT']['target_group_arn'] | |
table_name = os.environ.get('CREDSTASH_TABLE') | |
# Jenkins configuration | |
client_id = credstash.getSecret("jenkins.new_github_client_id", table=table_name) | |
client_secret = credstash.getSecret("jenkins.new_github_client_secret", table=table_name) | |
github_org_name = credstash.getSecret("jenkins.github_org_name", table=table_name) | |
github_admins = config['github']['admins'] | |
admin_email = credstash.getSecret("jenkins.admin_email", table=table_name) | |
# Jenkins Secrets | |
slack_team_domain = credstash.getSecret("jenkins.slack_team_domain", table=table_name) | |
slack_token = credstash.getSecret("jenkins.slack_token", table=table_name) | |
slack_channel = credstash.getSecret("jenkins.slack_channel", table=table_name) | |
deploy_channel = credstash.getSecret("jenkins.deploy_channel", table=table_name) | |
alert_channel = credstash.getSecret("jenkins.alert_channel", table=table_name) | |
test_channel = credstash.getSecret("jenkins.test_channel", table=table_name) | |
new_relic_api_key = credstash.getSecret("devops.new_relic_api_key", table=table_name) | |
github_api_token = credstash.getSecret("devops.github_api_token", table=table_name) | |
jenkins_private_key = credstash.getSecret("devops.app.kp", table=table_name) | |
file_n_path = "/tmp/init.sh" | |
# Write Jenkins key file to a file first and then use sed command to replace it in the init file | |
jenkins_private_key_path = "/tmp/jenkins.pem" | |
file = open(jenkins_private_key_path, "w") | |
file.write(jenkins_private_key + "\n") | |
file.close() | |
# move file to temporary location so we can edit it | |
# lambda files in the /tmp dir can be modified | |
os.system("cp files/init.sh {}".format(file_n_path)) | |
# configuration | |
os.system("sed -i'.original' -e 's/replace_client_id/{}/' {}".format(client_id, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_client_secret/{}/' {}".format(client_secret, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_github_org_name/{}/' {}".format(github_org_name, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_github_admins/{}/' {}".format(github_admins, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_admin_email/{}/' {}".format(admin_email, file_n_path)) | |
# secrets | |
os.system("sed -i'.original' -e 's/replace_slack_team_domain/{}/' {}".format(slack_team_domain, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_slack_token/{}/' {}".format(slack_token, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_slack_channel/{}/' {}".format(slack_channel, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_deploy_channel/{}/' {}".format(deploy_channel, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_alert_channel/{}/' {}".format(alert_channel, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_test_channel/{}/' {}".format(test_channel, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_new_relic_api_key/{}/' {}".format(new_relic_api_key, file_n_path)) | |
os.system("sed -i'.original' -e 's/replace_github_api_token/{}/' {}".format(github_api_token, file_n_path)) | |
os.system("sed -i'.original' -e '/replace_jenkins_private_key/r {}' -e '/replace_jenkins_private_key/d' {}".format(jenkins_private_key_path, file_n_path)) | |
# get the modified user data | |
with open(file_n_path, 'r') as myfile: | |
user_data = myfile.read() | |
# create the instance | |
ec2 = boto3.client('ec2') | |
response = ec2.run_instances( | |
ImageId=base_ami, | |
InstanceType=instance_type, | |
SecurityGroupIds=sgs, | |
SubnetId=subnet_id, | |
UserData=user_data, | |
MinCount=1, | |
MaxCount=1, | |
IamInstanceProfile={ 'Name': iam_role }, | |
BlockDeviceMappings=[ | |
{ | |
'DeviceName': config['ebs']['device_name'], | |
'Ebs': { | |
'DeleteOnTermination': config['ebs'].getboolean('delete_on_termination'), | |
'VolumeSize': int(config['ebs']['volume_size']), | |
'VolumeType': config['ebs']['volume_type'], | |
'Encrypted': True | |
} | |
}, | |
] | |
) | |
instance_id = response['Instances'][0]['InstanceId'] | |
# Sleep 1 minute in order for the user data script to finish on the instance | |
time.sleep(60) | |
logging.info('Successfully launched new instance: %s', instance_id) | |
old_instance_id = get_old_instance_id() | |
logging.info('Old instance ID: %s', old_instance_id) | |
tags = get_current_instance_tags() | |
# tag the instance | |
response = ec2.create_tags( | |
Resources=[ | |
response['Instances'][0]['InstanceId'] | |
], | |
Tags=tags | |
) | |
attach_instance_to_target_group(instance_id, old_instance_id, target_group_arn) | |
return instance_id | |
def attach_instance_to_target_group(instance_id, old_instance_id, target_group_arn): | |
elbv2 = boto3.client('elbv2', region_name="us-gov-west-1") | |
elbv2.register_targets( | |
TargetGroupArn=target_group_arn, | |
Targets=[ | |
{ | |
'Id': instance_id, | |
'Port': 8080 | |
}, | |
] | |
) | |
logging.info('Successfully attached instance ID %s to the ALB target group %s.' % | |
(instance_id, target_group_arn)) | |
# Wait for instances to become healthy | |
logging.info( | |
'Waiting for the ALB target group to have all healthy instances before removing the old instance ID...') | |
try: | |
waiter = elbv2.get_waiter('target_in_service') | |
waiter.wait( | |
TargetGroupArn=target_group_arn, | |
WaiterConfig={ | |
'Delay': 5, | |
'MaxAttempts': 300 | |
}, | |
Targets= [{'Id': instance_id, 'Port': 8080 }] | |
) | |
logging.info('New instances are healthy...') | |
logging.info('Deregistering old instances from the target group...') | |
elbv2.deregister_targets( | |
TargetGroupArn=target_group_arn, | |
Targets=[ | |
{ | |
'Id': old_instance_id, | |
'Port': 8080 | |
}, | |
] | |
) | |
# Sleep 20 seconds for the instance to deregister before terminating it | |
time.sleep(20) | |
# If waiter succeeded terminate the old instance | |
ec2 = boto3.resource('ec2') | |
ec2.instances.filter(InstanceIds=[old_instance_id]).terminate() | |
except WaiterError as we: | |
logging.error('Received Waiter error: %s' % we) | |
logging.info('New instances are not healthy...') | |
sys.exit(1) | |
def get_old_instance_id(): | |
ec2 = boto3.client('ec2') | |
info = ec2.describe_instances( | |
Filters=[ | |
{ | |
'Name': 'tag:Name', | |
'Values': ['<app_name>'] | |
}, | |
{ 'Name': 'instance-state-name', | |
'Values': ['running'] | |
} | |
] | |
) | |
return info['Reservations'][0]['Instances'][0]['InstanceId'] | |
def get_current_instance_tags(): | |
ec2 = boto3.client('ec2') | |
info = ec2.describe_instances( | |
Filters=[{ | |
'Name': 'tag:Name', | |
'Values': ['app_name_ec2'] | |
}] | |
) | |
tags = info['Reservations'][0]['Instances'][0]['Tags'] | |
now = datetime.now() | |
date = now.strftime("%Y%m%d-%H%M%S") | |
for tag in tags: | |
if tag.get('Key') == 'deployment_id': | |
tags.pop(tags.index(tag)) | |
tags.append( | |
{'Key': 'deployment_id', 'Value': 'deployment-id-{}'.format(date)}) | |
return tags | |
def latest_image(list_of_images): | |
latest = None | |
for image in list_of_images: | |
if not latest: | |
latest = image | |
continue | |
if parser.parse(image['CreationDate']) > parser.parse(latest['CreationDate']): | |
latest = image | |
return latest | |
def find_base_ami(): | |
ec2 = boto3.client('ec2') | |
filters = [ { | |
'Name': 'tag:app_group', | |
'Values': ['app_group'] | |
},{ | |
'Name': 'tag:app_project', | |
'Values': ['app_project'] | |
},{ | |
'Name': 'tag:type', | |
'Values': ['base-ami'] | |
},{ | |
'Name': 'tag:application', | |
'Values': ['base-ami'] | |
}] | |
response = ec2.describe_images(Filters=filters) | |
latest=latest_image(response['Images']) | |
return latest['ImageId'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# root | |
jenkins: | |
systemMessage: "Automating Configuration Devops Jenkins" | |
securityRealm: | |
github: | |
githubWebUri: "https://github.com" | |
githubApiUri: "https://api.github.com" | |
clientID: "<client_id>" | |
clientSecret: "<client_secret>" | |
oauthScopes: "read:org" | |
agentProtocols: | |
- "JNLP4-connect" | |
- "Ping" | |
authorizationStrategy: | |
github: | |
adminUserNames: "<admins>" | |
allowAnonymousJobStatusPermission: true | |
allowAnonymousReadPermission: true | |
allowCcTrayPermission: false | |
allowGithubWebHookPermission: true | |
authenticatedUserCreateJobPermission: false | |
authenticatedUserReadPermission: true | |
organizationNames: "<github_org_name>" | |
useRepositoryPermissions: true | |
disableRememberMe: true | |
mode: NORMAL | |
primaryView: | |
all: | |
name: "all" | |
quietPeriod: 5 | |
scmCheckoutRetryCount: 0 | |
views: | |
- all: | |
name: "all" | |
globalNodeProperties: | |
- envVars: | |
env: | |
- key: "AWS_DEFAULT_REGION" | |
value: "<aws_region>" | |
- key: "PATH" | |
value: "/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/dsva/.local/bin:/home/bin" | |
labelString: "deploy devops" | |
mode: NORMAL | |
numExecutors: 16 | |
primaryView: | |
all: | |
name: "all" | |
quietPeriod: 5 | |
scmCheckoutRetryCount: 0 | |
#root | |
credentials: | |
system: | |
domainCredentials: | |
- credentials: | |
- string: | |
scope: GLOBAL | |
id: "SLACK_TEAM_DOMAIN" | |
secret: "<jenkins.slack_team_domain>" | |
description: "DSVA team on Slack" | |
- string: | |
scope: GLOBAL | |
id: "SLACK_TOKEN" | |
secret: "<jenkins.slack_token>" | |
description: "Slack token" | |
- string: | |
scope: GLOBAL | |
id: "DEPLOY_SLACK_TOKEN" | |
secret: "<jenkins.slack_token>" | |
description: "Deploy Slack token" | |
- string: | |
scope: GLOBAL | |
id: "ALERT_SLACK_TOKEN" | |
secret: "<jenkins.slack_token>" | |
description: "Alert Slack Token" | |
- string: | |
scope: GLOBAL | |
id: "TEST_SLACK_TOKEN" | |
secret: "<jenkins.slack_token>" | |
description: "Test Slack token" | |
- string: | |
scope: GLOBAL | |
id: "SLACK_CHANNEL" | |
secret: "<jenkins.slack_channel>" | |
description: "Regular Slack Channel" | |
- string: | |
scope: GLOBAL | |
id: "DEPLOY_CHANNEL" | |
secret: "<jenkins.deploy_channel>" | |
description: "Deploy Slack Channel" | |
- string: | |
scope: GLOBAL | |
id: "ALERT_SLACK_CHANNEL" | |
secret: "<jenkins.alert_channel>" | |
description: "Alert Slack Channel" | |
- string: | |
scope: GLOBAL | |
id: "TEST_SLACK_CHANNEL" | |
secret: "<jenkins.test_channel>" | |
description: "Test Slack Channel" | |
- string: | |
scope: GLOBAL | |
id: "NEW_RELIC_API_KEY" | |
secret: "<devops.new_relic_api_key>" | |
description: "New Relic API Key" | |
- usernamePassword: | |
scope: GLOBAL | |
id: "va-bot" | |
username: "va-bot" | |
password: "<devops.github_api_token>" | |
description: "va-bot username/password" | |
- string: | |
scope: GLOBAL | |
id: "GIT_CREDENTIAL" | |
secret: "<devops.github_api_token>" | |
description: "va-bot personal access token" | |
# root | |
tool: | |
git: | |
installations: | |
- name: git | |
home: /usr/bin/git | |
# root | |
unclassified: | |
location: | |
adminAddress: "<admin_email>" | |
url: "http://<ip>" | |
slackNotifier: | |
teamDomain: "dsva" | |
baseUrl: "" | |
tokenCredentialId: "SLACK_TOKEN" | |
globalLibraries: | |
libraries: | |
- name: "devops-jenkins" | |
defaultVersion: "master" | |
implicit: true | |
retriever: | |
modernSCM: | |
scm: | |
git: | |
remote: "https://github.com/lalalala/-devops-jenkins.git" | |
credentialsId: "va-bot" | |
# root | |
jobs: | |
- script: > | |
job('seed-job'){ | |
displayName('seed-job') | |
logRotator { | |
numToKeep(15) | |
} | |
wrappers { | |
credentialsBinding { | |
string('GIT_CREDENTIAL', 'GIT_CREDENTIAL') | |
} | |
} | |
steps { | |
dsl(['seedJob.groovy']) | |
} | |
parameters { | |
stringParam('DEPLOYMENT_DEV_BRANCH', 'master', 'appeals-deployment branch') | |
} | |
triggers { | |
cron('H H(0-5) * * *') | |
} | |
} | |
- script: > | |
queue('seed-job') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
workflow-aggregator | |
blueocean | |
configuration-as-code | |
job-dsl | |
git-parameter | |
github-oauth | |
slack | |
ws-cleanup | |
credentials | |
configuration-as-code-support | |
envinject |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version='1.0' encoding='UTF-8'?> | |
<scriptApproval plugin="script-security"> | |
<approvedSignatures> | |
<string>method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild</string> | |
<string>method hudson.model.Cause getShortDescription</string> | |
<string>method hudson.model.Run getCauses</string> | |
<string>method hudson.model.Run getDurationString</string> | |
<string>method hudson.plugins.git.BranchSpec getName</string> | |
<string>method hudson.plugins.git.GitSCM getBranches</string> | |
<string>method java.lang.Process waitFor</string> | |
<string>method java.util.Random nextInt int</string> | |
<string>method org.kohsuke.github.GHIssue comment java.lang.String</string> | |
<string>method org.kohsuke.github.GHIssue getNumber</string> | |
<string>method org.kohsuke.github.GHPullRequest getMergeable</string> | |
<string>method org.kohsuke.github.GHPullRequest getMergeableState</string> | |
<string>method org.kohsuke.github.GHPullRequest listCommits</string> | |
<string>method org.kohsuke.github.GHPullRequest merge java.lang.String</string> | |
<string>method org.kohsuke.github.GHPullRequestCommitDetail getCommit</string> | |
<string>method org.kohsuke.github.GHPullRequestCommitDetail$Commit getAuthor</string> | |
<string>method org.kohsuke.github.GHRef getObject</string> | |
<string>method org.kohsuke.github.GHRef$GHObject getSha</string> | |
<string>method org.kohsuke.github.GHRepository createPullRequest java.lang.String java.lang.String java.lang.String java.lang.String</string> | |
<string>method org.kohsuke.github.GHRepository createRef java.lang.String java.lang.String</string> | |
<string>method org.kohsuke.github.GHRepository getPullRequest int</string> | |
<string>method org.kohsuke.github.GHRepository getRef java.lang.String</string> | |
<string>method org.kohsuke.github.GitHub getUser java.lang.String</string> | |
<string>method org.kohsuke.github.GitUser getEmail</string> | |
<string>new java.util.Date</string> | |
<string>new java.util.Random</string> | |
<string>staticMethod groovy.json.JsonOutput toJson java.lang.Object</string> | |
<string>staticMethod java.net.URLDecoder decode java.lang.String</string> | |
<string>staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods get java.util.Map java.lang.Object java.lang.Object</string> | |
<string>staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods minus java.lang.String java.lang.Object</string> | |
<string>staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods stripIndent java.lang.String</string> | |
<string>staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods stripMargin java.lang.String</string> | |
<string>staticMethod org.codehaus.groovy.runtime.ProcessGroovyMethods getText java.lang.Process</string> | |
<string>staticMethod org.codehaus.groovy.runtime.ScriptBytecodeAdapter createRange java.lang.Object java.lang.Object boolean</string> | |
<!-- For review_instance_deploy. TODO: evaluate custom Jenkins plugin --> | |
<string>staticField org.kohsuke.github.GHDeploymentState ERROR</string> | |
<string>staticField org.kohsuke.github.GHDeploymentState SUCCESS</string> | |
<string>staticMethod org.kohsuke.github.GitHub connect</string> | |
<string>staticMethod org.codehaus.groovy.runtime.EncodingGroovyMethods encodeHex byte[]</string> | |
<string>staticMethod java.security.MessageDigest getInstance java.lang.String</string> | |
<string>method groovy.lang.GString getBytes</string> | |
<string>method java.security.MessageDigest digest byte[]</string> | |
<string>method org.kohsuke.github.GHRepository createDeployment java.lang.String</string> | |
<string>method org.kohsuke.github.GHDeploymentBuilder autoMerge boolean</string> | |
<string>method org.kohsuke.github.GHDeploymentBuilder environment java.lang.String</string> | |
<string>method org.kohsuke.github.GHDeploymentBuilder requiredContexts java.util.List</string> | |
<string>method org.kohsuke.github.GHDeploymentBuilder create</string> | |
<string>method org.kohsuke.github.GitHub getRepository java.lang.String</string> | |
<string>method org.kohsuke.github.GHObject getId</string> | |
<string>method org.kohsuke.github.GHRepository createDeployStatus int org.kohsuke.github.GHDeploymentState</string> | |
<string>method org.kohsuke.github.GHDeploymentStatusBuilder targetUrl java.lang.String</string> | |
<string>method org.kohsuke.github.GHDeploymentStatusBuilder create</string> | |
<string>method org.kohsuke.github.GHDeploymentStatus getTargetUrl</string> | |
<!-- /review_instance_deploy --> | |
<!-- For scorecard_builds --> | |
<string>method org.kohsuke.github.GHRef delete</string> | |
<!-- /scorecard_builds --> | |
</approvedSignatures> | |
<aclApprovedSignatures/> | |
<approvedClasspathEntries/> | |
<pendingScripts/> | |
<pendingSignatures/> | |
<pendingClasspathEntries/> | |
</scriptApproval> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Grab('org.yaml:snakeyaml:1.17') | |
import groovy.lang.GroovyClassLoader | |
import groovy.transform.Field | |
import org.yaml.snakeyaml.Yaml | |
@Field seedJobWorkspace = "/var/lib/jenkins/jobs/seed-job/workspace/" | |
@Field workspaceDir = new File(seedJobWorkspace) | |
@Field repoPath = seedJobWorkspace + "deployment" | |
@Field jobDefDir = new File(repoPath + "/jobdefs") | |
@Field classLoader = new GroovyClassLoader(getClass().getClassLoader()) | |
def deploymentBranch | |
def checkout() { | |
def jenkinsRepo = "https://" + GIT_CREDENTIAL + "@github.com/lalala/deployment.git" | |
try { | |
deploymentBranch = "${DEPLOYMENT_DEV_BRANCH}" | |
} | |
catch(Exception ex){ | |
deploymentBranch = "master" | |
} | |
println("Cloning deployment repo with branch ${deploymentBranch}...") | |
def gitProc = ["git", "clone", "-b", deploymentBranch, jenkinsRepo].execute(null, workspaceDir) | |
def out = new StringBuffer() | |
def err = new StringBuffer() | |
gitProc.consumeProcessOutput(out, err) | |
gitProc.waitForOrKill(10*60*1000) // 10 minutes | |
println(out) | |
println(err) | |
def exitCode = gitProc.exitValue() | |
if (exitCode != 0) { | |
println("git exited with code: ${exitCode}") | |
throw new Exception("git process exit code was ${exitCode}") | |
} | |
} | |
def createFolderFromYaml(String folderName, File yamlFile) { | |
Yaml parser = new Yaml() | |
def metadata = parser.load(yamlFile.text) | |
println("Creating Folder... $folderName") | |
folder(folderName) { | |
displayName(metadata['displayName'] ?: "") | |
description(metadata['description'] ?: "") | |
} | |
} | |
def createFolder(String folderName, String folderFullName) { | |
println("Creating folder: $folderName") | |
folder(folderFullName) { | |
displayName(folderName) | |
} | |
} | |
def createJobFromGroovy(String folderName, File groovyFile) { | |
println("Creating Job... $groovyFile.name") | |
GroovyShell shell = new GroovyShell(classLoader, this.binding) | |
def script = shell.parse(groovyFile) | |
def arguments = [:] | |
arguments['folderName'] = folderName | |
arguments['jenkins'] = this | |
script.invokeMethod("createJob", arguments) | |
} | |
def scanFolder(File folder, String parentFolderName) { | |
def folderName = parentFolderName + "/" + folder.getName() | |
File folderFile = new File(folder.absolutePath + "/folder.yml") | |
// Create Jenkins folders | |
if(folderFile.exists()) { | |
createFolderFromYaml(folderName, folderFile) | |
} | |
else { | |
createFolder(folder.getName(), folderName) | |
} | |
// Process the rest of the folders in this directory | |
for (file in folder.listFiles()) { | |
if(file.isDirectory()) { | |
scanFolder(file, folderName) | |
} | |
else { | |
if (file.getName().toLowerCase().endsWith("job.groovy")) { | |
// Run all the *job.groovy scripts | |
createJobFromGroovy(folderName, file) | |
} | |
} | |
} | |
} | |
def scanRootFolder(File folder) { | |
println("Scanning root folder") | |
for (file in folder.listFiles()) { | |
if(file.isDirectory()) { | |
scanFolder(file, "") | |
} | |
} | |
} | |
// clean up the appeals deployment repo to make sure we have a clean start | |
["rm", "-rf", repoPath].execute().waitFor() | |
checkout() | |
// Add jobdefs dir to classpath in classLoaders used to run jobdef files | |
// This allows the scripts to import the common package under this directory | |
classLoader.addClasspath(jobDefDir.getAbsolutePath()) | |
// Start scanning for jobdef files | |
scanRootFolder(jobDefDir) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import jenkins.model.Jenkins | |
import jenkins.security.s2m.AdminWhitelistRule | |
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval; | |
import org.jenkinsci.plugins.scriptsecurity.scripts.languages.GroovyLanguage; | |
import jenkins.AgentProtocol | |
// Disable deprecated JNLP protocols | |
def protocols = AgentProtocol.all() | |
protocols.each { protocol -> | |
if(protocol.name && (protocol.name.contains("JNLP-connect") || protocol.name.contains("JNLP2-connect"))) { | |
protocols.remove(protocol) | |
jnlpChanged = true | |
println "Jenkins deprecated protocol ${protocol.name} has been disabled." | |
} | |
} | |
// Jenkins is noisy about this, even though it's not relevant to our situation | |
Jenkins.instance.getInjector() | |
.getInstance(AdminWhitelistRule.class) | |
.setMasterKillSwitch(false) | |
ScriptApproval.get().preapprove( | |
new File('/var/lib/jenkins/jobs/seed-job/workspace/seedJob.groovy').getText('UTF-8'), | |
GroovyLanguage.get() | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
service: jenkins | |
frameworkVersion: ">=1.0.0 <2.0.0" | |
package: | |
individually: true | |
exclude: | |
- .git/** | |
- lib/** | |
- .venv/** | |
- .venvdev/** | |
- .vscode/** | |
- __pycache__/** | |
custom: | |
pythonRequirements: | |
dockerizePip: true | |
provider: | |
name: aws | |
runtime: python3.6 | |
region: us-gov-west-1 | |
stage: ${opt:stage, 'utility'} | |
logRetentionInDays: 5 | |
memorySize: 128 | |
role: arn:aws-us-gov:iam::<accountid>:role/role | |
endpointType: regional | |
vpc: | |
securityGroupIds: | |
- sg-id | |
subnetIds: | |
- subnet-id | |
environment: | |
CREDSTASH_TABLE: "table-credstash" | |
stackTags: | |
team: "teamtags" | |
dev: "devops" | |
Environment: "utility" | |
functions: | |
deploy: | |
handler: jenkins.automate | |
timeout: 900 | |
layers: | |
- arn:aws-us-gov:lambda:us-gov-west-1:<accountid>:layer:credstashLayer:5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def job = hudson.model.Hudson.instance.getItemByFullName('seed-job') | |
hudson.model.Hudson.instance.queue.schedule(job, 0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment