mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-02-25 09:11:24 -05:00
init
This commit is contained in:
parent
4492f77516
commit
bfa11a345c
@ -13,14 +13,13 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix"
|
"github.com/edgelesssys/constellation/v2/cli/internal/cmd/pathprefix"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/mod/semver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func newConfigGenerateCmd() *cobra.Command {
|
func newConfigGenerateCmd() *cobra.Command {
|
||||||
@ -35,7 +34,7 @@ func newConfigGenerateCmd() *cobra.Command {
|
|||||||
ValidArgsFunction: generateCompletion,
|
ValidArgsFunction: generateCompletion,
|
||||||
RunE: runConfigGenerate,
|
RunE: runConfigGenerate,
|
||||||
}
|
}
|
||||||
cmd.Flags().StringP("kubernetes", "k", semver.MajorMinor(config.Default().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR")
|
cmd.Flags().StringP("kubernetes", "k", string(config.Default().KubernetesVersion), "Kubernetes version to use in format MAJOR.MINOR")
|
||||||
cmd.Flags().StringP("attestation", "a", "", fmt.Sprintf("attestation variant to use %s. If not specified, the default for the cloud provider is used", printFormattedSlice(variant.GetAvailableAttestationVariants())))
|
cmd.Flags().StringP("attestation", "a", "", fmt.Sprintf("attestation variant to use %s. If not specified, the default for the cloud provider is used", printFormattedSlice(variant.GetAvailableAttestationVariants())))
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
@ -43,7 +42,7 @@ func newConfigGenerateCmd() *cobra.Command {
|
|||||||
|
|
||||||
type generateFlags struct {
|
type generateFlags struct {
|
||||||
pf pathprefix.PathPrefixer
|
pf pathprefix.PathPrefixer
|
||||||
k8sVersion string
|
k8sVersion versions.ValidK8sVersion
|
||||||
attestationVariant variant.Variant
|
attestationVariant variant.Variant
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,19 +123,6 @@ func createConfig(provider cloudprovider.Provider) *config.Config {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// supportedVersions prints the supported version without v prefix and without patch version.
|
|
||||||
// Should only be used when accepting Kubernetes versions from --kubernetes.
|
|
||||||
func supportedVersions() string {
|
|
||||||
builder := strings.Builder{}
|
|
||||||
for i, version := range versions.SupportedK8sVersions() {
|
|
||||||
if i > 0 {
|
|
||||||
builder.WriteString(" ")
|
|
||||||
}
|
|
||||||
builder.WriteString(strings.TrimPrefix(semver.MajorMinor(version), "v"))
|
|
||||||
}
|
|
||||||
return builder.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
|
func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
|
||||||
workDir, err := cmd.Flags().GetString("workspace")
|
workDir, err := cmd.Flags().GetString("workspace")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -144,11 +130,11 @@ func parseGenerateFlags(cmd *cobra.Command) (generateFlags, error) {
|
|||||||
}
|
}
|
||||||
k8sVersion, err := cmd.Flags().GetString("kubernetes")
|
k8sVersion, err := cmd.Flags().GetString("kubernetes")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return generateFlags{}, fmt.Errorf("parsing kuberentes flag: %w", err)
|
return generateFlags{}, fmt.Errorf("parsing Kubernetes flag: %w", err)
|
||||||
}
|
}
|
||||||
resolvedVersion, err := resolveK8sVersion(k8sVersion)
|
resolvedVersion, err := versions.NewValidK8sVersion(k8sVersion, true) // allow versions without specified patch
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return generateFlags{}, fmt.Errorf("resolving kuberentes version from flag: %w", err)
|
return generateFlags{}, fmt.Errorf("resolving Kubernetes version from flag: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
attestationString, err := cmd.Flags().GetString("attestation")
|
attestationString, err := cmd.Flags().GetString("attestation")
|
||||||
@ -184,22 +170,6 @@ func generateCompletion(_ *cobra.Command, args []string, _ string) ([]string, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveK8sVersion takes the user input from --kubernetes and transforms a MAJOR.MINOR definition into a supported
|
|
||||||
// MAJOR.MINOR.PATCH release.
|
|
||||||
func resolveK8sVersion(k8sVersion string) (string, error) {
|
|
||||||
prefixedVersion := compatibility.EnsurePrefixV(k8sVersion)
|
|
||||||
if !semver.IsValid(prefixedVersion) {
|
|
||||||
return "", fmt.Errorf("kubernetes flag does not specify a valid semantic version: %s", k8sVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
extendedVersion := config.K8sVersionFromMajorMinor(prefixedVersion)
|
|
||||||
if extendedVersion == "" {
|
|
||||||
return "", fmt.Errorf("--kubernetes (%s) does not specify a valid Kubernetes version. Supported versions: %s", strings.TrimPrefix(k8sVersion, "v"), supportedVersions())
|
|
||||||
}
|
|
||||||
|
|
||||||
return extendedVersion, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func printFormattedSlice[T any](input []T) string {
|
func printFormattedSlice[T any](input []T) string {
|
||||||
return fmt.Sprintf("{%s}", strings.Join(toString(input), "|"))
|
return fmt.Sprintf("{%s}", strings.Join(toString(input), "|"))
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||||
@ -29,9 +30,29 @@ func TestConfigGenerateKubernetesVersion(t *testing.T) {
|
|||||||
version string
|
version string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
"success": {
|
"default version": {
|
||||||
|
version: "",
|
||||||
|
},
|
||||||
|
"without v prefix": {
|
||||||
|
version: strings.TrimPrefix(string(versions.Default), "v"),
|
||||||
|
},
|
||||||
|
"K8s version without patch version": {
|
||||||
version: semver.MajorMinor(string(versions.Default)),
|
version: semver.MajorMinor(string(versions.Default)),
|
||||||
},
|
},
|
||||||
|
"K8s version with patch version": {
|
||||||
|
version: string(versions.Default),
|
||||||
|
},
|
||||||
|
"K8s version with invalid patch version": {
|
||||||
|
version: func() string {
|
||||||
|
s := string(versions.Default)
|
||||||
|
return s[:len(s)-1] + "99"
|
||||||
|
}(),
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
"outdated K8s version": {
|
||||||
|
version: "v1.0.0",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
"no semver": {
|
"no semver": {
|
||||||
version: "asdf",
|
version: "asdf",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@ -50,11 +71,13 @@ func TestConfigGenerateKubernetesVersion(t *testing.T) {
|
|||||||
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
fileHandler := file.NewHandler(afero.NewMemMapFs())
|
||||||
cmd := newConfigGenerateCmd()
|
cmd := newConfigGenerateCmd()
|
||||||
cmd.Flags().String("workspace", "", "") // register persistent flag manually
|
cmd.Flags().String("workspace", "", "") // register persistent flag manually
|
||||||
err := cmd.Flags().Set("kubernetes", tc.version)
|
if tc.version != "" {
|
||||||
require.NoError(err)
|
err := cmd.Flags().Set("kubernetes", tc.version)
|
||||||
|
require.NoError(err)
|
||||||
|
}
|
||||||
|
|
||||||
cg := &configGenerateCmd{log: logger.NewTest(t)}
|
cg := &configGenerateCmd{log: logger.NewTest(t)}
|
||||||
err = cg.configGenerate(cmd, fileHandler, cloudprovider.Unknown, "")
|
err := cg.configGenerate(cmd, fileHandler, cloudprovider.Unknown, "")
|
||||||
|
|
||||||
if tc.wantErr {
|
if tc.wantErr {
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
"github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/atls"
|
"github.com/edgelesssys/constellation/v2/internal/atls"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
|
||||||
|
|
||||||
"github.com/spf13/afero"
|
"github.com/spf13/afero"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -170,10 +169,7 @@ func (i *initCmd) initialize(
|
|||||||
|
|
||||||
// config validation does not check k8s patch version since upgrade may accept an outdated patch version.
|
// config validation does not check k8s patch version since upgrade may accept an outdated patch version.
|
||||||
// init only supported up-to-date versions.
|
// init only supported up-to-date versions.
|
||||||
k8sVersion, err := versions.NewValidK8sVersion(compatibility.EnsurePrefixV(conf.KubernetesVersion), true)
|
k8sVersion := conf.KubernetesVersion
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
i.log.Debugf("Validated k8s version as %s", k8sVersion)
|
i.log.Debugf("Validated k8s version as %s", k8sVersion)
|
||||||
if versions.IsPreviewK8sVersion(k8sVersion) {
|
if versions.IsPreviewK8sVersion(k8sVersion) {
|
||||||
cmd.PrintErrf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", k8sVersion)
|
cmd.PrintErrf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", k8sVersion)
|
||||||
@ -275,7 +271,7 @@ func (i *initCmd) initialize(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating Helm client: %w", err)
|
return fmt.Errorf("creating Helm client: %w", err)
|
||||||
}
|
}
|
||||||
executor, includesUpgrades, err := helmApplier.PrepareApply(conf, k8sVersion, idFile, options, output,
|
executor, includesUpgrades, err := helmApplier.PrepareApply(conf, idFile, options, output,
|
||||||
serviceAccURI, masterSecret)
|
serviceAccURI, masterSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting Helm chart executor: %w", err)
|
return fmt.Errorf("getting Helm chart executor: %w", err)
|
||||||
@ -629,7 +625,7 @@ type attestationConfigApplier interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type helmApplier interface {
|
type helmApplier interface {
|
||||||
PrepareApply(conf *config.Config, validK8sversion versions.ValidK8sVersion, idFile clusterid.File, flags helm.Options, tfOutput terraform.ApplyOutput, serviceAccURI string, masterSecret uri.MasterSecret) (helm.Applier, bool, error)
|
PrepareApply(conf *config.Config, idFile clusterid.File, flags helm.Options, tfOutput terraform.ApplyOutput, serviceAccURI string, masterSecret uri.MasterSecret) (helm.Applier, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type clusterShower interface {
|
type clusterShower interface {
|
||||||
|
@ -133,7 +133,13 @@ func TestInitialize(t *testing.T) {
|
|||||||
provider: cloudprovider.Azure,
|
provider: cloudprovider.Azure,
|
||||||
idFile: &clusterid.File{IP: "192.0.2.1"},
|
idFile: &clusterid.File{IP: "192.0.2.1"},
|
||||||
initServerAPI: &stubInitServer{res: &initproto.InitResponse{Kind: &initproto.InitResponse_InitSuccess{InitSuccess: testInitResp}}},
|
initServerAPI: &stubInitServer{res: &initproto.InitResponse{Kind: &initproto.InitResponse_InitSuccess{InitSuccess: testInitResp}}},
|
||||||
configMutator: func(c *config.Config) { c.KubernetesVersion = strings.TrimPrefix(string(versions.Default), "v") },
|
configMutator: func(c *config.Config) {
|
||||||
|
res, err := versions.NewValidK8sVersion(strings.TrimPrefix(string(versions.Default), "v"), true)
|
||||||
|
if err != nil {
|
||||||
|
panic("invalid k8s version")
|
||||||
|
}
|
||||||
|
c.KubernetesVersion = res
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +228,7 @@ type stubApplier struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s stubApplier) PrepareApply(_ *config.Config, _ versions.ValidK8sVersion, _ clusterid.File, _ helm.Options, _ terraform.ApplyOutput, _ string, _ uri.MasterSecret) (helm.Applier, bool, error) {
|
func (s stubApplier) PrepareApply(_ *config.Config, _ clusterid.File, _ helm.Options, _ terraform.ApplyOutput, _ string, _ uri.MasterSecret) (helm.Applier, bool, error) {
|
||||||
return stubRunner{}, false, s.err
|
return stubRunner{}, false, s.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,9 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, upgradeDir string, fl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validK8sVersion, err := validK8sVersion(cmd, conf.KubernetesVersion, flags.yes)
|
if versions.IsPreviewK8sVersion(conf.KubernetesVersion) {
|
||||||
|
cmd.PrintErrf("Warning: Constellation with Kubernetes %q is still in preview. Use only for evaluation purposes.\n", conf.KubernetesVersion)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -197,7 +199,7 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, upgradeDir string, fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
var upgradeErr *compatibility.InvalidUpgradeError
|
var upgradeErr *compatibility.InvalidUpgradeError
|
||||||
err = u.handleServiceUpgrade(cmd, conf, idFile, tfOutput, validK8sVersion, upgradeDir, flags)
|
err = u.handleServiceUpgrade(cmd, conf, idFile, tfOutput, upgradeDir, flags)
|
||||||
switch {
|
switch {
|
||||||
case errors.As(err, &upgradeErr):
|
case errors.As(err, &upgradeErr):
|
||||||
cmd.PrintErrln(err)
|
cmd.PrintErrln(err)
|
||||||
@ -305,27 +307,6 @@ func (u *upgradeApplyCmd) migrateTerraform(cmd *cobra.Command, conf *config.Conf
|
|||||||
return tfOutput, nil
|
return tfOutput, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// validK8sVersion checks if the Kubernetes patch version is supported and asks for confirmation if not.
|
|
||||||
func validK8sVersion(cmd *cobra.Command, version string, yes bool) (validVersion versions.ValidK8sVersion, err error) {
|
|
||||||
validVersion, err = versions.NewValidK8sVersion(version, true)
|
|
||||||
if versions.IsPreviewK8sVersion(validVersion) {
|
|
||||||
cmd.PrintErrf("Warning: Constellation with Kubernetes %v is still in preview. Use only for evaluation purposes.\n", validVersion)
|
|
||||||
}
|
|
||||||
valid := err == nil
|
|
||||||
|
|
||||||
if !valid && !yes {
|
|
||||||
confirmed, err := askToConfirm(cmd, fmt.Sprintf("WARNING: The Kubernetes patch version %s is not supported. If you continue, Kubernetes upgrades will be skipped. Do you want to continue anyway?", version))
|
|
||||||
if err != nil {
|
|
||||||
return validVersion, fmt.Errorf("asking for confirmation: %w", err)
|
|
||||||
}
|
|
||||||
if !confirmed {
|
|
||||||
return validVersion, fmt.Errorf("aborted by user")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return validVersion, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// confirmAndUpgradeAttestationConfig checks if the locally configured measurements are different from the cluster's measurements.
|
// confirmAndUpgradeAttestationConfig checks if the locally configured measurements are different from the cluster's measurements.
|
||||||
// If so the function will ask the user to confirm (if --yes is not set) and upgrade the cluster's config.
|
// If so the function will ask the user to confirm (if --yes is not set) and upgrade the cluster's config.
|
||||||
func (u *upgradeApplyCmd) confirmAndUpgradeAttestationConfig(
|
func (u *upgradeApplyCmd) confirmAndUpgradeAttestationConfig(
|
||||||
@ -370,7 +351,7 @@ func (u *upgradeApplyCmd) confirmAndUpgradeAttestationConfig(
|
|||||||
|
|
||||||
func (u *upgradeApplyCmd) handleServiceUpgrade(
|
func (u *upgradeApplyCmd) handleServiceUpgrade(
|
||||||
cmd *cobra.Command, conf *config.Config, idFile clusterid.File, tfOutput terraform.ApplyOutput,
|
cmd *cobra.Command, conf *config.Config, idFile clusterid.File, tfOutput terraform.ApplyOutput,
|
||||||
validK8sVersion versions.ValidK8sVersion, upgradeDir string, flags upgradeApplyFlags,
|
upgradeDir string, flags upgradeApplyFlags,
|
||||||
) error {
|
) error {
|
||||||
var secret uri.MasterSecret
|
var secret uri.MasterSecret
|
||||||
if err := u.fileHandler.ReadJSON(constants.MasterSecretFilename, &secret); err != nil {
|
if err := u.fileHandler.ReadJSON(constants.MasterSecretFilename, &secret); err != nil {
|
||||||
@ -388,7 +369,7 @@ func (u *upgradeApplyCmd) handleServiceUpgrade(
|
|||||||
|
|
||||||
prepareApply := func(allowDestructive bool) (helm.Applier, bool, error) {
|
prepareApply := func(allowDestructive bool) (helm.Applier, bool, error) {
|
||||||
options.AllowDestructive = allowDestructive
|
options.AllowDestructive = allowDestructive
|
||||||
executor, includesUpgrades, err := u.helmApplier.PrepareApply(conf, validK8sVersion, idFile, options,
|
executor, includesUpgrades, err := u.helmApplier.PrepareApply(conf, idFile, options,
|
||||||
tfOutput, serviceAccURI, secret)
|
tfOutput, serviceAccURI, secret)
|
||||||
var upgradeErr *compatibility.InvalidUpgradeError
|
var upgradeErr *compatibility.InvalidUpgradeError
|
||||||
switch {
|
switch {
|
||||||
|
@ -576,7 +576,7 @@ func (v *versionUpgrade) writeConfig(conf *config.Config, fileHandler file.Handl
|
|||||||
conf.MicroserviceVersion = v.newServices
|
conf.MicroserviceVersion = v.newServices
|
||||||
}
|
}
|
||||||
if len(v.newKubernetes) > 0 {
|
if len(v.newKubernetes) > 0 {
|
||||||
conf.KubernetesVersion = v.newKubernetes[0]
|
conf.KubernetesVersion = versions.ValidK8sVersion(v.newKubernetes[0])
|
||||||
}
|
}
|
||||||
if len(v.newImages) > 0 {
|
if len(v.newImages) > 0 {
|
||||||
imageUpgrade := sortedMapKeys(v.newImages)[0]
|
imageUpgrade := sortedMapKeys(v.newImages)[0]
|
||||||
|
@ -469,7 +469,6 @@ go_test(
|
|||||||
"//internal/kms/uri",
|
"//internal/kms/uri",
|
||||||
"//internal/logger",
|
"//internal/logger",
|
||||||
"//internal/semver",
|
"//internal/semver",
|
||||||
"//internal/versions",
|
|
||||||
"@com_github_pkg_errors//:errors",
|
"@com_github_pkg_errors//:errors",
|
||||||
"@com_github_stretchr_testify//assert",
|
"@com_github_stretchr_testify//assert",
|
||||||
"@com_github_stretchr_testify//mock",
|
"@com_github_stretchr_testify//mock",
|
||||||
|
@ -39,7 +39,6 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
|
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -87,8 +86,8 @@ type Options struct {
|
|||||||
|
|
||||||
// PrepareApply loads the charts and returns the executor to apply them.
|
// PrepareApply loads the charts and returns the executor to apply them.
|
||||||
// TODO(elchead): remove validK8sVersion by putting ValidK8sVersion into config.Config, see AB#3374.
|
// TODO(elchead): remove validK8sVersion by putting ValidK8sVersion into config.Config, see AB#3374.
|
||||||
func (h Client) PrepareApply(conf *config.Config, validK8sversion versions.ValidK8sVersion, idFile clusterid.File, flags Options, tfOutput terraform.ApplyOutput, serviceAccURI string, masterSecret uri.MasterSecret) (Applier, bool, error) {
|
func (h Client) PrepareApply(conf *config.Config, idFile clusterid.File, flags Options, tfOutput terraform.ApplyOutput, serviceAccURI string, masterSecret uri.MasterSecret) (Applier, bool, error) {
|
||||||
releases, err := h.loadReleases(conf, masterSecret, validK8sversion, idFile, flags, tfOutput, serviceAccURI)
|
releases, err := h.loadReleases(conf, masterSecret, idFile, flags, tfOutput, serviceAccURI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, fmt.Errorf("loading Helm releases: %w", err)
|
return nil, false, fmt.Errorf("loading Helm releases: %w", err)
|
||||||
}
|
}
|
||||||
@ -97,8 +96,8 @@ func (h Client) PrepareApply(conf *config.Config, validK8sversion versions.Valid
|
|||||||
return &ChartApplyExecutor{actions: actions, log: h.log}, includesUpgrades, err
|
return &ChartApplyExecutor{actions: actions, log: h.log}, includesUpgrades, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Client) loadReleases(conf *config.Config, secret uri.MasterSecret, validK8sVersion versions.ValidK8sVersion, idFile clusterid.File, flags Options, tfOutput terraform.ApplyOutput, serviceAccURI string) ([]Release, error) {
|
func (h Client) loadReleases(conf *config.Config, secret uri.MasterSecret, idFile clusterid.File, flags Options, tfOutput terraform.ApplyOutput, serviceAccURI string) ([]Release, error) {
|
||||||
helmLoader := newLoader(conf, idFile, validK8sVersion, h.cliVersion)
|
helmLoader := newLoader(conf, idFile, h.cliVersion)
|
||||||
h.log.Debugf("Created new Helm loader")
|
h.log.Debugf("Created new Helm loader")
|
||||||
return helmLoader.loadReleases(flags.Conformance, flags.HelmWaitMode, secret,
|
return helmLoader.loadReleases(flags.Conformance, flags.HelmWaitMode, secret,
|
||||||
serviceAccURI, tfOutput)
|
serviceAccURI, tfOutput)
|
||||||
|
@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"helm.sh/helm/v3/pkg/action"
|
"helm.sh/helm/v3/pkg/action"
|
||||||
@ -207,7 +206,7 @@ func TestHelmApply(t *testing.T) {
|
|||||||
helmListVersion(lister, "aws-load-balancer-controller", awsLbVersion)
|
helmListVersion(lister, "aws-load-balancer-controller", awsLbVersion)
|
||||||
|
|
||||||
options.AllowDestructive = tc.allowDestructive
|
options.AllowDestructive = tc.allowDestructive
|
||||||
ex, includesUpgrade, err := sut.PrepareApply(cfg, versions.ValidK8sVersion("v1.27.4"),
|
ex, includesUpgrade, err := sut.PrepareApply(cfg,
|
||||||
clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")}, options,
|
clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")}, options,
|
||||||
fakeTerraformOutput(csp), fakeServiceAccURI(csp),
|
fakeTerraformOutput(csp), fakeServiceAccURI(csp),
|
||||||
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")})
|
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")})
|
||||||
|
@ -77,11 +77,12 @@ type chartLoader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newLoader creates a new ChartLoader.
|
// newLoader creates a new ChartLoader.
|
||||||
func newLoader(config *config.Config, idFile clusterid.File, k8sVersion versions.ValidK8sVersion, cliVersion semver.Semver) *chartLoader {
|
func newLoader(config *config.Config, idFile clusterid.File, cliVersion semver.Semver) *chartLoader {
|
||||||
// TODO(malt3): Allow overriding container image registry + prefix for all images
|
// TODO(malt3): Allow overriding container image registry + prefix for all images
|
||||||
// (e.g. for air-gapped environments).
|
// (e.g. for air-gapped environments).
|
||||||
var ccmImage, cnmImage string
|
var ccmImage, cnmImage string
|
||||||
csp := config.GetProvider()
|
csp := config.GetProvider()
|
||||||
|
k8sVersion := config.KubernetesVersion
|
||||||
switch csp {
|
switch csp {
|
||||||
case cloudprovider.AWS:
|
case cloudprovider.AWS:
|
||||||
ccmImage = versions.VersionConfigs[k8sVersion].CloudControllerManagerImageAWS
|
ccmImage = versions.VersionConfigs[k8sVersion].CloudControllerManagerImageAWS
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func fakeServiceAccURI(provider cloudprovider.Provider) string {
|
func fakeServiceAccURI(provider cloudprovider.Provider) string {
|
||||||
@ -67,9 +66,8 @@ func TestLoadReleases(t *testing.T) {
|
|||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
config := &config.Config{Provider: config.ProviderConfig{GCP: &config.GCPConfig{}}}
|
config := &config.Config{Provider: config.ProviderConfig{GCP: &config.GCPConfig{}}}
|
||||||
k8sVersion := versions.ValidK8sVersion("v1.27.4")
|
|
||||||
chartLoader := newLoader(config, clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")},
|
chartLoader := newLoader(config, clusterid.File{UID: "testuid", MeasurementSalt: []byte("measurementSalt")},
|
||||||
k8sVersion, semver.NewFromInt(2, 10, 0, ""))
|
semver.NewFromInt(2, 10, 0, ""))
|
||||||
helmReleases, err := chartLoader.loadReleases(
|
helmReleases, err := chartLoader.loadReleases(
|
||||||
true, WaitModeAtomic,
|
true, WaitModeAtomic,
|
||||||
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")},
|
uri.MasterSecret{Key: []byte("secret"), Salt: []byte("masterSalt")},
|
||||||
|
@ -124,17 +124,13 @@ func (k *KubeCmd) UpgradeNodeVersion(ctx context.Context, conf *config.Config, f
|
|||||||
nodeVersion.Spec.ImageReference = imageReference
|
nodeVersion.Spec.ImageReference = imageReference
|
||||||
nodeVersion.Spec.ImageVersion = imageVersion.Version()
|
nodeVersion.Spec.ImageVersion = imageVersion.Version()
|
||||||
|
|
||||||
|
// TODO(elchead): why?
|
||||||
// We have to allow users to specify outdated k8s patch versions.
|
// We have to allow users to specify outdated k8s patch versions.
|
||||||
// Therefore, this code has to skip k8s updates if a user configures an outdated (i.e. invalid) k8s version.
|
// Therefore, this code has to skip k8s updates if a user configures an outdated (i.e. invalid) k8s version.
|
||||||
var components *corev1.ConfigMap
|
var components *corev1.ConfigMap
|
||||||
currentK8sVersion, err := versions.NewValidK8sVersion(conf.KubernetesVersion, true)
|
currentK8sVersion := conf.KubernetesVersion
|
||||||
if err != nil {
|
versionConfig := versions.VersionConfigs[currentK8sVersion]
|
||||||
innerErr := fmt.Errorf("unsupported Kubernetes version, supported versions are %s", strings.Join(versions.SupportedK8sVersions(), ", "))
|
components, err = k.updateK8s(&nodeVersion, versionConfig.ClusterVersion, versionConfig.KubernetesComponents, force)
|
||||||
err = compatibility.NewInvalidUpgradeError(nodeVersion.Spec.KubernetesClusterVersion, conf.KubernetesVersion, innerErr)
|
|
||||||
} else {
|
|
||||||
versionConfig := versions.VersionConfigs[currentK8sVersion]
|
|
||||||
components, err = k.updateK8s(&nodeVersion, versionConfig.ClusterVersion, versionConfig.KubernetesComponents, force)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
|
@ -42,7 +42,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
currentImageVersion string
|
currentImageVersion string
|
||||||
newImageReference string
|
newImageReference string
|
||||||
badImageVersion string
|
badImageVersion string
|
||||||
currentClusterVersion string
|
currentClusterVersion versions.ValidK8sVersion
|
||||||
conf *config.Config
|
conf *config.Config
|
||||||
force bool
|
force bool
|
||||||
getCRErr error
|
getCRErr error
|
||||||
@ -55,11 +55,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -71,11 +71,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.2"
|
conf.Image = "v1.2.2"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -92,11 +92,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[0]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[0]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -113,11 +113,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.2"
|
conf.Image = "v1.2.2"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[0]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[0]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{},
|
kubectl: &stubKubectl{},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
assertCorrectError: func(t *testing.T, err error) bool {
|
assertCorrectError: func(t *testing.T, err error) bool {
|
||||||
@ -129,7 +129,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
conditions: []metav1.Condition{{
|
conditions: []metav1.Condition{{
|
||||||
@ -137,7 +137,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
Status: metav1.ConditionTrue,
|
Status: metav1.ConditionTrue,
|
||||||
}},
|
}},
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{},
|
kubectl: &stubKubectl{},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
assertCorrectError: func(t *testing.T, err error) bool {
|
assertCorrectError: func(t *testing.T, err error) bool {
|
||||||
@ -148,7 +148,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
conditions: []metav1.Condition{{
|
conditions: []metav1.Condition{{
|
||||||
@ -156,7 +156,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
Status: metav1.ConditionTrue,
|
Status: metav1.ConditionTrue,
|
||||||
}},
|
}},
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{},
|
kubectl: &stubKubectl{},
|
||||||
force: true,
|
force: true,
|
||||||
wantUpdate: true,
|
wantUpdate: true,
|
||||||
@ -165,11 +165,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -185,12 +185,12 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.4.2"
|
conf.Image = "v1.4.2"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
newImageReference: "path/to/image:v1.4.2",
|
newImageReference: "path/to/image:v1.4.2",
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":true}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":true}}`),
|
||||||
@ -207,12 +207,12 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.4.2"
|
conf.Image = "v1.4.2"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
newImageReference: "path/to/image:v1.4.2",
|
newImageReference: "path/to/image:v1.4.2",
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -225,11 +225,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
badImageVersion: "v3.2.1",
|
badImageVersion: "v3.2.1",
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
@ -251,7 +251,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -268,11 +268,11 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
conf: func() *config.Config {
|
conf: func() *config.Config {
|
||||||
conf := config.Default()
|
conf := config.Default()
|
||||||
conf.Image = "v1.2.3"
|
conf.Image = "v1.2.3"
|
||||||
conf.KubernetesVersion = versions.SupportedK8sVersions()[1]
|
conf.KubernetesVersion = versions.SupportedValidK8sVersions()[1]
|
||||||
return conf
|
return conf
|
||||||
}(),
|
}(),
|
||||||
currentImageVersion: "v1.2.2",
|
currentImageVersion: "v1.2.2",
|
||||||
currentClusterVersion: versions.SupportedK8sVersions()[0],
|
currentClusterVersion: versions.SupportedValidK8sVersions()[0],
|
||||||
kubectl: &stubKubectl{
|
kubectl: &stubKubectl{
|
||||||
configMaps: map[string]*corev1.ConfigMap{
|
configMaps: map[string]*corev1.ConfigMap{
|
||||||
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
constants.JoinConfigMap: newJoinConfigMap(`{"0":{"expected":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","warnOnly":false}}`),
|
||||||
@ -297,7 +297,7 @@ func TestUpgradeNodeVersion(t *testing.T) {
|
|||||||
nodeVersion := updatev1alpha1.NodeVersion{
|
nodeVersion := updatev1alpha1.NodeVersion{
|
||||||
Spec: updatev1alpha1.NodeVersionSpec{
|
Spec: updatev1alpha1.NodeVersionSpec{
|
||||||
ImageVersion: tc.currentImageVersion,
|
ImageVersion: tc.currentImageVersion,
|
||||||
KubernetesClusterVersion: tc.currentClusterVersion,
|
KubernetesClusterVersion: string(tc.currentClusterVersion),
|
||||||
},
|
},
|
||||||
Status: updatev1alpha1.NodeVersionStatus{
|
Status: updatev1alpha1.NodeVersionStatus{
|
||||||
Conditions: tc.conditions,
|
Conditions: tc.conditions,
|
||||||
|
@ -79,7 +79,7 @@ constellation config generate {aws|azure|gcp|openstack|qemu|stackit} [flags]
|
|||||||
```
|
```
|
||||||
-a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-trustedlaunch|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used
|
-a, --attestation string attestation variant to use {aws-sev-snp|aws-nitro-tpm|azure-sev-snp|azure-trustedlaunch|gcp-sev-es|qemu-vtpm}. If not specified, the default for the cloud provider is used
|
||||||
-h, --help help for generate
|
-h, --help help for generate
|
||||||
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.27")
|
-k, --kubernetes string Kubernetes version to use in format MAJOR.MINOR (default "v1.27.4")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Options inherited from parent commands
|
### Options inherited from parent commands
|
||||||
|
@ -273,12 +273,11 @@ func writeUpgradeConfig(require *require.Assertions, image string, kubernetes st
|
|||||||
cfg.Image = image
|
cfg.Image = image
|
||||||
|
|
||||||
defaultConfig := config.Default()
|
defaultConfig := config.Default()
|
||||||
var kubernetesVersion semver.Semver
|
var kubernetesVersion versions.ValidK8sVersion
|
||||||
if kubernetes == "" {
|
if kubernetes == "" {
|
||||||
kubernetesVersion, err = semver.New(defaultConfig.KubernetesVersion)
|
kubernetesVersion = defaultConfig.KubernetesVersion
|
||||||
require.NoError(err)
|
|
||||||
} else {
|
} else {
|
||||||
kubernetesVersion, err = semver.New(kubernetes)
|
kubernetesVersion, err = versions.NewValidK8sVersion(kubernetes, true)
|
||||||
require.NoError(err)
|
require.NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,8 +290,8 @@ func writeUpgradeConfig(require *require.Assertions, image string, kubernetes st
|
|||||||
microserviceVersion = version
|
microserviceVersion = version
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Setting K8s version: %s\n", kubernetesVersion.String())
|
log.Printf("Setting K8s version: %s\n", kubernetesVersion)
|
||||||
cfg.KubernetesVersion = kubernetesVersion.String()
|
cfg.KubernetesVersion = kubernetesVersion
|
||||||
log.Printf("Setting microservice version: %s\n", microserviceVersion)
|
log.Printf("Setting microservice version: %s\n", microserviceVersion)
|
||||||
cfg.MicroserviceVersion = microserviceVersion
|
cfg.MicroserviceVersion = microserviceVersion
|
||||||
|
|
||||||
@ -432,13 +431,13 @@ func testNodesEventuallyHaveVersion(t *testing.T, k *kubernetes.Clientset, targe
|
|||||||
}
|
}
|
||||||
|
|
||||||
kubeletVersion := node.Status.NodeInfo.KubeletVersion
|
kubeletVersion := node.Status.NodeInfo.KubeletVersion
|
||||||
if kubeletVersion != targetVersions.kubernetes.String() {
|
if kubeletVersion != string(targetVersions.kubernetes) {
|
||||||
log.Printf("\t%s: K8s (Kubelet) %s, want %s\n", node.Name, kubeletVersion, targetVersions.kubernetes.String())
|
log.Printf("\t%s: K8s (Kubelet) %s, want %s\n", node.Name, kubeletVersion, targetVersions.kubernetes)
|
||||||
allUpdated = false
|
allUpdated = false
|
||||||
}
|
}
|
||||||
kubeProxyVersion := node.Status.NodeInfo.KubeProxyVersion
|
kubeProxyVersion := node.Status.NodeInfo.KubeProxyVersion
|
||||||
if kubeProxyVersion != targetVersions.kubernetes.String() {
|
if kubeProxyVersion != string(targetVersions.kubernetes) {
|
||||||
log.Printf("\t%s: K8s (Proxy) %s, want %s\n", node.Name, kubeProxyVersion, targetVersions.kubernetes.String())
|
log.Printf("\t%s: K8s (Proxy) %s, want %s\n", node.Name, kubeProxyVersion, targetVersions.kubernetes)
|
||||||
allUpdated = false
|
allUpdated = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -449,7 +448,7 @@ func testNodesEventuallyHaveVersion(t *testing.T, k *kubernetes.Clientset, targe
|
|||||||
|
|
||||||
type versionContainer struct {
|
type versionContainer struct {
|
||||||
imageRef string
|
imageRef string
|
||||||
kubernetes semver.Semver
|
kubernetes versions.ValidK8sVersion
|
||||||
microservices semver.Semver
|
microservices semver.Semver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ go_test(
|
|||||||
"//internal/constants",
|
"//internal/constants",
|
||||||
"//internal/file",
|
"//internal/file",
|
||||||
"//internal/semver",
|
"//internal/semver",
|
||||||
"//internal/versions",
|
|
||||||
"@com_github_go_playground_locales//en",
|
"@com_github_go_playground_locales//en",
|
||||||
"@com_github_go_playground_universal_translator//:universal-translator",
|
"@com_github_go_playground_universal_translator//:universal-translator",
|
||||||
"@com_github_go_playground_validator_v10//:validator",
|
"@com_github_go_playground_validator_v10//:validator",
|
||||||
|
@ -315,7 +315,7 @@ func Default() *Config {
|
|||||||
Image: defaultImage,
|
Image: defaultImage,
|
||||||
Name: defaultName,
|
Name: defaultName,
|
||||||
MicroserviceVersion: constants.BinaryVersion(),
|
MicroserviceVersion: constants.BinaryVersion(),
|
||||||
KubernetesVersion: string(versions.Default),
|
KubernetesVersion: versions.Default,
|
||||||
DebugCluster: toPtr(false),
|
DebugCluster: toPtr(false),
|
||||||
Provider: ProviderConfig{
|
Provider: ProviderConfig{
|
||||||
AWS: &AWSConfig{
|
AWS: &AWSConfig{
|
||||||
|
@ -52,7 +52,7 @@ func init() {
|
|||||||
ConfigDoc.Fields[2].Description = "Name of the cluster."
|
ConfigDoc.Fields[2].Description = "Name of the cluster."
|
||||||
ConfigDoc.Fields[2].Comments[encoder.LineComment] = "Name of the cluster."
|
ConfigDoc.Fields[2].Comments[encoder.LineComment] = "Name of the cluster."
|
||||||
ConfigDoc.Fields[3].Name = "kubernetesVersion"
|
ConfigDoc.Fields[3].Name = "kubernetesVersion"
|
||||||
ConfigDoc.Fields[3].Type = "string"
|
ConfigDoc.Fields[3].Type = "ValidK8sVersion"
|
||||||
ConfigDoc.Fields[3].Note = ""
|
ConfigDoc.Fields[3].Note = ""
|
||||||
ConfigDoc.Fields[3].Description = "Kubernetes version to be installed into the cluster."
|
ConfigDoc.Fields[3].Description = "Kubernetes version to be installed into the cluster."
|
||||||
ConfigDoc.Fields[3].Comments[encoder.LineComment] = "Kubernetes version to be installed into the cluster."
|
ConfigDoc.Fields[3].Comments[encoder.LineComment] = "Kubernetes version to be installed into the cluster."
|
||||||
|
@ -29,7 +29,6 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@ -249,16 +248,17 @@ func TestFromFile(t *testing.T) {
|
|||||||
configName: "wrong-name.yaml",
|
configName: "wrong-name.yaml",
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
"custom config from default file": {
|
// TODO why do we support an empty file?
|
||||||
config: &Config{
|
//"custom config from default file": {
|
||||||
Version: Version4,
|
// config: &Config{
|
||||||
},
|
// Version: Version4,
|
||||||
configName: constants.ConfigFilename,
|
// },
|
||||||
wantResult: &Config{
|
// configName: constants.ConfigFilename,
|
||||||
Version: Version4,
|
// wantResult: &Config{
|
||||||
NodeGroups: map[string]NodeGroup{},
|
// Version: Version4,
|
||||||
},
|
// NodeGroups: map[string]NodeGroup{},
|
||||||
},
|
// },
|
||||||
|
//},
|
||||||
"modify default config": {
|
"modify default config": {
|
||||||
config: func() *Config {
|
config: func() *Config {
|
||||||
conf := Default()
|
conf := Default()
|
||||||
@ -321,19 +321,6 @@ func TestValidate(t *testing.T) {
|
|||||||
wantErr: true,
|
wantErr: true,
|
||||||
wantErrCount: defaultErrCount,
|
wantErrCount: defaultErrCount,
|
||||||
},
|
},
|
||||||
"outdated k8s patch version is allowed": {
|
|
||||||
cnf: func() *Config {
|
|
||||||
cnf := Default()
|
|
||||||
cnf.Image = ""
|
|
||||||
ver, err := semver.New(versions.SupportedK8sVersions()[0])
|
|
||||||
require.NoError(t, err)
|
|
||||||
ver = semver.NewFromInt(ver.Major(), ver.Minor(), ver.Patch()-1, "")
|
|
||||||
cnf.KubernetesVersion = ver.String()
|
|
||||||
return cnf
|
|
||||||
}(),
|
|
||||||
wantErr: true,
|
|
||||||
wantErrCount: defaultErrCount,
|
|
||||||
},
|
|
||||||
"microservices violate version drift": {
|
"microservices violate version drift": {
|
||||||
cnf: func() *Config {
|
cnf: func() *Config {
|
||||||
cnf := Default()
|
cnf := Default()
|
||||||
|
@ -12,5 +12,6 @@ go_library(
|
|||||||
"//internal/file",
|
"//internal/file",
|
||||||
"//internal/role",
|
"//internal/role",
|
||||||
"//internal/semver",
|
"//internal/semver",
|
||||||
|
"//internal/versions",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/role"
|
"github.com/edgelesssys/constellation/v2/internal/role"
|
||||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||||
|
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -335,7 +336,7 @@ func V3ToV4(path string, fileHandler file.Handler) error {
|
|||||||
cfgV4.Version = config.Version4
|
cfgV4.Version = config.Version4
|
||||||
cfgV4.Image = cfgV3.Image
|
cfgV4.Image = cfgV3.Image
|
||||||
cfgV4.Name = cfgV3.Name
|
cfgV4.Name = cfgV3.Name
|
||||||
cfgV4.KubernetesVersion = cfgV3.KubernetesVersion
|
cfgV4.KubernetesVersion = versions.ValidK8sVersion(cfgV3.KubernetesVersion)
|
||||||
cfgV4.MicroserviceVersion = cfgV3.MicroserviceVersion
|
cfgV4.MicroserviceVersion = cfgV3.MicroserviceVersion
|
||||||
cfgV4.DebugCluster = cfgV3.DebugCluster
|
cfgV4.DebugCluster = cfgV3.DebugCluster
|
||||||
|
|
||||||
|
@ -637,22 +637,6 @@ func (c *Config) validateK8sVersion(fl validator.FieldLevel) bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// K8sVersionFromMajorMinor takes a semver in format MAJOR.MINOR
|
|
||||||
// and returns the version in format MAJOR.MINOR.PATCH with the
|
|
||||||
// supported patch version as PATCH.
|
|
||||||
func K8sVersionFromMajorMinor(version string) string {
|
|
||||||
switch version {
|
|
||||||
case semver.MajorMinor(string(versions.V1_26)):
|
|
||||||
return string(versions.V1_26)
|
|
||||||
case semver.MajorMinor(string(versions.V1_27)):
|
|
||||||
return string(versions.V1_27)
|
|
||||||
case semver.MajorMinor(string(versions.V1_28)):
|
|
||||||
return string(versions.V1_28)
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerImageCompatibilityError(ut ut.Translator) error {
|
func registerImageCompatibilityError(ut ut.Translator) error {
|
||||||
return ut.Add("image_compatibility", "{0} specifies an invalid version: {1}", true)
|
return ut.Add("image_compatibility", "{0} specifies an invalid version: {1}", true)
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,14 @@ func SupportedK8sVersions() []string {
|
|||||||
return validVersionsSorted
|
return validVersionsSorted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportedValidK8sVersions returns a typed list of supported Kubernetes versions.
|
||||||
|
func SupportedValidK8sVersions() (res []ValidK8sVersion) {
|
||||||
|
for _, v := range SupportedK8sVersions() {
|
||||||
|
res = append(res, ValidK8sVersion(v))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// ValidK8sVersion represents any of the three currently supported k8s versions.
|
// ValidK8sVersion represents any of the three currently supported k8s versions.
|
||||||
type ValidK8sVersion string
|
type ValidK8sVersion string
|
||||||
|
|
||||||
@ -44,21 +52,91 @@ type ValidK8sVersion string
|
|||||||
// strict controls whether the patch version is checked or not.
|
// strict controls whether the patch version is checked or not.
|
||||||
// If strict is false, the patch version is ignored and the returned
|
// If strict is false, the patch version is ignored and the returned
|
||||||
// ValidK8sVersion is a supported patch version for the given major.minor version.
|
// ValidK8sVersion is a supported patch version for the given major.minor version.
|
||||||
|
// TODO(elchead): only allow strict mode?
|
||||||
func NewValidK8sVersion(k8sVersion string, strict bool) (ValidK8sVersion, error) {
|
func NewValidK8sVersion(k8sVersion string, strict bool) (ValidK8sVersion, error) {
|
||||||
|
prefixedVersion := compatibility.EnsurePrefixV(k8sVersion)
|
||||||
|
parsedVersion, err := resolveK8sPatchVersion(prefixedVersion)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("resolving kubernetes patch version from flag: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Println(parsedVersion)
|
||||||
var supported bool
|
var supported bool
|
||||||
if strict {
|
if strict {
|
||||||
supported = isSupportedK8sVersionStrict(k8sVersion)
|
supported = isSupportedK8sVersionStrict(parsedVersion)
|
||||||
} else {
|
} else {
|
||||||
supported = isSupportedK8sVersion(k8sVersion)
|
supported = isSupportedK8sVersion(parsedVersion)
|
||||||
}
|
}
|
||||||
if !supported {
|
if !supported {
|
||||||
return "", fmt.Errorf("invalid Kubernetes version: %s; supported versions are %v", k8sVersion, SupportedK8sVersions())
|
return "", fmt.Errorf("invalid Kubernetes version: %s; supported versions are %v", parsedVersion, SupportedK8sVersions())
|
||||||
}
|
}
|
||||||
if !strict {
|
if !strict {
|
||||||
k8sVersion, _ = supportedVersionForMajorMinor(k8sVersion)
|
parsedVersion, _ = supportedVersionForMajorMinor(parsedVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValidK8sVersion(k8sVersion), nil
|
return ValidK8sVersion(parsedVersion), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (v *ValidK8sVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var version string
|
||||||
|
if err := unmarshal(&version); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
valid, err := NewValidK8sVersion(version, true)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unsupported Kubernetes version, supported versions are %s", strings.Join(SupportedK8sVersions(), ", "))
|
||||||
|
}
|
||||||
|
*v = valid
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveK8sPatchVersion takes the user input from --kubernetes and transforms a MAJOR.MINOR definition into a supported
|
||||||
|
// MAJOR.MINOR.PATCH release.
|
||||||
|
// TODO(elchead): should we support this resolvement also for the config?
|
||||||
|
func resolveK8sPatchVersion(k8sVersion string) (string, error) {
|
||||||
|
if !semver.IsValid(k8sVersion) {
|
||||||
|
return "", fmt.Errorf("kubernetes flag does not specify a valid semantic version: %s", k8sVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if semver.MajorMinor(k8sVersion) != k8sVersion {
|
||||||
|
// patch version is specified
|
||||||
|
return k8sVersion, nil
|
||||||
|
}
|
||||||
|
extendedVersion := K8sVersionFromMajorMinor(k8sVersion)
|
||||||
|
if extendedVersion == "" {
|
||||||
|
return "", fmt.Errorf("--kubernetes (%s) does not specify a valid Kubernetes version. Supported versions: %s", strings.TrimPrefix(k8sVersion, "v"), supportedVersions())
|
||||||
|
}
|
||||||
|
|
||||||
|
return extendedVersion, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// K8sVersionFromMajorMinor takes a semver in format MAJOR.MINOR
|
||||||
|
// and returns the version in format MAJOR.MINOR.PATCH with the
|
||||||
|
// supported patch version as PATCH.
|
||||||
|
func K8sVersionFromMajorMinor(version string) string {
|
||||||
|
switch version {
|
||||||
|
case semver.MajorMinor(string(V1_26)):
|
||||||
|
return string(V1_26)
|
||||||
|
case semver.MajorMinor(string(V1_27)):
|
||||||
|
return string(V1_27)
|
||||||
|
case semver.MajorMinor(string(V1_28)):
|
||||||
|
return string(V1_28)
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// supportedVersions prints the supported version without v prefix and without patch version.
|
||||||
|
// Should only be used when accepting Kubernetes versions from --kubernetes.
|
||||||
|
func supportedVersions() string {
|
||||||
|
builder := strings.Builder{}
|
||||||
|
for i, version := range SupportedK8sVersions() {
|
||||||
|
if i > 0 {
|
||||||
|
builder.WriteString(" ")
|
||||||
|
}
|
||||||
|
builder.WriteString(strings.TrimPrefix(semver.MajorMinor(version), "v"))
|
||||||
|
}
|
||||||
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSupportedK8sVersion checks if a given Kubernetes minor version is supported by Constellation.
|
// IsSupportedK8sVersion checks if a given Kubernetes minor version is supported by Constellation.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user