Skip to content

Commit e4e0fcf

Browse files
stmcginnisk8s-infra-cherrypick-robot
authored andcommitted
Verify providers need upgrade before applying
If a user runs `upgrade plan` and the results show there are no available upgrades, the expectation is they then do not attempt to apply the plan. But nothing prevents them from doing so. If a non-upgrade plan is applied, the current apply logic does not handle the case where the "next version" is empty. To make this more robust, and to protect against users trying to apply plans with no available upgrades, this performs a quick validation on the plan providers to make sure they have a version to upgrade to. If not, the `upgrade apply` call ends up being a no-op and avoids potentially confusing error output. Signed-off-by: Sean McGinnis <[email protected]>
1 parent c24d0a9 commit e4e0fcf

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

cmd/clusterctl/client/cluster/upgrader.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,15 @@ func (u *providerUpgrader) ApplyPlan(ctx context.Context, opts UpgradeOptions, c
175175
return err
176176
}
177177

178+
// Make sure there is something to upgrade, clear providers that do not
179+
// need it
180+
for i := len(upgradePlan.Providers) - 1; i >= 0; i-- {
181+
if upgradePlan.Providers[i].NextVersion == "" {
182+
// Remove this from our plan
183+
upgradePlan.Providers = append(upgradePlan.Providers[:i], upgradePlan.Providers[i+1:]...)
184+
}
185+
}
186+
178187
// Do the upgrade
179188
return u.doUpgrade(ctx, upgradePlan, opts)
180189
}

cmd/clusterctl/client/cluster/upgrader_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,43 @@ func Test_providerUpgrader_ApplyPlan(t *testing.T) {
11001100
errorMsg: "detected multiple instances of the same provider",
11011101
opts: UpgradeOptions{},
11021102
},
1103+
{
1104+
name: "does not fail when there is nothing to upgrade",
1105+
fields: fields{
1106+
// config for two providers
1107+
reader: test.NewFakeReader().
1108+
WithProvider("cluster-api", clusterctlv1.CoreProviderType, "https://somewhere.com").
1109+
WithProvider("infra", clusterctlv1.InfrastructureProviderType, "https://somewhere.com"),
1110+
// two provider repositories, with current v1alpha3 contract and new versions for v1alpha4 contract
1111+
repository: map[string]repository.Repository{
1112+
"cluster-api": repository.NewMemoryRepository().
1113+
WithDefaultVersion("v2.0.0").
1114+
WithVersions("v2.0.0").
1115+
WithMetadata("v2.0.0", &clusterctlv1.Metadata{
1116+
ReleaseSeries: []clusterctlv1.ReleaseSeries{
1117+
{Major: 1, Minor: 0, Contract: oldContractVersionNotSupportedAnymore},
1118+
{Major: 2, Minor: 0, Contract: currentContractVersion},
1119+
},
1120+
}),
1121+
"infrastructure-infra": repository.NewMemoryRepository().
1122+
WithDefaultVersion("v3.0.0").
1123+
WithVersions("v3.0.0").
1124+
WithMetadata("v3.0.0", &clusterctlv1.Metadata{
1125+
ReleaseSeries: []clusterctlv1.ReleaseSeries{
1126+
{Major: 2, Minor: 0, Contract: oldContractVersionNotSupportedAnymore},
1127+
{Major: 3, Minor: 0, Contract: currentContractVersion},
1128+
},
1129+
}),
1130+
},
1131+
// two providers with up to date versions
1132+
proxy: test.NewFakeProxy().
1133+
WithProviderInventory("cluster-api", clusterctlv1.CoreProviderType, "v2.0.0", "cluster-api-system").
1134+
WithProviderInventory("infra", clusterctlv1.InfrastructureProviderType, "v3.0.0", "infra-system-1"),
1135+
},
1136+
contract: currentContractVersion,
1137+
wantErr: false,
1138+
opts: UpgradeOptions{},
1139+
},
11031140
}
11041141

11051142
for _, tt := range tests {

0 commit comments

Comments
 (0)