mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-10-01 01:36:09 -04:00
cli: show available cli upgrades on upgrade check command (#1394)
* cli: upgrade check show cli upgrades * only check compatibility for valid upgrades * use semver.Sort * extend unit tests * add unit test for new compatible cli versions * adapt to feedback * fix rebase * rework output * minor -> major Co-authored-by: Otto Bittner <cobittner@posteo.net> * minor -> major Co-authored-by: Otto Bittner <cobittner@posteo.net> * dynamic major version Co-authored-by: Otto Bittner <cobittner@posteo.net> * remove currentK8sVer argument * bazel gen & tidy * bazel update --------- Co-authored-by: Otto Bittner <cobittner@posteo.net>
This commit is contained in:
parent
33d0b8f59d
commit
46f5b1734e
@ -64,6 +64,7 @@ go_library(
|
||||
"//internal/license",
|
||||
"//internal/logger",
|
||||
"//internal/retry",
|
||||
"//internal/semver",
|
||||
"//internal/sigstore",
|
||||
"//internal/variant",
|
||||
"//internal/versions",
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
|
||||
conSemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versionsapi"
|
||||
@ -81,6 +82,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
|
||||
flags: flags,
|
||||
cliVersion: compatibility.EnsurePrefixV(constants.VersionInfo()),
|
||||
log: log,
|
||||
versionsapi: fetcher.NewFetcher(),
|
||||
},
|
||||
log: log,
|
||||
}
|
||||
@ -139,31 +141,33 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
|
||||
csp := conf.GetProvider()
|
||||
u.log.Debugf("Using provider %s", csp.String())
|
||||
|
||||
currentServices, currentImage, currentK8s, err := u.collect.currentVersions(cmd.Context())
|
||||
current, err := u.collect.currentVersions(cmd.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
supportedServices, supportedImages, supportedK8s, err := u.collect.supportedVersions(cmd.Context(), currentImage)
|
||||
supported, err := u.collect.supportedVersions(cmd.Context(), current.image, current.k8s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.log.Debugf("Current service version: %s", currentServices)
|
||||
u.log.Debugf("Supported service version: %s", supportedServices)
|
||||
u.log.Debugf("Current k8s version: %s", currentK8s)
|
||||
u.log.Debugf("Supported k8s version: %s", supportedK8s)
|
||||
u.log.Debugf("Current cli version: %s", current.cli)
|
||||
u.log.Debugf("Supported cli version(s): %s", supported.cli)
|
||||
u.log.Debugf("Current service version: %s", current.service)
|
||||
u.log.Debugf("Supported service version: %s", supported.service)
|
||||
u.log.Debugf("Current k8s version: %s", current.k8s)
|
||||
u.log.Debugf("Supported k8s version(s): %s", supported.k8s)
|
||||
|
||||
// Filter versions to only include upgrades
|
||||
newServices := supportedServices
|
||||
if err := compatibility.IsValidUpgrade(currentServices, supportedServices); err != nil {
|
||||
newServices := supported.service
|
||||
if err := compatibility.IsValidUpgrade(current.service, supported.service); err != nil {
|
||||
newServices = ""
|
||||
}
|
||||
|
||||
newKubernetes := filterK8sUpgrades(currentK8s, supportedK8s)
|
||||
sort.Strings(newKubernetes)
|
||||
newKubernetes := filterK8sUpgrades(current.k8s, supported.k8s)
|
||||
semver.Sort(newKubernetes)
|
||||
|
||||
supportedImages = filterImageUpgrades(currentImage, supportedImages)
|
||||
newImages, err := u.collect.newMeasurementes(cmd.Context(), csp, supportedImages)
|
||||
supported.image = filterImageUpgrades(current.image, supported.image)
|
||||
newImages, err := u.collect.newMeasurements(cmd.Context(), csp, supported.image)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -172,9 +176,12 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
|
||||
newServices: newServices,
|
||||
newImages: newImages,
|
||||
newKubernetes: newKubernetes,
|
||||
currentServices: currentServices,
|
||||
currentImage: currentImage,
|
||||
currentKubernetes: currentK8s,
|
||||
newCLI: supported.cli,
|
||||
newCompatibleCLI: supported.compatibleCLI,
|
||||
currentServices: current.service,
|
||||
currentImage: current.image,
|
||||
currentKubernetes: current.k8s,
|
||||
currentCLI: current.cli,
|
||||
}
|
||||
|
||||
updateMsg, err := upgrade.buildString()
|
||||
@ -204,6 +211,7 @@ func sortedMapKeys[T any](a map[string]T) []string {
|
||||
return keys
|
||||
}
|
||||
|
||||
// filterImageUpgrades filters out image versions that are not valid upgrades.
|
||||
func filterImageUpgrades(currentVersion string, newVersions []versionsapi.Version) []versionsapi.Version {
|
||||
newImages := []versionsapi.Version{}
|
||||
for i := range newVersions {
|
||||
@ -215,6 +223,7 @@ func filterImageUpgrades(currentVersion string, newVersions []versionsapi.Versio
|
||||
return newImages
|
||||
}
|
||||
|
||||
// filterK8sUpgrades filters out K8s versions that are not valid upgrades.
|
||||
func filterK8sUpgrades(currentVersion string, newVersions []string) []string {
|
||||
result := []string{}
|
||||
for i := range newVersions {
|
||||
@ -228,11 +237,13 @@ func filterK8sUpgrades(currentVersion string, newVersions []string) []string {
|
||||
}
|
||||
|
||||
type collector interface {
|
||||
currentVersions(ctx context.Context) (serviceVersions string, imageVersion string, k8sVersion string, err error)
|
||||
supportedVersions(ctx context.Context, version string) (serviceVersions string, imageVersions []versionsapi.Version, k8sVersions []string, err error)
|
||||
currentVersions(ctx context.Context) (currentVersionInfo, error)
|
||||
supportedVersions(ctx context.Context, version, currentK8sVersion string) (supportedVersionInfo, error)
|
||||
newImages(ctx context.Context, version string) ([]versionsapi.Version, error)
|
||||
newMeasurementes(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error)
|
||||
newMeasurements(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error)
|
||||
newerVersions(ctx context.Context, allowedVersions []string) ([]versionsapi.Version, error)
|
||||
newCLIVersions(ctx context.Context) ([]string, error)
|
||||
filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []string, currentK8sVersion string) ([]string, error)
|
||||
}
|
||||
|
||||
type versionCollector struct {
|
||||
@ -243,11 +254,12 @@ type versionCollector struct {
|
||||
client *http.Client
|
||||
rekor rekorVerifier
|
||||
flags upgradeCheckFlags
|
||||
versionsapi versionFetcher
|
||||
cliVersion string
|
||||
log debugLog
|
||||
}
|
||||
|
||||
func (v *versionCollector) newMeasurementes(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
// get expected measurements for each image
|
||||
upgrades, err := getCompatibleImageMeasurements(ctx, v.writer, v.client, v.rekor, []byte(v.flags.cosignPubKey), csp, images, v.log)
|
||||
if err != nil {
|
||||
@ -258,43 +270,79 @@ func (v *versionCollector) newMeasurementes(ctx context.Context, csp cloudprovid
|
||||
return upgrades, nil
|
||||
}
|
||||
|
||||
func (v *versionCollector) currentVersions(ctx context.Context) (serviceVersion string, imageVersion string, k8sVersion string, err error) {
|
||||
type currentVersionInfo struct {
|
||||
service string
|
||||
image string
|
||||
k8s string
|
||||
cli string
|
||||
}
|
||||
|
||||
func (v *versionCollector) currentVersions(ctx context.Context) (currentVersionInfo, error) {
|
||||
helmClient, err := helm.NewClient(kubectl.New(), constants.AdminConfFilename, constants.HelmNamespace, v.log)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("setting up helm client: %w", err)
|
||||
return currentVersionInfo{}, fmt.Errorf("setting up helm client: %w", err)
|
||||
}
|
||||
|
||||
serviceVersions, err := helmClient.Versions()
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("getting service versions: %w", err)
|
||||
return currentVersionInfo{}, fmt.Errorf("getting service versions: %w", err)
|
||||
}
|
||||
|
||||
imageVersion, err = getCurrentImageVersion(ctx, v.checker)
|
||||
imageVersion, err := getCurrentImageVersion(ctx, v.checker)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("getting image version: %w", err)
|
||||
return currentVersionInfo{}, fmt.Errorf("getting image version: %w", err)
|
||||
}
|
||||
|
||||
k8sVersion, err = getCurrentKubernetesVersion(ctx, v.checker)
|
||||
k8sVersion, err := getCurrentKubernetesVersion(ctx, v.checker)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("getting image version: %w", err)
|
||||
return currentVersionInfo{}, fmt.Errorf("getting Kubernetes version: %w", err)
|
||||
}
|
||||
|
||||
return serviceVersions.ConstellationServices(), imageVersion, k8sVersion, nil
|
||||
return currentVersionInfo{
|
||||
service: serviceVersions.ConstellationServices(),
|
||||
image: imageVersion,
|
||||
k8s: k8sVersion,
|
||||
cli: v.cliVersion,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type supportedVersionInfo struct {
|
||||
service string
|
||||
image []versionsapi.Version
|
||||
k8s []string
|
||||
// CLI versions including those incompatible with the current Kubernetes version.
|
||||
cli []string
|
||||
// CLI versions compatible with the current Kubernetes version.
|
||||
compatibleCLI []string
|
||||
}
|
||||
|
||||
// supportedVersions returns slices of supported versions.
|
||||
func (v *versionCollector) supportedVersions(ctx context.Context, version string) (serviceVersion string, imageVersions []versionsapi.Version, k8sVersions []string, err error) {
|
||||
k8sVersions = versions.SupportedK8sVersions()
|
||||
serviceVersion, err = helm.AvailableServiceVersions()
|
||||
func (v *versionCollector) supportedVersions(ctx context.Context, version, currentK8sVersion string) (supportedVersionInfo, error) {
|
||||
k8sVersions := versions.SupportedK8sVersions()
|
||||
serviceVersion, err := helm.AvailableServiceVersions()
|
||||
if err != nil {
|
||||
return "", nil, nil, fmt.Errorf("loading service versions: %w", err)
|
||||
return supportedVersionInfo{}, fmt.Errorf("loading service versions: %w", err)
|
||||
}
|
||||
imageVersions, err = v.newImages(ctx, version)
|
||||
imageVersions, err := v.newImages(ctx, version)
|
||||
if err != nil {
|
||||
return "", nil, nil, fmt.Errorf("loading image versions: %w", err)
|
||||
return supportedVersionInfo{}, fmt.Errorf("loading image versions: %w", err)
|
||||
}
|
||||
cliVersions, err := v.newCLIVersions(ctx)
|
||||
if err != nil {
|
||||
return supportedVersionInfo{}, fmt.Errorf("loading cli versions: %w", err)
|
||||
}
|
||||
compatibleCLIVersions, err := v.filterCompatibleCLIVersions(ctx, cliVersions, currentK8sVersion)
|
||||
if err != nil {
|
||||
return supportedVersionInfo{}, fmt.Errorf("filtering cli versions: %w", err)
|
||||
}
|
||||
|
||||
return serviceVersion, imageVersions, k8sVersions, nil
|
||||
return supportedVersionInfo{
|
||||
service: serviceVersion,
|
||||
image: imageVersions,
|
||||
k8s: k8sVersions,
|
||||
cli: cliVersions,
|
||||
compatibleCLI: compatibleCLIVersions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (v *versionCollector) newImages(ctx context.Context, version string) ([]versionsapi.Version, error) {
|
||||
@ -367,9 +415,12 @@ type versionUpgrade struct {
|
||||
newServices string
|
||||
newImages map[string]measurements.M
|
||||
newKubernetes []string
|
||||
newCLI []string
|
||||
newCompatibleCLI []string
|
||||
currentServices string
|
||||
currentImage string
|
||||
currentKubernetes string
|
||||
currentCLI string
|
||||
}
|
||||
|
||||
func (v *versionUpgrade) buildString() (string, error) {
|
||||
@ -410,8 +461,18 @@ func (v *versionUpgrade) buildString() (string, error) {
|
||||
return result.String(), nil
|
||||
}
|
||||
|
||||
result.WriteString("No upgrades available with this CLI.\nNewer versions may be available at: https://github.com/edgelesssys/constellation/releases\n")
|
||||
// no upgrades available
|
||||
if v.newServices == "" && len(v.newImages) == 0 {
|
||||
if len(v.newCompatibleCLI) > 0 {
|
||||
result.WriteString(fmt.Sprintf("Newer CLI versions that are compatible with your cluster are: %s\n", strings.Join(v.newCompatibleCLI, " ")))
|
||||
return result.String(), nil
|
||||
} else if len(v.newCLI) > 0 {
|
||||
result.WriteString(fmt.Sprintf("There are newer CLIs available (%s), however, you need to upgrade your cluster's Kubernetes version first.\n", strings.Join(v.newCLI, " ")))
|
||||
return result.String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
result.WriteString("You are up to date.\n")
|
||||
return result.String(), nil
|
||||
}
|
||||
|
||||
@ -510,6 +571,85 @@ func getCompatibleImageMeasurements(ctx context.Context, writer io.Writer, clien
|
||||
return upgrades, nil
|
||||
}
|
||||
|
||||
type versionFetcher interface {
|
||||
FetchVersionList(ctx context.Context, list versionsapi.List) (versionsapi.List, error)
|
||||
FetchCLIInfo(ctx context.Context, cliInfo versionsapi.CLIInfo) (versionsapi.CLIInfo, error)
|
||||
}
|
||||
|
||||
// newCLIVersions returns a list of versions of the CLI which are a valid upgrade.
|
||||
func (v *versionCollector) newCLIVersions(ctx context.Context) ([]string, error) {
|
||||
cliVersion, err := conSemver.New(constants.VersionInfo())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing current CLI version: %w", err)
|
||||
}
|
||||
list := versionsapi.List{
|
||||
Ref: v.flags.ref,
|
||||
Stream: v.flags.stream,
|
||||
Granularity: versionsapi.GranularityMajor,
|
||||
Base: fmt.Sprintf("v%d", cliVersion.Major),
|
||||
Kind: versionsapi.VersionKindCLI,
|
||||
}
|
||||
minorList, err := v.versionsapi.FetchVersionList(ctx, list)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing major versions: %w", err)
|
||||
}
|
||||
|
||||
var patchVersions []string
|
||||
for _, version := range minorList.Versions {
|
||||
if err := compatibility.IsValidUpgrade(v.cliVersion, version); err != nil {
|
||||
v.log.Debugf("Skipping incompatible minor version %q: %s", version, err)
|
||||
continue
|
||||
}
|
||||
list := versionsapi.List{
|
||||
Ref: v.flags.ref,
|
||||
Stream: v.flags.stream,
|
||||
Granularity: versionsapi.GranularityMinor,
|
||||
Base: version,
|
||||
Kind: versionsapi.VersionKindCLI,
|
||||
}
|
||||
patchList, err := v.versionsapi.FetchVersionList(ctx, list)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing minor versions for major version %s: %w", version, err)
|
||||
}
|
||||
patchVersions = append(patchVersions, patchList.Versions...)
|
||||
}
|
||||
|
||||
semver.Sort(patchVersions)
|
||||
|
||||
return patchVersions, nil
|
||||
}
|
||||
|
||||
// filterCompatibleCLIVersions filters a list of CLI versions which are compatible with the current Kubernetes version.
|
||||
func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []string, currentK8sVersion string) ([]string, error) {
|
||||
// filter out invalid upgrades and versions which are not compatible with the current Kubernetes version
|
||||
var compatibleVersions []string
|
||||
for _, version := range cliPatchVersions {
|
||||
if err := compatibility.IsValidUpgrade(v.cliVersion, version); err != nil {
|
||||
v.log.Debugf("Skipping incompatible patch version %q: %s", version, err)
|
||||
continue
|
||||
}
|
||||
req := versionsapi.CLIInfo{
|
||||
Ref: v.flags.ref,
|
||||
Stream: v.flags.stream,
|
||||
Version: version,
|
||||
}
|
||||
info, err := v.versionsapi.FetchCLIInfo(ctx, req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fetching CLI info: %w", err)
|
||||
}
|
||||
|
||||
for _, k8sVersion := range info.Kubernetes {
|
||||
if k8sVersion == currentK8sVersion {
|
||||
compatibleVersions = append(compatibleVersions, version)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
semver.Sort(compatibleVersions)
|
||||
|
||||
return compatibleVersions, nil
|
||||
}
|
||||
|
||||
type upgradeCheckFlags struct {
|
||||
configPath string
|
||||
force bool
|
||||
|
@ -42,26 +42,51 @@ func TestBuildString(t *testing.T) {
|
||||
"v2.5.0": measurements.DefaultsFor(cloudprovider.QEMU),
|
||||
},
|
||||
newKubernetes: []string{"v1.24.12", "v1.25.6"},
|
||||
newCLI: []string{"v2.5.0", "v2.6.0"},
|
||||
currentServices: "v2.4.0",
|
||||
currentImage: "v2.4.0",
|
||||
currentKubernetes: "v1.24.5",
|
||||
currentCLI: "v2.4.0",
|
||||
},
|
||||
expected: "The following updates are available with this CLI:\n Kubernetes: v1.24.5 --> v1.24.12 v1.25.6\n Images:\n v2.4.0 --> v2.5.0\n Includes these measurements:\n 4:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 8:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 9:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 11:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 12:\n expected: \"1234123412341234123412341234123412341234123412341234123412341234\"\n warnOnly: false\n 13:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n 15:\n expected: \"0000000000000000000000000000000000000000000000000000000000000000\"\n warnOnly: false\n \n Services: v2.4.0 --> v2.5.0\n",
|
||||
},
|
||||
"cli incompatible with K8s": {
|
||||
upgrade: versionUpgrade{
|
||||
newCLI: []string{"v2.5.0", "v2.6.0"},
|
||||
currentCLI: "v2.4.0",
|
||||
},
|
||||
expected: "There are newer CLIs available (v2.5.0 v2.6.0), however, you need to upgrade your cluster's Kubernetes version first.\n",
|
||||
},
|
||||
"cli compatible with K8s": {
|
||||
upgrade: versionUpgrade{
|
||||
newCompatibleCLI: []string{"v2.5.0", "v2.6.0"},
|
||||
currentCLI: "v2.4.0",
|
||||
},
|
||||
expected: "Newer CLI versions that are compatible with your cluster are: v2.5.0 v2.6.0\n",
|
||||
},
|
||||
"k8s only": {
|
||||
upgrade: versionUpgrade{
|
||||
newKubernetes: []string{"v1.24.12", "v1.25.6"},
|
||||
currentKubernetes: "v1.24.5",
|
||||
},
|
||||
expected: "The following updates are available with this CLI:\n Kubernetes: v1.24.5 --> v1.24.12 v1.25.6\n",
|
||||
},
|
||||
"no upgrades": {
|
||||
upgrade: versionUpgrade{
|
||||
newServices: "",
|
||||
newImages: map[string]measurements.M{},
|
||||
newKubernetes: []string{},
|
||||
newCLI: []string{},
|
||||
currentServices: "v2.5.0",
|
||||
currentImage: "v2.5.0",
|
||||
currentKubernetes: "v1.25.6",
|
||||
currentCLI: "v2.5.0",
|
||||
},
|
||||
expected: "No upgrades available with this CLI.\nNewer versions may be available at: https://github.com/edgelesssys/constellation/releases\n",
|
||||
expected: "You are up to date.\n",
|
||||
},
|
||||
"no upgrades #2": {
|
||||
upgrade: versionUpgrade{},
|
||||
expected: "No upgrades available with this CLI.\nNewer versions may be available at: https://github.com/edgelesssys/constellation/releases\n",
|
||||
expected: "You are up to date.\n",
|
||||
},
|
||||
}
|
||||
|
||||
@ -217,8 +242,9 @@ func TestUpgradeCheck(t *testing.T) {
|
||||
currentServicesVersions: "v2.4.0",
|
||||
currentImageVersion: "v2.4.0",
|
||||
currentK8sVersion: "v1.24.5",
|
||||
currentCLIVersion: "v2.4.0",
|
||||
images: []versionsapi.Version{v2_5},
|
||||
newCLIVersions: []string{"v2.5.0", "v2.6.0"},
|
||||
newCLIVersionsList: []string{"v2.5.0", "v2.6.0"},
|
||||
},
|
||||
flags: upgradeCheckFlags{
|
||||
configPath: constants.ConfigFilename,
|
||||
@ -255,28 +281,41 @@ func TestUpgradeCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
type stubVersionCollector struct {
|
||||
supportedServicesVersions string
|
||||
supportedImages []versionsapi.Version
|
||||
supportedImageVersions map[string]measurements.M
|
||||
supportedK8sVersions []string
|
||||
currentServicesVersions string
|
||||
currentImageVersion string
|
||||
currentK8sVersion string
|
||||
images []versionsapi.Version
|
||||
newCLIVersions []string
|
||||
someErr error
|
||||
supportedServicesVersions string
|
||||
supportedImages []versionsapi.Version
|
||||
supportedImageVersions map[string]measurements.M
|
||||
supportedK8sVersions []string
|
||||
supportedCLIVersions []string
|
||||
currentServicesVersions string
|
||||
currentImageVersion string
|
||||
currentK8sVersion string
|
||||
currentCLIVersion string
|
||||
images []versionsapi.Version
|
||||
newCLIVersionsList []string
|
||||
newCompatibleCLIVersionsList []string
|
||||
someErr error
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) newMeasurementes(_ context.Context, _ cloudprovider.Provider, _ []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
func (s *stubVersionCollector) newMeasurements(ctx context.Context, csp cloudprovider.Provider, images []versionsapi.Version) (map[string]measurements.M, error) {
|
||||
return s.supportedImageVersions, nil
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) currentVersions(_ context.Context) (serviceVersions string, imageVersion string, k8sVersion string, err error) {
|
||||
return s.currentServicesVersions, s.currentImageVersion, s.currentK8sVersion, s.someErr
|
||||
func (s *stubVersionCollector) currentVersions(ctx context.Context) (currentVersionInfo, error) {
|
||||
return currentVersionInfo{
|
||||
service: s.currentServicesVersions,
|
||||
image: s.currentImageVersion,
|
||||
k8s: s.currentK8sVersion,
|
||||
cli: s.currentCLIVersion,
|
||||
}, s.someErr
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) supportedVersions(_ context.Context, _ string) (serviceVersions string, imageVersions []versionsapi.Version, k8sVersions []string, err error) {
|
||||
return s.supportedServicesVersions, s.supportedImages, s.supportedK8sVersions, s.someErr
|
||||
func (s *stubVersionCollector) supportedVersions(ctx context.Context, version, currentK8sVersion string) (supportedVersionInfo, error) {
|
||||
return supportedVersionInfo{
|
||||
service: s.supportedServicesVersions,
|
||||
image: s.supportedImages,
|
||||
k8s: s.supportedK8sVersions,
|
||||
cli: s.supportedCLIVersions,
|
||||
}, s.someErr
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) newImages(_ context.Context, _ string) ([]versionsapi.Version, error) {
|
||||
@ -287,6 +326,14 @@ func (s *stubVersionCollector) newerVersions(_ context.Context, _ []string) ([]v
|
||||
return s.images, nil
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) newCLIVersions(ctx context.Context) ([]string, error) {
|
||||
return s.newCLIVersionsList, nil
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []string, currentK8sVersion string) ([]string, error) {
|
||||
return s.newCompatibleCLIVersionsList, nil
|
||||
}
|
||||
|
||||
type stubUpgradeChecker struct {
|
||||
image string
|
||||
k8sVersion string
|
||||
@ -300,3 +347,121 @@ func (u stubUpgradeChecker) CurrentImage(context.Context) (string, error) {
|
||||
func (u stubUpgradeChecker) CurrentKubernetesVersion(_ context.Context) (string, error) {
|
||||
return u.k8sVersion, u.err
|
||||
}
|
||||
|
||||
func TestNewCLIVersions(t *testing.T) {
|
||||
someErr := errors.New("some error")
|
||||
minorList := func() versionsapi.List {
|
||||
return versionsapi.List{
|
||||
Versions: []string{"v0.2.0"},
|
||||
}
|
||||
}
|
||||
patchList := func() versionsapi.List {
|
||||
return versionsapi.List{
|
||||
Versions: []string{"v0.2.1"},
|
||||
}
|
||||
}
|
||||
emptyVerList := func() versionsapi.List {
|
||||
return versionsapi.List{}
|
||||
}
|
||||
verCollector := func(minorList, patchList versionsapi.List, verListErr error) versionCollector {
|
||||
return versionCollector{
|
||||
cliVersion: "v0.1.0",
|
||||
versionsapi: stubVersionFetcher{
|
||||
minorList: minorList,
|
||||
patchList: patchList,
|
||||
versionListErr: verListErr,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
verCollector versionCollector
|
||||
wantErr bool
|
||||
}{
|
||||
"works": {
|
||||
verCollector: verCollector(minorList(), patchList(), nil),
|
||||
},
|
||||
"empty versions list": {
|
||||
verCollector: verCollector(emptyVerList(), emptyVerList(), nil),
|
||||
},
|
||||
"version list error": {
|
||||
verCollector: verCollector(minorList(), patchList(), someErr),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
_, err := tc.verCollector.newCLIVersions(context.Background())
|
||||
if tc.wantErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterCompatibleCLIVersions(t *testing.T) {
|
||||
someErr := errors.New("some error")
|
||||
verCollector := func(cliInfoErr error) versionCollector {
|
||||
return versionCollector{
|
||||
cliVersion: "v0.1.0",
|
||||
versionsapi: stubVersionFetcher{
|
||||
cliInfoErr: cliInfoErr,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
verCollector versionCollector
|
||||
cliPatchVersions []string
|
||||
wantErr bool
|
||||
}{
|
||||
"works": {
|
||||
verCollector: verCollector(nil),
|
||||
cliPatchVersions: []string{"v0.1.1"},
|
||||
},
|
||||
"cli info error": {
|
||||
verCollector: verCollector(someErr),
|
||||
cliPatchVersions: []string{"v0.1.1"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
|
||||
_, err := tc.verCollector.filterCompatibleCLIVersions(context.Background(), tc.cliPatchVersions, "v1.24.5")
|
||||
if tc.wantErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type stubVersionFetcher struct {
|
||||
minorList versionsapi.List
|
||||
patchList versionsapi.List
|
||||
versionListErr error
|
||||
cliInfoErr error
|
||||
}
|
||||
|
||||
func (f stubVersionFetcher) FetchVersionList(ctx context.Context, list versionsapi.List) (versionsapi.List, error) {
|
||||
switch list.Granularity {
|
||||
case versionsapi.GranularityMajor:
|
||||
return f.minorList, f.versionListErr
|
||||
case versionsapi.GranularityMinor:
|
||||
return f.patchList, f.versionListErr
|
||||
}
|
||||
return versionsapi.List{}, f.versionListErr
|
||||
}
|
||||
|
||||
func (f stubVersionFetcher) FetchCLIInfo(ctx context.Context, cliInfo versionsapi.CLIInfo) (versionsapi.CLIInfo, error) {
|
||||
return versionsapi.CLIInfo{}, f.cliInfoErr
|
||||
}
|
||||
|
@ -15,5 +15,7 @@ go_library(
|
||||
go_binary(
|
||||
name = "clidocgen",
|
||||
embed = [":clidocgen_lib"],
|
||||
# keep
|
||||
pure = "on",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
@ -18,11 +18,11 @@ import (
|
||||
|
||||
// CLIInfo contains information about a specific CLI version (i.e. it's compatibility with Kubernetes versions).
|
||||
type CLIInfo struct {
|
||||
// Ref is the reference name of the image.
|
||||
// Ref is the reference name of the CLI.
|
||||
Ref string `json:"ref,omitempty"`
|
||||
// Stream is the stream name of the image.
|
||||
// Stream is the stream name of the CLI.
|
||||
Stream string `json:"stream,omitempty"`
|
||||
// Version is the version of the image.
|
||||
// Version is the version of the CLI.
|
||||
Version string `json:"version,omitempty"`
|
||||
// Kubernetes contains all compatible Kubernetes versions.
|
||||
Kubernetes []string `json:"kubernetes,omitempty"`
|
||||
|
Loading…
Reference in New Issue
Block a user