From 65aa0a524465a42b7fde5eeb58c88db53bd74900 Mon Sep 17 00:00:00 2001 From: Travis Rhoden Date: Wed, 24 Jul 2019 12:30:48 -0600 Subject: [PATCH] Add/use hack/release.sh script for images This patch adds a hack/release.sh script and dependencies, and follows the same release practice as CAPV. This changes the location of the container images, mainly splitting the latest builds from master versus a release channel just for releases. A separate doc update needs to be made for this as well. --- Makefile | 56 ++-------- cluster/images/csi/Dockerfile | 42 +++++--- hack/match-release-tag.sh | 108 +++++++++++++++++++ hack/release.sh | 192 ++++++++++++++++++++++++++++++++++ 4 files changed, 336 insertions(+), 62 deletions(-) create mode 100755 hack/match-release-tag.sh create mode 100755 hack/release.sh diff --git a/Makefile b/Makefile index b009602456..ded46405e8 100644 --- a/Makefile +++ b/Makefile @@ -52,16 +52,9 @@ deps: # Ensure the version is injected into the binaries via a linker flag. export VERSION ?= $(shell git describe --always --dirty) -# Load the image registry include. -include hack/make/login-to-image-registry.mk - -# Define the images. -IMAGE_CSI := $(REGISTRY)/vsphere-csi -.PHONY: print-image - -# Printing the image version is defined early so Go modules aren't forced. -print-image: - @echo $(IMAGE_CSI):$(VERSION) +.PHONY: version +version: + @echo $(VERSION) ################################################################################ ## BUILD DIRS ## @@ -127,7 +120,6 @@ dist: dist-csi-tgz dist-csi-zip deploy: | $(DOCKER_SOCK) $(MAKE) build-bins $(MAKE) unit-test - $(MAKE) build-images $(MAKE) push-images ################################################################################ @@ -243,33 +235,16 @@ check: fmt vet lint ################################################################################ ## BUILD IMAGES ## ################################################################################ -IMAGE_CSI_D := image-csi-$(VERSION).d -build-csi-image csi-image: $(IMAGE_CSI_D) -$(IMAGE_CSI): $(IMAGE_CSI_D) -ifneq ($(GOOS),linux) -$(IMAGE_CSI_D): - $(error Please set GOOS=linux for building $@) -else -$(IMAGE_CSI_D): $(CSI_BIN) | $(DOCKER_SOCK) - cp -f $< cluster/images/csi/vsphere-csi - docker build -t $(IMAGE_CSI):$(VERSION) cluster/images/csi - docker tag $(IMAGE_CSI):$(VERSION) $(IMAGE_CSI):latest - @rm -f cluster/images/csi/vsphere-csi && touch $@ -endif - -build-images images: build-csi-image +.PHONY: images +images: | $(DOCKER_SOCK) + hack/release.sh ################################################################################ ## PUSH IMAGES ## ################################################################################ -.PHONY: push-$(IMAGE_CSI) upload-$(IMAGE_CSI) -push-csi-image upload-csi-image: upload-$(IMAGE_CSI) -push-$(IMAGE_CSI) upload-$(IMAGE_CSI): $(IMAGE_CSI_D) login-to-image-registry | $(DOCKER_SOCK) - docker push $(IMAGE_CSI):$(VERSION) - docker push $(IMAGE_CSI):latest - .PHONY: push-images upload-images -push-images upload-images: upload-csi-image +push-images: | $(DOCKER_SOCK) + hack/release.sh -p ################################################################################ ## CI IMAGE ## @@ -282,18 +257,3 @@ push-ci-image: print-ci-image: @$(MAKE) --no-print-directory -C hack/images/ci print - -################################################################################ -## PRINT VERISON ## -################################################################################ -.PHONY: version -version: - @echo $(VERSION) - -################################################################################ -## TODO(akutz) ## -################################################################################ -TODO := docs godoc releasenotes translation -.PHONY: $(TODO) -$(TODO): - @echo "$@ not yet implemented" diff --git a/cluster/images/csi/Dockerfile b/cluster/images/csi/Dockerfile index c740b64475..5cad5f12c7 100644 --- a/cluster/images/csi/Dockerfile +++ b/cluster/images/csi/Dockerfile @@ -1,16 +1,30 @@ -# 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. - -FROM photon:2.0 +################################################################################ +## BUILD ARGS ## +################################################################################ +# This build arg allows the specification of a custom Golang image. +ARG GOLANG_IMAGE=golang:1.12.6 + +# This build arg allows the specification of a custom Photon image. +ARG PHOTON_IMAGE=photon:2.0 + +################################################################################ +## BUILD STAGE ## +################################################################################ +# Build the manager as a statically compiled binary so it has no dependencies +# libc, muscl, etc. +FROM ${GOLANG_IMAGE} as builder +WORKDIR /build +COPY go.mod go.sum ./ +COPY pkg/ pkg/ +COPY cmd/ cmd/ +ENV CGO_ENABLED=0 +RUN go build -a -ldflags='-w -s -extldflags="static"' -o vsphere-csi ./cmd/vsphere-csi + +################################################################################ +## MAIN STAGE ## +################################################################################ +FROM ${PHOTON_IMAGE} +LABEL "maintainer" "Travis Rhoden " RUN tdnf -y remove toybox @@ -22,6 +36,6 @@ RUN tdnf -y install \ RUN tdnf clean all -ADD vsphere-csi /bin/ +COPY --from=builder /build/vsphere-csi /bin/vsphere-csi CMD ["/bin/vsphere-csi"] diff --git a/hack/match-release-tag.sh b/hack/match-release-tag.sh new file mode 100755 index 0000000000..96a6688611 --- /dev/null +++ b/hack/match-release-tag.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -o errexit +set -o nounset +set -o pipefail + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +usage() { + cat <&2; exit 1 + ;; + x) + EXAMPLES=1 + ;; + \?) + { echo "invalid option: -${OPTARG}"; usage; } 1>&2; exit 1 + ;; + :) + echo "option -${OPTARG} requires an argument" 1>&2; exit 1 + ;; + esac +done +shift $((OPTIND-1)) + +# The regular expression matches the following strings: +# * v1.0.0-alpha.0 +# * v1.0.0-beta.0 +# * v1.0.0-rc.0 +# * v1.0.0 +# Any occurence of a digit in the above examples may be multiple digits. +REGEX='^[[:space:]]{0,}v[[:digit:]]{1,}\.[[:digit:]]{1,}\.[[:digit:]]{1,}(-(alpha|beta|rc)\.[[:digit:]]{1,}){0,1}[[:space:]]{0,}$' + +# Match the tag against the regular expression for a release tag. +match() { + if [[ ${1} =~ ${REGEX} ]]; then + echo "yay: ${1}" + else + exit_code="${?}" + echo "nay: ${1}" + return "${exit_code}" + fi +} + +# Run examples to illustrate valid and invalid values. +examples() { + local semvers=" \ + v1.0.0-alpha.0 \ + v1.0.0-beta.0 \ + v1.0.0-rc.0 \ + v1.0.0 \ + v10.0.0 \ + v1.10.0 \ + v1.0.10 \ + v10.0.0-alpha.10 \ + v1.10.0-beta.10 \ + v1.0.10-rc.10 \ + 1.0.0 \ + v1.0.0+rc.0 \ + v10a.0.0 \ + 1.1.0-alpha.1 \ + v1.0.0-alpha.0a" + set +o errexit + for v in ${semvers}; do match "${v}"; done + return 0 +} + +main() { + # Get the tag from the remaining arguments or from "git describe --dirty" + [ "${#}" -eq "0" ] || tag="${1}" + [ -n "${tag-}" ] || tag="$(git describe --dirty)" + + # Match the tag against the regular expression for a release tag. + match "${tag}" 1>&2 +} + +{ [ "${EXAMPLES-}" ] && examples; } || main "${@-}" diff --git a/hack/release.sh b/hack/release.sh new file mode 100755 index 0000000000..a7849c8c12 --- /dev/null +++ b/hack/release.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +# Copyright 2019 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is used build new container images of the CAPV manager and +# clusterctl. When invoked without arguments, the default behavior is to build +# new ci images + +set -o errexit +set -o nounset +set -o pipefail + +# BASE_REPO is the root path of the image repository +readonly BASE_IMAGE_REPO=gcr.io/cloud-provider-vsphere + +# Release images +readonly CSI_IMAGE_RELEASE=${BASE_IMAGE_REPO}/csi/release/driver + +# PR images +readonly CSI_IMAGE_PR=${BASE_IMAGE_REPO}/csi/pr/driver + +# CI images +readonly CSI_IMAGE_CI=${BASE_IMAGE_REPO}/csi/ci/driver + +AUTH= +PUSH= +LATEST= +CSI_IMAGE_NAME= +VERSION=$(git describe --dirty --always 2>/dev/null) +GCR_KEY_FILE="${GCR_KEY_FILE:-}" + +BUILD_RELEASE_TYPE="${BUILD_RELEASE_TYPE-}" + +# If BUILD_RELEASE_TYPE is not set then check to see if this is a PR +# or release build. This may still be overridden below with the "-t" flag. +if [ -z "${BUILD_RELEASE_TYPE}" ]; then + if hack/match-release-tag.sh >/dev/null 2>&1; then + BUILD_RELEASE_TYPE=release + else + BUILD_RELEASE_TYPE=ci + fi +fi + +USAGE=" +usage: ${0} [FLAGS] + Builds and optionally pushes new images for vSphere CSI driver + +FLAGS + -h show this help and exit + -k path to GCR key file. Used to login to registry if specified + (defaults to: ${GCR_KEY_FILE}) + -l tag the images as \"latest\" in addition to their version + when used with -p, both tags will be pushed + -p push the images to the public container registry + -t the build/release type (defaults to ${BUILD_RELEASE_TYPE}) + one of [ci,pr,release] +" + +# Change directories to the parent directory of the one in which this +# script is located. +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +function error() { + local exit_code="${?}" + echo "${@}" 1>&2 + return "${exit_code}" +} + +function fatal() { + error "${@}" || exit 1 +} + +function build_images() { + case "${BUILD_RELEASE_TYPE}" in + ci) + # A non-PR, non-release build. This is usually a build off of master + CSI_IMAGE_NAME=${CSI_IMAGE_CI} + ;; + pr) + # A PR build + CSI_IMAGE_NAME=${CSI_IMAGE_PR} + ;; + release) + # On an annotated tag + CSI_IMAGE_NAME=${CSI_IMAGE_RELEASE} + ;; + esac + + echo "building ${CSI_IMAGE_NAME}:${VERSION}" + docker build \ + -f cluster/images/csi/Dockerfile \ + -t "${CSI_IMAGE_NAME}":"${VERSION}" \ + . + if [ "${LATEST}" ]; then + echo "tagging image ${CSI_IMAGE_NAME}:${VERSION} as latest" + docker tag "${CSI_IMAGE_NAME}":"${VERSION}" "${CSI_IMAGE_NAME}":latest + fi +} + +function logout() { + if [ "${AUTH}" ]; then + gcloud auth revoke + fi +} + +function login() { + # If GCR_KEY_FILE is set, use that service account to login + if [ "${GCR_KEY_FILE}" ]; then + trap logout EXIT + gcloud auth activate-service-account --key-file "${GCR_KEY_FILE}" || fatal "unable to login" + AUTH=1 + fi +} + +function push_images() { + [ "${CSI_IMAGE_NAME}" ] || fatal "CSI_IMAGE_NAME not set" + + login + + echo "pushing ${CSI_IMAGE_NAME}:${VERSION}" + docker push "${CSI_IMAGE_NAME}":"${VERSION}" + if [ "${LATEST}" ]; then + echo "also pushing ${CSI_IMAGE_NAME}:${VERSION} as latest" + docker push "${CSI_IMAGE_NAME}":latest + fi +} + +# Start of main script +while getopts ":hk:lpt:" opt; do + case ${opt} in + h) + error "${USAGE}" && exit 1 + ;; + k) + GCR_KEY_FILE="${OPTARG}" + ;; + l) + LATEST=1 + ;; + p) + PUSH=1 + ;; + t) + BUILD_RELEASE_TYPE="${OPTARG}" + ;; + \?) + error "invalid option: -${OPTARG} ${USAGE}" && exit 1 + ;; + :) + error "option -${OPTARG} requires an argument" && exit 1 + ;; + esac +done +shift $((OPTIND-1)) + +# Verify the GCR_KEY_FILE exists if defined +if [ "${GCR_KEY_FILE}" ]; then + [ -e "${GCR_KEY_FILE}" ] || fatal "key file ${GCR_KEY_FILE} does not exist" +fi + +# Validate build/release type. +case "${BUILD_RELEASE_TYPE}" in + ci|pr|release) + # do nothing + ;; + *) + fatal "invalid BUILD_RELEASE_TYPE: ${BUILD_RELEASE_TYPE}" + ;; +esac + +# make sure that Docker is available +docker ps >/dev/null 2>&1 || fatal "Docker not available" + +# build container images +build_images + +# Optionally push artifacts +if [ "${PUSH}" ]; then + push_images +fi