-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
80ab440
commit b5f18bb
Showing
14 changed files
with
772 additions
and
5 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
_packages/ | ||
_dependencies/ | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,38 @@ | ||
node { | ||
echo 'wat' | ||
sh "ls" | ||
sh "uname -a" | ||
sh "uptime" | ||
node('master') { | ||
stage('Setup env'){ | ||
TAG=sh(script: 'pwgen 5 1', returnStdout: true).trim() | ||
sh "nohup python3.6 ~/start.py utils small-1 ${TAG} 5 &" | ||
} | ||
} | ||
|
||
pipeline { | ||
agent none | ||
options { | ||
skipDefaultCheckout() | ||
timestamps() | ||
} | ||
stages { | ||
stage("Checkout & deploy") { | ||
when { | ||
branch 'master' | ||
} | ||
agent { | ||
node { | ||
label "utils-small-1-${TAG}" | ||
} | ||
} | ||
steps { | ||
checkout scm | ||
sh 'ls -lah' | ||
sh 'python3.6 deploy.py' | ||
} | ||
} | ||
} | ||
post { | ||
always { | ||
node('master') { | ||
sh "nohup python3.6 ~/stop.py ${TAG} &" | ||
} | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import subprocess | ||
import base64 | ||
import shutil | ||
import json | ||
import sys | ||
import os | ||
import boto3 | ||
|
||
lambda_client = boto3.client('lambda', region_name='us-east-1') | ||
lambda_meta_deployer = 'lambdaMetaDeployer' | ||
|
||
with_error = False | ||
|
||
def bootstrap(): | ||
# Cleanup and prepare packaging folder | ||
shutil.rmtree('_packages/') | ||
os.makedirs('_packages', exist_ok=True) | ||
|
||
shutil.rmtree('_dependencies/') | ||
os.makedirs('_dependencies', exist_ok=True) | ||
|
||
def scan_folders(): | ||
# Traverse the folder, detect functions and deploy each one individually | ||
for root, dirs, files in os.walk('.', topdown=False): | ||
if root.startswith('./.'): | ||
continue | ||
|
||
if root.startswith('./_'): | ||
continue | ||
|
||
if root == '.': | ||
continue | ||
|
||
# It's-a me, function! | ||
if 'config.json' in files: | ||
function_name = root[2:] | ||
|
||
if 'requirements.txt' in files: | ||
os.makedirs('_dependencies/{}'.format(function_name)) | ||
|
||
deploy(function_name) | ||
|
||
if with_error: | ||
raise Exception('Some functions were not deployed') | ||
|
||
def deploy(function_name): | ||
print('Packaging {}'.format(function_name)) | ||
|
||
with open(function_name + '/config.json') as config_file: | ||
config = json.load(config_file) | ||
|
||
validate_config(config) | ||
|
||
print('Using config: {}'.format(config)) | ||
|
||
setup_dependencies(function_name) | ||
|
||
create_package(function_name, config) | ||
|
||
upsert_function(function_name, config) | ||
|
||
def upsert_function(function_name, config): | ||
with open('_packages/{}.zip'.format(function_name), 'rb') as package: | ||
contents = package.read() | ||
b64_zip_str = base64.b64encode(contents).decode('utf-8') | ||
|
||
payload = { | ||
'zip_file': b64_zip_str, | ||
'config': config, | ||
'target_function': function_name | ||
} | ||
|
||
resp = lambda_client.invoke( | ||
FunctionName=lambda_meta_deployer, | ||
Payload=json.dumps(payload) | ||
) | ||
|
||
if resp['ResponseMetadata']['HTTPStatusCode'] != 200: | ||
print('Bad status code for {}: {}'.format(function_name, resp)) | ||
with_error = True | ||
else: | ||
print('{} deployed\n\n'.format(function_name)) | ||
|
||
def create_package(function_name, config): | ||
# Zip application-specific stuff | ||
cmd1 = 'cd {0}; zip -r9 ../_packages/{0}.zip *'.format(function_name) | ||
subprocess.run(cmd1, check=True, shell=True) | ||
|
||
# Add dependencies to package (if they exist) | ||
if os.path.exists('_dependencies/{}/'.format(function_name)): | ||
cmd2 = 'cd _dependencies/{0}; zip -r9 ../../_packages/{0}.zip *'.format(function_name) | ||
subprocess.run(cmd2, check=True, shell=True) | ||
|
||
if not os.stat('_packages/{0}.zip'.format(function_name)): | ||
error('internal', 'error_creating_zip') | ||
|
||
def setup_dependencies(function_name): | ||
if os.path.exists('{}/requirements.txt'.format(function_name)): | ||
cmd = 'pip3 install -r {0}/requirements.txt -t _dependencies/{0} '.format(function_name) | ||
subprocess.run(cmd, check=True, shell=True) | ||
|
||
def validate_config(config): | ||
if not 'memory' in config: | ||
error('config', 'missing_memory') | ||
|
||
if config['memory'] % 128 not in [64, 0]: | ||
error('config', 'invalid_memory') | ||
|
||
if not 'timeout' in config: | ||
error('config', 'missing_timeout') | ||
|
||
if not 'handler' in config: | ||
error('config', 'missing_handler') | ||
|
||
def error(major, minor): | ||
raise Exception(major + '_' + minor) | ||
|
||
if __name__ == '__main__': | ||
bootstrap() | ||
|
||
if len(sys.argv) == 1: | ||
scan_folders() | ||
else: | ||
for function_name in sys.argv[1:]: | ||
deploy(function_name) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"memory": 128, | ||
"timeout": 5, | ||
"handler": "jse.lambda_handler" | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
from datetime import datetime | ||
import boto3 | ||
|
||
ec2_client = boto3.client('ec2', region_name='us-east-1') | ||
|
||
def lambda_handler(_event, _context): | ||
query = ec2_client.describe_instances( | ||
Filters=[ | ||
{ | ||
'Name': 'tag-key', | ||
'Values': ['jenkins_slave_expiration_date'] | ||
}, | ||
{ | ||
'Name': 'instance-state-code', | ||
'Values': ['0', '16'] | ||
} | ||
], | ||
)['Reservations'] | ||
|
||
print('Found {} matching instances...'.format(len(query))) | ||
|
||
for instance in query: | ||
if len(instance['Instances']) > 1: | ||
print('Not sure what this means') | ||
|
||
data = instance['Instances'][0] | ||
|
||
expiration_date = None | ||
|
||
for tag in data['Tags']: | ||
if tag['Key'] == 'jenkins_slave_expiration_date': | ||
expiration_date = datetime.strptime(tag['Value'], '%Y-%m-%d %H:%M:%S.%f') | ||
break; | ||
|
||
if datetime.utcnow() >= expiration_date: | ||
instance_id = data['InstanceId'] | ||
|
||
print('Terminating instance {}'.format(instance_id)) | ||
|
||
ec2_client.terminate_instances( | ||
InstanceIds=[instance_id] | ||
) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"memory": 128, | ||
"timeout": 35, | ||
"handler": "jsl.lambda_handler" | ||
} |
Oops, something went wrong.