metropolis: replace version stamp with product info
This removes the stamped metropolis version library and the associated
stampgo infrastructure, and replaces it with the product info file.
The info is now stored in a separate file in the rootfs, instead of
embedded in the core binary. This has the benefit that the core binary
no longer needs to be relinked when stamping info changes.
The version logging in core/main, and the tconsole are updated to show
some of the additional info from the product info.
Change-Id: Ic5ed0e3598e8da71b96748e8d7abfedff41acd3f
Reviewed-on: https://review.monogon.dev/c/monogon/+/4207
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/metropolis/node/kubernetes/reconciler/BUILD.bazel b/metropolis/node/kubernetes/reconciler/BUILD.bazel
index 3e66db3..caac358 100644
--- a/metropolis/node/kubernetes/reconciler/BUILD.bazel
+++ b/metropolis/node/kubernetes/reconciler/BUILD.bazel
@@ -16,7 +16,7 @@
"//metropolis/node/core/consensus/client",
"//metropolis/node/core/curator",
"//metropolis/node/core/curator/proto/private",
- "//metropolis/version",
+ "//metropolis/node/core/productinfo",
"//osbase/event/etcd",
"//osbase/event/memory",
"//osbase/supervisor",
@@ -46,13 +46,19 @@
"reconciler_status_test.go",
"reconciler_test.go",
],
+ data = [
+ "//metropolis/node:product_info",
+ ],
embed = [":reconciler"],
+ x_defs = {
+ "source.monogon.dev/metropolis/node/core/productinfo.path": "$(rlocationpath //metropolis/node:product_info )",
+ },
deps = [
"//metropolis/node/core/consensus/client",
"//metropolis/node/core/curator",
"//metropolis/node/core/curator/proto/private",
+ "//metropolis/node/core/productinfo",
"//metropolis/proto/common",
- "//metropolis/version",
"//osbase/supervisor",
"//version",
"//version/spec",
diff --git a/metropolis/node/kubernetes/reconciler/reconciler_status.go b/metropolis/node/kubernetes/reconciler/reconciler_status.go
index b516207..914e4c2 100644
--- a/metropolis/node/kubernetes/reconciler/reconciler_status.go
+++ b/metropolis/node/kubernetes/reconciler/reconciler_status.go
@@ -19,7 +19,7 @@
"source.monogon.dev/metropolis/node/core/consensus/client"
"source.monogon.dev/metropolis/node/core/curator"
ppb "source.monogon.dev/metropolis/node/core/curator/proto/private"
- mversion "source.monogon.dev/metropolis/version"
+ "source.monogon.dev/metropolis/node/core/productinfo"
"source.monogon.dev/osbase/event/etcd"
"source.monogon.dev/osbase/event/memory"
"source.monogon.dev/osbase/supervisor"
@@ -69,8 +69,8 @@
// WaitReady watches the reconciler status and returns once initial
// reconciliation is done and the reconciled state is compatible.
-func WaitReady(ctx context.Context, etcdClient client.Namespaced) error {
- value := etcd.NewValue(etcdClient, statusKey, func(_, data []byte) (*ppb.KubernetesReconcilerStatus, error) {
+func (s *Service) WaitReady(ctx context.Context) error {
+ value := etcd.NewValue(s.Etcd, statusKey, func(_, data []byte) (*ppb.KubernetesReconcilerStatus, error) {
status := &ppb.KubernetesReconcilerStatus{}
if err := proto.Unmarshal(data, status); err != nil {
return nil, fmt.Errorf("could not unmarshal: %w", err)
@@ -98,11 +98,11 @@
state,
version.Semver(status.Version),
version.Release(status.MinimumCompatibleRelease),
- version.Semver(mversion.Version),
+ version.Semver(productinfo.Get().Version),
version.Release(minReconcilerRelease),
)
- if version.ReleaseLessThan(mversion.Version.Release, status.MinimumCompatibleRelease) {
+ if version.ReleaseLessThan(productinfo.Get().Version.Release, status.MinimumCompatibleRelease) {
supervisor.Logger(ctx).Info("Not ready, because the local node release is below the reconciler minimum compatible release. Waiting for status change.")
continue
}
@@ -218,8 +218,8 @@
}
publish := func() {
- minRelease := mversion.Version.Release
- maxRelease := mversion.Version.Release
+ minRelease := productinfo.Get().Version.Release
+ maxRelease := productinfo.Get().Version.Release
for _, release := range releaseStruct {
if version.ReleaseLessThan(release, minRelease) {
minRelease = release
@@ -275,7 +275,7 @@
return err
}
- shouldRun := !version.ReleaseLessThan(mversion.Version.Release, r.maxRelease)
+ shouldRun := !version.ReleaseLessThan(productinfo.Get().Version.Release, r.maxRelease)
if shouldRun {
supervisor.Logger(ctx).Info("This Kubernetes controller node has the latest release, starting election.")
err := supervisor.Run(ctx, "elect", s.elect)
@@ -293,7 +293,7 @@
if err != nil {
return err
}
- shouldRunNow := !version.ReleaseLessThan(mversion.Version.Release, r.maxRelease)
+ shouldRunNow := !version.ReleaseLessThan(productinfo.Get().Version.Release, r.maxRelease)
if shouldRunNow != shouldRun {
return errors.New("latest release changed, restarting")
}
@@ -360,7 +360,7 @@
doneStatus := &ppb.KubernetesReconcilerStatus{
State: ppb.KubernetesReconcilerStatus_STATE_DONE,
- Version: mversion.Version,
+ Version: productinfo.Get().Version,
MinimumCompatibleRelease: minApiserverRelease,
}
doneStatusBytes, err := proto.Marshal(doneStatus)
@@ -374,7 +374,7 @@
} else if proto.Equal(status, doneStatus) {
// The status is already what we would set, so leave it as is.
log.Info("Status is already up to date.")
- } else if !version.ReleaseLessThan(mversion.Version.Release, status.Version.Release) &&
+ } else if !version.ReleaseLessThan(productinfo.Get().Version.Release, status.Version.Release) &&
!version.ReleaseLessThan(status.MinimumCompatibleRelease, minApiserverRelease) {
// The status does not allow apiservers to start serving which would be
// incompatible after we reconcile. So just set the state to working.
@@ -408,8 +408,8 @@
log.Info("Status allows incompatible releases, need to restrict.")
status.State = ppb.KubernetesReconcilerStatus_STATE_WORKING
- if !version.ReleaseLessThan(status.Version.Release, mversion.Version.Release) {
- status.Version = mversion.Version
+ if !version.ReleaseLessThan(status.Version.Release, productinfo.Get().Version.Release) {
+ status.Version = productinfo.Get().Version
}
if version.ReleaseLessThan(status.MinimumCompatibleRelease, minApiserverRelease) {
status.MinimumCompatibleRelease = minApiserverRelease
@@ -428,7 +428,7 @@
if err != nil {
return err
}
- if version.ReleaseLessThan(mversion.Version.Release, releases.maxRelease) {
+ if version.ReleaseLessThan(productinfo.Get().Version.Release, releases.maxRelease) {
// We will likely get canceled soon by watchReleases restarting, unless
// this is a very short transient that is not noticed by watchReleases.
continue
diff --git a/metropolis/node/kubernetes/reconciler/reconciler_status_test.go b/metropolis/node/kubernetes/reconciler/reconciler_status_test.go
index f9d839f..1f17e69 100644
--- a/metropolis/node/kubernetes/reconciler/reconciler_status_test.go
+++ b/metropolis/node/kubernetes/reconciler/reconciler_status_test.go
@@ -15,26 +15,28 @@
"source.monogon.dev/metropolis/node/core/consensus/client"
"source.monogon.dev/metropolis/node/core/curator"
ppb "source.monogon.dev/metropolis/node/core/curator/proto/private"
+ "source.monogon.dev/metropolis/node/core/productinfo"
cpb "source.monogon.dev/metropolis/proto/common"
- mversion "source.monogon.dev/metropolis/version"
"source.monogon.dev/osbase/supervisor"
"source.monogon.dev/version"
vpb "source.monogon.dev/version/spec"
)
+var productInfo = productinfo.Get()
+
// TestMinimumReleasesNotAboveMetropolisRelease tests that minimum releases
// are not above the metropolis release itself, because that would cause
// things to get stuck.
func TestMinimumReleasesNotAboveMetropolisRelease(t *testing.T) {
- if version.ReleaseLessThan(mversion.Version.Release, minReconcilerRelease) {
+ if version.ReleaseLessThan(productInfo.Version.Release, minReconcilerRelease) {
t.Errorf("Metropolis release %s is below the minimum reconciler release %s",
- version.Semver(mversion.Version),
+ version.Semver(productInfo.Version),
version.Release(minReconcilerRelease),
)
}
- if version.ReleaseLessThan(mversion.Version.Release, minApiserverRelease) {
+ if version.ReleaseLessThan(productInfo.Version.Release, minApiserverRelease) {
t.Errorf("Metropolis release %s is below the minimum apiserver release %s",
- version.Semver(mversion.Version),
+ version.Semver(productInfo.Version),
version.Release(minApiserverRelease),
)
}
@@ -115,10 +117,13 @@
// will time out if WaitReady fails to return when it is supposed to.
func TestWaitReady(t *testing.T) {
cl := startEtcd(t)
+ s := Service{
+ Etcd: cl,
+ }
isReady := make(chan struct{})
supervisor.TestHarness(t, func(ctx context.Context) error {
- err := WaitReady(ctx, cl)
+ err := s.WaitReady(ctx)
if err != nil {
t.Error(err)
}
@@ -163,7 +168,7 @@
Version: &vpb.Version{
Release: &vpb.Version_Release{Major: 10000, Minor: 0, Patch: 0},
},
- MinimumCompatibleRelease: mversion.Version.Release,
+ MinimumCompatibleRelease: productInfo.Version.Release,
})
<-isReady
@@ -263,7 +268,7 @@
waitForActions := func() {
isReady := make(chan struct{})
supervisor.TestHarness(t, func(ctx context.Context) error {
- err := WaitReady(ctx, cl)
+ err := s.WaitReady(ctx)
if err != nil {
t.Error(err)
}