mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-24 06:59:40 -05:00
cli: use Semver type to represent microservice versions (#2125)
Previously we used strings to pass microservice versions. This invited bugs due to missing input validation.
This commit is contained in:
parent
2d3999440d
commit
1d5a8283e0
@ -33,7 +33,7 @@ func run(issuer atls.Issuer, openDevice vtpm.TPMOpenFunc, fileHandler file.Handl
|
||||
) {
|
||||
defer cloudLogger.Close()
|
||||
|
||||
log.With(zap.String("version", constants.VersionInfo())).Infof("Starting bootstrapper")
|
||||
log.With(zap.String("version", constants.BinaryVersion().String())).Infof("Starting bootstrapper")
|
||||
cloudLogger.Disclose("bootstrapper started running...")
|
||||
|
||||
uuid, err := getDiskUUID()
|
||||
|
@ -157,6 +157,7 @@ go_test(
|
||||
"//internal/kms/uri",
|
||||
"//internal/license",
|
||||
"//internal/logger",
|
||||
"//internal/semver",
|
||||
"//internal/versions",
|
||||
"//operators/constellation-node-operator/api/v1alpha1",
|
||||
"//verify/verifyproto",
|
||||
|
@ -86,7 +86,7 @@ func (c *createCmd) create(cmd *cobra.Command, creator cloudCreator, fileHandler
|
||||
return err
|
||||
}
|
||||
if !flags.force {
|
||||
if err := validateCLIandConstellationVersionAreEqual(constants.VersionInfo(), conf.Image, conf.MicroserviceVersion); err != nil {
|
||||
if err := validateCLIandConstellationVersionAreEqual(constants.BinaryVersion(), conf.Image, conf.MicroserviceVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -301,7 +301,7 @@ func must(err error) {
|
||||
}
|
||||
|
||||
// validateCLIandConstellationVersionAreEqual checks if the image and microservice version are equal (down to patch level) to the CLI version.
|
||||
func validateCLIandConstellationVersionAreEqual(cliVersion, imageVersion, microserviceVersion string) error {
|
||||
func validateCLIandConstellationVersionAreEqual(cliVersion semver.Semver, imageVersion string, microserviceVersion semver.Semver) error {
|
||||
parsedImageVersion, err := versionsapi.NewVersionFromShortPath(imageVersion, versionsapi.VersionKindImage)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing image version: %w", err)
|
||||
@ -312,21 +312,11 @@ func validateCLIandConstellationVersionAreEqual(cliVersion, imageVersion, micros
|
||||
return fmt.Errorf("parsing image semantical version: %w", err)
|
||||
}
|
||||
|
||||
semMicro, err := semver.New(microserviceVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing microservice version: %w", err)
|
||||
if !cliVersion.MajorMinorEqual(semImage) {
|
||||
return fmt.Errorf("image version %q does not match the major and minor version of the cli version %q", semImage.String(), cliVersion.String())
|
||||
}
|
||||
|
||||
semCLI, err := semver.New(cliVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing binary version: %w", err)
|
||||
}
|
||||
|
||||
if !semCLI.MajorMinorEqual(semImage) {
|
||||
return fmt.Errorf("image version %q does not match the major and minor version of the cli version %q", semImage.String(), semCLI.String())
|
||||
}
|
||||
if semCLI.Compare(semMicro) != 0 {
|
||||
return fmt.Errorf("cli version %q does not match microservice version %q", semCLI.String(), semMicro.String())
|
||||
if cliVersion.Compare(microserviceVersion) != 0 {
|
||||
return fmt.Errorf("cli version %q does not match microservice version %q", cliVersion.String(), microserviceVersion.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -273,52 +274,52 @@ func TestCheckDirClean(t *testing.T) {
|
||||
func TestValidateCLIandConstellationVersionCompatibility(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
imageVersion string
|
||||
microServiceVersion string
|
||||
cliVersion string
|
||||
microServiceVersion consemver.Semver
|
||||
cliVersion consemver.Semver
|
||||
wantErr bool
|
||||
}{
|
||||
"empty": {
|
||||
imageVersion: "",
|
||||
microServiceVersion: "",
|
||||
cliVersion: "",
|
||||
microServiceVersion: consemver.Semver{},
|
||||
cliVersion: consemver.Semver{},
|
||||
wantErr: true,
|
||||
},
|
||||
"invalid when image < CLI": {
|
||||
imageVersion: "v2.7.1",
|
||||
microServiceVersion: "v2.8.0",
|
||||
cliVersion: "v2.8.0",
|
||||
microServiceVersion: consemver.NewFromInt(2, 8, 0, ""),
|
||||
cliVersion: consemver.NewFromInt(2, 8, 0, ""),
|
||||
wantErr: true,
|
||||
},
|
||||
"invalid when microservice < CLI": {
|
||||
imageVersion: "v2.8.0",
|
||||
microServiceVersion: "v2.7.1",
|
||||
cliVersion: "v2.8.0",
|
||||
microServiceVersion: consemver.NewFromInt(2, 7, 1, ""),
|
||||
cliVersion: consemver.NewFromInt(2, 8, 0, ""),
|
||||
wantErr: true,
|
||||
},
|
||||
"valid release version": {
|
||||
imageVersion: "v2.9.0",
|
||||
microServiceVersion: "v2.9.0",
|
||||
cliVersion: "2.9.0",
|
||||
microServiceVersion: consemver.NewFromInt(2, 9, 0, ""),
|
||||
cliVersion: consemver.NewFromInt(2, 9, 0, ""),
|
||||
},
|
||||
"valid pre-version": {
|
||||
imageVersion: "ref/main/stream/nightly/v2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: "v2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
cliVersion: "2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
cliVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
},
|
||||
"image version suffix need not be equal to CLI version": {
|
||||
imageVersion: "ref/main/stream/nightly/v2.9.0-pre.0.19990626150512-9z36ce61799z",
|
||||
microServiceVersion: "v2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
cliVersion: "2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
cliVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
},
|
||||
"image version can have different patch version": {
|
||||
imageVersion: "ref/main/stream/nightly/v2.9.1-pre.0.19990626150512-9z36ce61799z",
|
||||
microServiceVersion: "v2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
cliVersion: "2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
cliVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
},
|
||||
"microService version suffix must be equal to CLI version": {
|
||||
imageVersion: "ref/main/stream/nightly/v2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: "v2.9.0-pre.0.19990626150512-9z36ce61799z",
|
||||
cliVersion: "2.9.0-pre.0.20230626150512-0a36ce61719f",
|
||||
microServiceVersion: consemver.NewFromInt(2, 9, 0, "pre.0.19990626150512-9z36ce61799z"),
|
||||
cliVersion: consemver.NewFromInt(2, 9, 0, "pre.0.20230626150512-0a36ce61719f"),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func (i *initCmd) initialize(cmd *cobra.Command, newDialer func(validator atls.V
|
||||
return err
|
||||
}
|
||||
if !flags.force {
|
||||
if err := validateCLIandConstellationVersionAreEqual(constants.VersionInfo(), conf.Image, conf.MicroserviceVersion); err != nil {
|
||||
if err := validateCLIandConstellationVersionAreEqual(constants.BinaryVersion(), conf.Image, conf.MicroserviceVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ func (m *stubMerger) kubeconfigEnvVar() string {
|
||||
func defaultConfigWithExpectedMeasurements(t *testing.T, conf *config.Config, csp cloudprovider.Provider) *config.Config {
|
||||
t.Helper()
|
||||
|
||||
conf.Image = "v" + constants.VersionInfo()
|
||||
conf.Image = constants.BinaryVersion().String()
|
||||
conf.Name = "kubernetes"
|
||||
|
||||
switch csp {
|
||||
|
@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -117,7 +118,7 @@ func TestStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
helmClient: stubHelmClient{
|
||||
serviceVersions: helm.NewServiceVersions("v1.0.0", "v1.0.0", "v1.1.0", "v1.1.0"),
|
||||
serviceVersions: helm.NewServiceVersions(consemver.NewFromInt(1, 0, 0, ""), consemver.NewFromInt(1, 0, 0, ""), consemver.NewFromInt(1, 1, 0, ""), consemver.NewFromInt(1, 1, 0, "")),
|
||||
},
|
||||
nodeVersion: updatev1alpha1.NodeVersion{
|
||||
Spec: updatev1alpha1.NodeVersionSpec{
|
||||
@ -167,7 +168,7 @@ func TestStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
helmClient: stubHelmClient{
|
||||
serviceVersions: helm.NewServiceVersions("v1.0.0", "v1.0.0", "v1.1.0", "v1.1.0"),
|
||||
serviceVersions: helm.NewServiceVersions(consemver.NewFromInt(1, 0, 0, ""), consemver.NewFromInt(1, 0, 0, ""), consemver.NewFromInt(1, 1, 0, ""), consemver.NewFromInt(1, 1, 0, "")),
|
||||
},
|
||||
nodeVersion: updatev1alpha1.NodeVersion{
|
||||
Spec: updatev1alpha1.NodeVersionSpec{
|
||||
|
@ -33,7 +33,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
|
||||
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
|
||||
conSemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/sigstore"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
@ -93,7 +93,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
|
||||
cosign: sigstore.CosignVerifier{},
|
||||
rekor: rekor,
|
||||
flags: flags,
|
||||
cliVersion: compatibility.EnsurePrefixV(constants.VersionInfo()),
|
||||
cliVersion: constants.BinaryVersion(),
|
||||
log: log,
|
||||
versionsapi: versionfetcher,
|
||||
},
|
||||
@ -202,9 +202,9 @@ func (u *upgradeCheckCmd) upgradeCheck(cmd *cobra.Command, fileHandler file.Hand
|
||||
|
||||
// Filter versions to only include upgrades
|
||||
newServices := supported.service
|
||||
if err := compatibility.IsValidUpgrade(current.service, supported.service); err != nil {
|
||||
newServices = ""
|
||||
u.log.Debugf("No valid service upgrades are available from %q to %q. The minor version can only drift by 1.\n", current.service, supported.service)
|
||||
if err := supported.service.IsUpgradeTo(current.service); err != nil {
|
||||
newServices = consemver.Semver{}
|
||||
u.log.Debugf("No valid service upgrades are available from %q to %q. The minor version can only drift by 1.\n", current.service.String(), supported.service.String())
|
||||
}
|
||||
|
||||
newKubernetes := filterK8sUpgrades(current.k8s, supported.k8s)
|
||||
@ -352,8 +352,8 @@ type collector interface {
|
||||
newImages(ctx context.Context, version string) ([]versionsapi.Version, error)
|
||||
newMeasurements(ctx context.Context, csp cloudprovider.Provider, attestationVariant variant.Variant, 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)
|
||||
newCLIVersions(ctx context.Context) ([]consemver.Semver, error)
|
||||
filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion string) ([]consemver.Semver, error)
|
||||
}
|
||||
|
||||
type versionCollector struct {
|
||||
@ -366,7 +366,7 @@ type versionCollector struct {
|
||||
rekor rekorVerifier
|
||||
flags upgradeCheckFlags
|
||||
versionsapi versionFetcher
|
||||
cliVersion string
|
||||
cliVersion consemver.Semver
|
||||
log debugLog
|
||||
}
|
||||
|
||||
@ -382,10 +382,10 @@ func (v *versionCollector) newMeasurements(ctx context.Context, csp cloudprovide
|
||||
}
|
||||
|
||||
type currentVersionInfo struct {
|
||||
service string
|
||||
service consemver.Semver
|
||||
image string
|
||||
k8s string
|
||||
cli string
|
||||
cli consemver.Semver
|
||||
}
|
||||
|
||||
func (v *versionCollector) currentVersions(ctx context.Context) (currentVersionInfo, error) {
|
||||
@ -418,20 +418,18 @@ func (v *versionCollector) currentVersions(ctx context.Context) (currentVersionI
|
||||
}
|
||||
|
||||
type supportedVersionInfo struct {
|
||||
service string
|
||||
service consemver.Semver
|
||||
image []versionsapi.Version
|
||||
k8s []string
|
||||
// CLI versions including those incompatible with the current Kubernetes version.
|
||||
cli []string
|
||||
cli []consemver.Semver
|
||||
// CLI versions compatible with the current Kubernetes version.
|
||||
compatibleCLI []string
|
||||
compatibleCLI []consemver.Semver
|
||||
}
|
||||
|
||||
// supportedVersions returns slices of supported versions.
|
||||
func (v *versionCollector) supportedVersions(ctx context.Context, version, currentK8sVersion string) (supportedVersionInfo, error) {
|
||||
k8sVersions := versions.SupportedK8sVersions()
|
||||
// Each CLI comes with a set of services that have the same version as the CLI.
|
||||
serviceVersion := compatibility.EnsurePrefixV(constants.VersionInfo())
|
||||
|
||||
imageVersions, err := v.newImages(ctx, version)
|
||||
if err != nil {
|
||||
@ -447,7 +445,8 @@ func (v *versionCollector) supportedVersions(ctx context.Context, version, curre
|
||||
}
|
||||
|
||||
return supportedVersionInfo{
|
||||
service: serviceVersion,
|
||||
// Each CLI comes with a set of services that have the same version as the CLI.
|
||||
service: constants.BinaryVersion(),
|
||||
image: imageVersions,
|
||||
k8s: k8sVersions,
|
||||
cli: cliVersions,
|
||||
@ -462,7 +461,7 @@ func (v *versionCollector) newImages(ctx context.Context, version string) ([]ver
|
||||
// additionally, we allow updates to the next minor version (e.g. 0.1.0 -> 0.2.0)
|
||||
// if the CLI minor version is newer than the cluster minor version
|
||||
currentImageMinorVer := semver.MajorMinor(version)
|
||||
currentCLIMinorVer := semver.MajorMinor(v.cliVersion)
|
||||
currentCLIMinorVer := semver.MajorMinor(v.cliVersion.String())
|
||||
nextImageMinorVer, err := compatibility.NextMinorVersion(currentImageMinorVer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("calculating next image minor version: %w", err)
|
||||
@ -522,15 +521,15 @@ func (v *versionCollector) newerVersions(ctx context.Context, allowedVersions []
|
||||
}
|
||||
|
||||
type versionUpgrade struct {
|
||||
newServices string
|
||||
newServices consemver.Semver
|
||||
newImages map[string]measurements.M
|
||||
newKubernetes []string
|
||||
newCLI []string
|
||||
newCompatibleCLI []string
|
||||
currentServices string
|
||||
newCLI []consemver.Semver
|
||||
newCompatibleCLI []consemver.Semver
|
||||
currentServices consemver.Semver
|
||||
currentImage string
|
||||
currentKubernetes string
|
||||
currentCLI string
|
||||
currentCLI consemver.Semver
|
||||
}
|
||||
|
||||
func (v *versionUpgrade) buildString() (string, error) {
|
||||
@ -560,7 +559,7 @@ func (v *versionUpgrade) buildString() (string, error) {
|
||||
fmt.Fprintln(&upgradeMsg, "")
|
||||
}
|
||||
|
||||
if v.newServices != "" {
|
||||
if v.newServices != (consemver.Semver{}) {
|
||||
upgradeMsg.WriteString(fmt.Sprintf(" Services: %s --> %s\n", v.currentServices, v.newServices))
|
||||
}
|
||||
|
||||
@ -572,12 +571,12 @@ func (v *versionUpgrade) buildString() (string, error) {
|
||||
}
|
||||
|
||||
// no upgrades available
|
||||
if v.newServices == "" && len(v.newImages) == 0 {
|
||||
if v.newServices == (consemver.Semver{}) && 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, " ")))
|
||||
result.WriteString(fmt.Sprintf("Newer CLI versions that are compatible with your cluster are: %s\n", strings.Join(consemver.ToStrings(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, " ")))
|
||||
result.WriteString(fmt.Sprintf("There are newer CLIs available (%s), however, you need to upgrade your cluster's Kubernetes version first.\n", strings.Join(consemver.ToStrings(v.newCLI), " ")))
|
||||
return result.String(), nil
|
||||
}
|
||||
}
|
||||
@ -589,7 +588,7 @@ func (v *versionUpgrade) buildString() (string, error) {
|
||||
func (v *versionUpgrade) writeConfig(conf *config.Config, fileHandler file.Handler, configPath string) error {
|
||||
// can't sort image map because maps are unsorted. services is only one string, k8s versions are sorted.
|
||||
|
||||
if v.newServices != "" {
|
||||
if v.newServices != (consemver.Semver{}) {
|
||||
conf.MicroserviceVersion = v.newServices
|
||||
}
|
||||
if len(v.newKubernetes) > 0 {
|
||||
@ -685,16 +684,12 @@ type versionFetcher interface {
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
func (v *versionCollector) newCLIVersions(ctx context.Context) ([]consemver.Semver, error) {
|
||||
list := versionsapi.List{
|
||||
Ref: v.flags.ref,
|
||||
Stream: v.flags.stream,
|
||||
Granularity: versionsapi.GranularityMajor,
|
||||
Base: fmt.Sprintf("v%d", cliVersion.Major),
|
||||
Base: fmt.Sprintf("v%d", constants.BinaryVersion().Major()),
|
||||
Kind: versionsapi.VersionKindCLI,
|
||||
}
|
||||
minorList, err := v.versionsapi.FetchVersionList(ctx, list)
|
||||
@ -704,7 +699,11 @@ func (v *versionCollector) newCLIVersions(ctx context.Context) ([]string, error)
|
||||
|
||||
var patchVersions []string
|
||||
for _, version := range minorList.Versions {
|
||||
if err := compatibility.IsValidUpgrade(v.cliVersion, version); err != nil {
|
||||
target, err := consemver.New(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing version %s: %w", version, err)
|
||||
}
|
||||
if err := target.IsUpgradeTo(v.cliVersion); err != nil {
|
||||
v.log.Debugf("Skipping incompatible minor version %q: %s", version, err)
|
||||
continue
|
||||
}
|
||||
@ -722,24 +721,29 @@ func (v *versionCollector) newCLIVersions(ctx context.Context) ([]string, error)
|
||||
patchVersions = append(patchVersions, patchList.Versions...)
|
||||
}
|
||||
|
||||
semver.Sort(patchVersions)
|
||||
out, err := consemver.NewSlice(patchVersions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing versions: %w", err)
|
||||
}
|
||||
|
||||
return patchVersions, nil
|
||||
consemver.Sort(out)
|
||||
|
||||
return out, 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) {
|
||||
func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliPatchVersions []consemver.Semver, currentK8sVersion string) ([]consemver.Semver, error) {
|
||||
// filter out invalid upgrades and versions which are not compatible with the current Kubernetes version
|
||||
var compatibleVersions []string
|
||||
var compatibleVersions []consemver.Semver
|
||||
for _, version := range cliPatchVersions {
|
||||
if err := compatibility.IsValidUpgrade(v.cliVersion, version); err != nil {
|
||||
if err := version.IsUpgradeTo(v.cliVersion); 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,
|
||||
Version: version.String(),
|
||||
}
|
||||
info, err := v.versionsapi.FetchCLIInfo(ctx, req)
|
||||
if err != nil {
|
||||
@ -753,7 +757,7 @@ func (v *versionCollector) filterCompatibleCLIVersions(ctx context.Context, cliP
|
||||
}
|
||||
}
|
||||
|
||||
semver.Sort(compatibleVersions)
|
||||
consemver.Sort(compatibleVersions)
|
||||
|
||||
return compatibleVersions, nil
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -40,30 +41,30 @@ func TestBuildString(t *testing.T) {
|
||||
}{
|
||||
"update everything": {
|
||||
upgrade: versionUpgrade{
|
||||
newServices: "v2.5.0",
|
||||
newServices: consemver.NewFromInt(2, 5, 0, ""),
|
||||
newImages: map[string]measurements.M{
|
||||
"v2.5.0": measurements.DefaultsFor(cloudprovider.QEMU, variant.QEMUVTPM{}),
|
||||
},
|
||||
newKubernetes: []string{"v1.24.12", "v1.25.6"},
|
||||
newCLI: []string{"v2.5.0", "v2.6.0"},
|
||||
currentServices: "v2.4.0",
|
||||
newCLI: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")},
|
||||
currentServices: consemver.NewFromInt(2, 4, 0, ""),
|
||||
currentImage: "v2.4.0",
|
||||
currentKubernetes: "v1.24.5",
|
||||
currentCLI: "v2.4.0",
|
||||
currentCLI: consemver.NewFromInt(2, 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",
|
||||
newCLI: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")},
|
||||
currentCLI: consemver.NewFromInt(2, 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",
|
||||
newCompatibleCLI: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")},
|
||||
currentCLI: consemver.NewFromInt(2, 4, 0, ""),
|
||||
},
|
||||
expected: "Newer CLI versions that are compatible with your cluster are: v2.5.0 v2.6.0\n",
|
||||
},
|
||||
@ -76,14 +77,14 @@ func TestBuildString(t *testing.T) {
|
||||
},
|
||||
"no upgrades": {
|
||||
upgrade: versionUpgrade{
|
||||
newServices: "",
|
||||
newServices: consemver.Semver{},
|
||||
newImages: map[string]measurements.M{},
|
||||
newKubernetes: []string{},
|
||||
newCLI: []string{},
|
||||
currentServices: "v2.5.0",
|
||||
newCLI: []consemver.Semver{},
|
||||
currentServices: consemver.NewFromInt(2, 5, 0, ""),
|
||||
currentImage: "v2.5.0",
|
||||
currentKubernetes: "v1.25.6",
|
||||
currentCLI: "v2.5.0",
|
||||
currentCLI: consemver.NewFromInt(2, 5, 0, ""),
|
||||
},
|
||||
expected: "You are up to date.\n",
|
||||
},
|
||||
@ -227,18 +228,18 @@ func TestUpgradeCheck(t *testing.T) {
|
||||
Kind: versionsapi.VersionKindImage,
|
||||
}
|
||||
collector := stubVersionCollector{
|
||||
supportedServicesVersions: "v2.5.0",
|
||||
supportedServicesVersions: consemver.NewFromInt(2, 5, 0, ""),
|
||||
supportedImages: []versionsapi.Version{v2_3},
|
||||
supportedImageVersions: map[string]measurements.M{
|
||||
"v2.3.0": measurements.DefaultsFor(cloudprovider.GCP, variant.GCPSEVES{}),
|
||||
},
|
||||
supportedK8sVersions: []string{"v1.24.5", "v1.24.12", "v1.25.6"},
|
||||
currentServicesVersions: "v2.4.0",
|
||||
currentServicesVersions: consemver.NewFromInt(2, 4, 0, ""),
|
||||
currentImageVersion: "v2.4.0",
|
||||
currentK8sVersion: "v1.24.5",
|
||||
currentCLIVersion: "v2.4.0",
|
||||
currentCLIVersion: consemver.NewFromInt(2, 4, 0, ""),
|
||||
images: []versionsapi.Version{v2_5},
|
||||
newCLIVersionsList: []string{"v2.5.0", "v2.6.0"},
|
||||
newCLIVersionsList: []consemver.Semver{consemver.NewFromInt(2, 5, 0, ""), consemver.NewFromInt(2, 6, 0, "")},
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
@ -305,18 +306,18 @@ func TestUpgradeCheck(t *testing.T) {
|
||||
}
|
||||
|
||||
type stubVersionCollector struct {
|
||||
supportedServicesVersions string
|
||||
supportedServicesVersions consemver.Semver
|
||||
supportedImages []versionsapi.Version
|
||||
supportedImageVersions map[string]measurements.M
|
||||
supportedK8sVersions []string
|
||||
supportedCLIVersions []string
|
||||
currentServicesVersions string
|
||||
supportedCLIVersions []consemver.Semver
|
||||
currentServicesVersions consemver.Semver
|
||||
currentImageVersion string
|
||||
currentK8sVersion string
|
||||
currentCLIVersion string
|
||||
currentCLIVersion consemver.Semver
|
||||
images []versionsapi.Version
|
||||
newCLIVersionsList []string
|
||||
newCompatibleCLIVersionsList []string
|
||||
newCLIVersionsList []consemver.Semver
|
||||
newCompatibleCLIVersionsList []consemver.Semver
|
||||
someErr error
|
||||
}
|
||||
|
||||
@ -350,11 +351,11 @@ func (s *stubVersionCollector) newerVersions(_ context.Context, _ []string) ([]v
|
||||
return s.images, nil
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) newCLIVersions(_ context.Context) ([]string, error) {
|
||||
func (s *stubVersionCollector) newCLIVersions(_ context.Context) ([]consemver.Semver, error) {
|
||||
return s.newCLIVersionsList, nil
|
||||
}
|
||||
|
||||
func (s *stubVersionCollector) filterCompatibleCLIVersions(_ context.Context, _ []string, _ string) ([]string, error) {
|
||||
func (s *stubVersionCollector) filterCompatibleCLIVersions(_ context.Context, _ []consemver.Semver, _ string) ([]consemver.Semver, error) {
|
||||
return s.newCompatibleCLIVersionsList, nil
|
||||
}
|
||||
|
||||
@ -408,7 +409,7 @@ func TestNewCLIVersions(t *testing.T) {
|
||||
}
|
||||
verCollector := func(minorList, patchList versionsapi.List, verListErr error) versionCollector {
|
||||
return versionCollector{
|
||||
cliVersion: "v0.1.0",
|
||||
cliVersion: consemver.NewFromInt(0, 1, 0, ""),
|
||||
versionsapi: stubVersionFetcher{
|
||||
minorList: minorList,
|
||||
patchList: patchList,
|
||||
@ -451,7 +452,7 @@ func TestFilterCompatibleCLIVersions(t *testing.T) {
|
||||
someErr := errors.New("some error")
|
||||
verCollector := func(cliInfoErr error) versionCollector {
|
||||
return versionCollector{
|
||||
cliVersion: "v0.1.0",
|
||||
cliVersion: consemver.NewFromInt(0, 1, 0, ""),
|
||||
versionsapi: stubVersionFetcher{
|
||||
cliInfoErr: cliInfoErr,
|
||||
},
|
||||
@ -460,16 +461,16 @@ func TestFilterCompatibleCLIVersions(t *testing.T) {
|
||||
|
||||
testCases := map[string]struct {
|
||||
verCollector versionCollector
|
||||
cliPatchVersions []string
|
||||
cliPatchVersions []consemver.Semver
|
||||
wantErr bool
|
||||
}{
|
||||
"works": {
|
||||
verCollector: verCollector(nil),
|
||||
cliPatchVersions: []string{"v0.1.1"},
|
||||
cliPatchVersions: []consemver.Semver{consemver.NewFromInt(0, 1, 1, "")},
|
||||
},
|
||||
"cli info error": {
|
||||
verCollector: verCollector(someErr),
|
||||
cliPatchVersions: []string{"v0.1.1"},
|
||||
cliPatchVersions: []consemver.Semver{consemver.NewFromInt(0, 1, 1, "")},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func runVersion(cmd *cobra.Command, _ []string) {
|
||||
commit, state, date, goVersion, compiler, platform = parseStamp()
|
||||
}
|
||||
|
||||
cmd.Printf("Version:\t%s (%s)\n", constants.VersionInfo(), constants.VersionBuild)
|
||||
cmd.Printf("Version:\t%s (%s)\n", constants.BinaryVersion().String(), constants.VersionBuild)
|
||||
cmd.Printf("GitCommit:\t%s\n", commit)
|
||||
cmd.Printf("GitTreeState:\t%s\n", state)
|
||||
cmd.Printf("BuildDate:\t%s\n", date)
|
||||
|
@ -30,7 +30,7 @@ func TestVersionCmd(t *testing.T) {
|
||||
|
||||
s, err := io.ReadAll(b)
|
||||
assert.NoError(err)
|
||||
assert.Contains(string(s), constants.VersionInfo())
|
||||
assert.Contains(string(s), constants.BinaryVersion().String())
|
||||
}
|
||||
|
||||
func TestParseBuildInfo(t *testing.T) {
|
||||
|
@ -459,6 +459,7 @@ go_test(
|
||||
"//internal/deploy/helm",
|
||||
"//internal/file",
|
||||
"//internal/logger",
|
||||
"//internal/semver",
|
||||
"@com_github_pkg_errors//:errors",
|
||||
"@com_github_spf13_afero//:afero",
|
||||
"@com_github_stretchr_testify//assert",
|
||||
|
@ -77,7 +77,7 @@ func NewClient(client crdClient, kubeConfigPath, helmNamespace string, log debug
|
||||
return &Client{kubectl: client, fs: fileHandler, actions: actions{config: actionConfig}, log: log}, nil
|
||||
}
|
||||
|
||||
func (c *Client) shouldUpgrade(releaseName, newVersion string, force bool) error {
|
||||
func (c *Client) shouldUpgrade(releaseName string, newVersion semver.Semver, force bool) error {
|
||||
currentVersion, err := c.currentVersion(releaseName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting version for %s: %w", releaseName, err)
|
||||
@ -88,14 +88,15 @@ func (c *Client) shouldUpgrade(releaseName, newVersion string, force bool) error
|
||||
// This may break for cert-manager or cilium if we decide to upgrade more than one minor version at a time.
|
||||
// Leaving it as is since it is not clear to me what kind of sanity check we could do.
|
||||
if !force {
|
||||
if err := compatibility.IsValidUpgrade(currentVersion, newVersion); err != nil {
|
||||
if err := newVersion.IsUpgradeTo(currentVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cliVersion := constants.BinaryVersion()
|
||||
// at this point we conclude that the release should be upgraded. check that this CLI supports the upgrade.
|
||||
if releaseName == constellationOperatorsInfo.releaseName || releaseName == constellationServicesInfo.releaseName {
|
||||
if compatibility.EnsurePrefixV(constants.VersionInfo()) != compatibility.EnsurePrefixV(newVersion) {
|
||||
return fmt.Errorf("this CLI only supports microservice version %s for upgrading", constants.VersionInfo())
|
||||
if cliVersion.Compare(newVersion) != 0 {
|
||||
return fmt.Errorf("this CLI only supports microservice version %s for upgrading", cliVersion.String())
|
||||
}
|
||||
}
|
||||
c.log.Debugf("Upgrading %s from %s to %s", releaseName, currentVersion, newVersion)
|
||||
@ -118,13 +119,17 @@ func (c *Client) Upgrade(ctx context.Context, config *config.Config, idFile clus
|
||||
}
|
||||
|
||||
// define target version the chart is upgraded to
|
||||
var upgradeVersion string
|
||||
var upgradeVersion semver.Semver
|
||||
if info == constellationOperatorsInfo || info == constellationServicesInfo {
|
||||
// ensure that the services chart has the same version as the CLI
|
||||
updateVersions(chart, compatibility.EnsurePrefixV(constants.VersionInfo()))
|
||||
updateVersions(chart, constants.BinaryVersion())
|
||||
upgradeVersion = config.MicroserviceVersion
|
||||
} else {
|
||||
upgradeVersion = chart.Metadata.Version
|
||||
chartVersion, err := semver.New(chart.Metadata.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing chart version: %w", err)
|
||||
}
|
||||
upgradeVersion = chartVersion
|
||||
}
|
||||
|
||||
var invalidUpgrade *compatibility.InvalidUpgradeError
|
||||
@ -222,49 +227,51 @@ func (c *Client) Versions() (ServiceVersions, error) {
|
||||
}
|
||||
|
||||
res := ServiceVersions{
|
||||
cilium: compatibility.EnsurePrefixV(ciliumVersion),
|
||||
certManager: compatibility.EnsurePrefixV(certManagerVersion),
|
||||
constellationOperators: compatibility.EnsurePrefixV(operatorsVersion),
|
||||
constellationServices: compatibility.EnsurePrefixV(servicesVersion),
|
||||
cilium: ciliumVersion,
|
||||
certManager: certManagerVersion,
|
||||
constellationOperators: operatorsVersion,
|
||||
constellationServices: servicesVersion,
|
||||
awsLBController: awsLBVersion,
|
||||
}
|
||||
if awsLBVersion != "" {
|
||||
res.awsLBController = compatibility.EnsurePrefixV(awsLBVersion)
|
||||
if awsLBVersion != (semver.Semver{}) {
|
||||
res.awsLBController = awsLBVersion
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// currentVersion returns the version of the currently installed helm release.
|
||||
func (c *Client) currentVersion(release string) (string, error) {
|
||||
func (c *Client) currentVersion(release string) (semver.Semver, error) {
|
||||
rel, err := c.actions.listAction(release)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return semver.Semver{}, err
|
||||
}
|
||||
|
||||
if len(rel) == 0 {
|
||||
return "", errReleaseNotFound
|
||||
return semver.Semver{}, errReleaseNotFound
|
||||
}
|
||||
if len(rel) > 1 {
|
||||
return "", fmt.Errorf("multiple releases found for %s", release)
|
||||
return semver.Semver{}, fmt.Errorf("multiple releases found for %s", release)
|
||||
}
|
||||
|
||||
if rel[0] == nil || rel[0].Chart == nil || rel[0].Chart.Metadata == nil {
|
||||
return "", fmt.Errorf("received invalid release %s", release)
|
||||
return semver.Semver{}, fmt.Errorf("received invalid release %s", release)
|
||||
}
|
||||
|
||||
return rel[0].Chart.Metadata.Version, nil
|
||||
return semver.New(rel[0].Chart.Metadata.Version)
|
||||
}
|
||||
|
||||
// ServiceVersions bundles the versions of all services that are part of Constellation.
|
||||
type ServiceVersions struct {
|
||||
cilium string
|
||||
certManager string
|
||||
constellationOperators string
|
||||
constellationServices string
|
||||
awsLBController string
|
||||
cilium semver.Semver
|
||||
certManager semver.Semver
|
||||
constellationOperators semver.Semver
|
||||
constellationServices semver.Semver
|
||||
awsLBController semver.Semver
|
||||
}
|
||||
|
||||
// NewServiceVersions returns a new ServiceVersions struct.
|
||||
func NewServiceVersions(cilium, certManager, constellationOperators, constellationServices string) ServiceVersions {
|
||||
func NewServiceVersions(cilium, certManager, constellationOperators, constellationServices semver.Semver) ServiceVersions {
|
||||
return ServiceVersions{
|
||||
cilium: cilium,
|
||||
certManager: certManager,
|
||||
@ -274,22 +281,22 @@ func NewServiceVersions(cilium, certManager, constellationOperators, constellati
|
||||
}
|
||||
|
||||
// Cilium returns the version of the Cilium release.
|
||||
func (s ServiceVersions) Cilium() string {
|
||||
func (s ServiceVersions) Cilium() semver.Semver {
|
||||
return s.cilium
|
||||
}
|
||||
|
||||
// CertManager returns the version of the cert-manager release.
|
||||
func (s ServiceVersions) CertManager() string {
|
||||
func (s ServiceVersions) CertManager() semver.Semver {
|
||||
return s.certManager
|
||||
}
|
||||
|
||||
// ConstellationOperators returns the version of the constellation-operators release.
|
||||
func (s ServiceVersions) ConstellationOperators() string {
|
||||
func (s ServiceVersions) ConstellationOperators() semver.Semver {
|
||||
return s.constellationOperators
|
||||
}
|
||||
|
||||
// ConstellationServices returns the version of the constellation-services release.
|
||||
func (s ServiceVersions) ConstellationServices() string {
|
||||
func (s ServiceVersions) ConstellationServices() semver.Semver {
|
||||
return s.constellationServices
|
||||
}
|
||||
|
||||
@ -385,12 +392,8 @@ func (c *Client) applyMigrations(ctx context.Context, releaseName string, values
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting %s version: %w", releaseName, err)
|
||||
}
|
||||
currentV, err := semver.New(current)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing current version: %w", err)
|
||||
}
|
||||
|
||||
if currentV.Major == 2 && currentV.Minor == 8 {
|
||||
if current.Major() == 2 && current.Minor() == 8 {
|
||||
// Rename/change the following function to implement any necessary migrations.
|
||||
return migrateFrom2_8(ctx, values, conf, c.kubectl)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
@ -49,7 +50,9 @@ func TestShouldUpgrade(t *testing.T) {
|
||||
|
||||
chart, err := loadChartsDir(helmFS, certManagerInfo.path)
|
||||
require.NoError(err)
|
||||
err = client.shouldUpgrade(certManagerInfo.releaseName, chart.Metadata.Version, false)
|
||||
chartVersion, err := semver.New(chart.Metadata.Version)
|
||||
require.NoError(err)
|
||||
err = client.shouldUpgrade(certManagerInfo.releaseName, chartVersion, false)
|
||||
if tc.wantError {
|
||||
tc.assertCorrectError(t, err)
|
||||
return
|
||||
|
@ -25,10 +25,10 @@ import (
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/cli/internal/helm/imageversion"
|
||||
"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/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/deploy/helm"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
)
|
||||
|
||||
@ -175,15 +175,15 @@ func (i *ChartLoader) loadRelease(info chartInfo, helmWaitMode helm.WaitMode) (h
|
||||
case certManagerInfo.releaseName:
|
||||
values = i.loadCertManagerValues()
|
||||
case constellationOperatorsInfo.releaseName:
|
||||
updateVersions(chart, compatibility.EnsurePrefixV(constants.VersionInfo()))
|
||||
updateVersions(chart, constants.BinaryVersion())
|
||||
values = i.loadOperatorsValues()
|
||||
case constellationServicesInfo.releaseName:
|
||||
updateVersions(chart, compatibility.EnsurePrefixV(constants.VersionInfo()))
|
||||
updateVersions(chart, constants.BinaryVersion())
|
||||
values = i.loadConstellationServicesValues()
|
||||
case awsLBControllerInfo.releaseName:
|
||||
values = i.loadAWSLBControllerValues()
|
||||
case csiInfo.releaseName:
|
||||
updateVersions(chart, compatibility.EnsurePrefixV(constants.VersionInfo()))
|
||||
updateVersions(chart, constants.BinaryVersion())
|
||||
values = i.loadCSIValues()
|
||||
}
|
||||
|
||||
@ -378,19 +378,19 @@ func extendConstellationServicesValues(
|
||||
}
|
||||
|
||||
// updateVersions changes all versions of direct dependencies that are set to "0.0.0" to newVersion.
|
||||
func updateVersions(chart *chart.Chart, newVersion string) {
|
||||
chart.Metadata.Version = newVersion
|
||||
func updateVersions(chart *chart.Chart, newVersion semver.Semver) {
|
||||
chart.Metadata.Version = newVersion.String()
|
||||
selectedDeps := chart.Metadata.Dependencies
|
||||
for i := range selectedDeps {
|
||||
if selectedDeps[i].Version == "0.0.0" {
|
||||
selectedDeps[i].Version = newVersion
|
||||
selectedDeps[i].Version = newVersion.String()
|
||||
}
|
||||
}
|
||||
|
||||
deps := chart.Dependencies()
|
||||
for i := range deps {
|
||||
if deps[i].Metadata.Version == "0.0.0" {
|
||||
deps[i].Metadata.Version = newVersion
|
||||
deps[i].Metadata.Version = newVersion.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ func main() {
|
||||
|
||||
flag.Parse()
|
||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
||||
log.With(zap.String("version", constants.VersionInfo()), zap.String("cloudProvider", *csp)).
|
||||
log.With(zap.String("version", constants.BinaryVersion().String()), zap.String("cloudProvider", *csp)).
|
||||
Infof("Starting disk-mapper")
|
||||
|
||||
// set up quote issuer for aTLS connections
|
||||
|
@ -12,6 +12,7 @@ go_library(
|
||||
deps = [
|
||||
"//internal/constants",
|
||||
"//internal/logger",
|
||||
"//internal/semver",
|
||||
"@sh_helm_helm_v3//pkg/action",
|
||||
"@sh_helm_helm_v3//pkg/cli",
|
||||
],
|
||||
|
@ -14,41 +14,42 @@ import (
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/logger"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"helm.sh/helm/v3/pkg/action"
|
||||
"helm.sh/helm/v3/pkg/cli"
|
||||
)
|
||||
|
||||
func servicesVersion(t *testing.T) (string, error) {
|
||||
func servicesVersion(t *testing.T) (semver.Semver, error) {
|
||||
t.Helper()
|
||||
log := logger.NewTest(t)
|
||||
settings := cli.New()
|
||||
settings.KubeConfig = "constellation-admin.conf"
|
||||
actionConfig := &action.Configuration{}
|
||||
if err := actionConfig.Init(settings.RESTClientGetter(), constants.HelmNamespace, "secret", log.Infof); err != nil {
|
||||
return "", fmt.Errorf("initializing config: %w", err)
|
||||
return semver.Semver{}, fmt.Errorf("initializing config: %w", err)
|
||||
}
|
||||
|
||||
return currentVersion(actionConfig, "constellation-services")
|
||||
}
|
||||
|
||||
func currentVersion(cfg *action.Configuration, release string) (string, error) {
|
||||
func currentVersion(cfg *action.Configuration, release string) (semver.Semver, error) {
|
||||
action := action.NewList(cfg)
|
||||
action.Filter = release
|
||||
rel, err := action.Run()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return semver.Semver{}, err
|
||||
}
|
||||
|
||||
if len(rel) == 0 {
|
||||
return "", fmt.Errorf("release %s not found", release)
|
||||
return semver.Semver{}, fmt.Errorf("release %s not found", release)
|
||||
}
|
||||
if len(rel) > 1 {
|
||||
return "", fmt.Errorf("multiple releases found for %s", release)
|
||||
return semver.Semver{}, fmt.Errorf("multiple releases found for %s", release)
|
||||
}
|
||||
|
||||
if rel[0] == nil || rel[0].Chart == nil || rel[0].Chart.Metadata == nil {
|
||||
return "", fmt.Errorf("received invalid release %s", release)
|
||||
return semver.Semver{}, fmt.Errorf("received invalid release %s", release)
|
||||
}
|
||||
|
||||
return rel[0].Chart.Metadata.Version, nil
|
||||
return semver.New(rel[0].Chart.Metadata.Version)
|
||||
}
|
||||
|
@ -293,11 +293,13 @@ func writeUpgradeConfig(require *require.Assertions, image string, kubernetes st
|
||||
require.NoError(err)
|
||||
}
|
||||
|
||||
var microserviceVersion string
|
||||
var microserviceVersion semver.Semver
|
||||
if microservices == "" {
|
||||
microserviceVersion = defaultConfig.MicroserviceVersion
|
||||
} else {
|
||||
microserviceVersion = microservices
|
||||
version, err := semver.New(microservices)
|
||||
require.NoError(err)
|
||||
microserviceVersion = version
|
||||
}
|
||||
|
||||
log.Printf("Setting K8s version: %s\n", kubernetesVersion.String())
|
||||
@ -330,10 +332,8 @@ func runUpgradeCheck(require *require.Assertions, cli, targetKubernetes string)
|
||||
require.Contains(string(stdout), targetKubernetes, fmt.Sprintf("Expected Kubernetes version %s in output.", targetKubernetes))
|
||||
}
|
||||
|
||||
cliVersion, err := semver.New(constants.VersionInfo())
|
||||
require.NoError(err)
|
||||
require.Contains(string(stdout), "Services:")
|
||||
require.Contains(string(stdout), fmt.Sprintf("--> %s", cliVersion.String()))
|
||||
require.Contains(string(stdout), fmt.Sprintf("--> %s", constants.BinaryVersion().String()))
|
||||
|
||||
log.Println(string(stdout))
|
||||
}
|
||||
@ -403,7 +403,7 @@ func testStatusEventuallyWorks(t *testing.T, cli string, timeout time.Duration)
|
||||
}, timeout, time.Minute)
|
||||
}
|
||||
|
||||
func testMicroservicesEventuallyHaveVersion(t *testing.T, wantMicroserviceVersion string, timeout time.Duration) {
|
||||
func testMicroservicesEventuallyHaveVersion(t *testing.T, wantMicroserviceVersion semver.Semver, timeout time.Duration) {
|
||||
require.Eventually(t, func() bool {
|
||||
version, err := servicesVersion(t)
|
||||
if err != nil {
|
||||
@ -460,7 +460,7 @@ func testNodesEventuallyHaveVersion(t *testing.T, k *kubernetes.Clientset, targe
|
||||
type versionContainer struct {
|
||||
imageRef string
|
||||
kubernetes semver.Semver
|
||||
microservices string
|
||||
microservices semver.Semver
|
||||
}
|
||||
|
||||
// runCommandWithSeparateOutputs runs the given command while separating buffers for
|
||||
|
@ -29,6 +29,7 @@ go_library(
|
||||
"//internal/config/instancetypes",
|
||||
"//internal/constants",
|
||||
"//internal/file",
|
||||
"//internal/semver",
|
||||
"//internal/versions",
|
||||
"@com_github_go_playground_locales//en",
|
||||
"@com_github_go_playground_universal_translator//:universal-translator",
|
||||
|
@ -40,10 +40,10 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config/imageversion"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
)
|
||||
|
||||
@ -63,7 +63,7 @@ type Config struct {
|
||||
Version string `yaml:"version" validate:"eq=v3"`
|
||||
// description: |
|
||||
// Machine image version used to create Constellation nodes.
|
||||
Image string `yaml:"image" validate:"required,version_compatibility"`
|
||||
Image string `yaml:"image" validate:"required,image_compatibility"`
|
||||
// description: |
|
||||
// Name of the cluster.
|
||||
Name string `yaml:"name" validate:"valid_name,required"`
|
||||
@ -75,7 +75,7 @@ type Config struct {
|
||||
KubernetesVersion string `yaml:"kubernetesVersion" validate:"required,supported_k8s_version"`
|
||||
// description: |
|
||||
// Microservice version to be installed into the cluster. Defaults to the version of the CLI.
|
||||
MicroserviceVersion string `yaml:"microserviceVersion" validate:"required,version_compatibility"`
|
||||
MicroserviceVersion semver.Semver `yaml:"microserviceVersion" validate:"required"`
|
||||
// description: |
|
||||
// DON'T USE IN PRODUCTION: enable debug mode and use debug images.
|
||||
DebugCluster *bool `yaml:"debugCluster" validate:"required"`
|
||||
@ -315,7 +315,7 @@ func Default() *Config {
|
||||
Version: Version3,
|
||||
Image: defaultImage,
|
||||
Name: defaultName,
|
||||
MicroserviceVersion: compatibility.EnsurePrefixV(constants.VersionInfo()),
|
||||
MicroserviceVersion: constants.BinaryVersion(),
|
||||
KubernetesVersion: string(versions.Default),
|
||||
StateDiskSizeGB: 30,
|
||||
DebugCluster: toPtr(false),
|
||||
@ -725,7 +725,7 @@ func (c *Config) Validate(force bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := validate.RegisterTranslation("version_compatibility", trans, registerVersionCompatibilityError, translateVersionCompatibilityError); err != nil {
|
||||
if err := validate.RegisterTranslation("image_compatibility", trans, registerImageCompatibilityError, translateImageCompatibilityError); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -750,7 +750,7 @@ func (c *Config) Validate(force bool) error {
|
||||
if force {
|
||||
versionCompatibilityValidator = returnsTrue
|
||||
}
|
||||
if err := validate.RegisterValidation("version_compatibility", versionCompatibilityValidator); err != nil {
|
||||
if err := validate.RegisterValidation("image_compatibility", versionCompatibilityValidator); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -800,6 +800,18 @@ func (c *Config) Validate(force bool) error {
|
||||
validate.RegisterStructValidation(validateMeasurement, measurements.Measurement{})
|
||||
validate.RegisterStructValidation(validateAttestation, AttestationConfig{})
|
||||
|
||||
if !force {
|
||||
// Validating MicroserviceVersion separately is required since it is a custom type.
|
||||
// The validation pkg we use does not allow accessing the field name during struct validation.
|
||||
// Because of this we can't print the offending field name in the error message, resulting in
|
||||
// suboptimal UX. Adding the field name to the struct validation of Semver would make it
|
||||
// impossible to use Semver for other fields.
|
||||
if err := validateMicroserviceVersion(constants.BinaryVersion(), c.MicroserviceVersion); err != nil {
|
||||
msg := "microserviceVersion: " + msgFromCompatibilityError(err, constants.BinaryVersion().String(), c.MicroserviceVersion.String())
|
||||
return &ValidationError{validationErrMsgs: []string{msg}}
|
||||
}
|
||||
}
|
||||
|
||||
err := validate.Struct(c)
|
||||
if err == nil {
|
||||
return nil
|
||||
|
@ -61,7 +61,7 @@ func init() {
|
||||
ConfigDoc.Fields[4].Description = "Kubernetes version to be installed into the cluster."
|
||||
ConfigDoc.Fields[4].Comments[encoder.LineComment] = "Kubernetes version to be installed into the cluster."
|
||||
ConfigDoc.Fields[5].Name = "microserviceVersion"
|
||||
ConfigDoc.Fields[5].Type = "string"
|
||||
ConfigDoc.Fields[5].Type = "Semver"
|
||||
ConfigDoc.Fields[5].Note = ""
|
||||
ConfigDoc.Fields[5].Description = "Microservice version to be installed into the cluster. Defaults to the version of the CLI."
|
||||
ConfigDoc.Fields[5].Comments[encoder.LineComment] = "Microservice version to be installed into the cluster. Defaults to the version of the CLI."
|
||||
|
@ -140,7 +140,7 @@ func TestNew(t *testing.T) {
|
||||
|
||||
func modifyConfigForAzureToPassValidate(c *Config) {
|
||||
c.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
|
||||
c.Image = "v" + constants.VersionInfo()
|
||||
c.Image = constants.BinaryVersion().String()
|
||||
c.Provider.Azure.SubscriptionID = "11111111-1111-1111-1111-111111111111"
|
||||
c.Provider.Azure.TenantID = "11111111-1111-1111-1111-111111111111"
|
||||
c.Provider.Azure.Location = "westus"
|
||||
@ -308,13 +308,25 @@ func TestValidate(t *testing.T) {
|
||||
cnf.Image = ""
|
||||
ver, err := semver.New(versions.SupportedK8sVersions()[0])
|
||||
require.NoError(t, err)
|
||||
ver.Patch = ver.Patch - 1
|
||||
ver = semver.NewFromInt(ver.Major(), ver.Minor(), ver.Patch()-1, "")
|
||||
cnf.KubernetesVersion = ver.String()
|
||||
return cnf
|
||||
}(),
|
||||
wantErr: true,
|
||||
wantErrCount: defaultErrCount,
|
||||
},
|
||||
"microservices violate version drift": {
|
||||
cnf: func() *Config {
|
||||
cnf := Default()
|
||||
cnf.Image = ""
|
||||
cliVersion := constants.BinaryVersion()
|
||||
cnf.MicroserviceVersion = semver.NewFromInt(cliVersion.Major()+2, cliVersion.Minor(), cliVersion.Patch(), "")
|
||||
return cnf
|
||||
}(),
|
||||
wantErr: true,
|
||||
// This is a very different value from the other error counts because of the way we are checking MicroserviceVersions.
|
||||
wantErrCount: 1,
|
||||
},
|
||||
"v0 is one error": {
|
||||
cnf: func() *Config {
|
||||
cnf := Default()
|
||||
@ -350,7 +362,7 @@ func TestValidate(t *testing.T) {
|
||||
cnf: func() *Config {
|
||||
cnf := Default()
|
||||
cnf.RemoveProviderAndAttestationExcept(cloudprovider.Azure)
|
||||
cnf.Image = "v" + constants.VersionInfo()
|
||||
cnf.Image = constants.BinaryVersion().String()
|
||||
az := cnf.Provider.Azure
|
||||
az.SubscriptionID = "01234567-0123-0123-0123-0123456789ab"
|
||||
az.TenantID = "01234567-0123-0123-0123-0123456789ab"
|
||||
@ -411,7 +423,7 @@ func TestValidate(t *testing.T) {
|
||||
cnf: func() *Config {
|
||||
cnf := Default()
|
||||
cnf.RemoveProviderAndAttestationExcept(cloudprovider.GCP)
|
||||
cnf.Image = "v" + constants.VersionInfo()
|
||||
cnf.Image = constants.BinaryVersion().String()
|
||||
gcp := cnf.Provider.GCP
|
||||
gcp.Region = "test-region"
|
||||
gcp.Project = "test-project"
|
||||
|
@ -11,5 +11,6 @@ go_library(
|
||||
"//internal/attestation/variant",
|
||||
"//internal/config",
|
||||
"//internal/file",
|
||||
"//internal/semver",
|
||||
],
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,11 +29,11 @@ const (
|
||||
// Config defines configuration used by CLI.
|
||||
type Config struct {
|
||||
Version string `yaml:"version" validate:"eq=v2"`
|
||||
Image string `yaml:"image" validate:"required,version_compatibility"`
|
||||
Image string `yaml:"image" validate:"required,image_compatibility"`
|
||||
Name string `yaml:"name" validate:"valid_name,required"`
|
||||
StateDiskSizeGB int `yaml:"stateDiskSizeGB" validate:"min=0"`
|
||||
KubernetesVersion string `yaml:"kubernetesVersion" validate:"required,supported_k8s_version"`
|
||||
MicroserviceVersion string `yaml:"microserviceVersion" validate:"required,version_compatibility"`
|
||||
MicroserviceVersion string `yaml:"microserviceVersion" validate:"required"`
|
||||
DebugCluster *bool `yaml:"debugCluster" validate:"required"`
|
||||
AttestationVariant string `yaml:"attestationVariant,omitempty" validate:"valid_attestation_variant"`
|
||||
Provider ProviderConfig `yaml:"provider" validate:"dive"`
|
||||
@ -195,6 +196,11 @@ func V2ToV3(path string, fileHandler file.Handler) error {
|
||||
return fmt.Errorf("reading config file %s using v2 format: %w", path, err)
|
||||
}
|
||||
|
||||
microserviceVersion, err := semver.New(cfgV2.MicroserviceVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing microservice version: %w", err)
|
||||
}
|
||||
|
||||
// Migrate to new format
|
||||
var cfgV3 config.Config
|
||||
cfgV3.Version = config.Version3
|
||||
@ -202,7 +208,7 @@ func V2ToV3(path string, fileHandler file.Handler) error {
|
||||
cfgV3.Name = cfgV2.Name
|
||||
cfgV3.StateDiskSizeGB = cfgV2.StateDiskSizeGB
|
||||
cfgV3.KubernetesVersion = cfgV2.KubernetesVersion
|
||||
cfgV3.MicroserviceVersion = cfgV2.MicroserviceVersion
|
||||
cfgV3.MicroserviceVersion = microserviceVersion
|
||||
cfgV3.DebugCluster = cfgV2.DebugCluster
|
||||
|
||||
switch {
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config/instancetypes"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
consemver "github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/edgelesssys/constellation/v2/internal/versions"
|
||||
)
|
||||
|
||||
@ -86,11 +87,11 @@ func translateInvalidK8sVersionError(ut ut.Translator, fe validator.FieldError)
|
||||
configured = compatibility.EnsurePrefixV(configured)
|
||||
switch {
|
||||
case !semver.IsValid(configured):
|
||||
errorMsg = "The configured version is not a valid semantic version"
|
||||
errorMsg = "The configured version is not a valid semantic version\n"
|
||||
case semver.Compare(configured, minVersion) == -1:
|
||||
errorMsg = fmt.Sprintf("The configured version %s is older than the oldest version supported by this CLI: %s", configured, minVersion)
|
||||
errorMsg = fmt.Sprintf("The configured version %s is older than the oldest version supported by this CLI: %s\n", configured, minVersion)
|
||||
case semver.Compare(configured, maxVersion) == 1:
|
||||
errorMsg = fmt.Sprintf("The configured version %s is newer than the newest version supported by this CLI: %s", configured, maxVersion)
|
||||
errorMsg = fmt.Sprintf("The configured version %s is newer than the newest version supported by this CLI: %s\n", configured, maxVersion)
|
||||
}
|
||||
|
||||
errorMsg = errorMsg + fmt.Sprintf("Supported versions: %s", strings.Join(validVersionsSorted, " "))
|
||||
@ -492,44 +493,21 @@ func K8sVersionFromMajorMinor(version string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func registerVersionCompatibilityError(ut ut.Translator) error {
|
||||
return ut.Add("version_compatibility", "{0} specifies an invalid version: {1}", true)
|
||||
}
|
||||
|
||||
func translateVersionCompatibilityError(ut ut.Translator, fe validator.FieldError) string {
|
||||
binaryVersion := constants.VersionInfo()
|
||||
err := validateVersionCompatibilityHelper(binaryVersion, fe.Field(), fe.Value().(string))
|
||||
var msg string
|
||||
|
||||
switch {
|
||||
case errors.Is(err, compatibility.ErrSemVer):
|
||||
msg = fmt.Sprintf("configured version (%s) does not adhere to SemVer syntax", fe.Value().(string))
|
||||
case errors.Is(err, compatibility.ErrMajorMismatch):
|
||||
msg = fmt.Sprintf("the CLI's major version (%s) has to match your configured major version (%s). Use --force to ignore the version mismatch.", constants.VersionInfo(), fe.Value().(string))
|
||||
case errors.Is(err, compatibility.ErrMinorDrift):
|
||||
msg = fmt.Sprintf("the CLI's minor version (%s) and the configured version (%s) are more than one minor version apart. Use --force to ignore the version mismatch.", constants.VersionInfo(), fe.Value().(string))
|
||||
case errors.Is(err, compatibility.ErrOutdatedCLI):
|
||||
msg = fmt.Sprintf("the CLI's version (%s) is older than the configured version (%s). Use --force to ignore the version mismatch.", constants.VersionInfo(), fe.Value().(string))
|
||||
default:
|
||||
msg = err.Error()
|
||||
}
|
||||
|
||||
t, _ := ut.T("version_compatibility", fe.Field(), msg)
|
||||
|
||||
return t
|
||||
func registerImageCompatibilityError(ut ut.Translator) error {
|
||||
return ut.Add("image_compatibility", "{0} specifies an invalid version: {1}", true)
|
||||
}
|
||||
|
||||
// Check that the validated field and the CLI version are not more than one minor version apart.
|
||||
func validateVersionCompatibility(fl validator.FieldLevel) bool {
|
||||
binaryVersion := constants.VersionInfo()
|
||||
if err := validateVersionCompatibilityHelper(binaryVersion, fl.FieldName(), fl.Field().String()); err != nil {
|
||||
binaryVersion := constants.BinaryVersion()
|
||||
if err := validateImageCompatibilityHelper(binaryVersion, fl.FieldName(), fl.Field().String()); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func validateVersionCompatibilityHelper(binaryVersion, fieldName, configuredVersion string) error {
|
||||
func validateImageCompatibilityHelper(binaryVersion consemver.Semver, fieldName, configuredVersion string) error {
|
||||
if fieldName == "image" {
|
||||
imageVersion, err := versionsapi.NewVersionFromShortPath(configuredVersion, versionsapi.VersionKindImage)
|
||||
if err != nil {
|
||||
@ -538,15 +516,51 @@ func validateVersionCompatibilityHelper(binaryVersion, fieldName, configuredVers
|
||||
configuredVersion = imageVersion.Version
|
||||
}
|
||||
|
||||
if fieldName == "microserviceVersion" {
|
||||
cliVersion := compatibility.EnsurePrefixV(binaryVersion)
|
||||
serviceVersion := compatibility.EnsurePrefixV(configuredVersion)
|
||||
if semver.Compare(cliVersion, serviceVersion) == -1 {
|
||||
return fmt.Errorf("the CLI's version (%s) is older than the configured version (%s)", cliVersion, serviceVersion)
|
||||
}
|
||||
return compatibility.BinaryWith(binaryVersion.String(), configuredVersion)
|
||||
}
|
||||
|
||||
func translateImageCompatibilityError(ut ut.Translator, fe validator.FieldError) string {
|
||||
binaryVersion := constants.BinaryVersion()
|
||||
err := validateImageCompatibilityHelper(binaryVersion, fe.Field(), fe.Value().(string))
|
||||
|
||||
msg := msgFromCompatibilityError(err, binaryVersion.String(), fe.Value().(string))
|
||||
|
||||
t, _ := ut.T("image_compatibility", fe.Field(), msg)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// msgFromCompatibilityError translates compatibility errors into user-facing error messages.
|
||||
func msgFromCompatibilityError(err error, binaryVersion, fieldValue string) string {
|
||||
switch {
|
||||
case errors.Is(err, compatibility.ErrSemVer):
|
||||
return fmt.Sprintf("configured version (%s) does not adhere to SemVer syntax", fieldValue)
|
||||
case errors.Is(err, compatibility.ErrMajorMismatch):
|
||||
return fmt.Sprintf("the CLI's major version (%s) has to match your configured major version (%s). Use --force to ignore the version mismatch.", binaryVersion, fieldValue)
|
||||
case errors.Is(err, compatibility.ErrMinorDrift):
|
||||
return fmt.Sprintf("the CLI's minor version (%s) and the configured version (%s) are more than one minor version apart. Use --force to ignore the version mismatch.", binaryVersion, fieldValue)
|
||||
case errors.Is(err, compatibility.ErrOutdatedCLI):
|
||||
return fmt.Sprintf("the CLI's version (%s) is older than the configured version (%s). Use --force to ignore the version mismatch.", binaryVersion, fieldValue)
|
||||
default:
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
func validateMicroserviceVersion(binaryVersion, version consemver.Semver) error {
|
||||
// Major versions always have to match.
|
||||
if binaryVersion.Major() != version.Major() {
|
||||
return compatibility.ErrMajorMismatch
|
||||
}
|
||||
// Allow newer CLIs (for upgrades), but dissallow newer service versions.
|
||||
if binaryVersion.Compare(version) == -1 {
|
||||
return compatibility.ErrOutdatedCLI
|
||||
}
|
||||
// Abort if minor version drift between CLI and versionA value is greater than 1.
|
||||
if binaryVersion.Minor()-version.Minor() > 1 {
|
||||
return compatibility.ErrMinorDrift
|
||||
}
|
||||
|
||||
return compatibility.BinaryWith(binaryVersion, configuredVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
func returnsTrue(_ validator.FieldLevel) bool {
|
||||
|
@ -9,26 +9,27 @@ package config
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestValidateVersionCompatibilityHelper checks that basic version and image short paths are correctly validated.
|
||||
func TestValidateVersionCompatibilityHelper(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
cli string
|
||||
cli semver.Semver
|
||||
target string
|
||||
wantError bool
|
||||
}{
|
||||
"full version works": {
|
||||
cli: "0.1.0",
|
||||
cli: semver.NewFromInt(0, 1, 0, ""),
|
||||
target: "v0.0.0",
|
||||
},
|
||||
"short path works": {
|
||||
cli: "0.1.0",
|
||||
cli: semver.NewFromInt(0, 1, 0, ""),
|
||||
target: "ref/main/stream/debug/v0.0.0-pre.0.20230109121528-d24fac00f018",
|
||||
},
|
||||
"minor version difference > 1": {
|
||||
cli: "0.0.0",
|
||||
cli: semver.NewFromInt(0, 0, 0, ""),
|
||||
target: "ref/main/stream/debug/v0.2.0-pre.0.20230109121528-d24fac00f018",
|
||||
wantError: true,
|
||||
},
|
||||
@ -38,7 +39,43 @@ func TestValidateVersionCompatibilityHelper(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := validateVersionCompatibilityHelper(tc.cli, "image", tc.target)
|
||||
err := validateImageCompatibilityHelper(tc.cli, "image", tc.target)
|
||||
if tc.wantError {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMicroserviceVersion(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
cli semver.Semver
|
||||
services semver.Semver
|
||||
wantError bool
|
||||
}{
|
||||
"success": {
|
||||
cli: semver.NewFromInt(0, 1, 0, ""),
|
||||
services: semver.NewFromInt(0, 0, 0, ""),
|
||||
},
|
||||
"minor version difference > 1": {
|
||||
cli: semver.NewFromInt(0, 0, 0, ""),
|
||||
services: semver.NewFromInt(0, 2, 0, "pre.0.20230109121528-d24fac00f018"),
|
||||
wantError: true,
|
||||
},
|
||||
"major version difference": {
|
||||
cli: semver.NewFromInt(0, 0, 0, ""),
|
||||
services: semver.NewFromInt(1, 0, 0, ""),
|
||||
wantError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
err := validateMicroserviceVersion(tc.cli, tc.services)
|
||||
if tc.wantError {
|
||||
assert.Error(err)
|
||||
return
|
||||
|
@ -17,4 +17,5 @@ go_library(
|
||||
"timestamp": "{STABLE_STAMP_TIME}",
|
||||
"versionInfo": "{STABLE_STAMP_VERSION}",
|
||||
},
|
||||
deps = ["//internal/semver"],
|
||||
)
|
||||
|
@ -11,7 +11,10 @@ Constants should never be overwritable by command line flags or configuration fi
|
||||
package constants
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/semver"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -231,9 +234,15 @@ b92PDCpM7FZAINQF88s1TZS/HmRXYk62UJ4eqPduvUnJmXhNikhLbMi6fw==
|
||||
`
|
||||
)
|
||||
|
||||
// VersionInfo returns the version of a binary.
|
||||
func VersionInfo() string {
|
||||
return versionInfo
|
||||
// BinaryVersion returns the version of this Binary.
|
||||
func BinaryVersion() semver.Semver {
|
||||
version, err := semver.New(versionInfo)
|
||||
if err != nil {
|
||||
// This is not user input, unrecoverable, should never happen.
|
||||
panic(fmt.Sprintf("parsing embedded version information: %s", err))
|
||||
}
|
||||
|
||||
return version
|
||||
}
|
||||
|
||||
// Timestamp returns the commit timestamp of a binary.
|
||||
|
@ -7,7 +7,7 @@ go_library(
|
||||
importpath = "github.com/edgelesssys/constellation/v2/internal/semver",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/constants",
|
||||
"//internal/compatibility",
|
||||
"@org_golang_x_mod//semver",
|
||||
],
|
||||
)
|
||||
@ -19,5 +19,6 @@ go_test(
|
||||
deps = [
|
||||
"@com_github_stretchr_testify//assert",
|
||||
"@com_github_stretchr_testify//require",
|
||||
"@in_gopkg_yaml_v3//:yaml_v3",
|
||||
],
|
||||
)
|
||||
|
@ -6,24 +6,37 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
/*
|
||||
Package semver provides functionality to parse and process semantic versions, as they are used in multiple components of Constellation.
|
||||
|
||||
The official [semantic versioning specification] disallows leading "v" prefixes.
|
||||
However, the Constellation config uses the "v" prefix for versions to make version strings more recognizable.
|
||||
This package bridges the gap between Go's semver pkg (doesn't allow "v" prefix) and the Constellation config (requires "v" prefix).
|
||||
|
||||
[semantic versioning specification]: https://semver.org/
|
||||
*/
|
||||
package semver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
// Sort sorts a list of semantic version strings using [ByVersion].
|
||||
func Sort(list []Semver) {
|
||||
sort.Sort(byVersion(list))
|
||||
}
|
||||
|
||||
// Semver represents a semantic version.
|
||||
type Semver struct {
|
||||
Major int
|
||||
Minor int
|
||||
Patch int
|
||||
Prerelease string
|
||||
major int
|
||||
minor int
|
||||
patch int
|
||||
prerelease string
|
||||
}
|
||||
|
||||
// New returns a Version from a string.
|
||||
@ -47,18 +60,72 @@ func New(version string) (Semver, error) {
|
||||
}
|
||||
|
||||
return Semver{
|
||||
Major: major,
|
||||
Minor: minor,
|
||||
Patch: patch,
|
||||
Prerelease: pre,
|
||||
major: major,
|
||||
minor: minor,
|
||||
patch: patch,
|
||||
prerelease: pre,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewFromInt constructs a new Semver from three integers and prerelease string: MAJOR.MINOR.PATCH-PRERELEASE.
|
||||
func NewFromInt(major, minor, patch int, prerelease string) Semver {
|
||||
return Semver{
|
||||
major: major,
|
||||
minor: minor,
|
||||
patch: patch,
|
||||
prerelease: prerelease,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSlice returns a slice of Semver from a slice of strings.
|
||||
func NewSlice(in []string) ([]Semver, error) {
|
||||
var out []Semver
|
||||
for _, version := range in {
|
||||
semVersion, err := New(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing version %s: %w", version, err)
|
||||
}
|
||||
out = append(out, semVersion)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ToStrings converts a slice of Semver to a slice of strings.
|
||||
func ToStrings(in []Semver) []string {
|
||||
var out []string
|
||||
for _, v := range in {
|
||||
out = append(out, v.String())
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Major returns the major version of the object.
|
||||
func (v Semver) Major() int {
|
||||
return v.major
|
||||
}
|
||||
|
||||
// Minor returns the minor version of the object.
|
||||
func (v Semver) Minor() int {
|
||||
return v.minor
|
||||
}
|
||||
|
||||
// Patch returns the patch version of the object.
|
||||
func (v Semver) Patch() int {
|
||||
return v.patch
|
||||
}
|
||||
|
||||
// Prerelease returns the prerelease section of the object.
|
||||
func (v Semver) Prerelease() string {
|
||||
return v.prerelease
|
||||
}
|
||||
|
||||
// String returns the string representation of the version.
|
||||
func (v Semver) String() string {
|
||||
version := fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch)
|
||||
if v.Prerelease != "" {
|
||||
return fmt.Sprintf("%s-%s", version, v.Prerelease)
|
||||
version := fmt.Sprintf("v%d.%d.%d", v.major, v.minor, v.patch)
|
||||
if v.prerelease != "" {
|
||||
return fmt.Sprintf("%s-%s", version, v.prerelease)
|
||||
}
|
||||
return version
|
||||
}
|
||||
@ -70,29 +137,51 @@ func (v Semver) Compare(other Semver) int {
|
||||
|
||||
// MajorMinorEqual returns if the major and minor version of two versions are equal.
|
||||
func (v Semver) MajorMinorEqual(other Semver) bool {
|
||||
return v.Major == other.Major && v.Minor == other.Minor
|
||||
return v.major == other.major && v.minor == other.minor
|
||||
}
|
||||
|
||||
// IsUpgradeTo returns if a version is an upgrade to another version.
|
||||
// It checks if the version of v is greater than the version of other and allows a drift of at most one minor version.
|
||||
func (v Semver) IsUpgradeTo(other Semver) bool {
|
||||
return v.Compare(other) > 0 && v.Major == other.Major && v.Minor-other.Minor <= 1
|
||||
}
|
||||
|
||||
// CompatibleWithBinary returns if a version is compatible version of the current built binary.
|
||||
// It checks if the version of the binary is equal or greater than the current version and allows a drift of at most one minor version.
|
||||
func (v Semver) CompatibleWithBinary() bool {
|
||||
binaryVersion, err := New(constants.VersionInfo())
|
||||
if err != nil {
|
||||
return false
|
||||
func (v Semver) IsUpgradeTo(other Semver) error {
|
||||
if v.Compare(other) <= 0 {
|
||||
return compatibility.NewInvalidUpgradeError(v.String(), other.String(), errors.New("current version newer than or equal to new version"))
|
||||
}
|
||||
if v.major != other.major {
|
||||
return compatibility.NewInvalidUpgradeError(v.String(), other.String(), compatibility.ErrMajorMismatch)
|
||||
}
|
||||
|
||||
return v.Compare(binaryVersion) == 0 || binaryVersion.IsUpgradeTo(v)
|
||||
if v.minor-other.minor > 1 {
|
||||
return compatibility.NewInvalidUpgradeError(v.String(), other.String(), compatibility.ErrMinorDrift)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextMinor returns the next minor version in the format "vMAJOR.MINOR".
|
||||
// NextMinor returns the next minor version in the format "vMAJOR.MINOR+1".
|
||||
func (v Semver) NextMinor() string {
|
||||
return fmt.Sprintf("v%d.%d", v.Major, v.Minor+1)
|
||||
return fmt.Sprintf("v%d.%d", v.major, v.minor+1)
|
||||
}
|
||||
|
||||
// MarshalYAML implements the yaml.Marshaller interface.
|
||||
func (v Semver) MarshalYAML() (any, error) {
|
||||
return v.String(), nil
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||
func (v *Semver) UnmarshalYAML(unmarshal func(any) error) error {
|
||||
var raw string
|
||||
if err := unmarshal(&raw); err != nil {
|
||||
return fmt.Errorf("unmarshalling to string: %w", err)
|
||||
}
|
||||
|
||||
version, err := New(raw)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing semantic version: %w", err)
|
||||
}
|
||||
|
||||
*v = version
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface.
|
||||
@ -115,3 +204,20 @@ func (v *Semver) UnmarshalJSON(data []byte) error {
|
||||
*v = version
|
||||
return nil
|
||||
}
|
||||
|
||||
// byVersion implements [sort.Interface] for sorting semantic version strings.
|
||||
// Copied from Go's semver pkg with minimal modification.
|
||||
// https://cs.opensource.google/go/x/mod/+/master:semver/semver.go
|
||||
type byVersion []Semver
|
||||
|
||||
func (vs byVersion) Len() int { return len(vs) }
|
||||
func (vs byVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
func (vs byVersion) Less(i, j int) bool {
|
||||
cmp := vs[i].Compare(vs[j])
|
||||
if cmp != 0 {
|
||||
return cmp < 0
|
||||
}
|
||||
|
||||
// if versions are equal, sort by lexicographic order
|
||||
return vs[i].String() < vs[j].String()
|
||||
}
|
||||
|
@ -7,20 +7,22 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
package semver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var (
|
||||
v1_18_0 = Semver{Major: 1, Minor: 18, Patch: 0}
|
||||
v1_18_0Pre = Semver{Major: 1, Minor: 18, Patch: 0, Prerelease: "pre"}
|
||||
v1_18_0PreExtra = Semver{Major: 1, Minor: 18, Patch: 0, Prerelease: "pre.1"}
|
||||
v1_19_0 = Semver{Major: 1, Minor: 19, Patch: 0}
|
||||
v1_18_1 = Semver{Major: 1, Minor: 18, Patch: 1}
|
||||
v1_20_0 = Semver{Major: 1, Minor: 20, Patch: 0}
|
||||
v2_0_0 = Semver{Major: 2, Minor: 0, Patch: 0}
|
||||
v1_18_0 = Semver{major: 1, minor: 18, patch: 0}
|
||||
v1_18_0Pre = Semver{major: 1, minor: 18, patch: 0, prerelease: "pre"}
|
||||
v1_18_0PreExtra = Semver{major: 1, minor: 18, patch: 0, prerelease: "pre.1"}
|
||||
v1_19_0 = Semver{major: 1, minor: 19, patch: 0}
|
||||
v1_18_1 = Semver{major: 1, minor: 18, patch: 1}
|
||||
v1_20_0 = Semver{major: 1, minor: 20, patch: 0}
|
||||
v2_0_0 = Semver{major: 2, minor: 0, patch: 0}
|
||||
)
|
||||
|
||||
func TestNewVersion(t *testing.T) {
|
||||
@ -32,19 +34,19 @@ func TestNewVersion(t *testing.T) {
|
||||
"valid version": {
|
||||
version: "v1.18.0",
|
||||
want: Semver{
|
||||
Major: 1,
|
||||
Minor: 18,
|
||||
Patch: 0,
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"valid version prerelease": {
|
||||
version: "v1.18.0-pre+yyyymmddhhmmss-abcdefabcdef",
|
||||
want: Semver{
|
||||
Major: 1,
|
||||
Minor: 18,
|
||||
Patch: 0,
|
||||
Prerelease: "pre",
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
prerelease: "pre",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@ -53,27 +55,27 @@ func TestNewVersion(t *testing.T) {
|
||||
"add prefix": {
|
||||
version: "1.18.0",
|
||||
want: Semver{
|
||||
Major: 1,
|
||||
Minor: 18,
|
||||
Patch: 0,
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"only major.minor": {
|
||||
version: "v1.18",
|
||||
want: Semver{
|
||||
Major: 1,
|
||||
Minor: 18,
|
||||
Patch: 0,
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
"only major": {
|
||||
version: "v1",
|
||||
want: Semver{
|
||||
Major: 1,
|
||||
Minor: 0,
|
||||
Patch: 0,
|
||||
major: 1,
|
||||
minor: 0,
|
||||
patch: 0,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@ -216,60 +218,59 @@ func TestComparison(t *testing.T) {
|
||||
|
||||
func TestCanUpgrade(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
version1 Semver
|
||||
version2 Semver
|
||||
want bool
|
||||
wantErr bool
|
||||
version1 Semver
|
||||
version2 Semver
|
||||
wantUpgrade bool
|
||||
}{
|
||||
"equal": {
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_0,
|
||||
want: false,
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_0,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"patch less than": {
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_1,
|
||||
want: true,
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_1,
|
||||
wantUpgrade: true,
|
||||
},
|
||||
"minor less then": {
|
||||
version1: v1_18_0,
|
||||
version2: v1_19_0,
|
||||
want: true,
|
||||
version1: v1_18_0,
|
||||
version2: v1_19_0,
|
||||
wantUpgrade: true,
|
||||
},
|
||||
"minor too big drift": {
|
||||
version1: v1_18_0,
|
||||
version2: v1_20_0,
|
||||
want: false,
|
||||
version1: v1_18_0,
|
||||
version2: v1_20_0,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"major too big drift": {
|
||||
version1: v1_18_0,
|
||||
version2: v2_0_0,
|
||||
want: false,
|
||||
version1: v1_18_0,
|
||||
version2: v2_0_0,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"greater than": {
|
||||
version1: v1_18_1,
|
||||
version2: v1_18_0,
|
||||
want: false,
|
||||
version1: v1_18_1,
|
||||
version2: v1_18_0,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"prerelease less than": {
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0,
|
||||
want: true,
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0,
|
||||
wantUpgrade: true,
|
||||
},
|
||||
"prerelease greater than": {
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_0Pre,
|
||||
want: false,
|
||||
version1: v1_18_0,
|
||||
version2: v1_18_0Pre,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"prerelease equal": {
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0Pre,
|
||||
want: false,
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0Pre,
|
||||
wantUpgrade: false,
|
||||
},
|
||||
"prerelease extra": {
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0PreExtra,
|
||||
want: true,
|
||||
version1: v1_18_0Pre,
|
||||
version2: v1_18_0PreExtra,
|
||||
wantUpgrade: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -277,7 +278,7 @@ func TestCanUpgrade(t *testing.T) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
assert.Equal(tc.want, tc.version2.IsUpgradeTo(tc.version1))
|
||||
assert.Equal(tc.wantUpgrade, tc.version2.IsUpgradeTo(tc.version1) == nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -304,3 +305,89 @@ func TestNextMinor(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionMarshalYAML(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
version Semver
|
||||
want string
|
||||
}{
|
||||
"simple": {
|
||||
version: Semver{
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
prerelease: "",
|
||||
},
|
||||
want: "v1.18.0\n",
|
||||
},
|
||||
"with prerelease": {
|
||||
version: Semver{
|
||||
major: 1,
|
||||
minor: 18,
|
||||
patch: 0,
|
||||
prerelease: "pre",
|
||||
},
|
||||
want: "v1.18.0-pre\n",
|
||||
},
|
||||
"empty semver": {
|
||||
version: Semver{},
|
||||
want: "v0.0.0\n",
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
marshalled, err := yaml.Marshal(tc.version)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want, string(marshalled))
|
||||
|
||||
var unmarshalled Semver
|
||||
err = yaml.Unmarshal(marshalled, &unmarshalled)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.version, unmarshalled)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionUnmarshalYAML(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
version []byte
|
||||
want Semver
|
||||
wantError bool
|
||||
}{
|
||||
"empty string": {
|
||||
version: []byte(""),
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
var actual Semver
|
||||
err := yaml.Unmarshal(tc.version, &actual)
|
||||
if tc.wantError {
|
||||
require.Error(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.want.Compare(actual), 0, fmt.Sprintf("expected %s, got %s", tc.want, actual))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSort(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
input []Semver
|
||||
want []Semver
|
||||
}{
|
||||
"": {
|
||||
input: []Semver{NewFromInt(2, 0, 0, ""), NewFromInt(0, 0, 0, ""), NewFromInt(1, 5, 0, "aa"), NewFromInt(1, 5, 0, "bb"), NewFromInt(1, 0, 0, "")},
|
||||
want: []Semver{NewFromInt(0, 0, 0, ""), NewFromInt(1, 0, 0, ""), NewFromInt(1, 5, 0, "aa"), NewFromInt(1, 5, 0, "bb"), NewFromInt(2, 0, 0, "")},
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
Sort(tc.input)
|
||||
require.Equal(t, tc.want, tc.input, fmt.Sprintf("expected %s, got %s", tc.want, tc.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func main() {
|
||||
|
||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
||||
log.With(
|
||||
zap.String("version", constants.VersionInfo()),
|
||||
zap.String("version", constants.BinaryVersion().String()),
|
||||
zap.String("cloudProvider", *provider),
|
||||
zap.String("attestationVariant", *attestationVariant),
|
||||
).Infof("Constellation Node Join Service")
|
||||
|
@ -34,7 +34,7 @@ func main() {
|
||||
flag.Parse()
|
||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
||||
|
||||
log.With(zap.String("version", constants.VersionInfo())).
|
||||
log.With(zap.String("version", constants.BinaryVersion().String())).
|
||||
Infof("Constellation Key Management Service")
|
||||
|
||||
// read master secret and salt
|
||||
|
@ -26,7 +26,7 @@ func main() {
|
||||
flag.Parse()
|
||||
log := logger.New(logger.JSONLog, logger.VerbosityFromInt(*verbosity))
|
||||
|
||||
log.With(zap.String("version", constants.VersionInfo()), zap.String("attestationVariant", *attestationVariant)).
|
||||
log.With(zap.String("version", constants.BinaryVersion().String()), zap.String("attestationVariant", *attestationVariant)).
|
||||
Infof("Constellation Verification Service")
|
||||
|
||||
variant, err := variant.FromString(*attestationVariant)
|
||||
|
Loading…
Reference in New Issue
Block a user