From 93367f2e0df19f5b9d04ee20ca2183cc6204fb8a Mon Sep 17 00:00:00 2001 From: omessir Date: Wed, 1 Nov 2023 12:52:20 -0400 Subject: [PATCH 1/2] fix agent version compatibility check --- cbcontainers/models/agent_version.go | 23 --- cbcontainers/models/operator_compatibility.go | 6 +- .../models/operator_compatibility_test.go | 52 ++--- cbcontainers/models/version.go | 130 ++++++++++++ cbcontainers/models/version_test.go | 194 ++++++++++++++++++ cbcontainers/processors/agent_processor.go | 2 +- .../remote_configuration/validation.go | 2 +- 7 files changed, 357 insertions(+), 52 deletions(-) delete mode 100644 cbcontainers/models/agent_version.go create mode 100644 cbcontainers/models/version.go create mode 100644 cbcontainers/models/version_test.go diff --git a/cbcontainers/models/agent_version.go b/cbcontainers/models/agent_version.go deleted file mode 100644 index 48c3b44b..00000000 --- a/cbcontainers/models/agent_version.go +++ /dev/null @@ -1,23 +0,0 @@ -package models - -type AgentVersion string - -const ( - AgentMinVersionNone AgentVersion = "none" - AgentMaxVersionLatest AgentVersion = "latest" - AgentVersionUnknown AgentVersion = "" -) - -func (v AgentVersion) IsLargerThan(version string) bool { - if v == AgentMinVersionNone || v == AgentVersionUnknown { - return false - } - return string(v) > version -} - -func (v AgentVersion) IsLessThan(version string) bool { - if v == AgentMaxVersionLatest || v == AgentVersionUnknown { - return false - } - return string(v) < version -} diff --git a/cbcontainers/models/operator_compatibility.go b/cbcontainers/models/operator_compatibility.go index 1509d929..66ca5466 100644 --- a/cbcontainers/models/operator_compatibility.go +++ b/cbcontainers/models/operator_compatibility.go @@ -4,8 +4,8 @@ import "fmt" // OperatorCompatibility shows the min and max supported agent versions. type OperatorCompatibility struct { - MinAgent AgentVersion `json:"min_agent"` - MaxAgent AgentVersion `json:"max_agent"` + MinAgent Version `json:"min_agent"` + MaxAgent Version `json:"max_agent"` } // CheckCompatibility uses the given entry to check whether the given agentVersion are compatible. @@ -13,7 +13,7 @@ type OperatorCompatibility struct { // It returns an error if the versions are not compatible, nil if they are. // If the min and max agent versions for this operator version are unknown it will // skip the check and return true. -func (c OperatorCompatibility) CheckCompatibility(agentVersion string) error { +func (c OperatorCompatibility) CheckCompatibility(agentVersion Version) error { if c.MaxAgent.IsLessThan(agentVersion) { return fmt.Errorf("agent version too high, upgrade the operator to use that agent version: max is [%s], desired is [%s]", c.MaxAgent, agentVersion) } diff --git a/cbcontainers/models/operator_compatibility_test.go b/cbcontainers/models/operator_compatibility_test.go index 499a8020..8c6a3717 100644 --- a/cbcontainers/models/operator_compatibility_test.go +++ b/cbcontainers/models/operator_compatibility_test.go @@ -9,28 +9,31 @@ import ( ) type testCase struct { - min models.AgentVersion - max models.AgentVersion - agent string + min models.Version + max models.Version + agent models.Version } func TestCheckCompatibilityCompatible(t *testing.T) { testCases := []testCase{ - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.7"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.8"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.7.1"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.7.5"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8.1"), agent: "2.8.1"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8.1"), agent: "2.7.1-alpha"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8.1"), agent: "2.7.1-beta"}, - {min: models.AgentMinVersionNone, max: models.AgentVersion("2.8.1"), agent: "0.0.1"}, - {min: models.AgentVersion("2.7"), max: models.AgentMaxVersionLatest, agent: "3.0.0"}, - {min: models.AgentVersion("2.7"), max: models.AgentMaxVersionLatest, agent: "50.0.0"}, - {min: models.AgentVersion("1.0"), max: models.AgentVersion("2.8"), agent: "1.5"}, - {min: models.AgentVersion("1.0"), max: models.AgentVersion("2.8"), agent: "2.0"}, - {min: models.AgentVersion("0.0"), max: models.AgentVersion("2.8"), agent: "0.0"}, - {min: models.AgentVersion("0.0"), max: models.AgentVersion("2.8"), agent: "1.0"}, - {min: models.AgentVersion("0.0"), max: models.AgentVersion("2.8"), agent: "2.0"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.7"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.8"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.7.1"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.7.5"}, + {min: models.Version("2.7"), max: models.Version("2.8.1"), agent: "2.8.1"}, + {min: models.Version("2.7"), max: models.Version("2.8.1"), agent: "2.7.1-alpha"}, + {min: models.Version("2.7"), max: models.Version("2.8.1"), agent: "2.7.1-beta"}, + {min: models.MinVersionNone, max: models.Version("2.8.1"), agent: "0.0.1"}, + {min: models.Version("2.7"), max: models.MaxVersionLatest, agent: "3.0.0"}, + {min: models.Version("2.7"), max: models.MaxVersionLatest, agent: "50.0.0"}, + {min: models.Version("1.0"), max: models.Version("2.8"), agent: "1.5"}, + {min: models.Version("1.0"), max: models.Version("2.8"), agent: "2.0"}, + {min: models.Version("0.0"), max: models.Version("2.8"), agent: "0.0"}, + {min: models.Version("0.0"), max: models.Version("2.8"), agent: "1.0"}, + {min: models.Version("0.0"), max: models.Version("2.8"), agent: "2.0"}, + {min: models.Version("1.2"), max: models.Version("1.30"), agent: "1.10"}, + {min: models.Version("1.1.2"), max: models.Version("1.1.30"), agent: "1.1.10"}, + {min: models.Version("1.2.105"), max: models.Version("1.30.0"), agent: "1.10.40"}, } testCheckCompatibility(t, testCases, true) @@ -38,12 +41,13 @@ func TestCheckCompatibilityCompatible(t *testing.T) { func TestCheckCompatibilityIncompatible(t *testing.T) { testCases := []testCase{ - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.8.1"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "3"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.6"}, - {min: models.AgentVersion("2.7"), max: models.AgentVersion("2.8"), agent: "2.6.9"}, - {min: models.AgentMinVersionNone, max: models.AgentVersion("2.8"), agent: "2.9"}, - {min: models.AgentVersion("2.7"), max: models.AgentMaxVersionLatest, agent: "2.6"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.8.1"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "3"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.6"}, + {min: models.Version("2.7"), max: models.Version("2.8"), agent: "2.6.9"}, + {min: models.MinVersionNone, max: models.Version("2.8"), agent: "2.9"}, + {min: models.Version("2.7"), max: models.MaxVersionLatest, agent: "2.6"}, + {min: models.Version("1.10"), max: models.Version("1.30"), agent: "1.2"}, } testCheckCompatibility(t, testCases, false) diff --git a/cbcontainers/models/version.go b/cbcontainers/models/version.go new file mode 100644 index 00000000..6589bbcb --- /dev/null +++ b/cbcontainers/models/version.go @@ -0,0 +1,130 @@ +package models + +import ( + "strconv" + "strings" +) + +type Version string + +const ( + MinVersionNone Version = "none" + MaxVersionLatest Version = "latest" + MaxVersionMain Version = "main" + VersionUnknown Version = "" +) + +func (v Version) isMaxVersion() bool { + return v == MaxVersionLatest || v == MaxVersionMain +} + +func (v Version) CompareWith(other Version) int { + // Split into version and pre-release parts + partsV := strings.SplitN(string(v), "-", 2) + partsOther := strings.SplitN(string(other), "-", 2) + + numbersV := strings.Split(partsV[0], ".") + numbersOther := strings.Split(partsOther[0], ".") + + // Normalize lengths: append zeros to the shorter version + for len(numbersV) < len(numbersOther) { + numbersV = append(numbersV, "0") + } + for len(numbersOther) < len(numbersV) { + numbersOther = append(numbersOther, "0") + } + + for i := 0; i < len(numbersV); i++ { + intA, errA := strconv.Atoi(numbersV[i]) + intB, errB := strconv.Atoi(numbersOther[i]) + + if errA != nil || errB != nil { + return 0 + } + + if intA > intB { + return 1 + } else if intA < intB { + return -1 + } + } + + // If one version has a pre-release and the other doesn't + if len(partsV) == 1 && len(partsOther) > 1 { + return 1 + } + if len(partsV) > 1 && len(partsOther) == 1 { + return -1 + } + + // If both have pre-releases, compare them lexicographically + if len(partsV) > 1 && len(partsOther) > 1 { + if partsV[1] > partsOther[1] { + return 1 + } else if partsV[1] < partsOther[1] { + return -1 + } + } + + return 0 +} + +func (v Version) IsLargerThan(other Version) bool { + if v == other { + return false + } + + if v.isMaxVersion() && other.isMaxVersion() { + return false + } + + if v == MaxVersionLatest || v == MaxVersionMain { + return true + } + + if other == MaxVersionLatest || other == MaxVersionMain { + return false + } + + if v == MinVersionNone || v == VersionUnknown { + return false + } + + if other == MinVersionNone || other == VersionUnknown { + return true + } + + return v.CompareWith(other) > 0 +} + +func (v Version) IsLessThan(other Version) bool { + if v == other { + return false + } + + if v.isMaxVersion() && other.isMaxVersion() { + return false + } + + if v == MinVersionNone { + return true + } + + if other == MinVersionNone { + return false + } + + if v == MaxVersionLatest || v == MaxVersionMain || v == VersionUnknown { + return false + } + + if other == VersionUnknown { + return false + } + + if other == MaxVersionLatest || other == MaxVersionMain { + return true + } + + return v.CompareWith(other) < 0 +} diff --git a/cbcontainers/models/version_test.go b/cbcontainers/models/version_test.go new file mode 100644 index 00000000..17b19cfb --- /dev/null +++ b/cbcontainers/models/version_test.go @@ -0,0 +1,194 @@ +package models + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +type testCase struct { + versionA Version + versionB Version +} + +func TestIsLargerThanTrue(t *testing.T) { + testCases := []testCase{ + {versionA: Version("1.0.0"), versionB: Version("0.9.9")}, // Basic comparison + {versionA: Version("1.1.1"), versionB: Version("1.1")}, // Different versions length + {versionA: Version("1.0.1"), versionB: Version("1.0.0")}, // Patch increment + {versionA: Version("1.1.0"), versionB: Version("1.0.10")}, // Minor increment + {versionA: Version("2.0.0"), versionB: Version("1.9.9")}, // Major increment + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0-alpha")}, // Pre-release comparison + {versionA: Version("2.0.0"), versionB: Version("2.0.0-beta")}, // Stable vs pre-release + {versionA: Version("1.2.0-alpha.2"), versionB: Version("1.2.0-alpha.1")}, // Pre-release with multiple segments (up to 9) + {versionA: Version("1.2.0-beta.1"), versionB: Version("1.2.0-alpha.10")}, // Different pre-release labels + {versionA: Version("1.11.0"), versionB: Version("1.2.0")}, // Double digits + {versionA: Version("1.0.10"), versionB: Version("1.0.2")}, // Patch number double digits + {versionA: Version("11.0.0"), versionB: Version("2.10.0")}, // Major double digits + {versionA: Version("1.1.1"), versionB: Version("1.1.0")}, // All segments incremented + {versionA: Version("3.0.0"), versionB: Version("2.10.10")}, // All previous segments at max + {versionA: Version("1.0.0-rc.1"), versionB: Version("1.0.0-beta.9")}, // Pre-release progression + {versionA: Version("1.0.0-rc.3"), versionB: Version("1.0.0-rc.1")}, // Pre-release with numbers (up to 9) + {versionA: Version("2.0.0"), versionB: Version("2.0.0-rc.10")}, // Stable vs long pre-release + {versionA: Version("1.0.1"), versionB: Version("1.0.0-alpha")}, // Patch increment over pre-release + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0-alpha.10")}, // Pre-release without numbers vs one with numbers + {versionA: Version("3.2.1"), versionB: Version("3.2.0")}, // Minor and patch increment + {versionA: Version("4.0.1"), versionB: Version("4.0.0")}, // Major increment with patch + {versionA: Version("5.2.0"), versionB: Version("5.1.10")}, // Major stable with minor and patch increments + {versionA: Version("1.2.3"), versionB: Version("1.2.0-alpha.4")}, // Stable vs pre-release with multiple segments + {versionA: Version("1.2.3-beta.5"), versionB: Version("1.2.3-alpha.5")}, // Same version, different pre-release + {versionA: Version("1.2.3-beta.9"), versionB: Version("1.2.3-beta.2")}, // Same version, pre-release with numbers (up to 9) + {versionA: Version("10.10.10"), versionB: Version("2.10.10")}, // Large major increment + {versionA: Version("0.0.1"), versionB: VersionUnknown}, // Version is always larger than an unknown version + {versionA: Version("0.0.1"), versionB: MinVersionNone}, // Version is always larger than a none version + {versionA: MaxVersionLatest, versionB: Version("0.0.1")}, // Latest version is always larger than other version + {versionA: MaxVersionMain, versionB: Version("0.0.1")}, // Main version is always larger than other version + } + + testIsLargerThan(t, testCases, true) +} + +func TestIsLargerThanFalse(t *testing.T) { + testCases := []testCase{ + {versionA: Version("0.9.9"), versionB: Version("0.9.9")}, // Same versions + {versionA: Version("1.1"), versionB: Version("1.1.1")}, // Different versions length + {versionA: MinVersionNone, versionB: MinVersionNone}, // Same version none + {versionA: VersionUnknown, versionB: VersionUnknown}, // Same version unknown + {versionA: MaxVersionLatest, versionB: MaxVersionLatest}, // Same version latest + {versionA: MaxVersionMain, versionB: MaxVersionMain}, // Same version main + {versionA: MaxVersionMain, versionB: MaxVersionLatest}, // Both max versions + {versionA: Version("1.1"), versionB: Version("1.1.0")}, // Same version with postfix 0 + {versionA: Version("1.1.0"), versionB: Version("1.1")}, // Same version with postfix 0 + {versionA: Version("0.9.9"), versionB: Version("1.0.0")}, // Basic comparison + {versionA: Version("1.0.0"), versionB: Version("1.0.1")}, // Patch increment + {versionA: Version("1.0.10"), versionB: Version("1.1.0")}, // Minor increment + {versionA: Version("1.9.9"), versionB: Version("2.0.0")}, // Major increment + {versionA: Version("2.0.0-alpha"), versionB: Version("2.0.0-beta")}, // Pre-release comparison + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0")}, // Stable vs pre-release + {versionA: Version("1.2.0-alpha.1"), versionB: Version("1.2.0-alpha.2")}, // Pre-release with multiple segments (up to 9) + {versionA: Version("1.2.0-alpha.10"), versionB: Version("1.2.0-beta.1")}, // Different pre-release labels + {versionA: Version("1.2.0"), versionB: Version("1.11.0")}, // Double digits + {versionA: Version("1.0.2"), versionB: Version("1.0.10")}, // Patch number double digits + {versionA: Version("2.10.0"), versionB: Version("11.0.0")}, // Major double digits + {versionA: Version("1.1.0"), versionB: Version("1.1.1")}, // All segments incremented + {versionA: Version("2.10.10"), versionB: Version("3.0.0")}, // All previous segments at max + {versionA: Version("1.0.0-beta.9"), versionB: Version("1.0.0-rc.1")}, // Pre-release progression + {versionA: Version("1.0.0-rc.1"), versionB: Version("1.0.0-rc.3")}, // Pre-release with numbers (up to 9) + {versionA: Version("2.0.0-rc.10"), versionB: Version("2.0.0")}, // Stable vs long pre-release + {versionA: Version("1.0.0-alpha"), versionB: Version("1.0.1")}, // Patch increment over pre-release + {versionA: Version("2.0.0-alpha.10"), versionB: Version("2.0.0-beta")}, // Pre-release without numbers vs one with numbers + {versionA: Version("3.2.0"), versionB: Version("3.2.1")}, // Minor and patch increment + {versionA: Version("4.0.0"), versionB: Version("4.0.1")}, // Major increment with patch + {versionA: Version("5.1.10"), versionB: Version("5.2.0")}, // Major stable with minor and patch increments + {versionA: Version("1.2.0-alpha.4"), versionB: Version("1.2.3")}, // Stable vs pre-release with multiple segments + {versionA: Version("1.2.3-alpha.5"), versionB: Version("1.2.3-beta.5")}, // Same version, different pre-release + {versionA: Version("1.2.3-beta.2"), versionB: Version("1.2.3-beta.9")}, // Same version, pre-release with numbers (up to 9) + {versionA: Version("2.10.10"), versionB: Version("10.10.10")}, // Large major increment + {versionA: VersionUnknown, versionB: Version("0.0.1")}, // Version is always larger than an unknown version + {versionA: MinVersionNone, versionB: Version("0.0.1")}, // Version is always larger than a none version + {versionA: Version("0.0.1"), versionB: MaxVersionLatest}, // Version latest is always larger than any other version + {versionA: Version("0.0.1"), versionB: MaxVersionMain}, // Version main is always larger than any other version + {versionA: Version("0.a.1"), versionB: Version("a.1.1")}, // Invalid versions considered as equals + } + + testIsLargerThan(t, testCases, false) +} + +func TestIsLessThanTrue(t *testing.T) { + testCases := []testCase{ + {versionA: Version("0.9.9"), versionB: Version("1.0.0")}, // Basic comparison + {versionA: Version("1.1"), versionB: Version("1.1.1")}, // Different versions length + {versionA: Version("1.0.0"), versionB: Version("1.0.1")}, // Patch increment + {versionA: Version("1.0.10"), versionB: Version("1.1.0")}, // Minor increment + {versionA: Version("1.9.9"), versionB: Version("2.0.0")}, // Major increment + {versionA: Version("2.0.0-alpha"), versionB: Version("2.0.0-beta")}, // Pre-release comparison + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0")}, // Stable vs pre-release + {versionA: Version("1.2.0-alpha.1"), versionB: Version("1.2.0-alpha.2")}, // Pre-release with multiple segments (up to 9) + {versionA: Version("1.2.0-alpha.10"), versionB: Version("1.2.0-beta.1")}, // Different pre-release labels + {versionA: Version("1.2.0"), versionB: Version("1.11.0")}, // Double digits + {versionA: Version("1.0.2"), versionB: Version("1.0.10")}, // Patch number double digits + {versionA: Version("2.10.0"), versionB: Version("11.0.0")}, // Major double digits + {versionA: Version("1.1.0"), versionB: Version("1.1.1")}, // All segments incremented + {versionA: Version("2.10.10"), versionB: Version("3.0.0")}, // All previous segments at max + {versionA: Version("1.0.0-beta.9"), versionB: Version("1.0.0-rc.1")}, // Pre-release progression + {versionA: Version("1.0.0-rc.1"), versionB: Version("1.0.0-rc.3")}, // Pre-release with numbers (up to 9) + {versionA: Version("2.0.0-rc.10"), versionB: Version("2.0.0")}, // Stable vs long pre-release + {versionA: Version("1.0.0-alpha"), versionB: Version("1.0.1")}, // Patch increment over pre-release + {versionA: Version("2.0.0-alpha.10"), versionB: Version("2.0.0-beta")}, // Pre-release without numbers vs one with numbers + {versionA: Version("3.2.0"), versionB: Version("3.2.1")}, // Minor and patch increment + {versionA: Version("4.0.0"), versionB: Version("4.0.1")}, // Major increment with patch + {versionA: Version("5.1.10"), versionB: Version("5.2.0")}, // Major stable with minor and patch increments + {versionA: Version("1.2.0-alpha.4"), versionB: Version("1.2.3")}, // Stable vs pre-release with multiple segments + {versionA: Version("1.2.3-alpha.5"), versionB: Version("1.2.3-beta.5")}, // Same version, different pre-release + {versionA: Version("1.2.3-beta.2"), versionB: Version("1.2.3-beta.9")}, // Same version, pre-release with numbers (up to 9) + {versionA: Version("2.10.10"), versionB: Version("10.10.10")}, // Large major increment + {versionA: MinVersionNone, versionB: Version("0.0.1")}, // Version is always larger than a none version + {versionA: Version("0.0.1"), versionB: MaxVersionLatest}, // Version latest is always larger than any other version + {versionA: Version("0.0.1"), versionB: MaxVersionMain}, // Version main is always larger than any other version + } + + testIsLessThan(t, testCases, true) +} + +func TestIsLessThanFalse(t *testing.T) { + testCases := []testCase{ + {versionA: Version("0.9.9"), versionB: Version("0.9.9")}, // Same versions + {versionA: MinVersionNone, versionB: MinVersionNone}, // Same version none + {versionA: VersionUnknown, versionB: VersionUnknown}, // Same version unknown + {versionA: MaxVersionLatest, versionB: MaxVersionLatest}, // Same version latest + {versionA: MaxVersionMain, versionB: MaxVersionMain}, // Same version main + {versionA: MaxVersionMain, versionB: MaxVersionLatest}, // Both max versions + {versionA: Version("1.1"), versionB: Version("1.1.0")}, // Same version with postfix 0 + {versionA: Version("1.1.0"), versionB: Version("1.1")}, // Same version with postfix 0 + {versionA: Version("1.0.0"), versionB: Version("0.9.9")}, // Basic comparison + {versionA: Version("1.1.1"), versionB: Version("1.1")}, // Different versions length + {versionA: Version("1.0.1"), versionB: Version("1.0.0")}, // Patch increment + {versionA: Version("1.1.0"), versionB: Version("1.0.10")}, // Minor increment + {versionA: Version("2.0.0"), versionB: Version("1.9.9")}, // Major increment + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0-alpha")}, // Pre-release comparison + {versionA: Version("2.0.0"), versionB: Version("2.0.0-beta")}, // Stable vs pre-release + {versionA: Version("1.2.0-alpha.2"), versionB: Version("1.2.0-alpha.1")}, // Pre-release with multiple segments (up to 9) + {versionA: Version("1.2.0-beta.1"), versionB: Version("1.2.0-alpha.10")}, // Different pre-release labels + {versionA: Version("1.11.0"), versionB: Version("1.2.0")}, // Double digits + {versionA: Version("1.0.10"), versionB: Version("1.0.2")}, // Patch number double digits + {versionA: Version("11.0.0"), versionB: Version("2.10.0")}, // Major double digits + {versionA: Version("1.1.1"), versionB: Version("1.1.0")}, // All segments incremented + {versionA: Version("3.0.0"), versionB: Version("2.10.10")}, // All previous segments at max + {versionA: Version("1.0.0-rc.1"), versionB: Version("1.0.0-beta.9")}, // Pre-release progression + {versionA: Version("1.0.0-rc.3"), versionB: Version("1.0.0-rc.1")}, // Pre-release with numbers (up to 9) + {versionA: Version("2.0.0"), versionB: Version("2.0.0-rc.10")}, // Stable vs long pre-release + {versionA: Version("1.0.1"), versionB: Version("1.0.0-alpha")}, // Patch increment over pre-release + {versionA: Version("2.0.0-beta"), versionB: Version("2.0.0-alpha.10")}, // Pre-release without numbers vs one with numbers + {versionA: Version("3.2.1"), versionB: Version("3.2.0")}, // Minor and patch increment + {versionA: Version("4.0.1"), versionB: Version("4.0.0")}, // Major increment with patch + {versionA: Version("5.2.0"), versionB: Version("5.1.10")}, // Major stable with minor and patch increments + {versionA: Version("1.2.3"), versionB: Version("1.2.0-alpha.4")}, // Stable vs pre-release with multiple segments + {versionA: Version("1.2.3-beta.5"), versionB: Version("1.2.3-alpha.5")}, // Same version, different pre-release + {versionA: Version("1.2.3-beta.9"), versionB: Version("1.2.3-beta.2")}, // Same version, pre-release with numbers (up to 9) + {versionA: Version("10.10.10"), versionB: Version("2.10.10")}, // Large major increment + {versionA: VersionUnknown, versionB: Version("0.0.1")}, // Version unknown is not considered less than other version + {versionA: MaxVersionMain, versionB: Version("0.0.1")}, // Version main is not less than other version + {versionA: Version("0.0.1"), versionB: VersionUnknown}, // Version is always larger than an unknown version + {versionA: Version("0.0.1"), versionB: MinVersionNone}, // Version is always larger than a none version + {versionA: Version("0.a.1"), versionB: Version("a.1.1")}, // Invalid versions considered as equals + } + + testIsLessThan(t, testCases, false) +} + +func testIsLargerThan(t *testing.T, testCases []testCase, expected bool) { + for i, testCase := range testCases { + t.Run(fmt.Sprintf("testIsLargerThan %d", i), func(t *testing.T) { + require.Equal(t, expected, testCase.versionA.IsLargerThan(testCase.versionB)) + }) + } +} + +func testIsLessThan(t *testing.T, testCases []testCase, expected bool) { + for i, testCase := range testCases { + t.Run(fmt.Sprintf("testIsLargerThan %d", i), func(t *testing.T) { + require.Equal(t, expected, testCase.versionA.IsLessThan(testCase.versionB)) + }) + } +} diff --git a/cbcontainers/processors/agent_processor.go b/cbcontainers/processors/agent_processor.go index 07fc6717..2630707c 100644 --- a/cbcontainers/processors/agent_processor.go +++ b/cbcontainers/processors/agent_processor.go @@ -130,5 +130,5 @@ func (processor *AgentProcessor) checkCompatibility(cbContainersAgent *cbcontain } // if there is no error check the compatibility and return the result - return m.CheckCompatibility(cbContainersAgent.Spec.Version) + return m.CheckCompatibility(models.Version(cbContainersAgent.Spec.Version)) } diff --git a/cbcontainers/remote_configuration/validation.go b/cbcontainers/remote_configuration/validation.go index 59735b7a..b8b4a86a 100644 --- a/cbcontainers/remote_configuration/validation.go +++ b/cbcontainers/remote_configuration/validation.go @@ -51,5 +51,5 @@ func (validator *ConfigurationChangeValidator) ValidateChange(change models.Conf versionToValidate = cr.Spec.Version } - return validator.OperatorCompatibilityData.CheckCompatibility(versionToValidate) + return validator.OperatorCompatibilityData.CheckCompatibility(models.Version(versionToValidate)) } From b7b3779603543fde0fdae2e18fec2425de81948f Mon Sep 17 00:00:00 2001 From: omessir Date: Thu, 2 Nov 2023 10:32:02 -0400 Subject: [PATCH 2/2] fix agent version compatibility check --- cbcontainers/remote_configuration/validation_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cbcontainers/remote_configuration/validation_test.go b/cbcontainers/remote_configuration/validation_test.go index 68141877..88e1402d 100644 --- a/cbcontainers/remote_configuration/validation_test.go +++ b/cbcontainers/remote_configuration/validation_test.go @@ -58,7 +58,7 @@ func TestValidateFailsIfSensorAndOperatorAreNotCompatible(t *testing.T) { name: "sensor version is too high", versionToApply: "5.0.0", operatorCompatibility: models.OperatorCompatibility{ - MinAgent: models.AgentMinVersionNone, + MinAgent: models.MinVersionNone, MaxAgent: "4.0.0", }, }, @@ -67,7 +67,7 @@ func TestValidateFailsIfSensorAndOperatorAreNotCompatible(t *testing.T) { versionToApply: "0.9", operatorCompatibility: models.OperatorCompatibility{ MinAgent: "1.0.0", - MaxAgent: models.AgentMaxVersionLatest, + MaxAgent: models.MaxVersionLatest, }, }, } @@ -121,8 +121,8 @@ func TestValidateSucceedsIfSensorAndOperatorAreCompatible(t *testing.T) { name: "operator supports 'infinite' versions", versionToApply: "5.0.0", operatorCompatibility: models.OperatorCompatibility{ - MinAgent: models.AgentMinVersionNone, - MaxAgent: models.AgentMaxVersionLatest, + MinAgent: models.MinVersionNone, + MaxAgent: models.MaxVersionLatest, }, }, }