Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions pkg/admin/prerun/upgrade_blocking.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package prerun

import (
"encoding/json"
"errors"
"fmt"
"io/fs"

embedded "github.com/openshift/microshift/assets"
"k8s.io/klog/v2"
)

func IsUpgradeBlocked(execVersion versionMetadata, dataVersion versionMetadata) (bool, error) {
buf, err := getBlockedUpgradesAsset()
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return false, nil
}
return false, fmt.Errorf("failed to load embedded blocked upgrades asset: %w", err)
}

m, err := unmarshalBlockedUpgrades(buf)
if err != nil {
return false, err
}

return isBlocked(m, execVersion.String(), dataVersion.String()), nil
}

func getBlockedUpgradesAsset() ([]byte, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is using an asset easier to manage than just embedding the list in this go module? Are you thinking of automation managing that file (in which case, yes, I agree YAML is going to be easier)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point I don't have any idea how we'll use this feature and manage the list. Asset just felt natural since we already embed some files that way but it's not a strong feeling and we can change it

return embedded.Asset("release/upgrade-blocks.json")
}

func unmarshalBlockedUpgrades(data []byte) (map[string][]string, error) {
var blockedEdges map[string][]string
err := json.Unmarshal(data, &blockedEdges)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal %q: %w", string(data), err)
}
return blockedEdges, nil
}

func isBlocked(blockedUpgrades map[string][]string, execVersion, dataVersion string) bool {
klog.InfoS("Checking if upgrade is allowed", "existing-data-version", dataVersion, "new-binary-version", execVersion, "blocked-upgrades", blockedUpgrades)

for targetVersion, fromVersions := range blockedUpgrades {
if targetVersion == execVersion {
for _, from := range fromVersions {
if from == dataVersion {
klog.ErrorS(nil, "Detected an attempt of unsupported upgrade", "existing-data-version", dataVersion, "new-binary-version", execVersion)
return true
}
}
}
}

klog.InfoS("Upgrade is allowed", "existing-data-version", dataVersion, "new-binary-version", execVersion)
return false
}
77 changes: 77 additions & 0 deletions pkg/admin/prerun/upgrade_blocking_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package prerun

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_UnmarshalBlockedUpgrades(t *testing.T) {
testData := []struct {
input string
expectedOutput map[string][]string
}{
{
input: `{"4.14.10": ["4.14.5", "4.14.4"]}`,
expectedOutput: map[string][]string{"4.14.10": {"4.14.5", "4.14.4"}},
},
{
input: `{}`,
expectedOutput: make(map[string][]string),
},
}

for _, td := range testData {
result, err := unmarshalBlockedUpgrades([]byte(td.input))
assert.NoError(t, err)
assert.Equal(t, td.expectedOutput, result)
}
}

func Test_IsBlocked(t *testing.T) {
edges := map[string][]string{
"4.14.10": {"4.14.5", "4.14.6"},
"4.15.5": {"4.15.2"},
}

testData := []struct {
dataVersion string
execVersion string
expectedResult bool
}{
{
dataVersion: "4.14.4",
execVersion: "4.14.10",
expectedResult: false,
},
{
dataVersion: "4.14.5",
execVersion: "4.14.10",
expectedResult: true,
},
{
dataVersion: "4.14.6",
execVersion: "4.14.10",
expectedResult: true,
},
{
dataVersion: "4.14.7",
execVersion: "4.14.10",
expectedResult: false,
},
{
dataVersion: "4.14.7",
execVersion: "4.15.0",
expectedResult: false,
},
{
dataVersion: "4.15.2",
execVersion: "4.15.5",
expectedResult: true,
},
}

for _, td := range testData {
assert.Equal(t, td.expectedResult, isBlocked(edges, td.execVersion, td.dataVersion))
}
}
2 changes: 1 addition & 1 deletion pkg/admin/prerun/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,5 @@ func checkVersionDiff(execVer, dataVer versionMetadata) (bool, error) {
}
}

return false, nil
return IsUpgradeBlocked(execVer, dataVer)
}