Use pversion to retrieve buildtime information

This commit is contained in:
Joshua Casey 2023-08-28 11:54:27 -05:00
parent 8edecffcc0
commit 38230fc518
13 changed files with 346 additions and 140 deletions

View File

@ -9,6 +9,9 @@ WORKDIR /work
COPY . .
ARG GOPROXY
ARG KUBE_GIT_VERSION
ENV KUBE_GIT_VERSION=$KUBE_GIT_VERSION
# Build the executable binary (CGO_ENABLED=0 means static linking)
# Pass in GOCACHE (build cache) and GOMODCACHE (module cache) so they
# can be re-used between image builds.

View File

@ -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
package cmd
import (
"encoding/json"
"fmt"
"github.com/spf13/cobra"
"k8s.io/component-base/version"
"sigs.k8s.io/yaml"
"go.pinniped.dev/internal/pversion"
)
//nolint:gochecknoinits
@ -15,14 +18,44 @@ func init() {
rootCmd.AddCommand(newVersionCommand())
}
//nolint:gochecknoglobals
var (
output = new(string)
// getBuildInfo can be overwritten by tests.
getBuildInfo = pversion.Get
)
func newVersionCommand() *cobra.Command {
return &cobra.Command{
RunE: func(cmd *cobra.Command, _ []string) error {
fmt.Fprintf(cmd.OutOrStdout(), "%#v\n", version.Get())
return nil
},
c := &cobra.Command{
RunE: runner,
Args: cobra.NoArgs, // do not accept positional arguments for this command
Use: "version",
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
}

View File

@ -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
package cmd
@ -9,8 +9,10 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
apimachineryversion "k8s.io/apimachinery/pkg/version"
"go.pinniped.dev/internal/here"
"go.pinniped.dev/internal/pversion"
)
var (
@ -19,8 +21,8 @@ var (
version \[flags\]
Flags:
-h, --help help for version
-h, --help help for version
-o, --output string one of 'yaml' or 'json'
`)
knownGoodHelpRegexpForVersion = here.Doc(`
@ -30,24 +32,55 @@ var (
version \[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) {
t.Cleanup(func() {
getBuildInfo = pversion.Get
})
tests := []struct {
name string
args []string
vars string
getBuildInfo func() apimachineryversion.Info
wantError bool
wantStdoutRegexp string
wantStderrRegexp string
}{
{
name: "no flags",
args: []string{},
wantStdoutRegexp: emptyVersionRegexp + "\n",
name: "no flags",
args: []string{},
getBuildInfo: func() apimachineryversion.Info {
return apimachineryversion.Info{GitVersion: "v55.66.44"}
},
wantStdoutRegexp: "v55.66.44\n",
},
{
name: "help flag passed",
@ -61,10 +94,44 @@ func TestNewVersionCmd(t *testing.T) {
wantStderrRegexp: `Error: unknown command "tuna" for "version"`,
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 {
tt := tt
t.Run(tt.name, func(t *testing.T) {
if tt.getBuildInfo != nil {
getBuildInfo = tt.getBuildInfo
}
cmd := newVersionCommand()
require.NotNil(t, cmd)

2
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/chromedp/cdproto v0.0.0-20230828023241-f357fd93b5d6
github.com/chromedp/chromedp v0.9.2
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/davecgh/go-spew v1.1.1
github.com/felixge/httpsnoop v1.0.3
@ -67,7 +68,6 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chromedp/sysutil v1.0.0 // 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/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cristalhq/jwt/v4 v4.0.2 // indirect

View File

@ -1,13 +1,8 @@
#!/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
set -euo pipefail
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
KUBE_ROOT="${ROOT}" # required by `hack/lib/version.sh`
source "${ROOT}/hack/lib/version.sh"
kube::version::ldflags
echo "-X 'go.pinniped.dev/internal/pversion.gitVersion=$KUBE_GIT_VERSION'"

View File

@ -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[*]-}"
}

View File

@ -206,12 +206,12 @@ registry_repo_tag="${registry_repo}:${tag}"
if [[ "$do_build" == "yes" ]]; then
# Rebuild the code
if [[ "$dockerfile_path" != "" ]]; then
log_note "Docker building the app with dockerfile $dockerfile_path..."
DOCKER_BUILDKIT=1 docker build . --tag "$registry_repo_tag" --file "$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" --build-arg "KUBE_GIT_VERSION=$KUBE_GIT_VERSION"
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 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

View File

@ -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
package apiserver
@ -14,11 +14,11 @@ import (
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/pkg/version"
"go.pinniped.dev/internal/controllerinit"
"go.pinniped.dev/internal/issuer"
"go.pinniped.dev/internal/plog"
"go.pinniped.dev/internal/pversion"
"go.pinniped.dev/internal/registry/credentialrequest"
"go.pinniped.dev/internal/registry/whoamirequest"
)
@ -59,7 +59,7 @@ func (c *Config) Complete() CompletedConfig {
&c.ExtraConfig,
}
versionInfo := version.Get()
versionInfo := pversion.Get()
completedCfg.GenericConfig.Version = &versionInfo
return CompletedConfig{completedConfig: &completedCfg}

View File

@ -19,7 +19,6 @@ import (
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/client-go/pkg/version"
"k8s.io/client-go/rest"
conciergeopenapi "go.pinniped.dev/generated/latest/client/concierge/openapi"
@ -37,6 +36,7 @@ import (
"go.pinniped.dev/internal/issuer"
"go.pinniped.dev/internal/kubeclient"
"go.pinniped.dev/internal/plog"
"go.pinniped.dev/internal/pversion"
"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).
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)
}
plog.Always("Running concierge",
"user-agent", rest.DefaultKubernetesUserAgent(),
"version", versionInfo(version.Get()),
"version", versionInfo(pversion.Get()),
"time-since-build", timeSinceCompile,
)

View File

@ -0,0 +1,83 @@
// 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"
}
}
}
}
if info.GitVersion == "v0.0.0" && info.GitCommit != "" {
info.GitVersion += fmt.Sprintf("-%s-%s",
k8sstrings.ShortenString(info.GitCommit, 8),
info.GitTreeState)
}
return info
}

View 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())
})
}

View File

@ -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
package apiserver
@ -17,11 +17,11 @@ import (
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
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"
"go.pinniped.dev/internal/controllerinit"
"go.pinniped.dev/internal/plog"
"go.pinniped.dev/internal/pversion"
"go.pinniped.dev/internal/registry/clientsecretrequest"
)
@ -61,7 +61,7 @@ func (c *Config) Complete() CompletedConfig {
&c.ExtraConfig,
}
versionInfo := version.Get()
versionInfo := pversion.Get()
completedCfg.GenericConfig.Version = &versionInfo
return CompletedConfig{completedConfig: &completedCfg}

View File

@ -33,7 +33,6 @@ import (
kubeinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/pkg/version"
"k8s.io/client-go/rest"
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
"k8s.io/utils/clock"
@ -66,6 +65,7 @@ import (
"go.pinniped.dev/internal/oidc/provider"
"go.pinniped.dev/internal/oidc/provider/manager"
"go.pinniped.dev/internal/plog"
"go.pinniped.dev/internal/pversion"
"go.pinniped.dev/internal/secret"
"go.pinniped.dev/internal/supervisor/apiserver"
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",
"user-agent", rest.DefaultKubernetesUserAgent(),
"version", versionInfo(version.Get()),
"version", versionInfo(pversion.Get()),
"arguments", os.Args,
)