diff --git a/README.md b/README.md index df235be..64a68ad 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,11 @@ A sample is built and hosted at `gcr.io/kubernetes1-226021/capd-manager:latest` Building Go binaries requires `go 1.12+` for go module support. -``` +```(bash) # required if `cluster-api-provider-docker` was cloned into $GOPATH export GO111MODULE=on -# build the binaries -go build ./cmd/capdctl -go build ./cmd/capd-manager -go build ./cmd/kind-test +# build the binaries into ${PWD}/bin +./script/build-binaries.sh ``` ### Building the image diff --git a/cmd/capd-manager/main.go b/cmd/capd-manager/main.go index f25c45d..b600ed7 100644 --- a/cmd/capd-manager/main.go +++ b/cmd/capd-manager/main.go @@ -25,6 +25,7 @@ import ( "k8s.io/klog" "k8s.io/klog/klogr" "sigs.k8s.io/cluster-api-provider-docker/actuators" + "sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo" "sigs.k8s.io/cluster-api/pkg/apis" "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset" @@ -101,6 +102,8 @@ func main() { } setupLogger.Info("starting the manager") + setupLogger.Info("Starting the controller") + setupLogger.Info(versioninfo.VersionInfo("capd-manager")) if err := mgr.Start(signals.SetupSignalHandler()); err != nil { setupLogger.Error(err, "failed to start the manager") diff --git a/cmd/capdctl/main.go b/cmd/capdctl/main.go index 1e2d7d2..81a2bd8 100644 --- a/cmd/capdctl/main.go +++ b/cmd/capdctl/main.go @@ -25,6 +25,7 @@ import ( "github.com/pkg/errors" "k8s.io/apimachinery/pkg/api/meta" + "sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo" "sigs.k8s.io/cluster-api-provider-docker/kind/controlplane" "sigs.k8s.io/cluster-api-provider-docker/objects" crclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -33,6 +34,7 @@ import ( const ( // Important to keep this consistent. controlPlaneSet = "controlplane" + capdctl = "capdctl" ) type machineOptions struct { @@ -63,7 +65,7 @@ func (mo *machineDeploymentOptions) initFlags(fs *flag.FlagSet) { func main() { setup := flag.NewFlagSet("setup", flag.ExitOnError) managementClusterName := setup.String("cluster-name", "management", "The name of the management cluster") - version := setup.String("capi-version", "v0.1.6", "The CRD versions to pull from CAPI. Does not support < v0.1.6.") + capiVersion := setup.String("capi-version", "v0.1.6", "The CRD versions to pull from CAPI. Does not support < v0.1.6.") capdImage := setup.String("capd-image", "gcr.io/kubernetes1-226021/capd-manager:latest", "The capd manager image to run") capiImage := setup.String("capi-image", "", "This is normally left blank and filled in automatically. But this will override the generated image name.") @@ -97,12 +99,12 @@ func main() { fmt.Printf("%+v\n", err) os.Exit(1) } - if err := makeManagementCluster(*managementClusterName, *version, *capdImage, *capiImage); err != nil { + if err := makeManagementCluster(*managementClusterName, *capiVersion, *capdImage, *capiImage); err != nil { fmt.Printf("%+v\n", err) os.Exit(1) } case "apply": - if err := applyControlPlane(*managementClusterName, *version, *capiImage, *capdImage); err != nil { + if err := applyControlPlane(*managementClusterName, *capiVersion, *capiImage, *capdImage); err != nil { fmt.Printf("%+v\n", err) os.Exit(1) } @@ -150,6 +152,8 @@ func main() { os.Exit(1) } fmt.Fprint(os.Stdout, md) + case "version": + fmt.Print(versioninfo.VersionInfo(capdctl)) case "help": fmt.Println(usage()) default: @@ -183,6 +187,9 @@ subcommands are: machine-deployment - Write a machine deployment object to stdout example: capdctl machine-deployment -name my-machine-deployment -cluster-name my-cluster -namespace my-namespace -kubelet-version v1.14.2 -replicas 1 | kubectl apply -f - + + version - Print version information for capdctl + example: capdctl version ` } diff --git a/cmd/kind-test/main.go b/cmd/kind-test/main.go index 4740153..407b8b6 100644 --- a/cmd/kind-test/main.go +++ b/cmd/kind-test/main.go @@ -22,6 +22,7 @@ import ( "os" "strings" + "sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo" "sigs.k8s.io/cluster-api-provider-docker/kind/actions" ) @@ -79,6 +80,8 @@ func main() { case "set-version": fmt.Println("setting version") version = inputs[1] + case "version": + fmt.Print(versioninfo.VersionInfo("kind-test")) default: fmt.Println("Unknown command") } diff --git a/cmd/versioninfo/versioninfo.go b/cmd/versioninfo/versioninfo.go new file mode 100644 index 0000000..adc3517 --- /dev/null +++ b/cmd/versioninfo/versioninfo.go @@ -0,0 +1,51 @@ +/* +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. +*/ + +package versioninfo + +import ( + "fmt" + "strings" +) + +var ( + // GitBranch is the branch from which this binary was built + GitBranch string + // GitReleaseTag is the git tag from which this binary is released + GitReleaseTag string + // GitReleaseCommit is the commit corresponding to the GitReleaseTag + GitReleaseCommit string + // GitTreeState indicates if the git tree, from which this binary was built, was clean or dirty + GitTreeState string + // GitCommit is the git commit at which this binary binary was built + GitCommit string + // GitMajor is the major version of the release + GitMajor string + // GitMinor is the minor version of the release + GitMinor string +) + +// VersionInfo returns version information for the supplied binary +func VersionInfo(binName string) string { + var vi strings.Builder + vi.WriteString(fmt.Sprintf("%s version info:\n", binName)) + vi.WriteString(fmt.Sprintf("GitReleaseTag: %q, Major: %q, Minor: %q, GitRelaseCommit: %q\n", GitReleaseTag, GitMajor, GitMinor, GitReleaseCommit)) + vi.WriteString(fmt.Sprintf("Git Branch: %q\n", GitBranch)) + vi.WriteString(fmt.Sprintf("Git commit: %q\n", GitCommit)) + vi.WriteString(fmt.Sprintf("Git tree state: %q\n", GitTreeState)) + + return vi.String() +} diff --git a/hack/set-workspace-status.sh b/hack/set-workspace-status.sh new file mode 100755 index 0000000..0264d15 --- /dev/null +++ b/hack/set-workspace-status.sh @@ -0,0 +1,80 @@ +#!/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 + +GIT_COMMIT="$(git describe --always --dirty --abbrev=14)" + +if git_status=$(git status --porcelain 2>/dev/null) && [[ -z ${git_status} ]]; then + GIT_TREE_STATE="clean" +else + GIT_TREE_STATE="dirty" +fi + +# mostly stolen from k8s.io/hack/lib/version.sh +# Use git describe to find the version based on tags. +if GIT_VERSION=$(git describe --tags --abbrev=14 2>/dev/null); then + # This translates the "git describe" to an actual semver.org + # compatible semantic version that looks something like this: + # v1.1.0-alpha.0.6+84c76d1142ea4d + # + # TODO: We continue calling this "git version" because so many + # downstream consumers are expecting it there. + DASHES_IN_VERSION=$(echo "${GIT_VERSION}" | sed "s/[^-]//g") + if [[ "${DASHES_IN_VERSION}" == "---" ]] ; then + # We have distance to subversion (v1.1.0-subversion-1-gCommitHash) + GIT_VERSION=$(echo "${GIT_VERSION}" | sed "s/-\([0-9]\{1,\}\)-g\([0-9a-f]\{14\}\)$/.\1\-\2/") + elif [[ "${DASHES_IN_VERSION}" == "--" ]] ; then + # We have distance to base tag (v1.1.0-1-gCommitHash) + GIT_VERSION=$(echo "${GIT_VERSION}" | sed "s/-g\([0-9a-f]\{14\}\)$/-\1/") + fi + if [[ "${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. + 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 [[ "${GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then + GIT_MAJOR=${BASH_REMATCH[1]} + GIT_MINOR=${BASH_REMATCH[2]} + fi + + # If GIT_VERSION is not a valid Semantic Version, then refuse to build. + if ! [[ "${GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then + GIT_VERSION=v0.0.0+${GIT_VERSION} + GIT_MAJOR=0 + GIT_MINOR=0 + fi +else + GIT_VERSION="UNKNOWN_GIT_VERSION" + GIT_MAJOR="UNKNOWN_GIT_MAJOR_VERSION" + GIT_MINOR="UNKNOWN_GIT_MINOR_VERSION" +fi + +if GIT_RELEASE_TAG=$(git describe --abbrev=0 --tags 2> /dev/null); then + GIT_RELEASE_COMMIT=$(git rev-list -n 1 ${GIT_RELEASE_TAG} | head -c 14) +else + GIT_RELEASE_TAG="UNKNOWN_RELEASE" + GIT_RELEASE_COMMIT="UNKNOWN_RELEAE_COMMIT" +fi + +GIT_BRANCH=$(git branch | grep \* | cut -d ' ' -f2) diff --git a/scripts/build-binaries.sh b/scripts/build-binaries.sh new file mode 100755 index 0000000..7fc4792 --- /dev/null +++ b/scripts/build-binaries.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env 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 xtrace + +# shellcheck source=/dev/null +source "$(dirname "$0")/../hack/utils.sh" +readonly REPO_PATH=$(get_root_path) +readonly CAPDCTL_BIN=${REPO_PATH}/bin/capdctl +readonly CAPDCTL_SRC=${REPO_PATH}/cmd/capdctl + +readonly CAPDMGR_BIN=${REPO_PATH}/bin/capd-manager +readonly CAPDMGR_SRC=${REPO_PATH}/cmd/capd-manager + +readonly KIND_TEST_BIN=${REPO_PATH}/bin/kind-test +readonly KIND_TEST_SRC=${REPO_PATH}/cmd/kind-test + +source "${REPO_PATH}/hack/set-workspace-status.sh" + +LDFLAGS="-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitBranch=${GIT_BRANCH} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitReleaseTag=${GIT_RELEASE_TAG} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitReleaseCommit=${GIT_RELEASE_COMMIT} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitTreeState=${GIT_TREE_STATE} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitCommit=${GIT_COMMIT} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitMajor=${GIT_MAJOR} \ +-X sigs.k8s.io/cluster-api-provider-docker/cmd/versioninfo.GitMinor=${GIT_MINOR}" + +# build capdctl +go build -ldflags "${LDFLAGS}" -o ${CAPDCTL_BIN} ${CAPDCTL_SRC} +# build capd-manager +go build -ldflags "${LDFLAGS}" -o ${CAPDMGR_BIN} ${CAPDMGR_SRC} +# build kind-test +go build -ldflags "${LDFLAGS}" -o ${KIND_TEST_BIN} ${KIND_TEST_SRC}