From 6d385aa0d5c5f69109252cf38fe7cfbf814274a1 Mon Sep 17 00:00:00 2001 From: Will Foster Date: Wed, 18 Sep 2024 16:28:05 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=B1=20clusterctl:=20add=20flag=20to=20?= =?UTF-8?q?skip=20lagging=20provider=20check=20in=20ApplyCustomPlan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/clusterctl/client/cluster/upgrader.go | 43 +++++++++++-------- .../client/cluster/upgrader_test.go | 2 +- cmd/clusterctl/client/upgrade.go | 8 +++- cmd/clusterctl/cmd/upgrade_apply.go | 4 ++ 4 files changed, 37 insertions(+), 20 deletions(-) diff --git a/cmd/clusterctl/client/cluster/upgrader.go b/cmd/clusterctl/client/cluster/upgrader.go index 11ec8f8f1891..d23eeeaf82e1 100644 --- a/cmd/clusterctl/client/cluster/upgrader.go +++ b/cmd/clusterctl/client/cluster/upgrader.go @@ -57,8 +57,9 @@ type UpgradePlan struct { // UpgradeOptions defines the options used to upgrade installation. type UpgradeOptions struct { - WaitProviders bool - WaitProviderTimeout time.Duration + WaitProviders bool + WaitProviderTimeout time.Duration + SkipLaggingProvidersCheck bool } // isPartialUpgrade returns true if at least one upgradeItem in the plan does not have a target version. @@ -180,7 +181,7 @@ func (u *providerUpgrader) ApplyCustomPlan(ctx context.Context, opts UpgradeOpti // Create a custom upgrade plan from the upgrade items, taking care of ensuring all the providers in a management // cluster are consistent with the API Version of Cluster API (contract). - upgradePlan, err := u.createCustomPlan(ctx, upgradeItems) + upgradePlan, err := u.createCustomPlan(ctx, opts, upgradeItems) if err != nil { return err } @@ -218,7 +219,7 @@ func (u *providerUpgrader) getUpgradePlan(ctx context.Context, providers []clust // createCustomPlan creates a custom upgrade plan from a set of upgrade items, taking care of ensuring all the providers // in a management cluster are consistent with the API Version of Cluster API (contract). -func (u *providerUpgrader) createCustomPlan(ctx context.Context, upgradeItems []UpgradeItem) (*UpgradePlan, error) { +func (u *providerUpgrader) createCustomPlan(ctx context.Context, opts UpgradeOptions, upgradeItems []UpgradeItem) (*UpgradePlan, error) { // Gets the API Version of Cluster API (contract). // The this is required to ensure all the providers in a management cluster are consistent with the contract supported by the core provider. // e.g if the core provider is v1beta1, all the provider should be v1beta1 as well. @@ -286,20 +287,22 @@ func (u *providerUpgrader) createCustomPlan(ctx context.Context, upgradeItems [] } // Before doing upgrades, checks if other providers in the management cluster are lagging behind the target contract. - for _, provider := range providerList.Items { - // skip providers already included in the upgrade plan - if upgradeInstanceNames.Has(provider.InstanceName()) { - continue - } + if !opts.SkipLaggingProvidersCheck { + for _, provider := range providerList.Items { + // skip providers already included in the upgrade plan + if upgradeInstanceNames.Has(provider.InstanceName()) { + continue + } - // Retrieves the contract that is supported by the current version of the provider. - contract, err := u.getProviderContractByVersion(ctx, provider, provider.Version) - if err != nil { - return nil, err - } + // Retrieves the contract that is supported by the current version of the provider. + contract, err := u.getProviderContractByVersion(ctx, provider, provider.Version) + if err != nil { + return nil, err + } - if contract != targetContract { - return nil, errors.Errorf("unable to complete that upgrade: the provider %s supports the %s API Version of Cluster API (contract), while the management cluster is being updated to %s. Please include the %[1]s provider in the upgrade", provider.InstanceName(), contract, targetContract) + if contract != targetContract { + return nil, errors.Errorf("unable to complete that upgrade: the provider %s supports the %s API Version of Cluster API (contract), while the management cluster is being updated to %s. Please include the %[1]s provider in the upgrade", provider.InstanceName(), contract, targetContract) + } } } return upgradePlan, nil @@ -448,7 +451,13 @@ func (u *providerUpgrader) doUpgrade(ctx context.Context, upgradePlan *UpgradePl } } - return waitForProvidersReady(ctx, InstallOptions(opts), installQueue, u.proxy) + // Convert UpgradeOptions to InstallOptions struct + installOptions := InstallOptions{ + WaitProviders: opts.WaitProviders, + WaitProviderTimeout: opts.WaitProviderTimeout, + } + + return waitForProvidersReady(ctx, installOptions, installQueue, u.proxy) } func (u *providerUpgrader) scaleDownProvider(ctx context.Context, provider clusterctlv1.Provider) error { diff --git a/cmd/clusterctl/client/cluster/upgrader_test.go b/cmd/clusterctl/client/cluster/upgrader_test.go index 322ad4c74d4a..bb9b7f4818db 100644 --- a/cmd/clusterctl/client/cluster/upgrader_test.go +++ b/cmd/clusterctl/client/cluster/upgrader_test.go @@ -791,7 +791,7 @@ func Test_providerUpgrader_createCustomPlan(t *testing.T) { }, providerInventory: newInventoryClient(tt.fields.proxy, nil), } - got, err := u.createCustomPlan(ctx, tt.args.providersToUpgrade) + got, err := u.createCustomPlan(ctx, UpgradeOptions{}, tt.args.providersToUpgrade) if tt.wantErr { g.Expect(err).To(HaveOccurred()) return diff --git a/cmd/clusterctl/client/upgrade.go b/cmd/clusterctl/client/upgrade.go index 5979c9461b72..e344e85b1d78 100644 --- a/cmd/clusterctl/client/upgrade.go +++ b/cmd/clusterctl/client/upgrade.go @@ -123,6 +123,9 @@ type ApplyUpgradeOptions struct { // WaitProviderTimeout sets the timeout per provider upgrade. WaitProviderTimeout time.Duration + + // SkipLaggingProvidersCheck skips checking if other providers in the management cluster are lagging behind the target contract during upgrade planning. + SkipLaggingProvidersCheck bool } func (c *clusterctlClient) ApplyUpgrade(ctx context.Context, options ApplyUpgradeOptions) error { @@ -171,8 +174,9 @@ func (c *clusterctlClient) ApplyUpgrade(ctx context.Context, options ApplyUpgrad len(options.AddonProviders) > 0 opts := cluster.UpgradeOptions{ - WaitProviders: options.WaitProviders, - WaitProviderTimeout: options.WaitProviderTimeout, + WaitProviders: options.WaitProviders, + WaitProviderTimeout: options.WaitProviderTimeout, + SkipLaggingProvidersCheck: options.SkipLaggingProvidersCheck, } // If we are upgrading a specific set of providers only, process the providers and call ApplyCustomPlan. diff --git a/cmd/clusterctl/cmd/upgrade_apply.go b/cmd/clusterctl/cmd/upgrade_apply.go index 402df535405d..c3fb46c4ee66 100644 --- a/cmd/clusterctl/cmd/upgrade_apply.go +++ b/cmd/clusterctl/cmd/upgrade_apply.go @@ -39,6 +39,7 @@ type upgradeApplyOptions struct { addonProviders []string waitProviders bool waitProviderTimeout int + skipLaggingProvidersCheck bool } var ua = &upgradeApplyOptions{} @@ -93,6 +94,8 @@ func init() { "Wait for providers to be upgraded.") upgradeApplyCmd.Flags().IntVar(&ua.waitProviderTimeout, "wait-provider-timeout", 5*60, "Wait timeout per provider upgrade in seconds. This value is ignored if --wait-providers is false") + upgradeApplyCmd.Flags().BoolVar(&ua.skipLaggingProvidersCheck, "skip-lagging-providers-check", false, + "Skips checking if other providers in the management cluster are lagging behind the target contract during upgrade planning") } func runUpgradeApply() error { @@ -130,5 +133,6 @@ func runUpgradeApply() error { AddonProviders: ua.addonProviders, WaitProviders: ua.waitProviders, WaitProviderTimeout: time.Duration(ua.waitProviderTimeout) * time.Second, + SkipLaggingProvidersCheck: ua.skipLaggingProvidersCheck, }) }