From 397aa370c60c5314a82f9c3e598c37b401286e36 Mon Sep 17 00:00:00 2001 From: Jan Schlicht Date: Tue, 15 Sep 2020 10:33:47 +0200 Subject: [PATCH] Add an option to wait for an instance uninstall (#1682) Similar to the 'wait' and 'wait-time' options for operator package installations, instance uninstalls can be waited upon to complete. Signed-off-by: Jan Schlicht --- pkg/kudoctl/cmd/uninstall.go | 25 +++++++++++++++++++------ pkg/kudoctl/cmd/uninstall_test.go | 11 +++++++++-- pkg/kudoctl/util/kudo/kudo.go | 20 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/pkg/kudoctl/cmd/uninstall.go b/pkg/kudoctl/cmd/uninstall.go index d755bcee1..27fc1b772 100644 --- a/pkg/kudoctl/cmd/uninstall.go +++ b/pkg/kudoctl/cmd/uninstall.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "time" "github.com/spf13/cobra" @@ -16,6 +17,8 @@ const ( type uninstallOptions struct { InstanceName string + Wait bool + WaitTime int64 } type uninstallCmd struct{} @@ -28,25 +31,32 @@ func (cmd *uninstallCmd) run(options uninstallOptions, settings *env.Settings) e return fmt.Errorf("failed to acquire kudo client: %w", err) } - return cmd.uninstall(kc, options.InstanceName, settings) + return cmd.uninstall(kc, options, settings) } -func (cmd *uninstallCmd) uninstall(kc *kudo.Client, instanceName string, settings *env.Settings) error { - instance, err := kc.GetInstance(instanceName, settings.Namespace) +func (cmd *uninstallCmd) uninstall(kc *kudo.Client, options uninstallOptions, settings *env.Settings) error { + instance, err := kc.GetInstance(options.InstanceName, settings.Namespace) if err != nil { return fmt.Errorf("failed to verify if instance already exists: %w", err) } if instance == nil { - return fmt.Errorf("instance %s in namespace %s does not exist in the cluster", instanceName, settings.Namespace) + return fmt.Errorf("instance %s in namespace %s does not exist in the cluster", options.InstanceName, settings.Namespace) } - err = kc.DeleteInstance(instanceName, settings.Namespace) + err = kc.DeleteInstance(options.InstanceName, settings.Namespace) if err != nil { return err } - clog.Printf("instance.%s/%s deleted\n", instance.APIVersion, instanceName) + if options.Wait { + waitDuration := time.Duration(options.WaitTime) * time.Second + if err := kc.WaitForInstanceDeleted(options.InstanceName, settings.Namespace, waitDuration); err != nil { + return err + } + } + + clog.Printf("instance.%s/%s deleted\n", instance.APIVersion, options.InstanceName) return nil } @@ -75,5 +85,8 @@ func newUninstallCmd() *cobra.Command { panic(err) } + uninstallCmd.Flags().BoolVar(&options.Wait, "wait", false, "Specify if the CLI should wait for the uninstall to complete before returning (default \"false\")") + uninstallCmd.Flags().Int64Var(&options.WaitTime, "wait-time", 300, "Specify the max wait time in seconds for CLI for the uninstall to complete before returning (default \"300\")") + return uninstallCmd } diff --git a/pkg/kudoctl/cmd/uninstall_test.go b/pkg/kudoctl/cmd/uninstall_test.go index a76cc81f6..588e6f16a 100644 --- a/pkg/kudoctl/cmd/uninstall_test.go +++ b/pkg/kudoctl/cmd/uninstall_test.go @@ -45,8 +45,12 @@ func TestUninstall(t *testing.T) { t.Fatalf("failed to install instance: %v", err) } + options := uninstallOptions{ + InstanceName: "nonexisting-instance", + } + cmd := uninstallCmd{} - err = cmd.uninstall(kc, "nonexisting-instance", settings) + err = cmd.uninstall(kc, options, settings) if err == nil { t.Errorf("expected an error but got none") } @@ -56,7 +60,10 @@ func TestUninstall(t *testing.T) { t.Errorf("expected error message '%s' but got '%v'", errMsg, err) } - err = cmd.uninstall(kc, testInstance.Name, settings) + options.InstanceName = testInstance.Name + options.Wait = true + + err = cmd.uninstall(kc, options, settings) if err != nil { t.Errorf("failed to uninstall instance: %v", err) } diff --git a/pkg/kudoctl/util/kudo/kudo.go b/pkg/kudoctl/util/kudo/kudo.go index 970776eb1..1d6acd389 100644 --- a/pkg/kudoctl/util/kudo/kudo.go +++ b/pkg/kudoctl/util/kudo/kudo.go @@ -295,6 +295,26 @@ func (c *Client) WaitForInstance(name, namespace string, oldInstance *kudoapi.In }) } +// WaitForInstanceDeleted waits for instance to be removed from the cluster. +func (c *Client) WaitForInstanceDeleted(name, namespace string, timeout time.Duration) error { + interval := 1 * time.Second + + return wait.PollImmediate(interval, timeout, func() (done bool, err error) { + instance, err := c.GetInstance(name, namespace) + if err != nil { + return false, err + } + + if instance == nil { + clog.V(2).Printf("instance %q was deleted\n", name) + return true, nil + } + + clog.V(4).Printf("instance %q is still running\n", name) + return false, nil + }) +} + // IsInstanceDone provides a check on instance to see if it is "finished" without retries // oldInstance is nil if there is no previous instance func (c *Client) IsInstanceDone(instance, oldInstance *kudoapi.Instance) (bool, error) {