From f7d6cccc7dfbcdade7abba16dae8fc9a2b3ad51f Mon Sep 17 00:00:00 2001 From: ycyaoxdu Date: Tue, 15 Mar 2022 11:19:04 +0800 Subject: [PATCH] feat: add command delete clusterset Signed-off-by: ycyaoxdu --- pkg/cmd/delete/clusterset/cmd.go | 49 ++++++++++++ pkg/cmd/delete/clusterset/exec.go | 108 +++++++++++++++++++++++++++ pkg/cmd/delete/clusterset/options.go | 24 ++++++ pkg/cmd/delete/cmd.go | 2 + 4 files changed, 183 insertions(+) create mode 100644 pkg/cmd/delete/clusterset/cmd.go create mode 100644 pkg/cmd/delete/clusterset/exec.go create mode 100644 pkg/cmd/delete/clusterset/options.go diff --git a/pkg/cmd/delete/clusterset/cmd.go b/pkg/cmd/delete/clusterset/cmd.go new file mode 100644 index 000000000..e30df8083 --- /dev/null +++ b/pkg/cmd/delete/clusterset/cmd.go @@ -0,0 +1,49 @@ +// Copyright Contributors to the Open Cluster Management project +package clusterset + +import ( + "fmt" + + genericclioptionsclusteradm "open-cluster-management.io/clusteradm/pkg/genericclioptions" + clusteradmhelpers "open-cluster-management.io/clusteradm/pkg/helpers" + + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericclioptions" +) + +var example = ` +# delete a clusterset. +%[1]s delete clusterset clusterset1 +` + +// NewCmd... +func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, streams genericclioptions.IOStreams) *cobra.Command { + o := newOptions(clusteradmFlags, streams) + + cmd := &cobra.Command{ + Use: "clusterset", + Short: "delete a clusterset", + Example: fmt.Sprintf(example, clusteradmhelpers.GetExampleHeader()), + SilenceUsage: true, + PreRunE: func(c *cobra.Command, args []string) error { + clusteradmhelpers.DryRunMessage(clusteradmFlags.DryRun) + + return nil + }, + RunE: func(c *cobra.Command, args []string) error { + if err := o.complete(c, args); err != nil { + return err + } + if err := o.validate(); err != nil { + return err + } + if err := o.run(); err != nil { + return err + } + + return nil + }, + } + + return cmd +} diff --git a/pkg/cmd/delete/clusterset/exec.go b/pkg/cmd/delete/clusterset/exec.go new file mode 100644 index 000000000..5b0b18d90 --- /dev/null +++ b/pkg/cmd/delete/clusterset/exec.go @@ -0,0 +1,108 @@ +// Copyright Contributors to the Open Cluster Management project +package clusterset + +import ( + "context" + "fmt" + + "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/watch" + clusterclientset "open-cluster-management.io/api/client/cluster/clientset/versioned" + "open-cluster-management.io/clusteradm/pkg/helpers" +) + +func (o *Options) complete(cmd *cobra.Command, args []string) (err error) { + + o.Clustersets = args + + return nil +} + +func (o *Options) validate() (err error) { + if len(o.Clustersets) == 0 { + return fmt.Errorf("the name of the clusterset must be specified") + } + if len(o.Clustersets) > 1 { + return fmt.Errorf("only one clusterset can be deleted") + } + return nil +} + +func (o *Options) run() (err error) { + restConfig, err := o.ClusteradmFlags.KubectlFactory.ToRESTConfig() + if err != nil { + return err + } + clusterClient, err := clusterclientset.NewForConfig(restConfig) + if err != nil { + return err + } + + clusterSetName := o.Clustersets[0] + + return o.runWithClient(clusterClient, o.ClusteradmFlags.DryRun, clusterSetName) +} + +// check unband first + +func (o *Options) runWithClient(clusterClient clusterclientset.Interface, + dryRun bool, + clusterset string) error { + + // check existing + _, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), clusterset, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + fmt.Fprintf(o.Streams.Out, "Clusterset %s is already deleted\n", clusterset) + return nil + } + return err + } + + // check binding + list, err := clusterClient.ClusterV1beta1().ManagedClusterSetBindings(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{ + FieldSelector: fmt.Sprintf("metadata.name=%s", clusterset), + }) + // if exist, return + if err == nil && len(list.Items) != 0 { + fmt.Fprintf(o.Streams.Out, "Clusterset %s still bind to a namespace! Please unbind before deleted.\n", clusterset) + return nil + } + if err != nil && !errors.IsNotFound(err) { + return err + } + + // start a goroutine to watch the delete event + errChannel := make(chan error) + go func(c chan<- error) { + // watch until clusterset is removed + e := helpers.WatchUntil( + func() (watch.Interface, error) { + return clusterClient.ClusterV1beta1().ManagedClusterSets().Watch(context.TODO(), metav1.ListOptions{ + FieldSelector: fmt.Sprintf("metadata.name=%s", clusterset), + }) + }, + func(event watch.Event) bool { + return event.Type == watch.Deleted + }, + ) + c <- e + + }(errChannel) + + // delete + err = clusterClient.ClusterV1beta1().ManagedClusterSets().Delete(context.TODO(), clusterset, metav1.DeleteOptions{}) + if err != nil { + return err + } + + // handle the error of watch function + if err = <-errChannel; err != nil { + return err + } + + fmt.Fprintf(o.Streams.Out, "Clusterset %s is deleted\n", clusterset) + return nil +} diff --git a/pkg/cmd/delete/clusterset/options.go b/pkg/cmd/delete/clusterset/options.go new file mode 100644 index 000000000..dd63e62e9 --- /dev/null +++ b/pkg/cmd/delete/clusterset/options.go @@ -0,0 +1,24 @@ +// Copyright Contributors to the Open Cluster Management project +package clusterset + +import ( + "k8s.io/cli-runtime/pkg/genericclioptions" + genericclioptionsclusteradm "open-cluster-management.io/clusteradm/pkg/genericclioptions" +) + +type Options struct { + //ClusteradmFlags: The generic optiosn from the clusteradm cli-runtime. + ClusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags + + Streams genericclioptions.IOStreams + + Clustersets []string +} + +func newOptions(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, streams genericclioptions.IOStreams) *Options { + return &Options{ + ClusteradmFlags: clusteradmFlags, + Streams: streams, + Clustersets: []string{}, + } +} diff --git a/pkg/cmd/delete/cmd.go b/pkg/cmd/delete/cmd.go index d7166291d..6eee7da4e 100644 --- a/pkg/cmd/delete/cmd.go +++ b/pkg/cmd/delete/cmd.go @@ -4,6 +4,7 @@ package get import ( "github.com/spf13/cobra" "k8s.io/cli-runtime/pkg/genericclioptions" + "open-cluster-management.io/clusteradm/pkg/cmd/delete/clusterset" "open-cluster-management.io/clusteradm/pkg/cmd/delete/token" "open-cluster-management.io/clusteradm/pkg/cmd/delete/work" genericclioptionsclusteradm "open-cluster-management.io/clusteradm/pkg/genericclioptions" @@ -18,6 +19,7 @@ func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, stream cmd.AddCommand(token.NewCmd(clusteradmFlags, streams)) cmd.AddCommand(work.NewCmd(clusteradmFlags, streams)) + cmd.AddCommand(clusterset.NewCmd(clusteradmFlags, streams)) return cmd }