Skip to content

Commit

Permalink
Merge pull request #199 from octarinesec/fix-agent-version-compatibility
Browse files Browse the repository at this point in the history
fix agent version compatibility check
  • Loading branch information
BenRub authored Nov 2, 2023
2 parents bebb6ef + b7b3779 commit 851af8b
Show file tree
Hide file tree
Showing 8 changed files with 361 additions and 56 deletions.
23 changes: 0 additions & 23 deletions cbcontainers/models/agent_version.go

This file was deleted.

6 changes: 3 additions & 3 deletions cbcontainers/models/operator_compatibility.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ 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.
//
// 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)
}
Expand Down
52 changes: 28 additions & 24 deletions cbcontainers/models/operator_compatibility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,45 @@ 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)
}

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)
Expand Down
130 changes: 130 additions & 0 deletions cbcontainers/models/version.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit 851af8b

Please sign in to comment.