Skip to content

Commit

Permalink
feat: introduce support for Kubernetes version compatibility checks
Browse files Browse the repository at this point in the history
This allows to enable/disable features based on Kubernetes version.

Signed-off-by: Andrey Smirnov <[email protected]>
  • Loading branch information
smira committed Sep 21, 2023
1 parent cf2754e commit ae33a4a
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 2 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ module github.com/siderolabs/go-kubernetes
go 1.21.1

require (
github.com/blang/semver/v4 v4.0.0
github.com/cosi-project/runtime v0.3.9
github.com/google/go-containerregistry v0.16.1
github.com/hashicorp/go-version v1.6.0
github.com/hexops/gotextdiff v1.0.3
github.com/siderolabs/gen v0.4.7
Expand Down Expand Up @@ -46,6 +48,7 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
10 changes: 8 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ github.com/ProtonMail/gopenpgp/v2 v2.7.3 h1:AJu1OI/1UWVYZl6QcCLKGu9OTngS2r52618u
github.com/ProtonMail/gopenpgp/v2 v2.7.3/go.mod h1:IhkNEDaxec6NyzSI0PlxapinnwPVIESk8/76da3Ct3g=
github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls=
github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/brianvoe/gofakeit/v6 v6.17.0 h1:obbQTJeHfktJtiZzq0Q1bEpsNUs+yHrYlPVWt7BtmJ4=
github.com/brianvoe/gofakeit/v6 v6.17.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
Expand Down Expand Up @@ -70,6 +72,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down Expand Up @@ -139,6 +143,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
Expand Down Expand Up @@ -278,8 +284,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
56 changes: 56 additions & 0 deletions kubernetes/compatibility/compatibility.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package compatibility provides some a way to enable/disable features based on Kubernetes version.
package compatibility

import (
"strings"

"github.com/blang/semver/v4"
"github.com/google/go-containerregistry/pkg/name"
)

// Version is the Kubernetes version to have running.
type Version semver.Version

// String returns the string representation of the version.
func (v Version) String() string {
return semver.Version(v).String()
}

// latest is used if the version can't be parsed.
var latest = Version{
Major: 1,
Minor: 99,
}

// VersionFromImageRef parses container image ref to return just Kubernetes version.
//
// If the version can't be parsed, assume latest version.
func VersionFromImageRef(imageRef string) Version {
// try to parse as tagged
ref, err := name.NewTag(imageRef)
if err != nil {
// try to cut digest part
var ok bool

imageRef, _, ok = strings.Cut(imageRef, "@")

if ok {
ref, err = name.NewTag(imageRef)
}

if err != nil {
return latest
}
}

v, err := semver.ParseTolerant(ref.TagStr())
if err != nil {
return latest
}

return Version(v)
}
64 changes: 64 additions & 0 deletions kubernetes/compatibility/compatibility_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package compatibility_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/siderolabs/go-kubernetes/kubernetes/compatibility"
)

func TestVersionFromImageRef(t *testing.T) {
for _, test := range []struct {
name string
imageRef string

expectedVersion compatibility.Version
}{
{
name: "just tag",
imageRef: "k8s.gcr.io/kube-apiserver:v1.18.0",

expectedVersion: compatibility.Version{Major: 1, Minor: 18},
},
{
name: "just tag 2",
imageRef: "ghcr.io/siderolabs/kubelet:v1.27.9",

expectedVersion: compatibility.Version{Major: 1, Minor: 27, Patch: 9},
},
{
name: "tag and digest",
imageRef: "ghcr.io/siderolabs/kubelet:v1.27.9@sha256:3f226f5b385960e311f19d6c9c3ea1778e86e6ad2e98a7bbbf1b1a63fe963916",

expectedVersion: compatibility.Version{Major: 1, Minor: 27, Patch: 9},
},
{
name: "only digest",
imageRef: "ghcr.io/siderolabs/kubelet@sha256:3f226f5b385960e311f19d6c9c3ea1778e86e6ad2e98a7bbbf1b1a63fe963916",

expectedVersion: compatibility.Version{Major: 1, Minor: 99},
},
{
name: "no tag or digest",
imageRef: "ghcr.io/siderolabs/kubelet",

expectedVersion: compatibility.Version{Major: 1, Minor: 99},
},
{
name: "invalid version",
imageRef: "ghcr.io/siderolabs/kubelet:alpha",

expectedVersion: compatibility.Version{Major: 1, Minor: 99},
},
} {
t.Run(test.name, func(t *testing.T) {
actualVersion := compatibility.VersionFromImageRef(test.imageRef)
assert.Equal(t, test.expectedVersion, actualVersion)
})
}
}
19 changes: 19 additions & 0 deletions kubernetes/compatibility/features.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package compatibility

import "github.com/blang/semver/v4"

// SupportsKubeletConfigContainerRuntimeEndpoint returns true if kubelet supports ContainerRuntimEndpoint in kubelet config.
func (v Version) SupportsKubeletConfigContainerRuntimeEndpoint() bool {
// see https://github.com/kubernetes/kubernetes/pull/112136
return semver.Version(v).GTE(semver.Version{Major: 1, Minor: 27})
}

// FeatureFlagSeccompDefaultEnabledByDefault returns true if a SeccompDefault feature flag is enabled by default.
func (v Version) FeatureFlagSeccompDefaultEnabledByDefault() bool {
// see https://github.com/kubernetes/kubernetes/pull/110805
return semver.Version(v).GTE(semver.Version{Major: 1, Minor: 25})
}
56 changes: 56 additions & 0 deletions kubernetes/compatibility/features_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package compatibility_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/siderolabs/go-kubernetes/kubernetes/compatibility"
)

func TestFeatures(t *testing.T) {
for _, test := range []struct {
versions []compatibility.Version

expectedSupportsKubeletConfigContainerRuntimeEndpoint bool
expectedFeatureFlagSeccompDefaultEnabledByDefault bool
}{
{
versions: []compatibility.Version{
{Major: 1, Minor: 24},
},

expectedSupportsKubeletConfigContainerRuntimeEndpoint: false,
expectedFeatureFlagSeccompDefaultEnabledByDefault: false,
},
{
versions: []compatibility.Version{
{Major: 1, Minor: 25},
{Major: 1, Minor: 26},
},
expectedSupportsKubeletConfigContainerRuntimeEndpoint: false,
expectedFeatureFlagSeccompDefaultEnabledByDefault: true,
},
{
versions: []compatibility.Version{
{Major: 1, Minor: 27},
{Major: 1, Minor: 28},
{Major: 1, Minor: 29},
{Major: 1, Minor: 99},
},
expectedSupportsKubeletConfigContainerRuntimeEndpoint: true,
expectedFeatureFlagSeccompDefaultEnabledByDefault: true,
},
} {
for _, version := range test.versions {
t.Run(version.String(), func(t *testing.T) {
assert.Equal(t, test.expectedSupportsKubeletConfigContainerRuntimeEndpoint, version.SupportsKubeletConfigContainerRuntimeEndpoint())
assert.Equal(t, test.expectedFeatureFlagSeccompDefaultEnabledByDefault, version.FeatureFlagSeccompDefaultEnabledByDefault())
})
}
}
}

0 comments on commit ae33a4a

Please sign in to comment.