Merge pull request #1634 from vmware-tanzu/jtc/1633/update-pinniped-cli-version-output
#1633 Update `pinniped version` output
This commit is contained in:
commit
9248db971a
@ -9,6 +9,9 @@ WORKDIR /work
|
|||||||
COPY . .
|
COPY . .
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
|
|
||||||
|
ARG KUBE_GIT_VERSION
|
||||||
|
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
|
||||||
|
|
||||||
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
# Build the executable binary (CGO_ENABLED=0 means static linking)
|
||||||
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
|
||||||
# can be re-used between image builds.
|
# can be re-used between image builds.
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/component-base/version"
|
"sigs.k8s.io/yaml"
|
||||||
|
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
@ -15,14 +18,44 @@ func init() {
|
|||||||
rootCmd.AddCommand(newVersionCommand())
|
rootCmd.AddCommand(newVersionCommand())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:gochecknoglobals
|
||||||
|
var (
|
||||||
|
output = new(string)
|
||||||
|
// getBuildInfo can be overwritten by tests.
|
||||||
|
getBuildInfo = pversion.Get
|
||||||
|
)
|
||||||
|
|
||||||
func newVersionCommand() *cobra.Command {
|
func newVersionCommand() *cobra.Command {
|
||||||
return &cobra.Command{
|
c := &cobra.Command{
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: runner,
|
||||||
fmt.Fprintf(cmd.OutOrStdout(), "%#v\n", version.Get())
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
Args: cobra.NoArgs, // do not accept positional arguments for this command
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print the version of this Pinniped CLI",
|
Short: "Print the version of this Pinniped CLI",
|
||||||
}
|
}
|
||||||
|
c.Flags().StringVarP(output, "output", "o", "", "one of 'yaml' or 'json'")
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func runner(cmd *cobra.Command, _ []string) error {
|
||||||
|
buildVersion := getBuildInfo()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case output == nil || *output == "":
|
||||||
|
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", buildVersion.GitVersion)
|
||||||
|
case *output == "json":
|
||||||
|
bytes, err := json.MarshalIndent(buildVersion, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s\n", bytes)
|
||||||
|
case *output == "yaml":
|
||||||
|
bytes, err := yaml.Marshal(buildVersion)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprint(cmd.OutOrStdout(), string(bytes))
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("'%s' is not a valid option for output", *output)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
@ -9,8 +9,10 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||||
|
|
||||||
"go.pinniped.dev/internal/here"
|
"go.pinniped.dev/internal/here"
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -19,8 +21,8 @@ var (
|
|||||||
version \[flags\]
|
version \[flags\]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for version
|
-h, --help help for version
|
||||||
|
-o, --output string one of 'yaml' or 'json'
|
||||||
`)
|
`)
|
||||||
|
|
||||||
knownGoodHelpRegexpForVersion = here.Doc(`
|
knownGoodHelpRegexpForVersion = here.Doc(`
|
||||||
@ -30,24 +32,55 @@ var (
|
|||||||
version \[flags\]
|
version \[flags\]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for version
|
-h, --help help for version
|
||||||
|
-o, --output string one of 'yaml' or 'json'
|
||||||
`)
|
`)
|
||||||
|
|
||||||
emptyVersionRegexp = `version.Info{Major:"", Minor:"", GitVersion:".*", GitCommit:".*", GitTreeState:"", BuildDate:".*", GoVersion:".*", Compiler:".*", Platform:".*/.*"}`
|
jsonRegexp = here.Doc(`{
|
||||||
|
"major": "\d*",
|
||||||
|
"minor": "\d*",
|
||||||
|
"gitVersion": "i am a version for json output",
|
||||||
|
"gitCommit": ".*",
|
||||||
|
"gitTreeState": ".*",
|
||||||
|
"buildDate": ".*",
|
||||||
|
"goVersion": ".*",
|
||||||
|
"compiler": ".*",
|
||||||
|
"platform": ".*/.*"
|
||||||
|
}`)
|
||||||
|
|
||||||
|
yamlRegexp = here.Doc(`buildDate: ".*"
|
||||||
|
compiler: .*
|
||||||
|
gitCommit: .*
|
||||||
|
gitTreeState: .*
|
||||||
|
gitVersion: i am a version for yaml output
|
||||||
|
goVersion: .*
|
||||||
|
major: "\d*"
|
||||||
|
minor: "\d*"
|
||||||
|
platform: .*/.*
|
||||||
|
`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewVersionCmd(t *testing.T) {
|
func TestNewVersionCmd(t *testing.T) {
|
||||||
|
t.Cleanup(func() {
|
||||||
|
getBuildInfo = pversion.Get
|
||||||
|
})
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
args []string
|
args []string
|
||||||
|
vars string
|
||||||
|
getBuildInfo func() apimachineryversion.Info
|
||||||
wantError bool
|
wantError bool
|
||||||
wantStdoutRegexp string
|
wantStdoutRegexp string
|
||||||
wantStderrRegexp string
|
wantStderrRegexp string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no flags",
|
name: "no flags",
|
||||||
args: []string{},
|
args: []string{},
|
||||||
wantStdoutRegexp: emptyVersionRegexp + "\n",
|
getBuildInfo: func() apimachineryversion.Info {
|
||||||
|
return apimachineryversion.Info{GitVersion: "v55.66.44"}
|
||||||
|
},
|
||||||
|
wantStdoutRegexp: "v55.66.44\n",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "help flag passed",
|
name: "help flag passed",
|
||||||
@ -61,10 +94,44 @@ func TestNewVersionCmd(t *testing.T) {
|
|||||||
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
|
||||||
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "json output",
|
||||||
|
args: []string{"--output", "json"},
|
||||||
|
getBuildInfo: func() apimachineryversion.Info {
|
||||||
|
return apimachineryversion.Info{
|
||||||
|
GitVersion: "i am a version for json output",
|
||||||
|
Platform: "a/b",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
wantStdoutRegexp: jsonRegexp,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "yaml output",
|
||||||
|
args: []string{"--output", "yaml"},
|
||||||
|
getBuildInfo: func() apimachineryversion.Info {
|
||||||
|
return apimachineryversion.Info{
|
||||||
|
GitVersion: "i am a version for yaml output",
|
||||||
|
Platform: "c/d",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
wantStdoutRegexp: yamlRegexp,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "incorrect output",
|
||||||
|
args: []string{"--output", "foo"},
|
||||||
|
wantError: true,
|
||||||
|
wantStderrRegexp: `Error: 'foo' is not a valid option for output`,
|
||||||
|
wantStdoutRegexp: knownGoodUsageRegexpForVersion,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if tt.getBuildInfo != nil {
|
||||||
|
getBuildInfo = tt.getBuildInfo
|
||||||
|
}
|
||||||
|
|
||||||
cmd := newVersionCommand()
|
cmd := newVersionCommand()
|
||||||
require.NotNil(t, cmd)
|
require.NotNil(t, cmd)
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -10,6 +10,7 @@ require (
|
|||||||
github.com/chromedp/cdproto v0.0.0-20230828023241-f357fd93b5d6
|
github.com/chromedp/cdproto v0.0.0-20230828023241-f357fd93b5d6
|
||||||
github.com/chromedp/chromedp v0.9.2
|
github.com/chromedp/chromedp v0.9.2
|
||||||
github.com/coreos/go-oidc/v3 v3.6.0
|
github.com/coreos/go-oidc/v3 v3.6.0
|
||||||
|
github.com/coreos/go-semver v0.3.1
|
||||||
github.com/creack/pty v1.1.18
|
github.com/creack/pty v1.1.18
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/felixge/httpsnoop v1.0.3
|
github.com/felixge/httpsnoop v1.0.3
|
||||||
@ -67,7 +68,6 @@ require (
|
|||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/chromedp/sysutil v1.0.0 // indirect
|
github.com/chromedp/sysutil v1.0.0 // indirect
|
||||||
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
|
||||||
github.com/coreos/go-semver v0.3.1 // indirect
|
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
|
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
# Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
|
echo "-X 'go.pinniped.dev/internal/pversion.gitVersion=$KUBE_GIT_VERSION'"
|
||||||
|
|
||||||
KUBE_ROOT="${ROOT}" # required by `hack/lib/version.sh`
|
|
||||||
source "${ROOT}/hack/lib/version.sh"
|
|
||||||
|
|
||||||
kube::version::ldflags
|
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Copyright 2014 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 has been changed from kube's default version.sh to expect KUBE_GIT_VERSION to be set
|
|
||||||
# by the caller. If it is set, it must be a semver version number, and it will be included
|
|
||||||
# in the result. If it is not set, then defaults indicating that the version is unknown will
|
|
||||||
# be included in the result.
|
|
||||||
#
|
|
||||||
# These changes are to allow the CI build steps to set the version number at build time
|
|
||||||
# without using the original behavior of this script, which was to look at previous git
|
|
||||||
# tags to guess the version number.
|
|
||||||
#
|
|
||||||
|
|
||||||
kube::version::get_version_vars() {
|
|
||||||
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
|
|
||||||
|
|
||||||
# If KUBE_GIT_VERSION is supplied
|
|
||||||
if [[ -n "${KUBE_GIT_VERSION:-""}" ]]; then
|
|
||||||
|
|
||||||
# If KUBE_GIT_VERSION is not a valid Semantic Version, then refuse to build.
|
|
||||||
if ! [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
|
|
||||||
echo "KUBE_GIT_VERSION should be a valid Semantic Version starting with a \"v\". Current value: ${KUBE_GIT_VERSION}"
|
|
||||||
echo "Please see more details here: https://semver.org"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${KUBE_GIT_VERSION}" =~ ^v([0-9]+)\.([0-9]+)(\.[0-9]+)?([-].*)?([+].*)?$ ]]; then
|
|
||||||
KUBE_GIT_MAJOR=${BASH_REMATCH[1]}
|
|
||||||
KUBE_GIT_MINOR=${BASH_REMATCH[2]}
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
# KUBE_GIT_VERSION was not supplied
|
|
||||||
# These values need to pass the validation in k8s.io/component-base/metrics:
|
|
||||||
# https://github.com/kubernetes/component-base/blob/v0.20.5/metrics/version_parser.go#L28-L50
|
|
||||||
KUBE_GIT_VERSION='v0.0.0'
|
|
||||||
KUBE_GIT_MAJOR='0'
|
|
||||||
KUBE_GIT_MINOR='0'
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# 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.
|
|
||||||
# IMPORTANT: if you update any of these, also update the lists in
|
|
||||||
# pkg/version/def.bzl and hack/print-workspace-status.sh.
|
|
||||||
kube::version::ldflags() {
|
|
||||||
kube::version::get_version_vars
|
|
||||||
|
|
||||||
local -a ldflags
|
|
||||||
function add_ldflag() {
|
|
||||||
local key=${1}
|
|
||||||
local val=${2}
|
|
||||||
# If you update these, also update the list component-base/version/def.bzl.
|
|
||||||
ldflags+=(
|
|
||||||
"-X 'k8s.io/client-go/pkg/version.${key}=${val}'"
|
|
||||||
"-X 'k8s.io/component-base/version.${key}=${val}'"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
add_ldflag "buildDate" "$(date ${SOURCE_DATE_EPOCH:+"--date=@${SOURCE_DATE_EPOCH}"} -u +'%Y-%m-%dT%H:%M:%SZ')"
|
|
||||||
if [[ -n ${KUBE_GIT_COMMIT-} ]]; then
|
|
||||||
add_ldflag "gitCommit" "${KUBE_GIT_COMMIT}"
|
|
||||||
add_ldflag "gitTreeState" "${KUBE_GIT_TREE_STATE}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n ${KUBE_GIT_VERSION-} ]]; then
|
|
||||||
add_ldflag "gitVersion" "${KUBE_GIT_VERSION}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n ${KUBE_GIT_MAJOR-} && -n ${KUBE_GIT_MINOR-} ]]; then
|
|
||||||
add_ldflag "gitMajor" "${KUBE_GIT_MAJOR}"
|
|
||||||
add_ldflag "gitMinor" "${KUBE_GIT_MINOR}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The -ldflags parameter takes a single string, so join the output.
|
|
||||||
echo "${ldflags[*]-}"
|
|
||||||
}
|
|
@ -206,12 +206,12 @@ registry_repo_tag="${registry_repo}:${tag}"
|
|||||||
if [[ "$do_build" == "yes" ]]; then
|
if [[ "$do_build" == "yes" ]]; then
|
||||||
# Rebuild the code
|
# Rebuild the code
|
||||||
if [[ "$dockerfile_path" != "" ]]; then
|
if [[ "$dockerfile_path" != "" ]]; then
|
||||||
log_note "Docker building the app with dockerfile $dockerfile_path..."
|
log_note "Docker building the app with dockerfile $dockerfile_path and KUBE_GIT_VERSION=$KUBE_GIT_VERSION"
|
||||||
DOCKER_BUILDKIT=1 docker build . --tag "$registry_repo_tag" --file "$dockerfile_path"
|
DOCKER_BUILDKIT=1 docker build . --tag "$registry_repo_tag" --file "$dockerfile_path" --build-arg "KUBE_GIT_VERSION=$KUBE_GIT_VERSION"
|
||||||
else
|
else
|
||||||
log_note "Docker building the app..."
|
log_note "Docker building the app with KUBE_GIT_VERSION=$KUBE_GIT_VERSION"
|
||||||
# DOCKER_BUILDKIT=1 is optional on MacOS but required on linux.
|
# DOCKER_BUILDKIT=1 is optional on MacOS but required on linux.
|
||||||
DOCKER_BUILDKIT=1 docker build . --tag "$registry_repo_tag"
|
DOCKER_BUILDKIT=1 docker build . --tag "$registry_repo_tag" --build-arg "KUBE_GIT_VERSION=$KUBE_GIT_VERSION"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2020-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package apiserver
|
package apiserver
|
||||||
@ -14,11 +14,11 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/errors"
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/client-go/pkg/version"
|
|
||||||
|
|
||||||
"go.pinniped.dev/internal/controllerinit"
|
"go.pinniped.dev/internal/controllerinit"
|
||||||
"go.pinniped.dev/internal/issuer"
|
"go.pinniped.dev/internal/issuer"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||||
"go.pinniped.dev/internal/registry/whoamirequest"
|
"go.pinniped.dev/internal/registry/whoamirequest"
|
||||||
)
|
)
|
||||||
@ -59,7 +59,7 @@ func (c *Config) Complete() CompletedConfig {
|
|||||||
&c.ExtraConfig,
|
&c.ExtraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
versionInfo := version.Get()
|
versionInfo := pversion.Get()
|
||||||
completedCfg.GenericConfig.Version = &versionInfo
|
completedCfg.GenericConfig.Version = &versionInfo
|
||||||
|
|
||||||
return CompletedConfig{completedConfig: &completedCfg}
|
return CompletedConfig{completedConfig: &completedCfg}
|
||||||
|
@ -19,7 +19,6 @@ import (
|
|||||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
"k8s.io/client-go/pkg/version"
|
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
|
||||||
conciergeopenapi "go.pinniped.dev/generated/latest/client/concierge/openapi"
|
conciergeopenapi "go.pinniped.dev/generated/latest/client/concierge/openapi"
|
||||||
@ -37,6 +36,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/issuer"
|
"go.pinniped.dev/internal/issuer"
|
||||||
"go.pinniped.dev/internal/kubeclient"
|
"go.pinniped.dev/internal/kubeclient"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -266,13 +266,13 @@ func main() error {
|
|||||||
|
|
||||||
// Dump out the time since compile (mostly useful for benchmarking our local development cycle latency).
|
// Dump out the time since compile (mostly useful for benchmarking our local development cycle latency).
|
||||||
var timeSinceCompile time.Duration
|
var timeSinceCompile time.Duration
|
||||||
if buildDate, err := time.Parse(time.RFC3339, version.Get().BuildDate); err == nil {
|
if buildDate, err := time.Parse(time.RFC3339, pversion.Get().BuildDate); err == nil {
|
||||||
timeSinceCompile = time.Since(buildDate).Round(time.Second)
|
timeSinceCompile = time.Since(buildDate).Round(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
plog.Always("Running concierge",
|
plog.Always("Running concierge",
|
||||||
"user-agent", rest.DefaultKubernetesUserAgent(),
|
"user-agent", rest.DefaultKubernetesUserAgent(),
|
||||||
"version", versionInfo(version.Get()),
|
"version", versionInfo(pversion.Get()),
|
||||||
"time-since-build", timeSinceCompile,
|
"time-since-build", timeSinceCompile,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
87
internal/pversion/version.go
Normal file
87
internal/pversion/version.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2023 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package pversion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/go-semver/semver"
|
||||||
|
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||||
|
k8sstrings "k8s.io/utils/strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// readBuildInfo is meant to be overwritten by tests.
|
||||||
|
//
|
||||||
|
//nolint:gochecknoglobals // these are swapped during unit tests.
|
||||||
|
var readBuildInfo = debug.ReadBuildInfo
|
||||||
|
|
||||||
|
// gitVersion is set using a linker flag
|
||||||
|
// -ldflags "-X 'go.pinniped.dev/internal/pversion.gitVersion=v9.8.7'"
|
||||||
|
// (or set for unit tests).
|
||||||
|
//
|
||||||
|
//nolint:gochecknoglobals // these are swapped during unit tests.
|
||||||
|
var gitVersion string
|
||||||
|
|
||||||
|
// Get returns the overall codebase version. It's for detecting
|
||||||
|
// what code a binary was built from.
|
||||||
|
//
|
||||||
|
// This function is very similar to the function defined in k8s.io/component-base (version/version.go)
|
||||||
|
// but is designed to work with golang's VCS build-time information.
|
||||||
|
//
|
||||||
|
// See:
|
||||||
|
// - https://github.com/kubernetes/component-base/blob/v0.28.0/version/version.go#L26-L42
|
||||||
|
// - https://tip.golang.org/doc/go1.18#go-version
|
||||||
|
func Get() apimachineryversion.Info {
|
||||||
|
info := apimachineryversion.Info{
|
||||||
|
Major: "0",
|
||||||
|
Minor: "0",
|
||||||
|
GitVersion: "v0.0.0",
|
||||||
|
GitTreeState: "dirty",
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
gitVersionWithoutLeadingV := gitVersion
|
||||||
|
if strings.HasPrefix(gitVersion, "v") {
|
||||||
|
gitVersionWithoutLeadingV, _ = strings.CutPrefix(gitVersion, "v")
|
||||||
|
}
|
||||||
|
|
||||||
|
gitVersionSemver, err := semver.NewVersion(gitVersionWithoutLeadingV)
|
||||||
|
if err == nil && gitVersionSemver != nil {
|
||||||
|
info.GitVersion = gitVersion
|
||||||
|
info.Major = fmt.Sprintf("%d", gitVersionSemver.Major)
|
||||||
|
info.Minor = fmt.Sprintf("%d", gitVersionSemver.Minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if debugBuildInfo, ok := readBuildInfo(); ok {
|
||||||
|
for _, buildSetting := range debugBuildInfo.Settings {
|
||||||
|
switch buildSetting.Key {
|
||||||
|
case "vcs.revision":
|
||||||
|
info.GitCommit = buildSetting.Value
|
||||||
|
case "vcs.time":
|
||||||
|
info.BuildDate = buildSetting.Value
|
||||||
|
case "vcs.modified":
|
||||||
|
if buildSetting.Value == "false" {
|
||||||
|
info.GitTreeState = "clean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureFakeDevVersion(&info)
|
||||||
|
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureFakeDevVersion(info *apimachineryversion.Info) {
|
||||||
|
if info != nil && info.GitVersion == "v0.0.0" && info.GitCommit != "" {
|
||||||
|
info.GitVersion += fmt.Sprintf("-%s-%s",
|
||||||
|
k8sstrings.ShortenString(info.GitCommit, 8),
|
||||||
|
info.GitTreeState)
|
||||||
|
}
|
||||||
|
}
|
127
internal/pversion/version_test.go
Normal file
127
internal/pversion/version_test.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// Copyright 2023 the Pinniped contributors. All Rights Reserved.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package pversion
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
originalGitVersion := gitVersion
|
||||||
|
t.Cleanup(func() {
|
||||||
|
gitVersion = originalGitVersion
|
||||||
|
readBuildInfo = debug.ReadBuildInfo
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when readBuildInfo() returns not ok", func(t *testing.T) {
|
||||||
|
gitVersion = ""
|
||||||
|
readBuildInfo = func() (info *debug.BuildInfo, ok bool) {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
info := apimachineryversion.Info{
|
||||||
|
Major: "0",
|
||||||
|
Minor: "0",
|
||||||
|
GitVersion: "v0.0.0",
|
||||||
|
GitTreeState: "dirty",
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
require.Equal(t, info, Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when readBuildInfo() returns ok", func(t *testing.T) {
|
||||||
|
gitVersion = "9.8.7"
|
||||||
|
readBuildInfo = func() (info *debug.BuildInfo, ok bool) {
|
||||||
|
buildInfo := debug.BuildInfo{
|
||||||
|
Settings: []debug.BuildSetting{
|
||||||
|
{Key: "vcs.revision", Value: "revision-value"},
|
||||||
|
{Key: "vcs.time", Value: "time-value"},
|
||||||
|
{Key: "vcs.modified", Value: "anything but 'true'"},
|
||||||
|
{Key: "other", Value: "ignored"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &buildInfo, true
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := apimachineryversion.Info{
|
||||||
|
Major: "9",
|
||||||
|
Minor: "8",
|
||||||
|
GitVersion: "9.8.7",
|
||||||
|
GitCommit: "revision-value",
|
||||||
|
GitTreeState: "dirty",
|
||||||
|
BuildDate: "time-value",
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, expected, Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when readBuildInfo() returns ok but gitVersion is not provided", func(t *testing.T) {
|
||||||
|
gitVersion = ""
|
||||||
|
readBuildInfo = func() (info *debug.BuildInfo, ok bool) {
|
||||||
|
buildInfo := debug.BuildInfo{
|
||||||
|
Settings: []debug.BuildSetting{
|
||||||
|
{Key: "vcs.revision", Value: "384850953501b7d66d466b4ca4d13a81bc54a7c3"},
|
||||||
|
{Key: "vcs.time", Value: "time-value"},
|
||||||
|
{Key: "vcs.modified", Value: "anything but 'true'"},
|
||||||
|
{Key: "other", Value: "ignored"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &buildInfo, true
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := apimachineryversion.Info{
|
||||||
|
Major: "0",
|
||||||
|
Minor: "0",
|
||||||
|
GitVersion: "v0.0.0-38485095-dirty",
|
||||||
|
GitCommit: "384850953501b7d66d466b4ca4d13a81bc54a7c3",
|
||||||
|
GitTreeState: "dirty",
|
||||||
|
BuildDate: "time-value",
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, expected, Get())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("when gitVersion is complex", func(t *testing.T) {
|
||||||
|
gitVersion = "v1.2.3-abc123"
|
||||||
|
readBuildInfo = func() (info *debug.BuildInfo, ok bool) {
|
||||||
|
buildInfo := debug.BuildInfo{
|
||||||
|
Settings: []debug.BuildSetting{
|
||||||
|
{Key: "vcs.revision", Value: "abc123"},
|
||||||
|
{Key: "vcs.time", Value: "time-value"},
|
||||||
|
{Key: "vcs.modified", Value: "false"},
|
||||||
|
{Key: "other", Value: "ignored"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return &buildInfo, true
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := apimachineryversion.Info{
|
||||||
|
Major: "1",
|
||||||
|
Minor: "2",
|
||||||
|
GitVersion: "v1.2.3-abc123",
|
||||||
|
GitCommit: "abc123",
|
||||||
|
GitTreeState: "clean",
|
||||||
|
BuildDate: "time-value",
|
||||||
|
GoVersion: runtime.Version(),
|
||||||
|
Compiler: runtime.Compiler,
|
||||||
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, expected, Get())
|
||||||
|
})
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 the Pinniped contributors. All Rights Reserved.
|
// Copyright 2022-2023 the Pinniped contributors. All Rights Reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package apiserver
|
package apiserver
|
||||||
@ -17,11 +17,11 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/pkg/version"
|
|
||||||
|
|
||||||
configv1alpha1clientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
configv1alpha1clientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/typed/config/v1alpha1"
|
||||||
"go.pinniped.dev/internal/controllerinit"
|
"go.pinniped.dev/internal/controllerinit"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
"go.pinniped.dev/internal/registry/clientsecretrequest"
|
"go.pinniped.dev/internal/registry/clientsecretrequest"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ func (c *Config) Complete() CompletedConfig {
|
|||||||
&c.ExtraConfig,
|
&c.ExtraConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
versionInfo := version.Get()
|
versionInfo := pversion.Get()
|
||||||
completedCfg.GenericConfig.Version = &versionInfo
|
completedCfg.GenericConfig.Version = &versionInfo
|
||||||
|
|
||||||
return CompletedConfig{completedConfig: &completedCfg}
|
return CompletedConfig{completedConfig: &completedCfg}
|
||||||
|
@ -33,7 +33,6 @@ import (
|
|||||||
kubeinformers "k8s.io/client-go/informers"
|
kubeinformers "k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/pkg/version"
|
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/utils/clock"
|
"k8s.io/utils/clock"
|
||||||
@ -66,6 +65,7 @@ import (
|
|||||||
"go.pinniped.dev/internal/oidc/provider"
|
"go.pinniped.dev/internal/oidc/provider"
|
||||||
"go.pinniped.dev/internal/oidc/provider/manager"
|
"go.pinniped.dev/internal/oidc/provider/manager"
|
||||||
"go.pinniped.dev/internal/plog"
|
"go.pinniped.dev/internal/plog"
|
||||||
|
"go.pinniped.dev/internal/pversion"
|
||||||
"go.pinniped.dev/internal/secret"
|
"go.pinniped.dev/internal/secret"
|
||||||
"go.pinniped.dev/internal/supervisor/apiserver"
|
"go.pinniped.dev/internal/supervisor/apiserver"
|
||||||
supervisorscheme "go.pinniped.dev/internal/supervisor/scheme"
|
supervisorscheme "go.pinniped.dev/internal/supervisor/scheme"
|
||||||
@ -681,7 +681,7 @@ func main() error { // return an error instead of plog.Fatal to allow defer stat
|
|||||||
|
|
||||||
plog.Always("Running supervisor",
|
plog.Always("Running supervisor",
|
||||||
"user-agent", rest.DefaultKubernetesUserAgent(),
|
"user-agent", rest.DefaultKubernetesUserAgent(),
|
||||||
"version", versionInfo(version.Get()),
|
"version", versionInfo(pversion.Get()),
|
||||||
"arguments", os.Args,
|
"arguments", os.Args,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user