From 16a58a0c0698cfeece40f9f6d6975d64207c74e7 Mon Sep 17 00:00:00 2001 From: Kiran Keshavamurthy Date: Thu, 29 Oct 2020 00:42:58 -0700 Subject: [PATCH] Add aws ci, boskos scripts --- images/capi/packer/ami/scripts/boskos.py | 129 +++++++++++++++++++++++ images/capi/packer/ami/scripts/ci-aws.sh | 96 +++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100755 images/capi/packer/ami/scripts/boskos.py create mode 100755 images/capi/packer/ami/scripts/ci-aws.sh diff --git a/images/capi/packer/ami/scripts/boskos.py b/images/capi/packer/ami/scripts/boskos.py new file mode 100755 index 0000000000..e5169fcfd1 --- /dev/null +++ b/images/capi/packer/ami/scripts/boskos.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Checks out a Image-Builder AWS account""" + +import argparse +import json +import os + +import requests +import time + +BOSKOS_HOST = os.environ.get("BOSKOS_HOST", "boskos") +BOSKOS_RESOURCE_NAME = os.environ.get('BOSKOS_RESOURCE_NAME') + + +def checkout_account(resource_type, user, input_state="free"): + url = f'http://{BOSKOS_HOST}/acquire' + data = { + 'type': resource_type, + 'owner': user, + 'state': input_state, + 'dest': 'busy', + } + + r = requests.post(url, data) + + if r.status_code == 200: + content = r.content.decode() + result = json.loads(content) + + print(f"export BOSKOS_RESOURCE_NAME={result['name']}") + print(f"export AWS_ACCESS_KEY_ID={result['userdata']['access-key-id']}") + print(f"export AWS_SECRET_ACCESS_KEY={result['userdata']['secret-access-key']}") + + else: + raise Exception(f"Got invalid response {r.status_code}: {r.reason}") + + +def release_account(user): + url = f'http://{BOSKOS_HOST}/release' + data = { + 'name': BOSKOS_RESOURCE_NAME, + 'owner': user, + 'dest': 'dirty', + } + + r = requests.post(url, data) + if r.status_code != 200: + raise Exception(f"Got invalid response {r.status_code}: {r.reason}") + + +def send_heartbeat(user): + url = f'http://{BOSKOS_HOST}/update' + data = { + 'name': BOSKOS_RESOURCE_NAME, + 'owner': user, + 'state': 'busy', + } + + while True: + print(f"POST-ing heartbeat for resource {BOSKOS_RESOURCE_NAME} to {BOSKOS_HOST}") + r = requests.post(url, data) + + if r.status_code == 200: + print(f"response status: {r.status_code}") + else: + print(f"Got invalid response {r.status_code}: {r.reason}") + + time.sleep(60) + + +def main(): + parser = argparse.ArgumentParser(description='Boskos AWS Account Management') + + parser.add_argument( + '--get', dest='checkout_account', action="store_true", + help='Checkout a Boskos AWS Account' + ) + + parser.add_argument( + '--release', dest='release_account', action="store_true", + help='Release a Boskos AWS Account' + ) + + parser.add_argument( + '--heartbeat', dest='send_heartbeat', action="store_true", + help='Send heartbeat for the checked out a Boskos AWS Account' + ) + + parser.add_argument( + '--resource-type', dest="resource_type", type=str, + default="image-builder-aws-account", + help="Type of Boskos resource to manage" + ) + + parser.add_argument( + '--user', dest="user", type=str, + default="image-builder", + help="username" + ) + + args = parser.parse_args() + + if args.checkout_account: + checkout_account(args.resource_type, args.user) + + elif args.release_account: + release_account(args.user) + + elif args.send_heartbeat: + send_heartbeat(args.user) + + +if __name__ == "__main__": + main() diff --git a/images/capi/packer/ami/scripts/ci-aws.sh b/images/capi/packer/ami/scripts/ci-aws.sh new file mode 100755 index 0000000000..2b32b1a0aa --- /dev/null +++ b/images/capi/packer/ami/scripts/ci-aws.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +################################################################################ +# usage: ci-aws.sh +# This program builds all the AWS AMIs. +# +# ENVIRONMENT VARIABLES +# JANITOR_ENABLED +# Set to 1 to run the aws-janitor command after running the tests. +################################################################################ + +set -o nounset +set -o pipefail + +CAPI_ROOT=$(dirname "${BASH_SOURCE[0]}")/../../.. +cd "${CAPI_ROOT}" || exit 1 + +cleanup() { + # stop boskos heartbeat + [[ -z ${HEART_BEAT_PID:-} ]] || kill -9 "${HEART_BEAT_PID}" +} +trap cleanup EXIT + +# If BOSKOS_HOST is set then acquire an AWS account from Boskos. +if [ -n "${BOSKOS_HOST:-}" ]; then + # Check out the account from Boskos and store the produced environment + # variables in a temporary file. + account_env_var_file="$(mktemp)" + python3 ./boskos.py --get 1>"${account_env_var_file}" + checkout_account_status="${?}" + + # If the checkout process was a success then load the account's + # environment variables into this process. + # shellcheck disable=SC1090 + [ "${checkout_account_status}" = "0" ] && . "${account_env_var_file}" + + # Always remove the account environment variable file. It contains + # sensitive information. + rm -f "${account_env_var_file}" + + if [ ! "${checkout_account_status}" = "0" ]; then + echo "error getting account from boskos" 1>&2 + exit "${checkout_account_status}" + fi + + python3 -u ./boskos.py --hearbeat >>$ARTIFACTS/boskos.log 2>&1 & + HEART_BEAT_PID=$(echo $!) +fi + +export PATH=${PWD}/.local/bin:$PATH +export PATH=${PYTHON_BIN_DIR:-"/root/.local/bin"}:$PATH + +# timestamp is in RFC-3339 format to match kubetest +export TIMESTAMP="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" +export JOB_NAME="${JOB_NAME:-"image-builder-ami"}" +export TAGS="creationTimestamp=${TIMESTAMP} jobName=${JOB_NAME}" + +make deps-ami +make -j build-ami-all + +test_status="${?}" + +# If Boskos is being used then release the AWS account back to Boskos. +[ -z "${BOSKOS_HOST:-}" ] || ./boskos.py --release + +# The janitor is typically not run as part of the process, but rather +# in a parallel process via a service on the same cluster that runs Prow and +# Boskos. +# +# However, setting JANITOR_ENABLED=1 tells this program to run the janitor +# after the test is executed. +if [ "${JANITOR_ENABLED:-0}" = "1" ]; then + if ! command -v aws-janitor >/dev/null 2>&1; then + echo "skipping janitor; aws-janitor not found" 1>&2 + else + aws-janitor -all -v 2 + fi +else + echo "skipping janitor; JANITOR_ENABLED=${JANITOR_ENABLED:-0}" 1>&2 +fi + +exit "${test_status}"