diff --git a/test/kubemark/common.sh b/test/kubemark/common.sh index c6352f1e24c..0c2d4294a89 100644 --- a/test/kubemark/common.sh +++ b/test/kubemark/common.sh @@ -39,8 +39,6 @@ MASTER_NAME="${INSTANCE_PREFIX}-kubemark-master" MASTER_TAG="kubemark-master" EVENT_STORE_NAME="${INSTANCE_PREFIX}-event-store" -RETRIES=3 - export KUBECTL="${KUBE_ROOT}/cluster/kubectl.sh" export KUBEMARK_DIRECTORY="${KUBE_ROOT}/test/kubemark" export RESOURCE_DIRECTORY="${KUBEMARK_DIRECTORY}/resources" @@ -48,25 +46,29 @@ export RESOURCE_DIRECTORY="${KUBEMARK_DIRECTORY}/resources" # Runs gcloud compute command with the given parameters. Up to $RETRIES will be made # to execute the command. # arguments: -# $@: all stuff that goes after 'gcloud compute ' +# $@: all stuff that goes after 'gcloud compute' function run-gcloud-compute-with-retries { - echo "" > /tmp/gcloud_retries + RETRIES="${RETRIES:-3}" for attempt in $(seq 1 ${RETRIES}); do - if ! gcloud compute $@ &> /tmp/gcloud_retries; then - if [[ $(grep -c "already exists" /tmp/gcloud_retries) -gt 0 ]]; then + local -r gcloud_result=$(gcloud compute "$@" 2>&1) + local -r ret_val="$?" + echo "${gcloud_result}" + if [[ "${ret_val}" -ne "0" ]]; then + if [[ $(echo "${gcloud_result}" | grep -c "already exists") -gt 0 ]]; then if [[ "${attempt}" == 1 ]]; then - echo -e "${color_red} Failed to $1 $2 $3 as the resource hasn't been deleted from a previous run.${color_norm}" >& 2 + echo -e "${color_red}Failed to $1 $2 $3 as the resource hasn't been deleted from a previous run.${color_norm}" >& 2 exit 1 fi echo -e "${color_yellow}Succeeded to $1 $2 $3 in the previous attempt, but status response wasn't received.${color_norm}" return 0 fi - echo -e "${color_yellow}Attempt $(($attempt+1)) failed to $1 $2 $3. Retrying.${color_norm}" >& 2 + echo -e "${color_yellow}Attempt $attempt failed to $1 $2 $3. Retrying.${color_norm}" >& 2 sleep $(($attempt * 5)) else + echo -e "${color_green}Succeeded to gcloud compute $1 $2 $3.${color_norm}" return 0 fi done - echo -e "${color_red} Failed to $1 $2 $3.${color_norm}" >& 2 + echo -e "${color_red}Failed to $1 $2 $3.${color_norm}" >& 2 exit 1 } diff --git a/test/kubemark/gce/util.sh b/test/kubemark/gce/util.sh new file mode 100644 index 00000000000..cc41a9af80b --- /dev/null +++ b/test/kubemark/gce/util.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +# Copyright 2017 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. + +function create-master-instance-with-resources { + GCLOUD_COMMON_ARGS="--project ${PROJECT} --zone ${ZONE}" + + run-gcloud-compute-with-retries disks create "${MASTER_NAME}-pd" \ + ${GCLOUD_COMMON_ARGS} \ + --type "${MASTER_DISK_TYPE}" \ + --size "${MASTER_DISK_SIZE}" + + if [ "${EVENT_PD:-false}" == "true" ]; then + run-gcloud-compute-with-retries disks create "${MASTER_NAME}-event-pd" \ + ${GCLOUD_COMMON_ARGS} \ + --type "${MASTER_DISK_TYPE}" \ + --size "${MASTER_DISK_SIZE}" + fi + + run-gcloud-compute-with-retries addresses create "${MASTER_NAME}-ip" \ + --project "${PROJECT}" \ + --region "${REGION}" -q + + MASTER_IP=$(gcloud compute addresses describe "${MASTER_NAME}-ip" \ + --project "${PROJECT}" --region "${REGION}" -q --format='value(address)') + + run-gcloud-compute-with-retries instances create "${MASTER_NAME}" \ + ${GCLOUD_COMMON_ARGS} \ + --address "${MASTER_IP}" \ + --machine-type "${MASTER_SIZE}" \ + --image-project="${MASTER_IMAGE_PROJECT}" \ + --image "${MASTER_IMAGE}" \ + --tags "${MASTER_TAG}" \ + --network "${NETWORK}" \ + --scopes "storage-ro,compute-rw,logging-write" \ + --boot-disk-size "${MASTER_ROOT_DISK_SIZE}" \ + --disk "name=${MASTER_NAME}-pd,device-name=master-pd,mode=rw,boot=no,auto-delete=no" + + if [ "${EVENT_PD:-false}" == "true" ]; then + echo "Attaching ${MASTER_NAME}-event-pd to ${MASTER_NAME}" + run-gcloud-compute-with-retries instances attach-disk "${MASTER_NAME}" \ + ${GCLOUD_COMMON_ARGS} \ + --disk "${MASTER_NAME}-event-pd" \ + --device-name="master-event-pd" + fi + + run-gcloud-compute-with-retries firewall-rules create "${MASTER_NAME}-https" \ + --project "${PROJECT}" \ + --network "${NETWORK}" \ + --source-ranges "0.0.0.0/0" \ + --target-tags "${MASTER_TAG}" \ + --allow "tcp:443" +} + +# Command to be executed is '$1'. +# No. of retries is '$2' (if provided) or 1 (default). +function execute-cmd-on-master-with-retries() { + RETRIES="${2:-1}" run-gcloud-compute-with-retries ssh "${MASTER_NAME}" --zone="${ZONE}" --project="${PROJECT}" --command="$1" +} + +function copy-files() { + run-gcloud-compute-with-retries copy-files --zone="${ZONE}" --project="${PROJECT}" $@ +} + +function delete-master-instance-and-resources { + GCLOUD_COMMON_ARGS="--project ${PROJECT} --zone ${ZONE} --quiet" + + gcloud compute instances delete "${MASTER_NAME}" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${MASTER_NAME}-pd" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${MASTER_NAME}-event-pd" \ + ${GCLOUD_COMMON_ARGS} &> /dev/null || true + + gcloud compute addresses delete "${MASTER_NAME}-ip" \ + --project "${PROJECT}" \ + --region "${REGION}" \ + --quiet || true + + gcloud compute firewall-rules delete "${MASTER_NAME}-https" \ + --project "${PROJECT}" \ + --quiet || true + + if [ "${SEPARATE_EVENT_MACHINE:-false}" == "true" ]; then + gcloud compute instances delete "${EVENT_STORE_NAME}" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${EVENT_STORE_NAME}-pd" \ + ${GCLOUD_COMMON_ARGS} || true + fi +} + +function delete-master-instance-and-resources { + GCLOUD_COMMON_ARGS="--project ${PROJECT} --zone ${ZONE} --quiet" + + gcloud compute instances delete "${MASTER_NAME}" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${MASTER_NAME}-pd" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${MASTER_NAME}-event-pd" \ + ${GCLOUD_COMMON_ARGS} &> /dev/null || true + + gcloud compute addresses delete "${MASTER_NAME}-ip" \ + --project "${PROJECT}" \ + --region "${REGION}" \ + --quiet || true + + gcloud compute firewall-rules delete "${MASTER_NAME}-https" \ + --project "${PROJECT}" \ + --quiet || true + + if [ "${SEPARATE_EVENT_MACHINE:-false}" == "true" ]; then + gcloud compute instances delete "${EVENT_STORE_NAME}" \ + ${GCLOUD_COMMON_ARGS} || true + + gcloud compute disks delete "${EVENT_STORE_NAME}-pd" \ + ${GCLOUD_COMMON_ARGS} || true + fi +} diff --git a/test/kubemark/skeleton/util.sh b/test/kubemark/skeleton/util.sh new file mode 100644 index 00000000000..4998057c832 --- /dev/null +++ b/test/kubemark/skeleton/util.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# Copyright 2017 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. + +# This script contains the helper functions that each provider hosting +# Kubermark must implement to use test/kubemark/start-kubemark.sh and +# test/kubemark/stop-kubemark.sh scripts. + +# This function should create a machine instance for the master along +# with any/all of the following resources: +# - Attach a PD to the master (optionally 1 more for storing events) +# - A public IP address for the master ($MASTER_IP) +# - A network firewall rule allowing all TCP traffic on port 443 in master +# Note: This step is compulsory in order for kubemark to work +# +# ENV vars that should be defined by the end of this function: +# 1. MASTER_IP +# 2. MASTER_NAME +# +# Recommended for this function to include retrying logic for the above +# operations in case of failures. +function create-master-instance-with-resources { + echo "MASTER_IP: $MASTER_IP" 1>&2 + echo "MASTER_NAME: $MASTER_NAME" 1>&2 +} + +# This function should execute the command('$1') on the master machine +# (possibly through SSH), retrying in case of failure. The allowed number of +# retries would be '$2' (if not provided, default to single try). +function execute-cmd-on-master-with-retries() { + echo "Executing command on the master" 1>&2 +} + +# This function should act as an scp for the kubemark cluster, which copies +# the files given by the first n-1 arguments to the remote location given +# by the n^th argument. +# +# Recommended for this function to include retrying logic in case of failures. +function copy-files() { + echo "Copying files" 1>&2 +} + +# This function should delete the master instance along with all the +# resources that have been allocated inside the function +# 'create-master-instance-with-resources' above. +# +# Recommended for this function to include retrying logic in case of failures. +function delete-master-instance-and-resources { + echo "Deleting master instance and its allocated resources" 1>&2 +} diff --git a/test/kubemark/start-kubemark.sh b/test/kubemark/start-kubemark.sh index e0e74d24a45..4bab969b0d2 100755 --- a/test/kubemark/start-kubemark.sh +++ b/test/kubemark/start-kubemark.sh @@ -20,6 +20,9 @@ TMP_ROOT="$(dirname "${BASH_SOURCE}")/../.." KUBE_ROOT=$(readlink -e ${TMP_ROOT} 2> /dev/null || perl -MCwd -e 'print Cwd::abs_path shift' ${TMP_ROOT}) source "${KUBE_ROOT}/test/kubemark/common.sh" +source "${KUBE_ROOT}/test/kubemark/skeleton/util.sh" +source "${KUBE_ROOT}/test/kubemark/cloud-provider-config.sh" +source "${KUBE_ROOT}/test/kubemark/${CLOUD_PROVIDER}/util.sh" # Write all environment variables that we need to pass to the kubemark master, # locally to the file ${RESOURCE_DIRECTORY}/kubemark-master-env.sh. @@ -51,57 +54,6 @@ EOF echo "Created the environment file for master." } -# Create the master instance along with all required network and disk resources. -function create-master-instance-with-resources { - GCLOUD_COMMON_ARGS="--project ${PROJECT} --zone ${ZONE}" - - run-gcloud-compute-with-retries disks create "${MASTER_NAME}-pd" \ - ${GCLOUD_COMMON_ARGS} \ - --type "${MASTER_DISK_TYPE}" \ - --size "${MASTER_DISK_SIZE}" - - if [ "${EVENT_PD:-false}" == "true" ]; then - run-gcloud-compute-with-retries disks create "${MASTER_NAME}-event-pd" \ - ${GCLOUD_COMMON_ARGS} \ - --type "${MASTER_DISK_TYPE}" \ - --size "${MASTER_DISK_SIZE}" - fi - - run-gcloud-compute-with-retries addresses create "${MASTER_NAME}-ip" \ - --project "${PROJECT}" \ - --region "${REGION}" -q - - MASTER_IP=$(gcloud compute addresses describe "${MASTER_NAME}-ip" \ - --project "${PROJECT}" --region "${REGION}" -q --format='value(address)') - - run-gcloud-compute-with-retries instances create "${MASTER_NAME}" \ - ${GCLOUD_COMMON_ARGS} \ - --address "${MASTER_IP}" \ - --machine-type "${MASTER_SIZE}" \ - --image-project="${MASTER_IMAGE_PROJECT}" \ - --image "${MASTER_IMAGE}" \ - --tags "${MASTER_TAG}" \ - --network "${NETWORK}" \ - --scopes "storage-ro,compute-rw,logging-write" \ - --boot-disk-size "${MASTER_ROOT_DISK_SIZE}" \ - --disk "name=${MASTER_NAME}-pd,device-name=master-pd,mode=rw,boot=no,auto-delete=no" - - if [ "${EVENT_PD:-false}" == "true" ]; then - echo "Attaching ${MASTER_NAME}-event-pd to ${MASTER_NAME}" - run-gcloud-compute-with-retries instances attach-disk "${MASTER_NAME}" \ - ${GCLOUD_COMMON_ARGS} \ - --disk "${MASTER_NAME}-event-pd" \ - --device-name="master-event-pd" - fi - - run-gcloud-compute-with-retries firewall-rules create "${INSTANCE_PREFIX}-kubemark-master-https" \ - --project "${PROJECT}" \ - --network "${NETWORK}" \ - --source-ranges "0.0.0.0/0" \ - --target-tags "${MASTER_TAG}" \ - --allow "tcp:443" -} - # Generate certs/keys for CA, master, kubelet and kubecfg, and tokens for kubelet # and kubeproxy. function generate-pki-config { @@ -119,33 +71,31 @@ function generate-pki-config { # Wait for the master to be reachable for executing commands on it. We do this by # trying to run the bash noop(:) on the master, with 10 retries. function wait-for-master-reachability { - until gcloud compute ssh --zone="${ZONE}" --project="${PROJECT}" "${MASTER_NAME}" --command=":" &> /dev/null; do - sleep 1 - done + execute-cmd-on-master-with-retries ":" 10 echo "Checked master reachability for remote command execution." } # Write all the relevant certs/keys/tokens to the master. function write-pki-config-to-master { - run-gcloud-compute-with-retries ssh --zone="${ZONE}" --project="${PROJECT}" "${MASTER_NAME}" \ - --command="sudo mkdir /home/kubernetes -p && sudo mkdir /etc/srv/kubernetes -p && \ - sudo bash -c \"echo ${CA_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/ca.crt\" && \ - sudo bash -c \"echo ${MASTER_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/server.cert\" && \ - sudo bash -c \"echo ${MASTER_KEY_BASE64} | base64 --decode > /etc/srv/kubernetes/server.key\" && \ - sudo bash -c \"echo ${KUBECFG_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/kubecfg.crt\" && \ - sudo bash -c \"echo ${KUBECFG_KEY_BASE64} | base64 --decode > /etc/srv/kubernetes/kubecfg.key\" && \ - sudo bash -c \"echo \"${KUBE_BEARER_TOKEN},admin,admin\" > /etc/srv/kubernetes/known_tokens.csv\" && \ - sudo bash -c \"echo \"${KUBELET_TOKEN},system:node:node-name,uid:kubelet,system:nodes\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ - sudo bash -c \"echo \"${KUBE_PROXY_TOKEN},system:kube-proxy,uid:kube_proxy\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ - sudo bash -c \"echo \"${HEAPSTER_TOKEN},system:heapster,uid:heapster\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ - sudo bash -c \"echo \"${NODE_PROBLEM_DETECTOR_TOKEN},system:node-problem-detector,uid:system:node-problem-detector\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ - sudo bash -c \"echo ${KUBE_PASSWORD},admin,admin > /etc/srv/kubernetes/basic_auth.csv\"" + PKI_SETUP_CMD="sudo mkdir /home/kubernetes -p && sudo mkdir /etc/srv/kubernetes -p && \ + sudo bash -c \"echo ${CA_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/ca.crt\" && \ + sudo bash -c \"echo ${MASTER_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/server.cert\" && \ + sudo bash -c \"echo ${MASTER_KEY_BASE64} | base64 --decode > /etc/srv/kubernetes/server.key\" && \ + sudo bash -c \"echo ${KUBECFG_CERT_BASE64} | base64 --decode > /etc/srv/kubernetes/kubecfg.crt\" && \ + sudo bash -c \"echo ${KUBECFG_KEY_BASE64} | base64 --decode > /etc/srv/kubernetes/kubecfg.key\" && \ + sudo bash -c \"echo \"${KUBE_BEARER_TOKEN},admin,admin\" > /etc/srv/kubernetes/known_tokens.csv\" && \ + sudo bash -c \"echo \"${KUBELET_TOKEN},system:node:node-name,uid:kubelet,system:nodes\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ + sudo bash -c \"echo \"${KUBE_PROXY_TOKEN},system:kube-proxy,uid:kube_proxy\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ + sudo bash -c \"echo \"${HEAPSTER_TOKEN},system:heapster,uid:heapster\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ + sudo bash -c \"echo \"${NODE_PROBLEM_DETECTOR_TOKEN},system:node-problem-detector,uid:system:node-problem-detector\" >> /etc/srv/kubernetes/known_tokens.csv\" && \ + sudo bash -c \"echo ${KUBE_PASSWORD},admin,admin > /etc/srv/kubernetes/basic_auth.csv\"" + execute-cmd-on-master-with-retries "${PKI_SETUP_CMD}" 3 echo "Wrote PKI certs, keys, tokens and admin password to master." } # Copy all the necessary resource files (scripts/configs/manifests) to the master. function copy-resource-files-to-master { - run-gcloud-compute-with-retries copy-files --zone="${ZONE}" --project="${PROJECT}" \ + copy-files \ "${SERVER_BINARY_TAR}" \ "${RESOURCE_DIRECTORY}/kubemark-master-env.sh" \ "${RESOURCE_DIRECTORY}/start-kubemark-master.sh" \ @@ -164,10 +114,10 @@ function copy-resource-files-to-master { # Make startup scripts executable and run start-kubemark-master.sh. function start-master-components { echo "" - gcloud compute ssh "${MASTER_NAME}" --zone="${ZONE}" --project="${PROJECT}" \ - --command="sudo chmod a+x /home/kubernetes/configure-kubectl.sh && \ - sudo chmod a+x /home/kubernetes/start-kubemark-master.sh && \ - sudo bash /home/kubernetes/start-kubemark-master.sh" + MASTER_STARTUP_CMD="sudo chmod a+x /home/kubernetes/configure-kubectl.sh && \ + sudo chmod a+x /home/kubernetes/start-kubemark-master.sh && \ + sudo bash /home/kubernetes/start-kubemark-master.sh" + execute-cmd-on-master-with-retries "${MASTER_STARTUP_CMD}" echo "The master has started and is now live." } diff --git a/test/kubemark/stop-kubemark.sh b/test/kubemark/stop-kubemark.sh index 6d5efd05bde..29d760cb852 100755 --- a/test/kubemark/stop-kubemark.sh +++ b/test/kubemark/stop-kubemark.sh @@ -19,6 +19,9 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. source "${KUBE_ROOT}/test/kubemark/common.sh" +source "${KUBE_ROOT}/test/kubemark/skeleton/util.sh" +source "${KUBE_ROOT}/test/kubemark/cloud-provider-config.sh" +source "${KUBE_ROOT}/test/kubemark/${CLOUD_PROVIDER}/util.sh" "${KUBECTL}" delete -f "${RESOURCE_DIRECTORY}/addons" &> /dev/null || true "${KUBECTL}" delete -f "${RESOURCE_DIRECTORY}/hollow-node.json" &> /dev/null || true @@ -29,30 +32,4 @@ rm -rf "${RESOURCE_DIRECTORY}/addons" \ "${RESOURCE_DIRECTORY}/hollow-node.json" \ "${RESOURCE_DIRECTORY}/kubemark-master-env.sh" &> /dev/null || true -GCLOUD_COMMON_ARGS="--project ${PROJECT} --zone ${ZONE} --quiet" - -gcloud compute instances delete "${MASTER_NAME}" \ - ${GCLOUD_COMMON_ARGS} || true - -gcloud compute disks delete "${MASTER_NAME}-pd" \ - ${GCLOUD_COMMON_ARGS} || true - -gcloud compute disks delete "${MASTER_NAME}-event-pd" \ - ${GCLOUD_COMMON_ARGS} &> /dev/null || true - -gcloud compute addresses delete "${MASTER_NAME}-ip" \ - --project "${PROJECT}" \ - --region "${REGION}" \ - --quiet || true - -gcloud compute firewall-rules delete "${INSTANCE_PREFIX}-kubemark-master-https" \ - --project "${PROJECT}" \ - --quiet || true - -if [ "${SEPARATE_EVENT_MACHINE:-false}" == "true" ]; then - gcloud compute instances delete "${EVENT_STORE_NAME}" \ - ${GCLOUD_COMMON_ARGS} || true - - gcloud compute disks delete "${EVENT_STORE_NAME}-pd" \ - ${GCLOUD_COMMON_ARGS} || true -fi +delete-master-instance-and-resources