Added migrations.d
This commit is contained in:
@@ -15,4 +15,5 @@ func newNoopAdaptiveWriteController() *adaptiveWriteController {
|
||||
}
|
||||
|
||||
func (c *adaptiveWriteController) Wait(ctx context.Context, n int) error { return nil }
|
||||
func (c *adaptiveWriteController) ObserveWrite(n int, dur interface{}) {}
|
||||
func (c *adaptiveWriteController) ObserveWrite(n int) {}
|
||||
func (c *adaptiveWriteController) ObserveSync() {}
|
||||
|
||||
@@ -224,9 +224,9 @@ func calculatePath(current, target string, available []string) ([]string, error)
|
||||
add(latestCurMinor)
|
||||
}
|
||||
|
||||
// Step 2: walk each intermediate minor using the lowest available patch in that minor.
|
||||
// Step 2: walk each intermediate minor using the latest available patch in that minor.
|
||||
for minor := cur.Minor + 1; minor < tgt.Minor; minor++ {
|
||||
bridge, ok := lowestPatchInMinor(versions, cur.Major, minor)
|
||||
bridge, ok := latestAnyPatchInMinor(versions, cur.Major, minor)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no available bridge version for v%d.%d.x", cur.Major, minor)
|
||||
}
|
||||
@@ -239,6 +239,23 @@ func calculatePath(current, target string, available []string) ([]string, error)
|
||||
return versionsToStrings(path), nil
|
||||
}
|
||||
|
||||
func latestAnyPatchInMinor(versions []Version, major, minor int) (Version, bool) {
|
||||
var found Version
|
||||
ok := false
|
||||
|
||||
for _, v := range versions {
|
||||
if v.Major != major || v.Minor != minor {
|
||||
continue
|
||||
}
|
||||
if !ok || found.Compare(v) < 0 {
|
||||
found = v
|
||||
ok = true
|
||||
}
|
||||
}
|
||||
|
||||
return found, ok
|
||||
}
|
||||
|
||||
func parseAndSortVersions(raw []string) ([]Version, error) {
|
||||
out := make([]Version, 0, len(raw))
|
||||
seen := map[string]struct{}{}
|
||||
|
||||
149
clitools/pkg/controller/osupgrade/planner_test.go
Normal file
149
clitools/pkg/controller/osupgrade/planner_test.go
Normal file
@@ -0,0 +1,149 @@
|
||||
package osupgrade
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCalculatePath(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
current string
|
||||
target string
|
||||
available []string
|
||||
want []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "same version returns nil path",
|
||||
current: "v1.34.6",
|
||||
target: "v1.34.6",
|
||||
available: []string{"v1.34.6"},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "same minor jumps directly to target",
|
||||
current: "v1.34.1",
|
||||
target: "v1.34.6",
|
||||
available: []string{"v1.34.1", "v1.34.3", "v1.34.6"},
|
||||
want: []string{"v1.34.6"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "next minor direct jump when no current minor patch available",
|
||||
current: "v1.34.6",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.6", "v1.35.1", "v1.35.3"},
|
||||
want: []string{"v1.35.3"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "finish current minor then target",
|
||||
current: "v1.34.1",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.1", "v1.34.6", "v1.35.1", "v1.35.3"},
|
||||
want: []string{"v1.34.6", "v1.35.3"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multi minor path uses latest bridge patch",
|
||||
current: "v1.33.10",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.1", "v1.34.6", "v1.35.1", "v1.35.3"},
|
||||
want: []string{"v1.34.6", "v1.35.3"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "multi minor path finishes current minor and latest bridge patch",
|
||||
current: "v1.33.1",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.33.5", "v1.33.9", "v1.34.1", "v1.34.6", "v1.35.3"},
|
||||
want: []string{"v1.33.9", "v1.34.6", "v1.35.3"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "duplicates in available are ignored",
|
||||
current: "v1.33.10",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.6", "v1.34.6", "v1.35.3", "v1.35.3"},
|
||||
want: []string{"v1.34.6", "v1.35.3"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "target missing returns error",
|
||||
current: "v1.34.6",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.6", "v1.35.1"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "missing bridge minor returns error",
|
||||
current: "v1.33.10",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.35.3"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "downgrade not supported",
|
||||
current: "v1.35.3",
|
||||
target: "v1.34.6",
|
||||
available: []string{"v1.34.6", "v1.35.3"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "cross major not supported",
|
||||
current: "v1.35.3",
|
||||
target: "v2.0.0",
|
||||
available: []string{"v1.35.3", "v2.0.0"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid current version returns error",
|
||||
current: "garbage",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.35.3"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid target version returns error",
|
||||
current: "v1.34.6",
|
||||
target: "wat",
|
||||
available: []string{"v1.34.6", "v1.35.3"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid available version returns error",
|
||||
current: "v1.34.6",
|
||||
target: "v1.35.3",
|
||||
available: []string{"v1.34.6", "broken", "v1.35.3"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
got, err := calculatePath(tt.current, tt.target, tt.available)
|
||||
if tt.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("expected error, got nil; path=%v", got)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Fatalf("calculatePath(%q, %q, %v)\n got: %v\n want: %v",
|
||||
tt.current, tt.target, tt.available, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user