From 4547cee6cbcf84083f6dfd70923cff86bd10abe6 Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Thu, 19 Jun 2014 17:02:54 -0700 Subject: [PATCH 1/5] Build runtime Docker images. Also added release process to push these images to GCS. --- build/build-image/make-binaries.sh | 2 +- build/build-image/run-integration.sh | 4 +- build/build-image/run-tests.sh | 2 + build/common.sh | 195 +++++++++++++++--- build/copy-output.sh | 7 +- build/json-extractor.py | 70 +++++++ build/make-binaries.sh | 1 + build/make-build-image.sh | 1 + build/make-clean.sh | 6 +- build/make-cross.sh | 7 +- build/make-run-image.sh | 30 +++ build/release.sh | 35 ++++ build/run-images/apiserver/Dockerfile | 25 +++ build/run-images/apiserver/run.sh | 21 ++ build/run-images/base/Dockerfile | 23 +++ .../run-images/controller-manager/Dockerfile | 25 +++ build/run-images/controller-manager/run.sh | 17 ++ build/run-images/proxy/Dockerfile | 24 +++ build/run-images/proxy/run.sh | 17 ++ build/run-integration.sh | 6 +- build/run-tests.sh | 6 +- build/shell.sh | 8 +- 22 files changed, 474 insertions(+), 58 deletions(-) create mode 100755 build/json-extractor.py create mode 100755 build/make-run-image.sh create mode 100755 build/release.sh create mode 100644 build/run-images/apiserver/Dockerfile create mode 100755 build/run-images/apiserver/run.sh create mode 100644 build/run-images/base/Dockerfile create mode 100644 build/run-images/controller-manager/Dockerfile create mode 100755 build/run-images/controller-manager/run.sh create mode 100644 build/run-images/proxy/Dockerfile create mode 100755 build/run-images/proxy/run.sh diff --git a/build/build-image/make-binaries.sh b/build/build-image/make-binaries.sh index baab646c85..6731f1751e 100755 --- a/build/build-image/make-binaries.sh +++ b/build/build-image/make-binaries.sh @@ -20,4 +20,4 @@ set -e source $(dirname $0)/common.sh -make-binaries +make-binaries "$@" diff --git a/build/build-image/run-integration.sh b/build/build-image/run-integration.sh index d007ea1ffb..b61bb879ed 100755 --- a/build/build-image/run-integration.sh +++ b/build/build-image/run-integration.sh @@ -21,11 +21,13 @@ source $(dirname $0)/common.sh ETCD_DIR="${KUBE_REPO_ROOT}/output/etcd" mkdir -p "${ETCD_DIR}" +echo "+++ Running integration test" + etcd -name test -data-dir ${ETCD_DIR} > "${KUBE_REPO_ROOT}/output/etcd.log" & ETCD_PID=$! sleep 5 -${KUBE_TARGET}/integration +${KUBE_TARGET}/linux/amd64/integration kill $ETCD_PID diff --git a/build/build-image/run-tests.sh b/build/build-image/run-tests.sh index 4c9e4fd466..c305ca4e5d 100755 --- a/build/build-image/run-tests.sh +++ b/build/build-image/run-tests.sh @@ -33,6 +33,8 @@ find_test_dirs() { cd "${KUBE_TARGET}" +echo "+++ Running unit tests" + if [[ -n "$1" ]]; then go test -cover -coverprofile="tmp.out" "$KUBE_GO_PACKAGE/$1" exit 0 diff --git a/build/common.sh b/build/common.sh index ec543f6ad9..a79d69aaba 100644 --- a/build/common.sh +++ b/build/common.sh @@ -37,39 +37,95 @@ readonly REMOTE_OUTPUT_DIR="/go/src/${KUBE_GO_PACKAGE}/output/build" readonly DOCKER_CONTAINER_NAME=kube-build readonly DOCKER_MOUNT="-v ${LOCAL_OUTPUT_DIR}:${REMOTE_OUTPUT_DIR}" -# Verify that the right utilitites and such are installed. -if [[ -z "$(which docker)" ]]; then - echo "Can't find 'docker' in PATH, please fix and retry." >&2 - echo "See https://docs.docker.com/installation/#installation for installation instructions." >&2 - exit 1 -fi +readonly KUBE_RUN_IMAGE_BASE="kubernetes" +readonly KUBE_RUN_BINARIES=" + apiserver + controller-manager + proxy + " -if [[ "$OSTYPE" == "darwin"* ]]; then - if [[ -z "$(which boot2docker)" ]]; then - echo "It looks like you are running on Mac OS X and boot2docker can't be found." >&2 - echo "See: https://docs.docker.com/installation/mac/" >&2 - exit 1 +# Verify that the right utilities and such are installed for building Kube. +function verify-prereqs() { + if [[ -z "$(which docker)" ]]; then + echo "Can't find 'docker' in PATH, please fix and retry." >&2 + echo "See https://docs.docker.com/installation/#installation for installation instructions." >&2 + return 1 fi - if [[ $(boot2docker status) != "running" ]]; then - echo "boot2docker VM isn't started. Please run 'boot2docker start'" >&2 - exit 1 - fi -fi -if ! docker info > /dev/null 2>&1 ; then - echo "Can't connect to 'docker' daemon. please fix and retry." >&2 - echo >&2 - echo "Possible causes:" >&2 - echo " - On Mac OS X, boot2docker VM isn't started" >&2 - echo " - On Mac OS X, DOCKER_HOST env variable isn't set approriately" >&2 - echo " - On Linux, user isn't in 'docker' group. Add and relogin." >&2 - echo " - On Linux, Docker daemon hasn't been started or has crashed" >&2 - exit 1 -fi + if [[ "$OSTYPE" == "darwin"* ]]; then + if [[ -z "$(which boot2docker)" ]]; then + echo "It looks like you are running on Mac OS X and boot2docker can't be found." >&2 + echo "See: https://docs.docker.com/installation/mac/" >&2 + return 1 + fi + if [[ $(boot2docker status) != "running" ]]; then + echo "boot2docker VM isn't started. Please run 'boot2docker start'" >&2 + return 1 + fi + fi + + if ! docker info > /dev/null 2>&1 ; then + echo "Can't connect to 'docker' daemon. please fix and retry." >&2 + echo >&2 + echo "Possible causes:" >&2 + echo " - On Mac OS X, boot2docker VM isn't started" >&2 + echo " - On Mac OS X, DOCKER_HOST env variable isn't set approriately" >&2 + echo " - On Linux, user isn't in 'docker' group. Add and relogin." >&2 + echo " - On Linux, Docker daemon hasn't been started or has crashed" >&2 + return 1 + fi +} + +# Verify things are set up for uploading to GCS +function verify-gcs-prereqs() { + if [[ -z "$(which gsutil)" || -z "$(which gcloud)" ]]; then + echo "Releasing Kubernetes requires gsutil and gcloud. Please download," + echo "install and authorize through the Google Cloud SDK: " + echo + echo " https://developers.google.com/cloud/sdk/" + return 1 + fi + + FIND_ACCOUNT="gcloud auth list 2>/dev/null | grep '(active)' | awk '{ print \$2 }'" + GCLOUD_ACCOUNT=${GCLOUD_ACCOUNT-$(eval ${FIND_ACCOUNT})} + if [[ -z "${GCLOUD_ACCOUNT}" ]]; then + echo "No account authorized through gcloud. Please fix with:" + echo + echo " gcloud auth login" + return 1 + fi + + FIND_PROJECT="gcloud config list project | tail -n 1 | awk '{ print \$3 }'" + GCLOUD_PROJECT=${GCLOUD_PROJECT-$(eval ${FIND_PROJECT})} + if [[ -z "${GCLOUD_PROJECT}" ]]; then + echo "No account authorized through gcloud. Please fix with:" + echo + echo " gcloud config set project " + return 1 + fi +} + +# Create a unique bucket name for releasing Kube and make sure it exists. +function ensure-gcs-release-bucket() { + if which md5 > /dev/null; then + HASH=$(md5 -q -s "$GCLOUD_PROJECT") + else + HASH=$(echo -n "$GCLOUD_PROJECT" | md5sum) + fi + HASH=${HASH:0:5} + KUBE_RELEASE_BUCKET=${KUBE_RELEASE_BUCKET-kubernetes-releases-$HASH} + KUBE_RELEASE_PREFIX=${KUBE_RELEASE_PREFIX-devel/} + DOCKER_REG_PREFIX=${DOCKER_REG_PREFIX-docker-reg/} + + if ! gsutil ls gs://${KUBE_RELEASE_BUCKET} >/dev/null 2>&1 ; then + echo "Creating Google Cloud Storage bucket: $RELEASE_BUCKET" + gsutil mb gs://${KUBE_RELEASE_BUCKET} + fi +} # Set up the context directory for the kube-build image and build it. function build-image() { - local -r BUILD_CONTEXT_DIR=${KUBE_REPO_ROOT}/output/build-image + local -r BUILD_CONTEXT_DIR="${KUBE_REPO_ROOT}/output/images/${KUBE_BUILD_IMAGE}" local -r SOURCE=" api build @@ -79,19 +135,47 @@ function build-image() { third_party LICENSE " - local -r DOCKER_BUILD_CMD="docker build -t ${KUBE_BUILD_IMAGE} ${BUILD_CONTEXT_DIR}" - - echo "+++ Building Docker image ${KUBE_BUILD_IMAGE}. First run can take minutes." - mkdir -p ${BUILD_CONTEXT_DIR} tar czf ${BUILD_CONTEXT_DIR}/kube-source.tar.gz ${SOURCE} cp build/build-image/Dockerfile ${BUILD_CONTEXT_DIR}/Dockerfile + docker-build "${KUBE_BUILD_IMAGE}" "${BUILD_CONTEXT_DIR}" +} +# Builds the runtime image. Assumes that the appropriate binaries are already +# built and in output/build/. +function run-image() { + local -r BUILD_CONTEXT_BASE="${KUBE_REPO_ROOT}/output/images/${KUBE_RUN_IMAGE_BASE}" + + # First build the base image. This one brings in all of the binaries. + mkdir -p "${BUILD_CONTEXT_BASE}" + tar czf ${BUILD_CONTEXT_BASE}/kube-bins.tar.gz \ + -C "output/build/linux/amd64" \ + ${KUBE_RUN_BINARIES} + cp -R build/run-images/base/* "${BUILD_CONTEXT_BASE}/" + docker-build "${KUBE_RUN_IMAGE_BASE}" "${BUILD_CONTEXT_BASE}" + + for b in $KUBE_RUN_BINARIES ; do + local SUB_CONTEXT_DIR="${BUILD_CONTEXT_BASE}-$b" + mkdir -p "${SUB_CONTEXT_DIR}" + cp -R build/run-images/$b/* "${SUB_CONTEXT_DIR}/" + docker-build "${KUBE_RUN_IMAGE_BASE}-$b" "${SUB_CONTEXT_DIR}" + done +} + +# Build a docker image from a Dockerfile. +# $1 is the name of the image to build +# $2 is the location of the "context" directory, with the Dockerfile at the root. +function docker-build() { + local -r IMAGE=$1 + local -r CONTEXT_DIR=$2 + local -r BUILD_CMD="docker build -t ${IMAGE} ${CONTEXT_DIR}" + + echo "+++ Building Docker image ${IMAGE}. This can take a while." set +e # We are handling the error here manually - local -r DOCKER_OUTPUT="$(${DOCKER_BUILD_CMD} 2>&1)" + local -r DOCKER_OUTPUT="$(${BUILD_CMD} 2>&1)" if [ $? -ne 0 ]; then set -e - echo "+++ Docker build command failed." >&2 + echo "+++ Docker build command failed for ${IMAGE}" >&2 echo >&2 echo "${DOCKER_OUTPUT}" >&2 echo >&2 @@ -102,7 +186,52 @@ function build-image() { return 1 fi set -e +} +function ensure-gcs-docker-registry() { + local -r REG_CONTAINER_NAME="gcs-registry" + + local -r RUNNING=$(docker inspect ${REG_CONTAINER_NAME} 2>/dev/null \ + | build/json-extractor.py 0.State.Running 2>/dev/null) + + [[ "$RUNNING" != "true" ]] || return 0 + + # Grovel around and find the OAuth token in the gcloud config + local -r BOTO=~/.config/gcloud/legacy_credentials/${GCLOUD_ACCOUNT}/.boto + local -r REFRESH_TOKEN=$(grep 'gs_oauth2_refresh_token =' $BOTO | awk '{ print $3 }') + + if [[ -z $REFRESH_TOKEN ]]; then + echo "Couldn't find OAuth 2 refresh token in ${BOTO}" >&2 + return 1 + fi + + # If we have an old one sitting around, remove it + docker rm ${REG_CONTAINER_NAME} >/dev/null 2>&1 || true + + echo "+++ Starting GCS backed Docker registry" + local DOCKER="docker run -d --name=${REG_CONTAINER_NAME} " + DOCKER+="-e GCS_BUCKET=${KUBE_RELEASE_BUCKET} " + DOCKER+="-e STORAGE_PATH=${DOCKER_REG_PREFIX} " + DOCKER+="-e GCP_OAUTH2_REFRESH_TOKEN=${REFRESH_TOKEN} " + DOCKER+="-p 127.0.0.1:5000:5000 " + DOCKER+="jbeda/docker-registry" + + ${DOCKER} + + # Give it time to spin up before we start throwing stuff at it + sleep 5 +} + +function push-images-to-gcs() { + ensure-gcs-docker-registry + + # Tag each of our run binaries with the right registry and push + for b in ${KUBE_RUN_BINARIES} ; do + echo "+++ Tagging and pushing ${KUBE_RUN_IMAGE_BASE}-$b" + docker tag "${KUBE_RUN_IMAGE_BASE}-$b" "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" + docker push "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" + docker rmi "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" + done } # Run a command in the kube-build image. This assumes that the image has diff --git a/build/copy-output.sh b/build/copy-output.sh index bf7dafafbb..8ba6b187d8 100755 --- a/build/copy-output.sh +++ b/build/copy-output.sh @@ -14,13 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Make all of the Kubernetes binaries. +# Copies any built binaries off the Docker machine. # -# This makes the docker build image, builds the binaries and copies them out -# of the docker container. +# This is a no-op on Linux when the Docker daemon is local. This is only +# necessary on Mac OS X with boot2docker. set -e source $(dirname $0)/common.sh +verify-prereqs copy-output diff --git a/build/json-extractor.py b/build/json-extractor.py new file mode 100755 index 0000000000..e8b62f5910 --- /dev/null +++ b/build/json-extractor.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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 is a very simple utility that reads a JSON document from stdin, parses it +# and returns the specified value. The value is described using a simple dot +# notation. If any errors are encountered along the way, an error is output and +# a failure value is returned. + +from __future__ import print_function + +import json +import sys + +def PrintError(*err): + print(*err, file=sys.stderr) + +def main(): + try: + obj = json.load(sys.stdin) + except Exception, e: + PrintError("Error loading JSON: {0}".format(str(e))) + + if len(sys.argv) == 1: + # if we don't have a query string, return success + return 0 + elif len(sys.argv) > 2: + PrintError("Usage: {0} ".format(sys.args[0])) + return 1 + + query_list = sys.argv[1].split('.') + for q in query_list: + if isinstance(obj, dict): + if q not in obj: + PrintError("Couldn't find '{0}' in dict".format(q)) + return 1 + obj = obj[q] + elif isinstance(obj, list): + try: + index = int(q) + except: + PrintError("Can't use '{0}' to index into array".format(q)) + return 1 + if index >= len(obj): + PrintError("Index ({0}) is greater than length of list ({1})".format(q, len(obj))) + return 1 + obj = obj[index] + else: + PrintError("Trying to query non-queryable object: {0}".format(q)) + return 1 + + if isinstance(obj, str): + print(obj) + else: + print(json.dumps(obj, indent=2)) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/build/make-binaries.sh b/build/make-binaries.sh index 3df5e05193..15bc65dee8 100755 --- a/build/make-binaries.sh +++ b/build/make-binaries.sh @@ -23,5 +23,6 @@ set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command build/build-image/make-binaries.sh "$@" diff --git a/build/make-build-image.sh b/build/make-build-image.sh index d96995dc83..66c465fcfb 100755 --- a/build/make-build-image.sh +++ b/build/make-build-image.sh @@ -25,4 +25,5 @@ set -e source $(dirname $0)/common.sh +verify-prereqs build-image diff --git a/build/make-clean.sh b/build/make-clean.sh index a0b2192c81..cbfcc53e17 100755 --- a/build/make-clean.sh +++ b/build/make-clean.sh @@ -14,14 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Make all of the Kubernetes binaries. -# -# This makes the docker build image, builds the binaries and copies them out -# of the docker container. +# Clean out the output directory on the docker host. set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command rm -rf output/build/* diff --git a/build/make-cross.sh b/build/make-cross.sh index 2fe8141649..815a9f8f6e 100755 --- a/build/make-cross.sh +++ b/build/make-cross.sh @@ -14,14 +14,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Make all of the Kubernetes binaries. +# Make all of the Kubernetes binaries for cross compile targets # -# This makes the docker build image, builds the binaries and copies them out -# of the docker container. +# This makes the docker build image, builds the cross binaries and copies them +# out of the docker container. set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command build/build-image/make-cross.sh diff --git a/build/make-run-image.sh b/build/make-run-image.sh new file mode 100755 index 0000000000..6e6ef7cfe9 --- /dev/null +++ b/build/make-run-image.sh @@ -0,0 +1,30 @@ +#! /bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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. + +# Build the docker image necessary for running Kubernetes +# +# This script will make the 'run image' after building all of the necessary +# binaries. + +set -e + +source $(dirname $0)/common.sh + +verify-prereqs +build-image +run-build-command build/build-image/make-binaries.sh "$@" +copy-output +run-image diff --git a/build/release.sh b/build/release.sh new file mode 100755 index 0000000000..1823c39617 --- /dev/null +++ b/build/release.sh @@ -0,0 +1,35 @@ +#! /bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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. + +# Build a Kubernetes release. This will build the binaries, create the Docker +# images and other build artifacts. All intermediate artifacts will be hosted +# publicly on Google Cloud Storage currently. + +set -e + +source $(dirname $0)/common.sh + +verify-prereqs +verify-gcs-prereqs +ensure-gcs-release-bucket +build-image +run-build-command build/build-image/make-binaries.sh +run-build-command build/build-image/make-cross.sh +run-build-command build/build-image/run-tests.sh +run-build-command build/build-image/run-integration.sh +copy-output +run-image +push-images-to-gcs diff --git a/build/run-images/apiserver/Dockerfile b/build/run-images/apiserver/Dockerfile new file mode 100644 index 0000000000..4259309f97 --- /dev/null +++ b/build/run-images/apiserver/Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# 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 file creates a minimal container for running Kubernetes binaries + +FROM kubernetes +MAINTAINER Joe Beda + +ENV ETCD_SERVERS http://127.0.0.1:4001 +ENV KUBE_MINIONS "" + +ADD . /kubernetes + +CMD ['./run.sh'] diff --git a/build/run-images/apiserver/run.sh b/build/run-images/apiserver/run.sh new file mode 100755 index 0000000000..75ce1747e5 --- /dev/null +++ b/build/run-images/apiserver/run.sh @@ -0,0 +1,21 @@ +#! /bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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. + +# If the user doesn't specify a minion, assume we are running in a single node +# configuration and that we have a local minion. +KUBE_MINIONS=${KUBE_MINIONS:$(hostname -f)} + +./apiserver -master=127.0.0.1:8080 -etcd_servers="${ETCD_SERVERS}" --machines="${KUBE_MINIONS}" diff --git a/build/run-images/base/Dockerfile b/build/run-images/base/Dockerfile new file mode 100644 index 0000000000..823840e14c --- /dev/null +++ b/build/run-images/base/Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# 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 file creates a minimal container for running Kubernetes binaries + +FROM busybox +MAINTAINER Joe Beda + +WORKDIR /kubernetes + +# Upload Kubernetes +ADD kube-bins.tar.gz /kubernetes diff --git a/build/run-images/controller-manager/Dockerfile b/build/run-images/controller-manager/Dockerfile new file mode 100644 index 0000000000..c983de1298 --- /dev/null +++ b/build/run-images/controller-manager/Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# 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 file creates a minimal container for running Kubernetes binaries + +FROM kubernetes +MAINTAINER Joe Beda + +ENV ETCD_SERVERS http://127.0.0.1:4001 +ENV API_SERVER 127.0.0.1:8080 + +ADD . /kubernetes + +CMD ['./run.sh'] diff --git a/build/run-images/controller-manager/run.sh b/build/run-images/controller-manager/run.sh new file mode 100755 index 0000000000..46b6eacf96 --- /dev/null +++ b/build/run-images/controller-manager/run.sh @@ -0,0 +1,17 @@ +#! /bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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. + +./controller-manager -etcd_servers="${ETCD_SERVERS}" -master="${API_SERVER}" diff --git a/build/run-images/proxy/Dockerfile b/build/run-images/proxy/Dockerfile new file mode 100644 index 0000000000..f880f065b4 --- /dev/null +++ b/build/run-images/proxy/Dockerfile @@ -0,0 +1,24 @@ +# Copyright 2014 Google Inc. All rights reserved. +# +# 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 file creates a minimal container for running Kubernetes binaries + +FROM kubernetes +MAINTAINER Joe Beda + +ENV ETCD_SERVERS http://127.0.0.1:4001 + +ADD . /kubernetes + +CMD ['./run.sh'] diff --git a/build/run-images/proxy/run.sh b/build/run-images/proxy/run.sh new file mode 100755 index 0000000000..c85d47f8d4 --- /dev/null +++ b/build/run-images/proxy/run.sh @@ -0,0 +1,17 @@ +#! /bin/bash + +# Copyright 2014 Google Inc. All rights reserved. +# +# 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. + +./proxy --etcd_servers="${ETCD_SERVERS}" diff --git a/build/run-integration.sh b/build/run-integration.sh index f15f1a4650..c4a41ba04d 100755 --- a/build/run-integration.sh +++ b/build/run-integration.sh @@ -14,15 +14,13 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Make all of the Kubernetes binaries. -# -# This makes the docker build image, builds the binaries and copies them out -# of the docker container. +# Run the integration test. set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command build/build-image/make-binaries.sh "integration" run-build-command build/build-image/run-integration.sh diff --git a/build/run-tests.sh b/build/run-tests.sh index 869b5454bb..6accabc624 100755 --- a/build/run-tests.sh +++ b/build/run-tests.sh @@ -14,14 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Make all of the Kubernetes binaries. -# -# This makes the docker build image, builds the binaries and copies them out -# of the docker container. +# Run all of the golang unit tests. set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command build/build-image/run-tests.sh "$@" diff --git a/build/shell.sh b/build/shell.sh index 0fa412c772..d1bd2a4be3 100755 --- a/build/shell.sh +++ b/build/shell.sh @@ -14,16 +14,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Build the docker image necessary for building Kubernetes +# Run a bash script in the Docker build image. # -# This script will package the parts of the repo that we need to build -# Kubernetes into a tar file and put it in the right place in the output -# directory. It will then copy over the Dockerfile and build the kube-build -# image. +# This container will have a snapshot of the current sources. set -e source $(dirname $0)/common.sh +verify-prereqs build-image run-build-command bash From 8d1913b5f4caec4fe4eeeeaaa3cbb5143fe0d060 Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Fri, 20 Jun 2014 10:50:46 -0700 Subject: [PATCH 2/5] Expand `build/README.md`. --- build/README.md | 41 ++++++++++++++++++++++++++++++++++++++--- build/common.sh | 6 +++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/build/README.md b/build/README.md index 0d10510d1d..8f986d0cdf 100644 --- a/build/README.md +++ b/build/README.md @@ -4,13 +4,48 @@ To build Kubernetes you need to have access to a Docker installation through eit ## Requirements -1. Run on Mac OS X. The best way to go is to use `boot2docker`. See instructions [here](https://docs.docker.com/installation/mac/). -2. Run on Linux against a local Docker. Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS. The scripts here assume that they are using a local Docker server and that they can "reach around" docker and grab results directly from the file system. +1. Be running Docker. 2 options supported/tested: + 1. **Mac OS X** The best way to go is to use `boot2docker`. See instructions [here](https://docs.docker.com/installation/mac/). + 1. **Linux with local Docker** Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS. The scripts here assume that they are using a local Docker server and that they can "reach around" docker and grab results directly from the file system. +1. Have python installed. Pretty much it is installed everywhere at this point so you can probably ignore this. +1. For releasing, have the [Google Cloud SDK](https://developers.google.com/cloud/sdk/) installed and configured. The default release mechanism will upload Docker images to a private registry backed by Google Cloud Storage. Non-image release artifacts will be uploaded to Google Cloud Storage also. + +## Key scripts + +* `make-binaries.sh`: This will compile all of the Kubernetes binaries in a Docker container +* `run-tests.sh`: This will run the Kubernetes unit tests in a Docker container +* `run-integration.sh`: This will build and run the integration test in a Docker container +* `make-cross.sh`: This will make all cross-compiled binaries (currently just cloudcfg). +* `copy-output.sh`: This will copy the contents of `output/build` from any remote Docker container to the local `output/build`. Right now this is only necessary on Mac OS X with `boot2docker`. +* `make-clean.sh`: Clean out the contents of `output/build`. +* `shell.sh`: Drop into a `bash` shell in a build container with a snapshot of the current repo code. +* `release.sh`: Build everything, test it, upload the results to a GCS bucket. Docker images are also sent to the same bucket using the [`google/docker-registry`](https://registry.hub.docker.com/u/google/docker-registry/) Docker image. + +## Releasing + +The `release.sh` script will build a release. It will build binaries, run tests, build runtime Docker images and then upload all build artifacts to a GCS bucket. + +The GCS bucket that is used is named `kubernetes-releases-NNNNN`. The `NNNNN` is a random string derived from an md5 hash of the project name. + +The release process can be customized with environment variables: +* `KUBE_RELEASE_BUCKET`: Override the bucket to be used for uploading releases. +* `KUBE_RELEASE_PREFIX`: The prefix for all non-docker image build artifacts. This defaults to `devel/` +* `KUBE_DOCKER_REG_PREFIX`: The prefix for storage of the docker registry. This defaults to `docker-reg/` + +The release Docker images (all defined in `build/run-images/*/Dockerfile`): +* `kubernetes-apiserver`: Runs the main API server. It is parameterized with environment variables for `ETCD_SERVERS` and `KUBE_MINIONS` with defaults for localhost. +* `kubernetes-controller-manager`: Runs a set external controllers (see `DESIGN.md` for details). It is parameterized with environment variables for `ETCD_SERVERS` and `API_SERVER`. +* `kubernetes-proxy`: Runs the proxy server on each individual node. This is parameterized for `ETCD_SERVERS` and is required to be launched with `--net=host` Docker option to function correctly. + +Other build artifacts: +* **TODO:** package up client utilties and cluster bring up scripts. ## Basic Flow The scripts directly under `build/` are used to build and test. They will ensure that the `kube-build` Docker image is built (based on `build/build-image/Dockerfile`) and then execute the appropriate command in that container. If necessary (for Mac OS X), the scripts will also copy results out. -The `kube-build` container image is built by first creating a "context" directory in `output/build-image`. It is done there instead of at the root of the Kubernetes repo to minimize the amount of data we need to package up when building the image. +The `kube-build` container image is built by first creating a "context" directory in `output/images/build-image`. It is done there instead of at the root of the Kubernetes repo to minimize the amount of data we need to package up when building the image. Everything in `build/build-image/` is meant to be run inside of the container. If it doesn't think it is running in the container it'll throw a warning. While you can run some of that stuff outside of the container, it wasn't built to do so. + +The files necessarily for the release Docker images are in `build/run-images/*`. All of this is staged into `output/images` similar to build-image. The `base` image is used as a base for each of the specialized containers and is generally never pushed to a shared repository. diff --git a/build/common.sh b/build/common.sh index a79d69aaba..25d076733f 100644 --- a/build/common.sh +++ b/build/common.sh @@ -115,7 +115,7 @@ function ensure-gcs-release-bucket() { HASH=${HASH:0:5} KUBE_RELEASE_BUCKET=${KUBE_RELEASE_BUCKET-kubernetes-releases-$HASH} KUBE_RELEASE_PREFIX=${KUBE_RELEASE_PREFIX-devel/} - DOCKER_REG_PREFIX=${DOCKER_REG_PREFIX-docker-reg/} + KUBE_DOCKER_REG_PREFIX=${KUBE_DOCKER_REG_PREFIX-docker-reg/} if ! gsutil ls gs://${KUBE_RELEASE_BUCKET} >/dev/null 2>&1 ; then echo "Creating Google Cloud Storage bucket: $RELEASE_BUCKET" @@ -211,7 +211,7 @@ function ensure-gcs-docker-registry() { echo "+++ Starting GCS backed Docker registry" local DOCKER="docker run -d --name=${REG_CONTAINER_NAME} " DOCKER+="-e GCS_BUCKET=${KUBE_RELEASE_BUCKET} " - DOCKER+="-e STORAGE_PATH=${DOCKER_REG_PREFIX} " + DOCKER+="-e STORAGE_PATH=${KUBE_DOCKER_REG_PREFIX} " DOCKER+="-e GCP_OAUTH2_REFRESH_TOKEN=${REFRESH_TOKEN} " DOCKER+="-p 127.0.0.1:5000:5000 " DOCKER+="jbeda/docker-registry" @@ -227,7 +227,7 @@ function push-images-to-gcs() { # Tag each of our run binaries with the right registry and push for b in ${KUBE_RUN_BINARIES} ; do - echo "+++ Tagging and pushing ${KUBE_RUN_IMAGE_BASE}-$b" + echo "+++ Tagging and pushing ${KUBE_RUN_IMAGE_BASE}-$b to GCS bucket ${KUBE_RELEASE_BUCKET}" docker tag "${KUBE_RUN_IMAGE_BASE}-$b" "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" docker push "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" docker rmi "localhost:5000/${KUBE_RUN_IMAGE_BASE}-$b" From 0376098ee1d77e2c7c67ee71822c03e721cc964d Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Fri, 20 Jun 2014 11:08:50 -0700 Subject: [PATCH 3/5] Reorganize build script file for clarity --- build/common.sh | 136 +++++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 64 deletions(-) diff --git a/build/common.sh b/build/common.sh index 25d076733f..fe3bf352ed 100644 --- a/build/common.sh +++ b/build/common.sh @@ -44,6 +44,9 @@ readonly KUBE_RUN_BINARIES=" proxy " +# --------------------------------------------------------------------------- +# Basic setup functions + # Verify that the right utilities and such are installed for building Kube. function verify-prereqs() { if [[ -z "$(which docker)" ]]; then @@ -105,23 +108,8 @@ function verify-gcs-prereqs() { fi } -# Create a unique bucket name for releasing Kube and make sure it exists. -function ensure-gcs-release-bucket() { - if which md5 > /dev/null; then - HASH=$(md5 -q -s "$GCLOUD_PROJECT") - else - HASH=$(echo -n "$GCLOUD_PROJECT" | md5sum) - fi - HASH=${HASH:0:5} - KUBE_RELEASE_BUCKET=${KUBE_RELEASE_BUCKET-kubernetes-releases-$HASH} - KUBE_RELEASE_PREFIX=${KUBE_RELEASE_PREFIX-devel/} - KUBE_DOCKER_REG_PREFIX=${KUBE_DOCKER_REG_PREFIX-docker-reg/} - - if ! gsutil ls gs://${KUBE_RELEASE_BUCKET} >/dev/null 2>&1 ; then - echo "Creating Google Cloud Storage bucket: $RELEASE_BUCKET" - gsutil mb gs://${KUBE_RELEASE_BUCKET} - fi -} +# --------------------------------------------------------------------------- +# Building # Set up the context directory for the kube-build image and build it. function build-image() { @@ -188,6 +176,73 @@ function docker-build() { set -e } + +# Run a command in the kube-build image. This assumes that the image has +# already been built. This will sync out all output data from the build. +function run-build-command() { + [[ -n "$@" ]] || { echo "Invalid input." >&2; return 4; } + + local -r DOCKER="docker run --rm --name=${DOCKER_CONTAINER_NAME} -it ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" + + docker rm ${DOCKER_CONTAINER_NAME} >/dev/null 2>&1 || true + + ${DOCKER} "$@" +} + +# If the Docker server is remote, copy the results back out. +function copy-output() { + if [[ "$OSTYPE" == "darwin"* ]]; then + # When we are on the Mac with boot2docker Now we need to copy the results + # back out. Ideally we would leave the container around and use 'docker cp' + # to copy the results out. However, that doesn't work for mounted volumes + # currently (https://github.com/dotcloud/docker/issues/1992). And it is + # just plain broken (https://github.com/dotcloud/docker/issues/6483). + # + # The easiest thing I (jbeda) could figure out was to launch another + # container pointed at the same volume, tar the output directory and ship + # that tar over stdou. + local DOCKER="docker run -a stdout --rm --name=${DOCKER_CONTAINER_NAME} ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" + + # Kill any leftover container + docker rm ${DOCKER_CONTAINER_NAME} >/dev/null 2>&1 || true + + echo "+++ Syncing back output directory from boot2docker VM" + mkdir -p "${LOCAL_OUTPUT_DIR}" + rm -rf "${LOCAL_OUTPUT_DIR}/*" + ${DOCKER} sh -c "tar c -C ${REMOTE_OUTPUT_DIR} ." \ + | tar xv -C "${LOCAL_OUTPUT_DIR}" + + # I (jbeda) also tried getting rsync working using 'docker run' as the + # 'remote shell'. This mostly worked but there was a hang when + # closing/finishing things off. Ug. + # + # local DOCKER="docker run -i --rm --name=${DOCKER_CONTAINER_NAME} ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" + # DOCKER+=" bash -c 'shift ; exec \"\$@\"' --" + # rsync --blocking-io -av -e "${DOCKER}" foo:${REMOTE_OUTPUT_DIR}/ ${LOCAL_OUTPUT_DIR} + fi +} + +# --------------------------------------------------------------------------- +# Release + +# Create a unique bucket name for releasing Kube and make sure it exists. +function ensure-gcs-release-bucket() { + if which md5 > /dev/null; then + HASH=$(md5 -q -s "$GCLOUD_PROJECT") + else + HASH=$(echo -n "$GCLOUD_PROJECT" | md5sum) + fi + HASH=${HASH:0:5} + KUBE_RELEASE_BUCKET=${KUBE_RELEASE_BUCKET-kubernetes-releases-$HASH} + KUBE_RELEASE_PREFIX=${KUBE_RELEASE_PREFIX-devel/} + KUBE_DOCKER_REG_PREFIX=${KUBE_DOCKER_REG_PREFIX-docker-reg/} + + if ! gsutil ls gs://${KUBE_RELEASE_BUCKET} >/dev/null 2>&1 ; then + echo "Creating Google Cloud Storage bucket: $RELEASE_BUCKET" + gsutil mb gs://${KUBE_RELEASE_BUCKET} + fi +} + function ensure-gcs-docker-registry() { local -r REG_CONTAINER_NAME="gcs-registry" @@ -234,50 +289,3 @@ function push-images-to-gcs() { done } -# Run a command in the kube-build image. This assumes that the image has -# already been built. This will sync out all output data from the build. -function run-build-command() { - [[ -n "$@" ]] || { echo "Invalid input." >&2; return 4; } - - local -r DOCKER="docker run --rm --name=${DOCKER_CONTAINER_NAME} -it ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" - - docker rm ${DOCKER_CONTAINER_NAME} >/dev/null 2>&1 || true - - ${DOCKER} "$@" - -} - -# If the Docker server is remote, copy the results back out. -function copy-output() { - if [[ "$OSTYPE" == "darwin"* ]]; then - # When we are on the Mac with boot2docker Now we need to copy the results - # back out. Ideally we would leave the container around and use 'docker cp' - # to copy the results out. However, that doesn't work for mounted volumes - # currently (https://github.com/dotcloud/docker/issues/1992). And it is - # just plain broken (https://github.com/dotcloud/docker/issues/6483). - # - # The easiest thing I (jbeda) could figure out was to launch another - # container pointed at the same volume, tar the output directory and ship - # that tar over stdou. - local DOCKER="docker run -a stdout --rm --name=${DOCKER_CONTAINER_NAME} ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" - - # Kill any leftover container - docker rm ${DOCKER_CONTAINER_NAME} >/dev/null 2>&1 || true - - echo "+++ Syncing back output directory from boot2docker VM" - mkdir -p "${LOCAL_OUTPUT_DIR}" - rm -rf "${LOCAL_OUTPUT_DIR}/*" - ${DOCKER} sh -c "tar c -C ${REMOTE_OUTPUT_DIR} ." \ - | tar xv -C "${LOCAL_OUTPUT_DIR}" - - # I (jbeda) also tried getting rsync working using 'docker run' as the - # 'remote shell'. This mostly worked but there was a hang when - # closing/finishing things off. Ug. - # - # local DOCKER="docker run -i --rm --name=${DOCKER_CONTAINER_NAME} ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}" - # DOCKER+=" bash -c 'shift ; exec \"\$@\"' --" - # rsync --blocking-io -av -e "${DOCKER}" foo:${REMOTE_OUTPUT_DIR}/ ${LOCAL_OUTPUT_DIR} - fi -} - - From 96f8cd3761b8bc2cdf17c8053c48665136941681 Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Fri, 20 Jun 2014 11:17:08 -0700 Subject: [PATCH 4/5] jbeda/docker-registry -> google/docker-registry --- build/common.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/common.sh b/build/common.sh index fe3bf352ed..8824f97122 100644 --- a/build/common.sh +++ b/build/common.sh @@ -269,7 +269,7 @@ function ensure-gcs-docker-registry() { DOCKER+="-e STORAGE_PATH=${KUBE_DOCKER_REG_PREFIX} " DOCKER+="-e GCP_OAUTH2_REFRESH_TOKEN=${REFRESH_TOKEN} " DOCKER+="-p 127.0.0.1:5000:5000 " - DOCKER+="jbeda/docker-registry" + DOCKER+="google/docker-registry" ${DOCKER} From 866cad9bd98dabcd26850dcc81f60a965a94dd4d Mon Sep 17 00:00:00 2001 From: Joe Beda Date: Fri, 20 Jun 2014 15:17:14 -0700 Subject: [PATCH 5/5] Build platform specific tarballs and upload them to the release directory. --- build/README.md | 13 +++++++++++++ build/common.sh | 42 +++++++++++++++++++++++++++++++++++++++++- build/release.sh | 2 ++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/build/README.md b/build/README.md index 8f986d0cdf..cf759f7a4a 100644 --- a/build/README.md +++ b/build/README.md @@ -49,3 +49,16 @@ The `kube-build` container image is built by first creating a "context" director Everything in `build/build-image/` is meant to be run inside of the container. If it doesn't think it is running in the container it'll throw a warning. While you can run some of that stuff outside of the container, it wasn't built to do so. The files necessarily for the release Docker images are in `build/run-images/*`. All of this is staged into `output/images` similar to build-image. The `base` image is used as a base for each of the specialized containers and is generally never pushed to a shared repository. + +## TODOs + +@jbeda is going on vacation and can't complete this work for a while. Here are the logical next steps: + +* [ ] Get a cluster up and running with the Docker images. Perhaps start with a local cluster and move up to a GCE cluster. +* [ ] Implement #186 and #187. This will make it easier to develop Kubernetes. +* [ ] Deprecate/replace most of the stuff in the hack/ +* [ ] Put together a true client distribution. You should be able to download the tarball for your platform and get a Kube cluster running in <5 minutes. Not `git clone`. +* [ ] Plumb in a version so we can do proper versioned releases. Probably create a `./VERSION` and dope it with the git hash or something? +* [ ] Create an install script that'll let us do a `curl https://[URL] | bash` to get that tarball down and ensure that other dependencies (cloud SDK?) are installed and configured correctly. +* [ ] Support Windows as a client. +* [ ] Support uploading to the Docker index instead of the GCS bucket. This'll allow easier installs for those not running on GCE diff --git a/build/common.sh b/build/common.sh index 8824f97122..864d3c3e83 100644 --- a/build/common.sh +++ b/build/common.sh @@ -44,6 +44,9 @@ readonly KUBE_RUN_BINARIES=" proxy " +# This is where the final release artifacts are created locally +readonly RELEASE_DIR="${KUBE_REPO_ROOT}/output/release" + # --------------------------------------------------------------------------- # Basic setup functions @@ -176,7 +179,6 @@ function docker-build() { set -e } - # Run a command in the kube-build image. This assumes that the image has # already been built. This will sync out all output data from the build. function run-build-command() { @@ -289,3 +291,41 @@ function push-images-to-gcs() { done } +# Package up all of the cross compiled clients +function package-tarballs() { + mkdir -p "${RELEASE_DIR}" + + # Find all of the built cloudcfg binaries + for platform in output/build/*/* ; do + echo $platform + local PLATFORM_TAG=$(echo $platform | awk -F / '{ printf "%s-%s", $3, $4 }') + echo "+++ Building client package for $PLATFORM_TAG" + + local CLIENT_RELEASE_STAGE="${KUBE_REPO_ROOT}/output/release-stage/${PLATFORM_TAG}/kubernetes" + mkdir -p "${CLIENT_RELEASE_STAGE}" + mkdir -p "${CLIENT_RELEASE_STAGE}/bin" + + cp $platform/* "${CLIENT_RELEASE_STAGE}/bin" + + local CLIENT_PACKAGE_NAME="${RELEASE_DIR}/kubernetes-${PLATFORM_TAG}.tar.gz" + tar czf ${CLIENT_PACKAGE_NAME} \ + -C "${CLIENT_RELEASE_STAGE}/.." \ + . + done +} + +function copy-release-to-gcs() { + # TODO: This isn't atomic. There will be points in time where there will be + # no active release. Also, if something fails, the release could be half- + # copied. The real way to do this would perhaps to have some sort of release + # version so that we are never overwriting a destination. + local -r GCS_DESTINATION="gs://${KUBE_RELEASE_BUCKET}/${KUBE_RELEASE_PREFIX}" + + echo "+++ Copying client tarballs to ${GCS_DESTINATION}" + + # First delete all objects at the destination + gsutil -q rm -f -R "${GCS_DESTINATION}" >/dev/null 2>&1 || true + + # Now upload everything in release directory + gsutil -m cp -r "${RELEASE_DIR}" "${GCS_DESTINATION}" >/dev/null 2>&1 +} diff --git a/build/release.sh b/build/release.sh index 1823c39617..0d405eb260 100755 --- a/build/release.sh +++ b/build/release.sh @@ -32,4 +32,6 @@ run-build-command build/build-image/run-tests.sh run-build-command build/build-image/run-integration.sh copy-output run-image +package-tarballs push-images-to-gcs +copy-release-to-gcs