Rework hack/ and build/ directories.

* Rewrite a bunch of the hack/ directory with modular reusable bash libraries.
* Have 'build/*' build on 'hack/*'.  The stuff in build now just runs hack/* in a docker container.
* Use a docker data container to enable faster incremental builds.
* Standardize output to _output/{local,dockerized}/bin/OS/ARCH/*.  This regularized placement makes cross compilation work.
* Move travis specific scripts under hack/travis

With new dockerized incremental builds, I can do a no-op `make quick-release` in ~30s.  This is a significant improvement.
pull/6/head
Joe Beda 2014-10-22 16:26:59 -07:00
parent 203a3d0cec
commit 5d33ce46cc
51 changed files with 1005 additions and 789 deletions

2
.gitignore vendored
View File

@ -37,4 +37,4 @@ network_closure.sh
/third_party/pkg
# also ignore etcd installed by hack/install-etcd.sh
/third_party/etcd
/third_party/etcd*

View File

@ -6,17 +6,17 @@ go:
install:
- go get code.google.com/p/go.tools/cmd/cover
- ./hack/install-etcd.sh
- ./hack/travis/install-etcd.sh
- ./hack/verify-gofmt.sh
- ./hack/verify-boilerplate.sh
- ./hack/install-std-race.sh
- ./hack/travis/install-std-race.sh
- ./hack/build-go.sh
- go get ./contrib/podex
script:
- KUBE_TIMEOUT='-timeout 60s' ./hack/test-go.sh
- PATH=$HOME/gopath/bin:./third_party/etcd/bin:$PATH ./hack/test-cmd.sh
- PATH=$HOME/gopath/bin:./third_party/etcd/bin:$PATH ./hack/test-integration.sh
- PATH=$HOME/gopath/bin:./third_party/etcd:$PATH ./hack/test-cmd.sh
- PATH=$HOME/gopath/bin:./third_party/etcd:$PATH ./hack/test-integration.sh
- ./hack/benchmark-go.sh
notifications:

View File

@ -9,7 +9,8 @@
OUT_DIR = _output
GODEPS_PKG_DIR = Godeps/_workspace/pkg
export GOFLAGS
KUBE_GOFLAGS = $(GOFLAGS)
export KUBE_GOFLAGS
# Build code.
#
@ -49,7 +50,7 @@ check test:
# make test_integration
test_integration test_integ:
hack/test-integration.sh
.PHONY: integration
.PHONY: test_integration test_integ
# Build and run end-to-end tests.
#
@ -97,7 +98,7 @@ release:
#
# Example:
# make release-skip-tests
release-skip-tests:
release-skip-tests quick-release:
KUBE_RELEASE_RUN_TESTS=n build/release.sh
.PHONY: release-skip-tests
.PHONY: release-skip-tests quick-release

View File

@ -18,12 +18,13 @@ There is also early support for building Docker "run" containers
## Key scripts
* `make-server.sh`: This will compile all of the Kubernetes server binaries for linux/amd64
* `make-client.sh`: This will make all cross-compiled client binaries
* `run-tests.sh`: This will run the Kubernetes unit tests
* `run-integration.sh`: This will build and run the integration test
* `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` and remove any local built container images.
* `run.sh`: Run a command in a build docker container. Common invocations:
* `run.sh hack/build-go.sh`: Build just linux binaries in the container. Pass options and packages as necessary.
* `run.sh hack/build-cross.sh`: Build all binaries for all platforms
* `run.sh hack/test-go.sh`: Run all unit tests
* `run.sh hack/test-integration.sh`: Run integration test
* `copy-output.sh`: This will copy the contents of `_output/dockerized/bin` from any remote Docker container to the local `_output/dockerized/bin`. Right now this is only necessary on Mac OS X with `boot2docker` when your git repo isn't under `/Users`.
* `make-clean.sh`: Clean out the contents of `_output/dockerized` and remove any local built container images.
* `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, and (optionally) upload the results to a GCS bucket.
@ -81,10 +82,10 @@ If the release script is set to upload to GCS, it'll do the following:
These are in no particular order
* [ ] Harmonize with scripts in `hack/`. How much do we support building outside of Docker and these scripts?
* [X] Harmonize with scripts in `hack/`. How much do we support building outside of Docker and these scripts?
* [ ] 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)[https://github.com/GoogleCloudPlatform/kubernetes/issues/186]. This will make it easier to develop Kubernetes.
* [ ] Deprecate/replace most of the stuff in the hack/
* [X] Deprecate/replace most of the stuff in the hack/
* [ ] 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/test Windows as a client.
* [ ] Finish support for the Dockerized runtime. Issue (#19)[https://github.com/GoogleCloudPlatform/kubernetes/issues/19]. A key issue here is to make this fast/light enough that we can use it for development workflows.

View File

@ -25,6 +25,10 @@ ENV GOARCH amd64
# Get the code coverage tool and godep
RUN go get code.google.com/p/go.tools/cmd/cover github.com/tools/godep
# We use rsync to copy some binaries around. It is faster (0.3s vs. 1.1s) on my
# machine vs. `install`
RUN apt-get update && apt-get install -y rsync
# Download and symlink etcd. We need this for our integration tests.
RUN mkdir -p /usr/local/src/etcd &&\
cd /usr/local/src/etcd &&\
@ -39,6 +43,10 @@ WORKDIR /go/src/github.com/GoogleCloudPlatform/kubernetes
# Propagate the git tree version into the build image
ADD kube-version-defs /kube-version-defs
ENV KUBE_GIT_VERSION_FILE /kube-version-defs
# Make output from the dockerized build go someplace else
ENV KUBE_OUTPUT_SUBPATH _output/dockerized
# Upload Kubernetes source
ADD kube-source.tar.gz /go/src/github.com/GoogleCloudPlatform/kubernetes

View File

@ -1,81 +0,0 @@
#!/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.
# This script sets up a go workspace locally and builds all go components.
# You can 'source' this file if you want to set up GOPATH in your local shell.
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
cd "${KUBE_ROOT}"
readonly KUBE_TARGET="${KUBE_ROOT}/_output/build"
readonly KUBE_GO_PACKAGE=github.com/GoogleCloudPlatform/kubernetes
server_targets=(
cmd/proxy
cmd/apiserver
cmd/controller-manager
cmd/kubelet
plugin/cmd/scheduler
)
client_targets=(
cmd/kubecfg
cmd/kubectl
cmd/e2e
)
mkdir -p "${KUBE_TARGET}"
if [[ ! -f "/kube-build-image" ]]; then
echo "WARNING: This script should be run in the kube-build container image!" >&2
fi
if [[ -f "/kube-version-defs" ]]; then
source "/kube-version-defs"
else
echo "WARNING: No version information provided in build image"
fi
function kube::build::make_binary() {
local -r gopkg=$1
local -r bin=${gopkg##*/}
echo "+++ Building ${bin} for ${GOOS}/${GOARCH}"
pushd "${KUBE_ROOT}" >/dev/null
godep go build -ldflags "${KUBE_LD_FLAGS-}" -o "${ARCH_TARGET}/${bin}" "${gopkg}"
popd >/dev/null
}
function kube::build::make_binaries() {
[[ $# -gt 0 ]] || {
echo "!!! Internal error. kube::build::make_binaries called with no targets."
}
local -a targets=("$@")
local -a binaries=()
local target
for target in "${targets[@]}"; do
binaries+=("${KUBE_GO_PACKAGE}/${target}")
done
ARCH_TARGET="${KUBE_TARGET}/${GOOS}/${GOARCH}"
mkdir -p "${ARCH_TARGET}"
local b
for b in "${binaries[@]}"; do
kube::build::make_binary "$b"
done
}

View File

@ -1,39 +0,0 @@
#!/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.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
source "${KUBE_ROOT}/build/build-image/common.sh"
platforms=(linux/amd64 $KUBE_CROSSPLATFORMS)
targets=("${client_targets[@]}")
if [[ $# -gt 0 ]]; then
targets=("$@")
fi
for platform in "${platforms[@]}"; do
(
# Subshell to contain these exports
export GOOS=${platform%/*}
export GOARCH=${platform##*/}
kube::build::make_binaries "${targets[@]}"
)
done

View File

@ -1,29 +0,0 @@
#!/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.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
source "${KUBE_ROOT}/build/build-image/common.sh"
targets=("${server_targets[@]}")
if [[ $# -gt 0 ]]; then
targets=("$@")
fi
kube::build::make_binaries "${targets[@]}"

View File

@ -25,7 +25,7 @@ cd "${KUBE_ROOT}"
# This'll canonicalize the path
KUBE_ROOT=$PWD
source hack/config-go.sh
source hack/lib/init.sh
# Incoming options
#
@ -49,37 +49,38 @@ readonly KUBE_BUILD_IMAGE_REPO=kube-build
readonly KUBE_BUILD_IMAGE_CROSS_TAG=cross
readonly KUBE_BUILD_IMAGE_CROSS="${KUBE_BUILD_IMAGE_REPO}:${KUBE_BUILD_IMAGE_CROSS_TAG}"
readonly KUBE_BUILD_GOLANG_VERSION=1.3
# KUBE_BUILD_DATA_CONTAINER_NAME=kube-build-data-<hash>
readonly KUBE_GO_PACKAGE="github.com/GoogleCloudPlatform/kubernetes"
# We set up a volume so that we have the same _output directory from one run of
# the container to the next.
# Here we map the output directories across both the local and remote _output
# directories:
#
# Note that here "LOCAL" is local to the docker daemon. In the boot2docker case
# this is still inside the VM. We use the same directory in both cases though.
# *_OUTPUT_ROOT - the base of all output in that environment.
# *_OUTPUT_SUBPATH - location where golang stuff is built/cached. Also
# persisted across docker runs with a volume mount.
# *_OUTPUT_BINPATH - location where final binaries are placed. If the remote
# is really remote, this is the stuff that has to be copied
# back.
readonly LOCAL_OUTPUT_ROOT="${KUBE_ROOT}/_output"
readonly LOCAL_OUTPUT_BUILD="${LOCAL_OUTPUT_ROOT}/build"
readonly LOCAL_OUTPUT_SUBPATH="${LOCAL_OUTPUT_ROOT}/dockerized"
readonly LOCAL_OUTPUT_BINPATH="${LOCAL_OUTPUT_SUBPATH}/bin"
readonly LOCAL_OUTPUT_IMAGE_STAGING="${LOCAL_OUTPUT_ROOT}/images"
readonly REMOTE_OUTPUT_ROOT="/go/src/${KUBE_GO_PACKAGE}/_output"
readonly REMOTE_OUTPUT_DIR="${REMOTE_OUTPUT_ROOT}/build"
readonly DOCKER_MOUNT_ARGS=(--volume "${LOCAL_OUTPUT_BUILD}:${REMOTE_OUTPUT_DIR}")
readonly REMOTE_OUTPUT_SUBPATH="${REMOTE_OUTPUT_ROOT}/dockerized"
readonly REMOTE_OUTPUT_BINPATH="${REMOTE_OUTPUT_SUBPATH}/bin"
readonly KUBE_CLIENT_BINARIES=(
kubecfg
kubectl
readonly DOCKER_MOUNT_ARGS_BASE=(--volume "${LOCAL_OUTPUT_BINPATH}:${REMOTE_OUTPUT_BINPATH}")
# DOCKER_MOUNT_ARGS=("${DOCKER_MOUNT_ARGS_BASE[@]}" --volumes-from "${KUBE_BUILD_DATA_CONTAINER_NAME}")
# We create a Docker data container to cache incremental build artifacts. We
# need to cache both the go tree in _output and the go tree under Godeps.
readonly REMOTE_OUTPUT_GOPATH="${REMOTE_OUTPUT_SUBPATH}/go"
readonly REMOTE_GODEP_GOPATH="/go/src/${KUBE_GO_PACKAGE}/Godeps/_workspace/pkg"
readonly DOCKER_DATA_MOUNT_ARGS=(
--volume "${REMOTE_OUTPUT_GOPATH}"
--volume "${REMOTE_GODEP_GOPATH}"
)
readonly KUBE_SERVER_BINARIES=(
apiserver
controller-manager
kubelet
proxy
scheduler
)
readonly KUBE_SERVER_PLATFORMS=(
linux/amd64
)
readonly KUBE_RUN_IMAGE_BASE="kubernetes"
readonly KUBE_RUN_IMAGES=(
@ -102,26 +103,32 @@ readonly RELEASE_DIR="${LOCAL_OUTPUT_ROOT}/release-tars"
# up some dynamic constants.
#
# Vars set:
# KUBE_ROOT_HASH
# KUBE_BUILD_IMAGE_TAG
# KUBE_BUILD_IMAGE
# KUBE_BUILD_CONTAINER_NAME
# KUBE_ROOT_HASH
# KUBE_BUILD_DATA_CONTAINER_NAME
# DOCKER_MOUNT_ARGS
function kube::build::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
exit 1
fi
if kube::build::is_osx; 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
exit 1
fi
if [[ $(boot2docker status) != "running" ]]; then
echo "boot2docker VM isn't started. Please run 'boot2docker start'" >&2
return 1
exit 1
else
# Reach over and set the clock. After sleep/resume the clock will skew.
echo "+++ Setting boot2docker clock"
boot2docker ssh sudo date -u -D "%Y%m%d%H%M.%S" --set "$(date -u +%Y%m%d%H%M.%S)" >/dev/null
fi
fi
@ -130,20 +137,23 @@ function kube::build::verify_prereqs() {
echo "Can't connect to 'docker' daemon. please fix and retry."
echo
echo "Possible causes:"
echo " - On Mac OS X, boot2docker VM isn't started"
echo " - On Mac OS X, DOCKER_HOST env variable isn't set approriately"
echo " - On Mac OS X, boot2docker VM isn't installed or started"
echo " - On Mac OS X, docker env variable isn't set approriately. Run:"
echo " \$(boot2docker shellinit)"
echo " - On Linux, user isn't in 'docker' group. Add and relogin."
echo " - Something like 'sudo usermod -a -G docker ${USER-user}'"
echo " - RHEL7 bug and workaround: https://bugzilla.redhat.com/show_bug.cgi?id=1119282#c8"
echo " - On Linux, Docker daemon hasn't been started or has crashed"
} >&2
return 1
exit 1
fi
KUBE_ROOT_HASH=$(kube::build::short_hash "$KUBE_ROOT")
KUBE_BUILD_IMAGE_TAG="build-${KUBE_ROOT_HASH}"
KUBE_BUILD_IMAGE="${KUBE_BUILD_IMAGE_REPO}:${KUBE_BUILD_IMAGE_TAG}"
KUBE_BUILD_CONTAINER_NAME="kube-build-${KUBE_ROOT_HASH}"
KUBE_BUILD_DATA_CONTAINER_NAME="kube-build-data-${KUBE_ROOT_HASH}"
DOCKER_MOUNT_ARGS=("${DOCKER_MOUNT_ARGS_BASE[@]}" --volumes-from "${KUBE_BUILD_DATA_CONTAINER_NAME}")
}
# ---------------------------------------------------------------------------
@ -156,19 +166,22 @@ function kube::build::is_osx() {
function kube::build::clean_output() {
# Clean out the output directory if it exists.
if kube::build::build_image_built ; then
echo "+++ Cleaning out _output/build via docker build image"
kube::build::run_build_command bash -c "rm -rf '${REMOTE_OUTPUT_DIR}'/*"
echo "+++ Cleaning out _output/dockerized/bin/ via docker build image"
kube::build::run_build_command bash -c "rm -rf '${REMOTE_OUTPUT_BINPATH}'/*"
else
echo "!!! Build image not built. Cannot clean via docker build image."
fi
echo "+++ Removing data container"
docker rm "${KUBE_BUILD_DATA_CONTAINER_NAME}" >/dev/null 2>&1 || true
echo "+++ Cleaning out local _output directory"
rm -rf "${LOCAL_OUTPUT_ROOT}"
}
# Make sure the _output directory is created and mountable by docker
function kube::build::prepare_output() {
mkdir -p "${LOCAL_OUTPUT_ROOT}"
mkdir -p "${LOCAL_OUTPUT_SUBPATH}"
# On RHEL/Fedora SELinux is enabled by default and currently breaks docker
# volume mounts. We can work around this by explicitly adding a security
@ -249,13 +262,14 @@ function kube::build::build_image() {
build
cmd
examples
Godeps/Godeps.json
Godeps/_workspace/src
Godeps/Godeps.json
hack
LICENSE
pkg
plugin
README.md
test
third_party
)
@ -263,9 +277,10 @@ function kube::build::build_image() {
mkdir -p "${build_context_dir}"
tar czf "${build_context_dir}/kube-source.tar.gz" "${source[@]}"
cat >"${build_context_dir}/kube-version-defs" <<EOF
KUBE_LD_FLAGS="$(kube::version_ldflags)"
EOF
kube::version::get_version_vars
kube::version::save_version_vars "${build_context_dir}/kube-version-defs"
cp build/build-image/Dockerfile ${build_context_dir}/Dockerfile
kube::build::docker_build "${KUBE_BUILD_IMAGE}" "${build_context_dir}"
}
@ -281,7 +296,7 @@ function kube::build::build_image_cross() {
}
# Builds the runtime image. Assumes that the appropriate binaries are already
# built and in _output/build/.
# built and in $LOCAL_OUTPUT_BINPATH.
function kube::build::run_image() {
[[ ${KUBE_BUILD_RUN_IMAGES} =~ ^[yY]$ ]] || return 0
@ -290,7 +305,7 @@ function kube::build::run_image() {
# 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 "${LOCAL_OUTPUT_ROOT}/build/linux/amd64" \
-C "${LOCAL_OUTPUT_BINPATH}/linux/amd64" \
"${KUBE_RUN_IMAGES[@]}"
cp -R build/run-images/base/* "${build_context_base}/"
kube::build::docker_build "${KUBE_RUN_IMAGE_BASE}" "${build_context_base}"
@ -350,11 +365,26 @@ function kube::build::clean_images() {
docker rmi $(docker images -q --filter 'dangling=true') 2> /dev/null || true
}
function kube::build::ensure_data_container() {
if ! docker inspect "${KUBE_BUILD_DATA_CONTAINER_NAME}" >/dev/null 2>&1; then
echo "+++ Creating data container"
local -ra docker_cmd=(
docker run
"${DOCKER_DATA_MOUNT_ARGS[@]}"
--name "${KUBE_BUILD_DATA_CONTAINER_NAME}"
"${KUBE_BUILD_IMAGE}"
true
)
"${docker_cmd[@]}"
fi
}
# 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 kube::build::run_build_command() {
[[ $# != 0 ]] || { echo "Invalid input." >&2; return 4; }
kube::build::ensure_data_container
kube::build::prepare_output
local -a docker_run_opts=(
@ -389,10 +419,10 @@ function kube::build::run_build_command() {
# docker) or if it is "local" and we can access the output without going through
# docker.
function kube::build::is_output_remote() {
rm -f "${LOCAL_OUTPUT_BUILD}/test_for_remote"
kube::build::run_build_command touch "${REMOTE_OUTPUT_DIR}/test_for_remote"
rm -f "${LOCAL_OUTPUT_SUBPATH}/test_for_remote"
kube::build::run_build_command touch "${REMOTE_OUTPUT_BINPATH}/test_for_remote"
[[ ! -e "${LOCAL_OUTPUT_BUILD}/test_for_remote" ]]
[[ ! -e "${LOCAL_OUTPUT_BINPATH}/test_for_remote" ]]
}
# If the Docker server is remote, copy the results back out.
@ -409,14 +439,14 @@ function kube::build::copy_output() {
# container pointed at the same volume, tar the output directory and ship
# that tar over stdout.
echo "+++ Syncing back _output directory from boot2docker VM"
rm -rf "${LOCAL_OUTPUT_BUILD}"
mkdir -p "${LOCAL_OUTPUT_BUILD}"
echo "+++ Syncing back _output/dockerized/bin directory from remote Docker"
rm -rf "${LOCAL_OUTPUT_BINPATH}"
mkdir -p "${LOCAL_OUTPUT_BINPATH}"
# The '</dev/null' here makes us run docker in a "non-interactive" mode. Not
# doing this corrupts the output stream.
kube::build::run_build_command sh -c "tar c -C ${REMOTE_OUTPUT_DIR} . ; sleep 1" </dev/null \
| tar xv -C "${LOCAL_OUTPUT_BUILD}"
kube::build::run_build_command sh -c "tar c -C ${REMOTE_OUTPUT_BINPATH} . ; sleep 1" </dev/null \
| tar xv -C "${LOCAL_OUTPUT_BINPATH}"
# I (jbeda) also tried getting rsync working using 'docker run' as the
# 'remote shell'. This mostly worked but there was a hang when
@ -424,7 +454,7 @@ function kube::build::copy_output() {
#
# local DOCKER="docker run -i --rm --name=${KUBE_BUILD_CONTAINER_NAME} ${DOCKER_MOUNT} ${KUBE_BUILD_IMAGE}"
# DOCKER+=" bash -c 'shift ; exec \"\$@\"' --"
# rsync --blocking-io -av -e "${DOCKER}" foo:${REMOTE_OUTPUT_DIR}/ ${LOCAL_OUTPUT_BUILD}
# rsync --blocking-io -av -e "${DOCKER}" foo:${REMOTE_OUTPUT_BINPATH}/ ${LOCAL_OUTPUT_BINPATH}
else
echo "+++ Output directory is local. No need to copy results out."
fi
@ -448,7 +478,7 @@ function kube::release::package_tarballs() {
function kube::release::package_client_tarballs() {
# Find all of the built kubecfg binaries
local platform platforms
platforms=($(cd "${LOCAL_OUTPUT_ROOT}/build" ; echo */*))
platforms=($(cd "${LOCAL_OUTPUT_BINPATH}" ; echo */*))
for platform in "${platforms[@]}" ; do
local platform_tag=${platform/\//-} # Replace a "/" for a "-"
echo "+++ Building tarball: client $platform_tag"
@ -458,9 +488,9 @@ function kube::release::package_client_tarballs() {
mkdir -p "${release_stage}/client/bin"
# This fancy expression will expand to prepend a path
# (${LOCAL_OUTPUT_ROOT}/build/${platform}/) to every item in the
# (${LOCAL_OUTPUT_BINPATH}/${platform}/) to every item in the
# KUBE_CLIENT_BINARIES array.
cp "${KUBE_CLIENT_BINARIES[@]/#/${LOCAL_OUTPUT_ROOT}/build/${platform}/}" \
cp "${KUBE_CLIENT_BINARIES[@]/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}" \
"${release_stage}/client/bin/"
local package_name="${RELEASE_DIR}/kubernetes-client-${platform_tag}.tar.gz"
@ -480,9 +510,9 @@ function kube::release::package_server_tarballs() {
mkdir -p "${release_stage}/server/bin"
# This fancy expression will expand to prepend a path
# (${LOCAL_OUTPUT_ROOT}/build/${platform}/) to every item in the
# (${LOCAL_OUTPUT_BINPATH}/${platform}/) to every item in the
# KUBE_SERVER_BINARIES array.
cp "${KUBE_SERVER_BINARIES[@]/#/${LOCAL_OUTPUT_ROOT}/build/${platform}/}" \
cp "${KUBE_SERVER_BINARIES[@]/#/${LOCAL_OUTPUT_BINPATH}/${platform}/}" \
"${release_stage}/server/bin/"
local package_name="${RELEASE_DIR}/kubernetes-server-${platform_tag}.tar.gz"
@ -517,7 +547,7 @@ function kube::release::package_full_tarball() {
rm -rf "${release_stage}"
mkdir -p "${release_stage}"
cp -R "${LOCAL_OUTPUT_ROOT}/build" "${release_stage}/platforms"
cp -R "${LOCAL_OUTPUT_BINPATH}" "${release_stage}/platforms"
# We want everything in /cluster except saltbase. That is only needed on the
# server.

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,5 +1,19 @@
#!/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.
set -e
set -x

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,31 +0,0 @@
#! /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.
# Make all of the Kubernetes server binaries.
#
# This makes the docker build image, builds the binaries and copies them out
# of the docker container.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "$KUBE_ROOT/build/common.sh"
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command build/build-image/make-server.sh "$@"
kube::build::copy_output

View File

@ -1,5 +1,19 @@
#!/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.
set -e
set -x

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#
@ -29,12 +29,11 @@ KUBE_RELEASE_RUN_TESTS=${KUBE_RELEASE_RUN_TESTS-y}
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command build/build-image/make-client.sh
kube::build::run_build_command build/build-image/make-server.sh
kube::build::run_build_command hack/build-cross.sh
if [[ $KUBE_RELEASE_RUN_TESTS =~ ^[yY]$ ]]; then
kube::build::run_build_command build/build-image/run-tests.sh
kube::build::run_build_command build/build-image/run-integration.sh
kube::build::run_build_command hack/test-go.sh
kube::build::run_build_command hack/test-integration.sh
fi
kube::build::copy_output

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -1,28 +0,0 @@
#! /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.
# Run all of the golang unit tests.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "$KUBE_ROOT/build/common.sh"
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command build/build-image/run-tests.sh "$@"

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#
@ -14,7 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Run the integration test.
# Run a command in the docker build container. Typically this will be one of
# the commands in `hack/`. When running in the build container the user is sure
# to have a consistent reproducible build environment.
set -o errexit
set -o nounset
@ -25,5 +27,8 @@ source "$KUBE_ROOT/build/common.sh"
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command build/build-image/make-binaries.sh "./cmd/integration"
kube::build::run_build_command build/build-image/run-integration.sh
kube::build::run_build_command "$@"
if [[ ${KUBE_RUN_COPY_OUTPUT:-y} =~ ^[yY]$ ]]; then
kube::build::copy_output
fi

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#
@ -27,4 +27,4 @@ source "$KUBE_ROOT/build/common.sh"
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command bash
kube::build::run_build_command bash || true

View File

@ -58,17 +58,21 @@ case "$(uname -m)" in
;;
esac
kubecfg="${KUBE_ROOT}/_output/build/${host_os}/${host_arch}/kubecfg"
if [[ ! -x "$kubecfg" ]]; then
kubecfg="${KUBE_ROOT}/platforms/${host_os}/${host_arch}/kubecfg"
fi
# Gather up the list of likely places and use ls to find the latest one.
locations=(
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/kubecfg"
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/kubecfg"
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/kubecfg"
)
kubecfg=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
if [[ ! -x "$kubecfg" ]]; then
{
echo "It looks as if you don't have a compiled kubecfg binary."
echo
echo "If you are running from a clone of the git repo, please run"
echo "'./build/make-client.sh'. Note that this requires having Docker installed."
echo "'./build/run.sh hack/build-cross.sh'. Note that this requires having"
echo "Docker installed."
echo
echo "If you are running from a binary release tarball, something is wrong. "
echo "Look at http://kubernetes.io/ for information on how to contact the "

View File

@ -58,17 +58,21 @@ case "$(uname -m)" in
;;
esac
kubectl="${KUBE_ROOT}/_output/build/${host_os}/${host_arch}/kubectl"
if [[ ! -x "$kubectl" ]]; then
kubectl="${KUBE_ROOT}/platforms/${host_os}/${host_arch}/kubectl"
fi
# Gather up the list of likely places and use ls to find the latest one.
locations=(
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/kubectl"
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/kubectl"
"${KUBE_ROOT}/platforms/${host_os}/${host_arch}/kubectl"
)
kubectl=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
if [[ ! -x "$kubectl" ]]; then
{
echo "It looks as if you don't have a compiled kubectl binary."
echo
echo "If you are running from a clone of the git repo, please run"
echo "'./build/make-client'. Note that this requires having Docker installed."
echo "'./build/run.sh hack/build-cross.sh'. Note that this requires having"
echo "Docker installed."
echo
echo "If you are running from a binary release tarball, something is wrong. "
echo "Look at http://kubernetes.io/ for information on how to contact the "

View File

@ -124,7 +124,8 @@ function kube-push {
# Execute prior to running tests to build a release if required for env
function test-build-release {
echo "Vagrant provider can skip release build"
# Make a release
"${KUBE_ROOT}/build/release.sh"
}
# Execute prior to running tests to initialize required structure

View File

@ -18,4 +18,6 @@ set -o errexit
set -o nounset
set -o pipefail
KUBE_COVER=" " KUBE_RACE=" " hack/test-go.sh "" -test.run="^X" -benchtime=1s -bench=. -benchmem
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
KUBE_COVER=" " KUBE_RACE=" " "${KUBE_ROOT}/hack/test-go.sh" "" -test.run="^X" -benchtime=1s -bench=. -benchmem

View File

@ -1,4 +1,4 @@
#! /bin/bash
#!/bin/bash
# Copyright 2014 Google Inc. All rights reserved.
#
@ -14,19 +14,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# Make all of the client Kubernetes binaries for cross compile targets
#
# This makes the docker build image, builds the cross binaries and copies them
# out of the docker container.
# This script sets up a go workspace locally and builds all for all appropriate
# platforms.
set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "$KUBE_ROOT/build/common.sh"
source "${KUBE_ROOT}/hack/lib/init.sh"
kube::build::verify_prereqs
kube::build::build_image
kube::build::run_build_command build/build-image/make-client.sh "$@"
kube::build::copy_output
KUBE_BUILD_PLATFORMS=("${KUBE_SERVER_PLATFORMS[@]}")
kube::golang::build_binaries "${KUBE_SERVER_TARGETS[@]}"
KUBE_BUILD_PLATFORMS=("${KUBE_CLIENT_PLATFORMS[@]}")
kube::golang::build_binaries "${KUBE_CLIENT_TARGETS[@]}" "${KUBE_TEST_TARGETS[@]}"
kube::golang::place_bins

View File

@ -21,42 +21,7 @@ set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"
# Set the environment variables required by the build.
source "${KUBE_ROOT}/hack/config-go.sh"
# Go to the top of the tree.
cd "${KUBE_ROOT}"
# Check for `go` binary and set ${GOPATH}.
kube::setup_go_environment
# Fetch the version.
version_ldflags=$(kube::version_ldflags)
# Use eval to preserve embedded quoted strings.
eval "goflags=(${GOFLAGS:-})"
targets=()
for arg; do
if [[ "${arg}" == -* ]]; then
# Assume arguments starting with a dash are flags to pass to go.
goflags+=("${arg}")
else
targets+=("${arg}")
fi
done
if [[ ${#targets[@]} -eq 0 ]]; then
targets=($(kube::default_build_targets))
fi
binaries=($(kube::binaries_from_targets "${targets[@]}"))
echo "Building local go components"
# Note that the flags to 'go build' are duplicated in the dockerized build setup
# (build/build-image/common.sh). If we add more command line options to our
# standard build we'll want to duplicate them there. This needs to be fixed
go install "${goflags[@]:+${goflags[@]}}" \
-ldflags "${version_ldflags}" \
"${binaries[@]}"
kube::golang::build_binaries "$@"
kube::golang::place_bins

View File

@ -1,212 +0,0 @@
#!/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.
# This script sets up a go workspace locally and builds all go components.
# You can 'source' this file if you want to set up GOPATH in your local shell.
# --- Environment Variables used as inputs by config-go.sh ---
# Function: kube::version_ldflags()
# These variables are only needed if you are not building from a clone of the
# full kubernetes repository.
# KUBE_GIT_COMMIT - Used to set the git commit id corresponding to this
# source code.
# KUBE_GIT_TREE_STATE - "clean" indicates no changes since the git commit id
# "dirty" indicates source code changes after the git
# commit id
# KUBE_GIT_VERSION - "vX.Y" used to indicate the last release version.
#
# Function: kube::setup_go_environment
# KUBE_EXTRA_GOPATH - Value will be appended to the GOPATH after this project
# but before the Godeps.
# KUBE_NO_GODEPS - If set to any value the Godeps will not be included in
# the final GOPATH.
# --- Environment Variables set by sourcing config-go.sh ---
# KUBE_ROOT - Path to the top of the build tree.
# KUBE_TARGET - Path where output Go files are saved.
# KUBE_GO_PACKAGE - Full name of the Kubernetes Go package.
# --- Environment Variables set by running functions ---
# Function: kube::setup_go_environment
# GOPATH - Will be set to include this project, anything you have you set in
# in ${KUBE_EXTRA_GOPATH}, and the Godeps if ${KUBE_NO_GODEPS} is
# unset.
# --- Helper Functions ---
# Function kube::version_ldflags() prints the value that needs to be passed to
# the -ldflags parameter of go build in order to set the Kubernetes based on the
# git tree status.
kube::version_ldflags() {
(
# Run this in a subshell to prevent settings/variables from leaking.
set -o errexit
set -o nounset
set -o pipefail
unset CDPATH
cd "${KUBE_ROOT}"
declare -a ldflags=()
if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$(git rev-parse "HEAD^{commit}" 2>/dev/null); then
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitCommit" "${KUBE_GIT_COMMIT}")
if [[ -z ${KUBE_GIT_TREE_STATE-} ]]; then
# Check if the tree is dirty. default to dirty
if git_status=$(git status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then
KUBE_GIT_TREE_STATE="clean"
else
KUBE_GIT_TREE_STATE="dirty"
fi
fi
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitTreeState" "${KUBE_GIT_TREE_STATE}")
# Use git describe to find the version based on annotated tags.
if [[ -n ${KUBE_GIT_VERSION-} ]] || KUBE_GIT_VERSION=$(git describe --tag --abbrev=14 "${KUBE_GIT_COMMIT}^{commit}" 2>/dev/null); then
if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then
# git describe --dirty only considers changes to existing files, but
# that is problematic since new untracked .go files affect the build,
# so use our idea of "dirty" from git status instead.
KUBE_GIT_VERSION+="-dirty"
fi
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitVersion" "${KUBE_GIT_VERSION}")
# Try to match the "git describe" output to a regex to try to extract
# the "major" and "minor" versions and whether this is the exact tagged
# version or whether the tree is between two tagged versions.
if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)([.-].*)?$ ]]; then
git_major=${BASH_REMATCH[1]}
git_minor=${BASH_REMATCH[2]}
if [[ -n "${BASH_REMATCH[3]}" ]]; then
git_minor+="+"
fi
ldflags+=(
-X "${KUBE_GO_PACKAGE}/pkg/version.gitMajor" "${git_major}"
-X "${KUBE_GO_PACKAGE}/pkg/version.gitMinor" "${git_minor}"
)
fi
fi
fi
# The -ldflags parameter takes a single string, so join the output.
echo "${ldflags[*]-}"
)
}
# kube::setup_go_environment will check that the `go` commands is available in
# ${PATH}. If not running on Travis, it will also check that the Go version is
# good enough for the Kubernetes build.
#
# Also set ${GOPATH} and environment variables needed by Go.
kube::setup_go_environment() {
if [[ -z "$(which go)" ]]; then
echo "Can't find 'go' in PATH, please fix and retry." >&2
echo "See http://golang.org/doc/install for installation instructions." >&2
exit 1
fi
# Travis continuous build uses a head go release that doesn't report
# a version number, so we skip this check on Travis. Its unnecessary
# there anyway.
if [[ "${TRAVIS:-}" != "true" ]]; then
local go_version
go_version=($(go version))
if [[ "${go_version[2]}" < "go1.2" ]]; then
echo "Detected go version: ${go_version[*]}." >&2
echo "Kubernetes requires go version 1.2 or greater." >&2
echo "Please install Go version 1.2 or later" >&2
exit 1
fi
fi
GOPATH=${KUBE_TARGET}
# Append KUBE_EXTRA_GOPATH to the GOPATH if it is defined.
if [[ -n ${KUBE_EXTRA_GOPATH:-} ]]; then
GOPATH=${GOPATH}:${KUBE_EXTRA_GOPATH}
fi
# Append the tree maintained by `godep` to the GOPATH unless KUBE_NO_GODEPS
# is defined.
if [[ -z ${KUBE_NO_GODEPS:-} ]]; then
GOPATH="${GOPATH}:${KUBE_ROOT}/Godeps/_workspace"
fi
export GOPATH
# Unset GOBIN in case it already exists in the current session.
unset GOBIN
}
# kube::default_build_targets return list of all build targets
kube::default_build_targets() {
echo "cmd/proxy"
echo "cmd/apiserver"
echo "cmd/controller-manager"
echo "cmd/e2e"
echo "cmd/kubelet"
echo "cmd/kubecfg"
echo "cmd/kubectl"
echo "plugin/cmd/scheduler"
}
# kube::binaries_from_targets take a list of build targets and return the
# full go package to be built
kube::binaries_from_targets() {
local target
for target; do
echo "${KUBE_GO_PACKAGE}/${target}"
done
}
# --- Environment Variables ---
# Make ${KUBE_ROOT} an absolute path.
KUBE_ROOT=$(
set -o errexit
set -o nounset
set -o pipefail
unset CDPATH
kube_root=$(dirname "${BASH_SOURCE}")/..
cd "${kube_root}"
pwd
)
export KUBE_ROOT
KUBE_TARGET="${KUBE_ROOT}/_output/go"
mkdir -p "${KUBE_TARGET}"
export KUBE_TARGET
KUBE_GO_PACKAGE=github.com/GoogleCloudPlatform/kubernetes
export KUBE_GO_PACKAGE
(
# Create symlink named ${KUBE_GO_PACKAGE} under _output/go/src.
# So that Go knows how to import Kubernetes sources by full path.
# Use a subshell to avoid leaking these variables.
set -o errexit
set -o nounset
set -o pipefail
go_pkg_dir="${KUBE_TARGET}/src/${KUBE_GO_PACKAGE}"
go_pkg_basedir=$(dirname "${go_pkg_dir}")
mkdir -p "${go_pkg_basedir}"
rm -f "${go_pkg_dir}"
# TODO: This symlink should be relative.
ln -s "${KUBE_ROOT}" "${go_pkg_dir}"
)

View File

@ -19,4 +19,49 @@ source "${KUBE_ROOT}/cluster/kube-env.sh"
source "${KUBE_ROOT}/cluster/$KUBERNETES_PROVIDER/util.sh"
detect-master > /dev/null
${KUBE_ROOT}/_output/go/bin/e2e -host="https://${KUBE_MASTER_IP-}"
# Detect the OS name/arch so that we can find our binary
case "$(uname -s)" in
Darwin)
host_os=darwin
;;
Linux)
host_os=linux
;;
*)
echo "Unsupported host OS. Must be Linux or Mac OS X." >&2
exit 1
;;
esac
case "$(uname -m)" in
x86_64*)
host_arch=amd64
;;
i?86_64*)
host_arch=amd64
;;
amd64*)
host_arch=amd64
;;
arm*)
host_arch=arm
;;
i?86*)
host_arch=x86
;;
*)
echo "Unsupported host arch. Must be x86_64, 386 or arm." >&2
exit 1
;;
esac
# Gather up the list of likely places and use ls to find the latest one.
locations=(
"${KUBE_ROOT}/_output/dockerized/bin/${host_os}/${host_arch}/e2e"
"${KUBE_ROOT}/_output/local/bin/${host_os}/${host_arch}/e2e"
)
e2e=$( (ls -t "${locations[@]}" 2>/dev/null || true) | head -1 )
"${e2e}" -host="https://${KUBE_MASTER_IP-}"

View File

@ -72,9 +72,6 @@ func main() {
}
if *build {
if !run("build-local", "hack/build-go.sh") {
log.Fatal("Error building. Aborting.")
}
if !runBash("build-release", `test-build-release`) {
log.Fatal("Error building. Aborting.")
}

44
hack/lib/etcd.sh Normal file
View File

@ -0,0 +1,44 @@
#!/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.
# A set of helpers for starting/running etcd for tests
kube::etcd::start() {
local host=${ETCD_HOST:-127.0.0.1}
local port=${ETCD_PORT:-4001}
which etcd >/dev/null || {
kube::log::usage "etcd must be in your PATH"
exit 1
}
if pgrep etcd >/dev/null 2>&1; then
kube::log::usage "etcd appears to already be running on this machine. Please kill and restart the test."
exit 1
fi
# Start etcd
ETCD_DIR=$(mktemp -d -t test-etcd.XXXXXX)
etcd -name test -data-dir ${ETCD_DIR} -addr ${host}:${port} >/dev/null 2>/dev/null &
ETCD_PID=$!
kube::util::wait_for_url "http://${host}:${port}/v2/keys/" "etcd: "
}
kube::etcd::cleanup() {
kill "${ETCD_PID-}" >/dev/null 2>&1 || :
rm -rf "${ETCD_DIR-}"
}

272
hack/lib/golang.sh Normal file
View File

@ -0,0 +1,272 @@
#!/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.
# The golang package that we are building.
readonly KUBE_GO_PACKAGE=github.com/GoogleCloudPlatform/kubernetes
readonly KUBE_GOPATH="${KUBE_OUTPUT}/go"
# The set of server targets that we are only building for Linux
readonly KUBE_SERVER_TARGETS=(
cmd/proxy
cmd/apiserver
cmd/controller-manager
cmd/kubelet
plugin/cmd/scheduler
)
readonly KUBE_SERVER_BINARIES=("${KUBE_SERVER_TARGETS[@]##*/}")
# The server platform we are building on.
readonly KUBE_SERVER_PLATFORMS=(
linux/amd64
)
# The set of client targets that we are building for all platforms
readonly KUBE_CLIENT_TARGETS=(
cmd/kubecfg
cmd/kubectl
)
readonly KUBE_CLIENT_BINARIES=("${KUBE_CLIENT_TARGETS[@]##*/}")
# The set of test targets that we are building for all platforms
readonly KUBE_TEST_TARGETS=(
cmd/e2e
cmd/integration
)
readonly KUBE_TEST_BINARIES=("${KUBE_TEST_TARGETS[@]##*/}")
# If we update this we need to also update the set of golang compilers we build
# in 'build/build-image/Dockerfile'
readonly KUBE_CLIENT_PLATFORMS=(
linux/amd64
linux/386
linux/arm
darwin/amd64
darwin/386
)
readonly KUBE_ALL_TARGETS=(
"${KUBE_SERVER_TARGETS[@]}"
"${KUBE_CLIENT_TARGETS[@]}"
"${KUBE_TEST_TARGETS[@]}"
)
readonly KUBE_ALL_BINARIES=("${KUBE_ALL_TARGETS[@]##*/}")
# kube::binaries_from_targets take a list of build targets and return the
# full go package to be built
kube::golang::binaries_from_targets() {
local target
for target; do
echo "${KUBE_GO_PACKAGE}/${target}"
done
}
# Asks golang what it thinks the host platform is. The go tool chain does some
# slightly different things when the target platform matches the host platform.
kube::golang::host_platform() {
echo "$(go env GOHOSTOS)/$(go env GOHOSTARCH)"
}
kube::golang::current_platform() {
local os="${GOOS-}"
if [[ -z $os ]]; then
os=$(go env GOHOSTOS)
fi
local arch="${GOARCH-}"
if [[ -z $arch ]]; then
arch=$(go env GOHOSTARCH)
fi
echo "$os/$arch"
}
# Takes the the platform name ($1) and sets the appropriate golang env variables
# for that platform.
kube::golang::set_platform_envs() {
[[ -n ${1-} ]] || {
kube::log::error_exit "!!! Internal error. No platform set in kube::golang::set_platform_envs"
}
export GOOS=${platform%/*}
export GOARCH=${platform##*/}
}
kube::golang::unset_platform_envs() {
unset GOOS
unset GOARCH
}
# Create the GOPATH tree under $KUBE_OUTPUT
kube::golang::create_gopath_tree() {
local go_pkg_dir="${KUBE_GOPATH}/src/${KUBE_GO_PACKAGE}"
local go_pkg_basedir=$(dirname "${go_pkg_dir}")
mkdir -p "${go_pkg_basedir}"
rm -f "${go_pkg_dir}"
# TODO: This symlink should be relative.
ln -s "${KUBE_ROOT}" "${go_pkg_dir}"
}
# kube::golang::setup_env will check that the `go` commands is available in
# ${PATH}. If not running on Travis, it will also check that the Go version is
# good enough for the Kubernetes build.
#
# Input Vars:
# KUBE_EXTRA_GOPATH - If set, this is included in created GOPATH
# KUBE_NO_GODEPS - If set, we don't add 'Godeps/_workspace' to GOPATH
#
# Output Vars:
# export GOPATH - A modified GOPATH to our created tree along with extra
# stuff.
# export GOBIN - This is actively unset if already set as we want binaries
# placed in a predictable place.
kube::golang::setup_env() {
kube::golang::create_gopath_tree
if [[ -z "$(which go)" ]]; then
kube::log::usage_from_stdin <<EOF
Can't find 'go' in PATH, please fix and retry.
See http://golang.org/doc/install for installation instructions.
EOF
exit 2
fi
# Travis continuous build uses a head go release that doesn't report
# a version number, so we skip this check on Travis. It's unnecessary
# there anyway.
if [[ "${TRAVIS:-}" != "true" ]]; then
local go_version
go_version=($(go version))
if [[ "${go_version[2]}" < "go1.2" ]]; then
kube::log::usage_from_stdin <<EOF
Detected go version: ${go_version[*]}.
Kubernetes requires go version 1.2 or greater.
Please install Go version 1.2 or later.
EOF
exit 2
fi
fi
GOPATH=${KUBE_GOPATH}
# Append KUBE_EXTRA_GOPATH to the GOPATH if it is defined.
if [[ -n ${KUBE_EXTRA_GOPATH:-} ]]; then
GOPATH="${GOPATH}:${KUBE_EXTRA_GOPATH}"
fi
# Append the tree maintained by `godep` to the GOPATH unless KUBE_NO_GODEPS
# is defined.
if [[ -z ${KUBE_NO_GODEPS:-} ]]; then
GOPATH="${GOPATH}:${KUBE_ROOT}/Godeps/_workspace"
fi
export GOPATH
# Unset GOBIN in case it already exists in the current session.
unset GOBIN
}
# This will take binaries from $GOPATH/bin and copy them to the appropriate
# place in ${KUBE_OUTPUT_BINDIR}
#
# Ideally this wouldn't be necessary and we could just set GOBIN to
# KUBE_OUTPUT_BINDIR but that won't work in the face of cross compilation. 'go
# install' will place binaries that match the host platform directly in $GOBIN
# while placing cross compiled binaries into `platform_arch` subdirs. This
# complicates pretty much everything else we do around packaging and such.
kube::golang::place_bins() {
local host_platform
host_platform=$(kube::golang::host_platform)
kube::log::status "Placing binaries"
local platform
for platform in "${KUBE_CLIENT_PLATFORMS[@]}"; do
# The substitution on platform_src below will replace all slashes with
# underscores. It'll transform darwin/amd64 -> darwin_amd64.
local platform_src="/${platform//\//_}"
if [[ $platform == $host_platform ]]; then
platform_src=""
fi
local full_binpath_src="${KUBE_GOPATH}/bin${platform_src}"
if [[ -d "${full_binpath_src}" ]]; then
mkdir -p "${KUBE_OUTPUT_BINPATH}/${platform}"
find "${full_binpath_src}" -maxdepth 1 -type f -exec \
rsync -pt {} "${KUBE_OUTPUT_BINPATH}/${platform}" \;
fi
done
}
# Build binaries targets specified
#
# Input:
# $@ - targets and go flags. If no targets are set then all binaries targets
# are built.
# KUBE_BUILD_PLATFORMS - Incoming variable of targets to build for. If unset
# then just the host architecture is built.
kube::golang::build_binaries() {
# Create a sub-shell so that we don't pollute the outer environment
(
# Check for `go` binary and set ${GOPATH}.
kube::golang::setup_env
# Fetch the version.
local version_ldflags
version_ldflags=$(kube::version::ldflags)
# Use eval to preserve embedded quoted strings.
local goflags
eval "goflags=(${KUBE_GOFLAGS:-})"
local -a targets=()
local arg
for arg; do
if [[ "${arg}" == -* ]]; then
# Assume arguments starting with a dash are flags to pass to go.
goflags+=("${arg}")
else
targets+=("${arg}")
fi
done
if [[ ${#targets[@]} -eq 0 ]]; then
targets=("${KUBE_ALL_TARGETS[@]}")
fi
local -a platforms=("${KUBE_BUILD_PLATFORMS[@]:+${KUBE_BUILD_PLATFORMS[@]}}")
if [[ ${#platforms[@]} -eq 0 ]]; then
platforms=("$(kube::golang::host_platform)")
fi
local binaries
binaries=($(kube::golang::binaries_from_targets "${targets[@]}"))
local platform
for platform in "${platforms[@]}"; do
kube::golang::set_platform_envs "${platform}"
kube::log::status "Building go targets for ${platform}:" "${targets[@]}"
go install "${goflags[@]:+${goflags[@]}}" \
-ldflags "${version_ldflags}" \
"${binaries[@]}"
done
)
}

View File

@ -18,21 +18,25 @@ set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
source "${KUBE_ROOT}/build/build-image/common.sh"
# The root of the build/dist directory
KUBE_ROOT=$(
unset CDPATH
kube_root=$(dirname "${BASH_SOURCE}")/../..
cd "${kube_root}"
pwd
)
kube::build::make_binaries "./cmd/integration"
KUBE_OUTPUT_SUBPATH="${KUBE_OUTPUT_SUBPATH:-_output/local}"
KUBE_OUTPUT="${KUBE_ROOT}/${KUBE_OUTPUT_SUBPATH}"
KUBE_OUTPUT_BINPATH="${KUBE_OUTPUT}/bin"
readonly ETCD_DIR="${KUBE_ROOT}/_output/etcd"
mkdir -p "${ETCD_DIR}"
source "${KUBE_ROOT}/hack/lib/util.sh"
source "${KUBE_ROOT}/hack/lib/logging.sh"
echo "+++ Running integration test"
kube::log::install_errexit
etcd -name test -data-dir ${ETCD_DIR} > "${KUBE_ROOT}/_output/etcd.log" &
readonly ETCD_PID=$!
source "${KUBE_ROOT}/hack/lib/version.sh"
source "${KUBE_ROOT}/hack/lib/golang.sh"
source "${KUBE_ROOT}/hack/lib/etcd.sh"
sleep 5
"${KUBE_TARGET}/linux/amd64/integration"
kill $ETCD_PID
KUBE_OUTPUT_HOSTBIN="${KUBE_OUTPUT_BINPATH}/$(kube::golang::host_platform)"

137
hack/lib/logging.sh Normal file
View File

@ -0,0 +1,137 @@
#!/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.
# Handler for when we exit automatically on an error.
# Borrowed from https://gist.github.com/ahendrix/7030300
kube::log::errexit() {
local err="${PIPESTATUS[@]}"
# If the shell we are in doesn't have errexit set (common in subshells) then
# don't dump stacks.
set +o | grep -qe "-o errexit" || return
set +o xtrace
local code="${1:-1}"
kube::log::error_exit "'${BASH_COMMAND}' exited with status $err" "${1:-1}" 1
}
kube::log::install_errexit() {
# trap ERR to provide an error handler whenever a command exits nonzero this
# is a more verbose version of set -o errexit
trap 'kube::log::errexit' ERR
# setting errtrace allows our ERR trap handler to be propagated to functions,
# expansions and subshells
set -o errtrace
}
# Print out the stack trace
#
# Args:
# $1 The number of stack frames to skip when printing.
kube::log::stack() {
local stack_skip=${1:-0}
stack_skip=$((stack_skip + 1))
if [[ ${#FUNCNAME[@]} -gt $stack_skip ]]; then
echo "Call stack:" >&2
local i
for ((i=1 ; i <= ${#FUNCNAME[@]} - $stack_skip ; i++))
do
local frame_no=$((i - 1 + stack_skip))
local source_file=${BASH_SOURCE[$frame_no]}
local source_lineno=${BASH_LINENO[$((frame_no - 1))]}
local funcname=${FUNCNAME[$frame_no]}
echo " $i: ${source_file}:${source_lineno} ${funcname}(...)" >&2
done
fi
}
# Log an error and exit.
# Args:
# $1 Message to log with the error
# $2 The error code to return
# $3 The number of stack frames to skip when printing.
kube::log::error_exit() {
local message="${1:-}"
local code="${2:-1}"
local stack_skip="${3:-0}"
stack_skip=$((stack_skip + 1))
local source_file=${BASH_SOURCE[$stack_skip]}
local source_line=${BASH_LINENO[$((stack_skip - 1))]}
echo "!!! Error in ${source_file}:${source_line}" >&2
[[ -z ${1-} ]] || {
echo " ${1}" >&2
}
kube::log::stack $stack_skip
echo "Exiting with status ${code}" >&2
exit "${code}"
}
# Log an error but keep going. Don't dump the stack or exit.
kube::log::error() {
echo "!!! ${1-}" >&2
shift
for message; do
echo " $message" >&2
done
}
# Print an usage message to stderr. The arguments are printed directly.
kube::log::usage() {
echo >&2
local message
for message; do
echo "$message" >&2
done
echo >&2
}
kube::log::usage_from_stdin() {
local messages=()
while read -r line; do
messages+=$line
done
kube::log::usage "${messages[@]}"
}
# Print out some info that isn't a top level status line
kube::log::info() {
for message; do
echo "$message"
done
}
kube::log::info_from_stdin() {
local messages=()
while read -r line; do
messages+=$line
done
kube::log::info "${messages[@]}"
}
# Print a status line. Formatted to show up in a stream of output.
kube::log::status() {
echo "+++ $1"
shift
for message; do
echo " $message"
done
}

28
hack/install-etcd.sh → hack/lib/util.sh Executable file → Normal file
View File

@ -14,13 +14,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
kube::util::sortable_date() {
date "+%Y%m%d-%H%M%S"
}
cd third_party
git clone https://github.com/coreos/etcd.git
cd etcd
git checkout ab4bcc18694644d12f0c038339d8d039072502b1
./build
kube::util::wait_for_url() {
local url=$1
local prefix=${2:-}
local wait=${3:-0.2}
local times=${4:-10}
local i
for i in $(seq 1 $times); do
local out
if out=$(curl -fs $url 2>/dev/null); then
kube::log::status ${prefix}${out}
return 0
fi
sleep $wait
done
kube::log::error "Timed out waiting for ${url}"
return 1
}

126
hack/lib/version.sh Normal file
View File

@ -0,0 +1,126 @@
#!/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.
# -----------------------------------------------------------------------------
# Version management helpers. These functions help to set, save and load the
# following variables:
#
# KUBE_GIT_COMMIT - The git commit id corresponding to this
# source code.
# KUBE_GIT_TREE_STATE - "clean" indicates no changes since the git commit id
# "dirty" indicates source code changes after the git commit id
# KUBE_GIT_VERSION - "vX.Y" used to indicate the last release version.
# KUBE_GIT_MAJOR - The major part of the version
# KUBE_GIT_MINOR - The minor component of the version
# Grovels through git to set a set of env variables.
#
# If KUBE_GIT_VERSION_FILE, this function will load from that file instead of
# querying git.
kube::version::get_version_vars() {
if [[ -n ${KUBE_GIT_VERSION_FILE-} ]]; then
kube::version::load_version_vars "${KUBE_GIT_VERSION_FILE}"
return
fi
local git=(git --work-tree "${KUBE_ROOT}")
if [[ -n ${KUBE_GIT_COMMIT-} ]] || KUBE_GIT_COMMIT=$("${git[@]}" rev-parse "HEAD^{commit}" 2>/dev/null); then
if [[ -z ${KUBE_GIT_TREE_STATE-} ]]; then
# Check if the tree is dirty. default to dirty
if git_status=$("${git[@]}" status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then
KUBE_GIT_TREE_STATE="clean"
else
KUBE_GIT_TREE_STATE="dirty"
fi
fi
# Use git describe to find the version based on annotated tags.
if [[ -n ${KUBE_GIT_VERSION-} ]] || KUBE_GIT_VERSION=$("${git[@]}" describe --abbrev=14 "${KUBE_GIT_COMMIT}^{commit}" 2>/dev/null); then
if [[ "${KUBE_GIT_TREE_STATE}" == "dirty" ]]; then
# git describe --dirty only considers changes to existing files, but
# that is problematic since new untracked .go files affect the build,
# so use our idea of "dirty" from git status instead.
KUBE_GIT_VERSION+="-dirty"
fi
# Try to match the "git describe" output to a regex to try to extract
# the "major" and "minor" versions and whether this is the exact tagged
# version or whether the tree is between two tagged versions.
if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)([.-].*)?$ ]]; then
KUBE_GIT_MAJOR=${BASH_REMATCH[1]}
KUBE_GIT_MINOR=${BASH_REMATCH[2]}
if [[ -n "${BASH_REMATCH[3]}" ]]; then
KUBE_GIT_MINOR+="+"
fi
fi
fi
fi
}
# Saves the environment flags to $1
kube::version::save_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kube::version::save_version_vars"
return 1
}
cat <<EOF >"${version_file}"
KUBE_GIT_COMMIT='${KUBE_GIT_COMMIT-}'
KUBE_GIT_TREE_STATE='${KUBE_GIT_TREE_STATE-}'
KUBE_GIT_VERSION='${KUBE_GIT_VERSION-}'
KUBE_GIT_MAJOR='${KUBE_GIT_MAJOR-}'
KUBE_GIT_MINOR='${KUBE_GIT_MINOR-}'
EOF
}
# Loads up the version variables from file $1
kube::version::load_version_vars() {
local version_file=${1-}
[[ -n ${version_file} ]] || {
echo "!!! Internal error. No file specified in kube::version::load_version_vars"
return 1
}
source "${version_file}"
}
# Prints the value that needs to be passed to the -ldflags parameter of go build
# in order to set the Kubernetes based on the git tree status.
kube::version::ldflags() {
kube::version::get_version_vars
local -a ldflags=()
if [[ -n ${KUBE_GIT_COMMIT-} ]]; then
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitCommit" "${KUBE_GIT_COMMIT}")
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitTreeState" "${KUBE_GIT_TREE_STATE}")
fi
if [[ -n ${KUBE_GIT_VERSION-} ]]; then
ldflags+=(-X "${KUBE_GO_PACKAGE}/pkg/version.gitVersion" "${KUBE_GIT_VERSION}")
fi
if [[ -n ${KUBE_GIT_MAJOR-} && -n ${KUBE_GIT_MINOR-} ]]; then
ldflags+=(
-X "${KUBE_GO_PACKAGE}/pkg/version.gitMajor" "${KUBE_GIT_MAJOR}"
-X "${KUBE_GO_PACKAGE}/pkg/version.gitMinor" "${KUBE_GIT_MINOR}"
)
fi
# The -ldflags parameter takes a single string, so join the output.
echo "${ldflags[*]-}"
}

View File

@ -22,8 +22,7 @@ set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/util.sh"
source "${KUBE_ROOT}/hack/config-go.sh"
source "${KUBE_ROOT}/hack/lib/init.sh"
function cleanup()
{
@ -31,18 +30,15 @@ function cleanup()
[[ -n ${CTLRMGR_PID-} ]] && kill ${CTLRMGR_PID} 1>&2 2>/dev/null
[[ -n ${KUBELET_PID-} ]] && kill ${KUBELET_PID} 1>&2 2>/dev/null
[[ -n ${PROXY_PID-} ]] && kill ${PROXY_PID} 1>&2 2>/dev/null
[[ -n ${ETCD_PID-} ]] && kill ${ETCD_PID} 1>&2 2>/dev/null
rm -rf ${ETCD_DIR} 1>&2 2>/dev/null
echo
echo "Complete"
kube::etcd::cleanup
kube::log::status "Clean up complete"
}
trap cleanup EXIT SIGINT
set -e
# Start etcd
start_etcd
kube::etcd::start
ETCD_HOST=${ETCD_HOST:-127.0.0.1}
ETCD_PORT=${ETCD_PORT:-4001}
@ -50,24 +46,25 @@ API_PORT=${API_PORT:-8080}
API_HOST=${API_HOST:-127.0.0.1}
KUBELET_PORT=${KUBELET_PORT:-10250}
CTLRMGR_PORT=${CTLRMGR_PORT:-10252}
GO_OUT=${KUBE_TARGET}/bin
# Check kubectl
out=$("${GO_OUT}/kubectl")
echo kubectl: $out
kube::log::status "Running kubectl with no options"
"${KUBE_OUTPUT_HOSTBIN}/kubectl"
# Start kubelet
${GO_OUT}/kubelet \
kube::log::status "Starting kubelet"
"${KUBE_OUTPUT_HOSTBIN}/kubelet" \
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
--hostname_override="127.0.0.1" \
--address="127.0.0.1" \
--port="$KUBELET_PORT" 1>&2 &
KUBELET_PID=$!
wait_for_url "http://127.0.0.1:${KUBELET_PORT}/healthz" "kubelet: "
kube::util::wait_for_url "http://127.0.0.1:${KUBELET_PORT}/healthz" "kubelet: "
# Start apiserver
${GO_OUT}/apiserver \
kube::log::status "Starting apiserver"
"${KUBE_OUTPUT_HOSTBIN}/apiserver" \
--address="127.0.0.1" \
--port="${API_PORT}" \
--etcd_servers="http://${ETCD_HOST}:${ETCD_PORT}" \
@ -75,33 +72,42 @@ ${GO_OUT}/apiserver \
--portal_net="10.0.0.0/24" 1>&2 &
APISERVER_PID=$!
wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
kube_cmd=(
"${KUBE_OUTPUT_HOSTBIN}/kubectl"
)
kube_flags=(
-s "http://127.0.0.1:${API_PORT}"
--match-server-version
)
# Start controller manager
${GO_OUT}/controller-manager \
kube::log::status "Starting CONTROLLER-MANAGER"
"${KUBE_OUTPUT_HOSTBIN}/controller-manager" \
--machines="127.0.0.1" \
--master="127.0.0.1:${API_PORT}" 1>&2 &
CTLRMGR_PID=$!
wait_for_url "http://127.0.0.1:${CTLRMGR_PORT}/healthz" "controller-manager: "
kube::util::wait_for_url "http://127.0.0.1:${CTLRMGR_PORT}/healthz" "controller-manager: "
KUBE_CMD="${GO_OUT}/kubectl"
KUBE_FLAGS="-s http://127.0.0.1:${API_PORT} --match-server-version"
kube::log::status "Testing kubectl(pods)"
"${kube_cmd[@]}" get pods "${kube_flags[@]}"
${KUBE_CMD} get pods ${KUBE_FLAGS}
echo "kubectl(pods): ok"
kube::log::status "Testing kubectl(services)"
"${kube_cmd[@]}" get services "${kube_flags[@]}"
"${kube_cmd[@]}" create -f examples/guestbook/frontend-service.json "${kube_flags[@]}"
"${kube_cmd[@]}" delete service frontend "${kube_flags[@]}"
${KUBE_CMD} get services ${KUBE_FLAGS}
${KUBE_CMD} create -f examples/guestbook/frontend-service.json ${KUBE_FLAGS}
${KUBE_CMD} delete service frontend ${KUBE_FLAGS}
echo "kubectl(services): ok"
kube::log::status "Testing kubectl(minions)"
"${kube_cmd[@]}" get minions "${kube_flags[@]}"
"${kube_cmd[@]}" get minions 127.0.0.1 "${kube_flags[@]}"
${KUBE_CMD} get minions ${KUBE_FLAGS}
${KUBE_CMD} get minions 127.0.0.1 ${KUBE_FLAGS}
echo "kubectl(minions): ok"
kube::log::status "TEST PASSED"
# Start proxy
#PROXY_LOG=/tmp/kube-proxy.log
#${GO_OUT}/proxy \
#${KUBE_OUTPUT_HOSTBIN}/proxy \
# --etcd_servers="http://127.0.0.1:${ETCD_PORT}" 1>&2 &
#PROXY_PID=$!

View File

@ -19,30 +19,28 @@ set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/config-go.sh"
source "${KUBE_ROOT}/hack/lib/init.sh"
# Go to the top of the tree.
cd "${KUBE_ROOT}"
kube::golang::setup_env
# Check for `go` binary and set ${GOPATH}.
kube::setup_go_environment
find_test_dirs() {
cd src/${KUBE_GO_PACKAGE}
find . -not \( \
\( \
-wholename './output' \
-o -wholename './_output' \
-o -wholename './release' \
-o -wholename './target' \
-o -wholename '*/third_party/*' \
-o -wholename '*/Godeps/*' \
\) -prune \
\) -name '*_test.go' -print0 | xargs -0n1 dirname | sed 's|^\./||' | sort -u
kube::test::find_dirs() {
(
cd ${KUBE_ROOT}
find . -not \( \
\( \
-wholename './output' \
-o -wholename './_output' \
-o -wholename './release' \
-o -wholename './target' \
-o -wholename '*/third_party/*' \
-o -wholename '*/Godeps/*' \
\) -prune \
\) -name '*_test.go' -print0 | xargs -0n1 dirname | sed 's|^\./||' | sort -u
)
}
find_test_pkgs() {
find_test_dirs | xargs -n1 printf "${KUBE_GO_PACKAGE}/%s\n"
kube::test::find_pkgs() {
kube::test::find_dirs | xargs -n1 printf "${KUBE_GO_PACKAGE}/%s\n"
}
# -covermode=atomic becomes default with -race in Go >=1.3
@ -50,10 +48,8 @@ KUBE_COVER=${KUBE_COVER:--cover -covermode=atomic}
KUBE_TIMEOUT=${KUBE_TIMEOUT:--timeout 60s}
KUBE_RACE=${KUBE_RACE:--race}
cd "${KUBE_TARGET}"
usage() {
cat << EOF
kube::test::usage() {
kube::log::usage_from_stdin <<EOF
usage: $0 [OPTIONS] [TARGETS]
OPTIONS:
@ -69,24 +65,24 @@ iterations=1
while getopts "hi:" opt ; do
case $opt in
h)
usage
kube::test::usage
exit 0
;;
i)
iterations="$OPTARG"
if ! isnum "${iterations}" || [[ "${iterations}" -le 0 ]]; then
echo "$0": argument to -i must be numeric and greater than 0 >&2
usage >&2
kube::log::usage "'$0': argument to -i must be numeric and greater than 0"
kube::test::usage
exit 1
fi
;;
?)
usage >&2
kube::test::usage
exit 1
;;
:)
echo "Option -$OPTARG <value>" >&2
usage >&2
kube::log::usage "Option -$OPTARG <value>"
kube::test::usage
exit 1
;;
esac
@ -94,7 +90,7 @@ done
shift $((OPTIND - 1))
# Use eval to preserve embedded quoted strings.
eval "goflags=(${GOFLAGS:-})"
eval "goflags=(${KUBE_GOFLAGS:-})"
# Filter out arguments that start with "-" and move them to goflags.
testcases=()
@ -105,19 +101,18 @@ for arg; do
testcases+=("${arg}")
fi
done
set -- ${testcases[@]+"${testcases[@]}"}
set -- "${testcases[@]+${testcases[@]}}"
if [[ "${iterations}" -gt 1 ]]; then
if [[ $iterations -gt 1 ]]; then
if [[ $# -eq 0 ]]; then
set -- $(find_test_dirs)
set -- $(kube::test::find_dirs)
fi
echo "Running ${iterations} times"
kube::log::status "Running ${iterations} times"
fails=0
for arg; do
trap 'exit 1' SIGINT
echo
pkg=${KUBE_GO_PACKAGE}/${arg}
echo "${pkg}"
kube::log::status "${pkg}"
# keep going, even if there are failures
pass=0
count=0
@ -130,7 +125,7 @@ if [[ "${iterations}" -gt 1 ]]; then
fi
count=$((count + 1))
done 2>&1
echo "${pass}" / "${count}" passed
kube::log::status "${pass} / ${count} passed"
done
if [[ ${fails} -gt 0 ]]; then
exit 1
@ -140,8 +135,8 @@ if [[ "${iterations}" -gt 1 ]]; then
fi
if [[ -n "${1-}" ]]; then
covdir="/tmp/k8s_coverage/$(date "+%s")"
echo saving coverage output in "${covdir}"
covdir="/tmp/k8s_coverage/$(kube::util::sortable_date)"
kube::log::status "Saving coverage output in '${covdir}'"
for arg; do
trap 'exit 1' SIGINT
mkdir -p "${covdir}/${arg}"
@ -155,7 +150,7 @@ if [[ -n "${1-}" ]]; then
exit 0
fi
find_test_pkgs | xargs go test "${goflags[@]:+${goflags[@]}}" \
kube::test::find_pkgs | xargs go test "${goflags[@]:+${goflags[@]}}" \
${KUBE_RACE} \
${KUBE_TIMEOUT} \
${KUBE_COVER}

View File

@ -19,34 +19,28 @@ set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/config-go.sh"
source "${KUBE_ROOT}/hack/util.sh"
source "${KUBE_ROOT}/hack/lib/init.sh"
cleanup() {
kill "${ETCD_PID-}" >/dev/null 2>&1 || :
rm -rf "${ETCD_DIR-}"
echo ""
echo "Complete"
kube::etcd::cleanup
kube::log::status "Integration test cleanup complete"
}
if [[ "${KUBE_NO_BUILD_INTEGRATION+set}" != "set" ]]; then
if [[ -z ${KUBE_NO_BUILD_INTEGRATION-} ]]; then
"${KUBE_ROOT}/hack/build-go.sh" cmd/integration
fi
# Run cleanup to stop etcd on interrupt or other kill signal.
trap cleanup HUP INT QUIT TERM
start_etcd
kube::etcd::start
echo ""
echo "Integration test cases..."
echo ""
GOFLAGS="-tags 'integration no-docker' -test.v" \
kube::log::status "Running integration test cases"
KUBE_GOFLAGS="-tags 'integration no-docker' -test.v" \
"${KUBE_ROOT}/hack/test-go.sh" test/integration
echo ""
echo "Integration scenario ..."
echo ""
"${KUBE_TARGET}/bin/integration"
kube::log::status "Running integration test scenario"
"${KUBE_OUTPUT_HOSTBIN}/integration"
cleanup

View File

@ -19,13 +19,10 @@ set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
source "${KUBE_ROOT}/build/build-image/common.sh"
echo "+++ Running unit tests"
ETCD_VERSION=${ETCD_VERSION:-v0.4.6}
if [[ -n "${1-}" ]]; then
godep go test -cover -coverprofile=tmp.out "$KUBE_GO_PACKAGE/$1"
exit 0
fi
godep go test ./...
cd "${KUBE_ROOT}/third_party"
curl -sL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz \
| tar xzf -
ln -sF etcd-${ETCD_VERSION}-linux-amd64 etcd

View File

@ -20,10 +20,10 @@ set -o errexit
set -o nounset
set -o pipefail
if [ "${TRAVIS}" == "true" ]; then
if [[ "${TRAVIS}" == "true" ]]; then
GO_VERSION=($(go version))
if [ ${GO_VERSION[2]} \< "go1.3" ]; then
if [[ ${GO_VERSION[2]} < "go1.3" ]]; then
echo "Installing the -race compatible version of the std go library"
go install -a -race std
fi

View File

@ -1,66 +0,0 @@
#!/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.
# Provides simple utility functions
function wait_for_url {
url=$1
prefix=${2:-}
wait=${3:-0.2}
times=${4:-10}
set +e
for i in $(seq 1 $times); do
out=$(curl -fs $url 2>/dev/null)
if [ $? -eq 0 ]; then
set -e
echo ${prefix}${out}
return 0
fi
sleep $wait
done
echo "ERROR: timed out for $url"
set -e
return 1
}
function start_etcd {
host=${ETCD_HOST:-127.0.0.1}
port=${ETCD_PORT:-4001}
set +e
if [ "$(which etcd)" == "" ]; then
echo "etcd must be in your PATH"
exit 1
fi
running_etcd=$(ps -ef | grep etcd | grep -c name)
if [ "$running_etcd" != "0" ]; then
echo "etcd appears to already be running on this machine, please kill and restart the test."
exit 1
fi
# Stop on any failures
set -e
# Start etcd
export ETCD_DIR=$(mktemp -d -t test-etcd.XXXXXX)
etcd -name test -data-dir ${ETCD_DIR} -addr ${host}:${port} >/dev/null 2>/dev/null &
export ETCD_PID=$!
wait_for_url "http://localhost:4001/v2/keys/" "etcd: "
}

View File

@ -20,20 +20,33 @@ set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
result=0
cd ${KUBE_ROOT}
gofiles="$(find "${KUBE_ROOT}" -type f | grep "[.]go$" | grep -v "Godeps/\|third_party/\|release/\|_?output/|target/")"
for file in ${gofiles}; do
result=0
find_files() {
find . -not \( \
\( \
-wholename './output' \
-o -wholename './_output' \
-o -wholename './release' \
-o -wholename './target' \
-o -wholename '*/third_party/*' \
-o -wholename '*/Godeps/*' \
\) -prune \
\) -name '*.go'
}
for file in $(find_files); do
if [[ "$("${KUBE_ROOT}/hooks/boilerplate.sh" "${file}")" -eq "0" ]]; then
echo "Boilerplate header is wrong for: ${file}"
result=1
fi
done
dirs=("cluster" "hack" "hooks")
dirs=("cluster" "hack" "hooks" "build")
for dir in ${dirs[@]}; do
for file in $(grep -r -l "" "${KUBE_ROOT}/${dir}/" | grep "[.]sh"); do
for file in $(find "$dir" -name '*.sh'); do
if [[ "$("${KUBE_ROOT}/hooks/boilerplate.sh" "${file}")" -eq "0" ]]; then
echo "Boilerplate header is wrong for: ${file}"
result=1

View File

@ -20,6 +20,7 @@ set -o errexit
set -o nounset
set -o pipefail
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
GO_VERSION=($(go version))
@ -28,11 +29,24 @@ if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.2|go1.3') ]]; then
exit 0
fi
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
cd "${KUBE_ROOT}"
files="$(find "${KUBE_ROOT}" -type f | grep "[.]go$" | grep -v "third_party/\|release/\|_?output/\|target/\|Godeps/")"
bad=$(gofmt -s -l ${files})
if [[ -n "${bad}" ]]; then
echo "$bad"
find_files() {
find . -not \( \
\( \
-wholename './output' \
-o -wholename './_output' \
-o -wholename './release' \
-o -wholename './target' \
-o -wholename '*/third_party/*' \
-o -wholename '*/Godeps/*' \
\) -prune \
\) -name '*.go'
}
bad_files=$(find_files | xargs gofmt -s -l)
if [[ -n "${bad_files}" ]]; then
echo "!!! gofmt needs to be run on the following files: "
echo "${bad_files}"
exit 1
fi

View File

@ -19,19 +19,15 @@ set -o errexit
set -o nounset
set -o pipefail
KUBE_REPO_ROOT=$(dirname "${BASH_SOURCE}")/..
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
source "${KUBE_ROOT}/hack/lib/init.sh"
# Set the environment variables required by the build.
source "${KUBE_REPO_ROOT}/hack/config-go.sh"
kube::golang::setup_env
# Go to the top of the tree.
cd "${KUBE_REPO_ROOT}"
# Check for `go` binary and set ${GOPATH}.
kube::setup_go_environment
cd "${KUBE_ROOT}"
# Use eval to preserve embedded quoted strings.
eval "goflags=(${GOFLAGS:-})"
eval "goflags=(${KUBE_GOFLAGS:-})"
# Filter out arguments that start with "-" and move them to goflags.
targets=()
@ -43,19 +39,20 @@ for arg; do
fi
done
if [[ "${targets[@]+set}" != "set" ]]; then
if [[ ${#targets[@]} -eq 0 ]]; then
targets=("...")
fi
rc=0
# Filter silly "exit status 1" lines and send main output to stdout.
#
# This is tricky - pipefail means any non-zero exit in a pipeline is reported,
# and errexit exits on error. Turning that into an || expression blocks the
# errexit. But $? is still not useful because grep will return an error when it
# receives no input, which is exactly what go vet produces on success. In short,
# if go vet fails (produces output), grep will succeed, but if go vet succeeds
# (produces no output) grep will fail. Then we just look at PIPESTATUS[0] which
# is go's exit code.
# receives no input, which is exactly what go vet produces on success. In
# short, if go vet fails (produces output), grep will succeed, but if go vet
# succeeds (produces no output) grep will fail. Then we just look at
# PIPESTATUS[0] which is go's exit code.
rc=0
go vet "${goflags[@]:+${goflags[@]}}" "${targets[@]/#/./}" 2>&1 \
| grep -v "^exit status " \
|| rc=${PIPESTATUS[0]}