diff --git a/pkg/karmadactl/cmdinit/cmdinit.go b/pkg/karmadactl/cmdinit/cmdinit.go index 847bdc60f..5d55d170d 100644 --- a/pkg/karmadactl/cmdinit/cmdinit.go +++ b/pkg/karmadactl/cmdinit/cmdinit.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/cobra" "k8s.io/klog/v2" + "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/kubernetes" "github.com/karmada-io/karmada/pkg/version" @@ -16,6 +17,43 @@ const ( initLong = `Install karmada in kubernetes.` ) +var ( + initExamples = templates.Examples(` + # Install Karmada in Kubernetes cluster + # The karmada-apiserver binds the master node's IP by default + %[1]s init + + # China mainland registry mirror can be specified by using kube-image-mirror-country + %[1]s init --kube-image-mirror-country=cn + + # Kube registry can be specified by using kube-image-registry + %[1]s init --kube-image-registry=registry.cn-hangzhou.aliyuncs.com/google_containers + + # Specify the URL to download CRD tarball + %[1]s init --crds https://github.com/karmada-io/karmada/releases/download/%[2]s/crds.tar.gz + + # Specify the local CRD tarball + %[1]s init --crds /root/crds.tar.gz + + # Use PVC to persistent storage etcd data + %[1]s init --etcd-storage-mode PVC --storage-classes-name {StorageClassesName} + + # Use hostPath to persistent storage etcd data. For data security, only 1 etcd pod can run in hostPath mode + %[1]s init --etcd-storage-mode hostPath --etcd-replicas 1 + + # Use hostPath to persistent storage etcd data but select nodes by labels + %[1]s init --etcd-storage-mode hostPath --etcd-node-selector-labels karmada.io/etcd=true + + # Private registry can be specified for all images + %[1]s init --etcd-image local.registry.com/library/etcd:3.5.3-0 + + # Deploy highly available(HA) karmada + %[1]s init --karmada-apiserver-replicas 3 --etcd-replicas 3 --etcd-storage-mode PVC --storage-classes-name {StorageClassesName} + + # Specify external IPs(load balancer or HA IP) which used to sign the certificate + %[1]s init --cert-external-ip 10.235.1.2 --cert-external-dns www.karmada.io`) +) + // NewCmdInit install karmada on kubernetes func NewCmdInit(parentCommand string) *cobra.Command { opts := kubernetes.CommandInitOption{} @@ -92,39 +130,5 @@ func initExample(parentCommand string) string { klog.Infof("No default release version found. build version: %s", version.Get().String()) releaseVer = &version.ReleaseVersion{} } - example := ` -# Install Karmada in Kubernetes cluster -# The karmada-apiserver binds the master node's IP by default` + "\n" + - fmt.Sprintf("%s init", parentCommand) + ` - -# China mainland registry mirror can be specified by using kube-image-mirror-country` + "\n" + - fmt.Sprintf("%s init --kube-image-mirror-country=cn", parentCommand) + ` - -# Kube registry can be specified by using kube-image-registry` + "\n" + - fmt.Sprintf("%s init --kube-image-registry=registry.cn-hangzhou.aliyuncs.com/google_containers", parentCommand) + ` - -# Specify the URL to download CRD tarball` + "\n" + - fmt.Sprintf("%s init --crds https://github.com/karmada-io/karmada/releases/download/%s/crds.tar.gz", parentCommand, releaseVer.FirstMinorRelease()) + ` - -# Specify the local CRD tarball` + "\n" + - fmt.Sprintf("%s init --crds /root/crds.tar.gz", parentCommand) + ` - -# Use PVC to persistent storage etcd data` + "\n" + - fmt.Sprintf("%s init --etcd-storage-mode PVC --storage-classes-name {StorageClassesName}", parentCommand) + ` - -# Use hostPath to persistent storage etcd data. For data security, only 1 etcd pod can run in hostPath mode` + "\n" + - fmt.Sprintf("%s init --etcd-storage-mode hostPath --etcd-replicas 1", parentCommand) + ` - -# Use hostPath to persistent storage etcd data but select nodes by labels` + "\n" + - fmt.Sprintf("%s init --etcd-storage-mode hostPath --etcd-node-selector-labels karmada.io/etcd=true", parentCommand) + ` - -# Private registry can be specified for all images` + "\n" + - fmt.Sprintf("%s init --etcd-image local.registry.com/library/etcd:3.5.3-0", parentCommand) + ` - -# Deploy highly available(HA) karmada` + "\n" + - fmt.Sprintf("%s init --karmada-apiserver-replicas 3 --etcd-replicas 3 --etcd-storage-mode PVC --storage-classes-name {StorageClassesName}", parentCommand) + ` - -# Specify external IPs(load balancer or HA IP) which used to sign the certificate` + "\n" + - fmt.Sprintf("%s init --cert-external-ip 10.235.1.2 --cert-external-dns www.karmada.io", parentCommand) - return example + return fmt.Sprintf(initExamples, parentCommand, releaseVer.FirstMinorRelease()) } diff --git a/pkg/karmadactl/cordon.go b/pkg/karmadactl/cordon.go index de9fd4894..e170007da 100644 --- a/pkg/karmadactl/cordon.go +++ b/pkg/karmadactl/cordon.go @@ -11,6 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/strategicpatch" + "k8s.io/kubectl/pkg/util/templates" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" @@ -23,6 +24,13 @@ var ( uncordonShort = `Mark cluster as schedulable` uncordonLong = `Mark cluster as schedulable.` + + cordonExample = templates.Examples(` + # Mark cluster "foo" as unschedulable. + %[1]s cordon foo`) + uncordonExample = templates.Examples(` + # Mark cluster "foo" as schedulable. + %[1]s uncordon foo`) ) const ( @@ -40,7 +48,7 @@ func NewCmdCordon(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comm Use: "cordon CLUSTER", Short: cordonShort, Long: cordonLong, - Example: cordonExample(parentCommand), + Example: fmt.Sprintf(cordonExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -61,13 +69,6 @@ func NewCmdCordon(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comm return cmd } -func cordonExample(parentCommand string) string { - example := ` -# Mark cluster "foo" as unschedulable` + "\n" + - fmt.Sprintf("%s cordon foo", parentCommand) - return example -} - // NewCmdUncordon defines the `uncordon` command that mark cluster as schedulable. func NewCmdUncordon(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command { opts := CommandCordonOption{} @@ -75,7 +76,7 @@ func NewCmdUncordon(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Co Use: "uncordon CLUSTER", Short: uncordonShort, Long: uncordonLong, - Example: uncordonExample(parentCommand), + Example: fmt.Sprintf(uncordonExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -94,13 +95,6 @@ func NewCmdUncordon(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Co return cmd } -func uncordonExample(parentCommand string) string { - example := ` -# Mark cluster "foo" as schedulable.` + "\n" + - fmt.Sprintf("%s uncordon foo", parentCommand) - return example -} - // CommandCordonOption holds all command options for cordon and uncordon type CommandCordonOption struct { // global flags diff --git a/pkg/karmadactl/deinit.go b/pkg/karmadactl/deinit.go index 36e6da9b8..9fc1898a5 100644 --- a/pkg/karmadactl/deinit.go +++ b/pkg/karmadactl/deinit.go @@ -10,6 +10,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" + "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" ) @@ -19,6 +20,12 @@ const ( karmadaNodeLabel = "karmada.io/etcd" ) +var ( + deInitExample = templates.Examples(` + # Remove Karmada from the Kubernetes cluster. + %[1]s deinit`) +) + // CommandDeInitOption options for deinit. type CommandDeInitOption struct { // KubeConfig holds host cluster KUBECONFIG file path. @@ -40,7 +47,7 @@ func NewCmdDeInit(parentCommand string) *cobra.Command { Use: "deinit", Short: "Removes Karmada from Kubernetes", Long: "Removes Karmada from Kubernetes", - Example: deInitExample(parentCommand), + Example: fmt.Sprintf(deInitExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(); err != nil { @@ -62,13 +69,6 @@ func NewCmdDeInit(parentCommand string) *cobra.Command { return cmd } -func deInitExample(parentCommand string) string { - example := ` -# Remove Karmada from the Kubernetes cluster` + "\n" + - fmt.Sprintf("%s deinit", parentCommand) - return example -} - // Complete the conditions required to be able to run deinit. func (o *CommandDeInitOption) Complete() error { if o.KubeConfig == "" { diff --git a/pkg/karmadactl/describe.go b/pkg/karmadactl/describe.go index 0547ce01b..9066ade77 100644 --- a/pkg/karmadactl/describe.go +++ b/pkg/karmadactl/describe.go @@ -13,10 +13,30 @@ import ( "k8s.io/cli-runtime/pkg/resource" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/describe" + "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/karmadactl/options" ) +var ( + describeExample = templates.Examples(` + # Describe a pod in cluster(member1) + %[1]s describe pods/nginx -C=member1 + + # Describe all pods in cluster(member1) + %[1]s describe pods -C=member1 + + # Describe a pod identified by type and name in "pod.json" in cluster(member1) + %[1]s describe -f pod.json -C=member1 + + # Describe pods by label name=myLabel in cluster(member1) + %[1]s describe po -l name=myLabel -C=member1 + + # Describe all pods managed by the 'frontend' replication controller in cluster(member1) + # (rc-created pods get the name of the rc as a prefix in the pod name) + %[1]s describe pods frontend -C=member1`) +) + // NewCmdDescribe new describe command. func NewCmdDescribe(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command { ioStreams := genericclioptions.IOStreams{In: getIn, Out: getOut, ErrOut: getErr} @@ -36,7 +56,7 @@ func NewCmdDescribe(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Co Use: "describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME) (-C CLUSTER)", Short: "Show details of a specific resource or group of resources in a cluster", SilenceUsage: true, - Example: describeExample(parentCommand), + Example: fmt.Sprintf(describeExample, parentCommand), RunE: func(cmd *cobra.Command, args []string) error { if err := o.Complete(karmadaConfig, args); err != nil { return err @@ -86,26 +106,6 @@ type CommandDescribeOptions struct { genericclioptions.IOStreams } -func describeExample(parentCommand string) string { - example := ` -# Describe a pod in cluster(member1)` + "\n" + - fmt.Sprintf("%s describe pods/nginx -C=member1", parentCommand) + ` - -# Describe all pods in cluster(member1)` + "\n" + - fmt.Sprintf("%s describe pods -C=member1", parentCommand) + ` - -# # Describe a pod identified by type and name in "pod.json" in cluster(member1)` + "\n" + - fmt.Sprintf("%s describe -f pod.json -C=member1", parentCommand) + ` - -# Describe pods by label name=myLabel in cluster(member1)` + "\n" + - fmt.Sprintf("%s describe po -l name=myLabel -C=member1", parentCommand) + ` - -# Describe all pods managed by the 'frontend' replication controller in cluster(member1) -# (rc-created pods get the name of the rc as a prefix in the pod name)` + "\n" + - fmt.Sprintf("%s describe pods frontend -C=member1", parentCommand) - return example -} - // Complete ensures that options are valid and marshals them if necessary func (o *CommandDescribeOptions) Complete(karmadaConfig KarmadaConfig, args []string) error { var err error diff --git a/pkg/karmadactl/exec.go b/pkg/karmadactl/exec.go index 78548fdc1..0e830cbff 100644 --- a/pkg/karmadactl/exec.go +++ b/pkg/karmadactl/exec.go @@ -8,6 +8,7 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" kubectlexec "k8s.io/kubectl/pkg/cmd/exec" cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/karmadactl/options" ) @@ -16,6 +17,28 @@ const ( defaultPodExecTimeout = 60 * time.Second ) +var ( + execExample = templates.Examples(` + # Get output from running the 'date' command from pod mypod, using the first container by default in cluster(member1) + %[1]s exec mypod -C=member1 -- date + + # Get output from running the 'date' command in ruby-container from pod mypod in cluster(member1) + %[1]s exec mypod -c ruby-container -C=member1 -- date + + # Get output from running the 'date' command in ruby-container from pod mypod in cluster(member1) + %[1]sexec mypod -c ruby-container -C=member1 -- date + + # Switch to raw terminal mode; sends stdin to 'bash' in ruby-container from pod mypod in cluster(member1) + # and sends stdout/stderr from 'bash' back to the client + %[1]s exec mypod -c ruby-container -C=member1 -i -t -- bash -il + + # Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default in cluster(member1) + %[1]s exec deploy/mydeployment -C=member1 -- date + + # Get output from running 'date' command from the first pod of the service myservice, using the first container by default in cluster(member1) + %[1]s exec svc/myservice -C=member1 -- date`) +) + // NewCmdExec new exec command. func NewCmdExec(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command { streams := genericclioptions.IOStreams{In: getIn, Out: getOut, ErrOut: getErr} @@ -32,7 +55,7 @@ func NewCmdExec(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman Use: "exec (POD | TYPE/NAME) [-c CONTAINER] [flags] (-C CLUSTER) -- COMMAND [args...]", Short: "Execute a command in a container in a cluster", Long: "Execute a command in a container in a cluster", - Example: execExample(parentCommand), + Example: fmt.Sprintf(execExample, parentCommand), RunE: func(cmd *cobra.Command, args []string) error { argsLenAtDash := cmd.ArgsLenAtDash() if err := o.Complete(karmadaConfig, cmd, args, argsLenAtDash); err != nil { @@ -62,29 +85,6 @@ func NewCmdExec(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman return cmd } -func execExample(parentCommand string) string { - example := ` -# Get output from running the 'date' command from pod mypod, using the first container by default in cluster(member1)` + "\n" + - fmt.Sprintf("%s exec mypod -C=member1 -- date", parentCommand) + ` - -# Get output from running the 'date' command from pod mypod in namespace(foo), using the first container by default in cluster(member1)` + "\n" + - fmt.Sprintf("%s exec mypod -C=member1 --namespace foo -- date", parentCommand) + ` - -# Get output from running the 'date' command in ruby-container from pod mypod in cluster(member1)` + "\n" + - fmt.Sprintf("%s exec mypod -c ruby-container -C=member1 -- date", parentCommand) + ` - -# Switch to raw terminal mode; sends stdin to 'bash' in ruby-container from pod mypod in cluster(member1) -# and sends stdout/stderr from 'bash' back to the client` + "\n" + - fmt.Sprintf("%s exec mypod -c ruby-container -C=member1 -i -t -- bash -il", parentCommand) + ` - -# Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default in cluster(member1)` + "\n" + - fmt.Sprintf("%s exec deploy/mydeployment -C=member1 -- date", parentCommand) + ` - -# Get output from running 'date' command from the first pod of the service myservice, using the first container by default in cluster(member1)` + "\n" + - fmt.Sprintf("%s exec svc/myservice -C=member1 -- date", parentCommand) - return example -} - // ExecOptions declare the arguments accepted by the Exec command type ExecOptions struct { // global flags diff --git a/pkg/karmadactl/get.go b/pkg/karmadactl/get.go index 4c151ce76..54bfb476b 100644 --- a/pkg/karmadactl/get.go +++ b/pkg/karmadactl/get.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubectl/pkg/cmd/get" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/interrupt" + "k8s.io/kubectl/pkg/util/templates" utilpointer "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" @@ -59,6 +60,31 @@ var ( eventColumn = metav1.TableColumnDefinition{Name: "EVENT", Type: "string", Format: "", Priority: 0} getShort = `Display one or many resources` + + getExample = templates.Examples(` + # List all pods in ps output format + %[1]s get pods + + # List all pods in ps output format with more information (such as node name) + %[1]s get pods -o wide + + # List all pods of member1 cluster in ps output format + %[1]s get pods -C member1 + + # List a single replicasets controller with specified NAME in ps output format + %[1]s get replicasets nginx + + # List deployments in JSON output format, in the "v1" version of the "apps" API group + %[1]s get deployments.v1.apps -o json + + # Return only the phase value of the specified resource + %[1]s get -o template deployment/nginx -C member1 --template={{.spec.replicas}} + + # List all replication controllers and services together in ps output format + %[1]s get rs,services + + # List one or more resources by their type and names + %[1]s get rs/nginx-cb87b6d88 service/kubernetes`) ) // NewCmdGet New get command @@ -69,7 +95,7 @@ func NewCmdGet(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Command Use: "get [NAME | -l label | -n namespace] [flags]", Short: getShort, SilenceUsage: true, - Example: getExample(parentCommand), + Example: fmt.Sprintf(getExample, parentCommand), RunE: func(cmd *cobra.Command, args []string) error { if err := o.Complete(karmadaConfig); err != nil { return err @@ -1038,34 +1064,6 @@ func Exists(path string) bool { return true } -func getExample(parentCommand string) string { - example := ` -# List all pods in ps output format` + "\n" + - fmt.Sprintf("%s get pods", parentCommand) + ` - -# List all pods in ps output format with more information (such as node name)` + "\n" + - fmt.Sprintf("%s get pods -o wide", parentCommand) + ` - -# List all pods of member1 cluster in ps output format` + "\n" + - fmt.Sprintf("%s get pods -C member1", parentCommand) + ` - -# List a single replicasets controller with specified NAME in ps output format ` + "\n" + - fmt.Sprintf("%s get replicasets nginx", parentCommand) + ` - -# List deployments in JSON output format, in the "v1" version of the "apps" API group ` + "\n" + - fmt.Sprintf("%s get deployments.v1.apps -o json", parentCommand) + ` - -# Return only the phase value of the specified resource ` + "\n" + - fmt.Sprintf("%s get -o template deployment/nginx -C member1 --template={{.spec.replicas}}", parentCommand) + ` - -# List all replication controllers and services together in ps output format ` + "\n" + - fmt.Sprintf("%s get rs,services", parentCommand) + ` - -# List one or more resources by their type and names ` + "\n" + - fmt.Sprintf("%s get rs/nginx-cb87b6d88 service/kubernetes", parentCommand) - return example -} - // skipPrinter allows conditionally suppressing object output via the output field. // table objects are suppressed by setting their Rows to nil (allowing column definitions to propagate to the delegate). // non-table objects are suppressed by not calling the delegate at all. diff --git a/pkg/karmadactl/join.go b/pkg/karmadactl/join.go index 1374bb60e..58b400461 100644 --- a/pkg/karmadactl/join.go +++ b/pkg/karmadactl/join.go @@ -10,6 +10,7 @@ import ( kubeclient "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/klog/v2" + "k8s.io/kubectl/pkg/util/templates" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" "github.com/karmada-io/karmada/pkg/apis/cluster/validation" @@ -21,6 +22,10 @@ import ( var ( joinShort = `Register a cluster to control plane` joinLong = `Join registers a cluster to control plane.` + + joinExample = templates.Examples(` + # Join cluster into karamada control plane, if '--cluster-context' not specified, take the cluster name as the context + %[1]s join CLUSTER_NAME --cluster-kubeconfig=`) ) // NewCmdJoin defines the `join` command that registers a cluster. @@ -31,7 +36,7 @@ func NewCmdJoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman Use: "join CLUSTER_NAME --cluster-kubeconfig=", Short: joinShort, Long: joinLong, - Example: joinExample(parentCommand), + Example: fmt.Sprintf(joinExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -53,13 +58,6 @@ func NewCmdJoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman return cmd } -func joinExample(parentCommand string) string { - example := ` -# Join cluster into karamada control plane, if '--cluster-context' not specified, take the cluster name as the context` + "\n" + - fmt.Sprintf("%s join CLUSTER_NAME --cluster-kubeconfig=", parentCommand) - return example -} - // CommandJoinOption holds all command options. type CommandJoinOption struct { options.GlobalCommandOptions diff --git a/pkg/karmadactl/logs.go b/pkg/karmadactl/logs.go index c7e9d97f1..fc5ed9d7e 100644 --- a/pkg/karmadactl/logs.go +++ b/pkg/karmadactl/logs.go @@ -11,6 +11,7 @@ import ( "k8s.io/client-go/rest" kubectllogs "k8s.io/kubectl/pkg/cmd/logs" cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" "github.com/karmada-io/karmada/pkg/karmadactl/options" @@ -22,6 +23,30 @@ const ( var ( logsUsageErrStr = fmt.Sprintf("expected '%s'.\nPOD or TYPE/NAME is a required argument for the logs command", logsUsageStr) + logsExample = templates.Examples(` + # Return snapshot logs from pod nginx with only one container in cluster(member1) + %[1]s logs nginx -C=member1 + + # Return snapshot logs from pod nginx with multi containers in cluster(member1) + %[1]s logs nginx --all-containers=true -C=member1 + + # Return snapshot logs from all containers in pods defined by label app=nginx in cluster(member1) + %[1]s logs -l app=nginx --all-containers=true -C=member1 + + # Return snapshot of previous terminated ruby container logs from pod web-1 in cluster(member1) + %[1]s logs -p -c ruby web-1 -C=member1 + + # Begin streaming the logs of the ruby container in pod web-1 in cluster(member1) + %[1]s logs -f -c ruby web-1 -C=member1 + + # Begin streaming the logs from all containers in pods defined by label app=nginx in cluster(member1) + %[1]s logs -f -l app=nginx --all-containers=true -C=member1 + + # Display only the most recent 20 lines of output in pod nginx in cluster(member1) + %[1]s logs --tail=20 nginx -C=member1 + + # Show all logs from pod nginx written in the last hour in cluster(member1) + %[1]s logs --since=1h nginx -C=member1`) ) // NewCmdLogs new logs command. @@ -35,7 +60,7 @@ func NewCmdLogs(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman Use: logsUsageStr, Short: "Print the logs for a container in a pod in a cluster", SilenceUsage: true, - Example: logsExample(parentCommand), + Example: fmt.Sprintf(logsExample, parentCommand), RunE: func(cmd *cobra.Command, args []string) error { if err := o.Complete(karmadaConfig, cmd, args); err != nil { return err @@ -57,34 +82,6 @@ func NewCmdLogs(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comman return cmd } -func logsExample(parentCommand string) string { - example := ` -# Return snapshot logs from pod nginx with only one container in cluster(member1)` + "\n" + - fmt.Sprintf("%s logs nginx -C=member1", parentCommand) + ` - -# Return snapshot logs from pod nginx with multi containers in cluster(member1)` + "\n" + - fmt.Sprintf("%s logs nginx --all-containers=true -C=member1", parentCommand) + ` - -# Return snapshot logs from all containers in pods defined by label app=nginx in cluster(member1)` + "\n" + - fmt.Sprintf("%s logs -l app=nginx --all-containers=true -C=member1", parentCommand) + ` - -# Return snapshot of previous terminated ruby container logs from pod web-1 in cluster(member1)` + "\n" + - fmt.Sprintf("%s logs -p -c ruby web-1 -C=member1", parentCommand) + ` - -# Begin streaming the logs of the ruby container in pod web-1 in cluster(member1)` + "\n" + - fmt.Sprintf("%s logs -f -c ruby web-1 -C=member1", parentCommand) + ` - -# Begin streaming the logs from all containers in pods defined by label app=nginx in cluster(member1) ` + "\n" + - fmt.Sprintf("%s logs -f -l app=nginx --all-containers=true -C=member1", parentCommand) + ` - -# Display only the most recent 20 lines of output in pod nginx in cluster(member1) ` + "\n" + - fmt.Sprintf("%s logs --tail=20 nginx -C=member1", parentCommand) + ` - -# Show all logs from pod nginx written in the last hour in cluster(member1) ` + "\n" + - fmt.Sprintf("%s logs --since=1h nginx -C=member1", parentCommand) - return example -} - // LogsOptions contains the input to the logs command. type LogsOptions struct { // global flags diff --git a/pkg/karmadactl/promote.go b/pkg/karmadactl/promote.go index 6a8a3e235..de2213140 100644 --- a/pkg/karmadactl/promote.go +++ b/pkg/karmadactl/promote.go @@ -18,6 +18,7 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/rest" cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1" workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2" @@ -30,8 +31,26 @@ import ( ) var ( - promoteShort = `Promote resources from legacy clusters to karmada control plane` - promoteLong = `Promote resources from legacy clusters to karmada control plane. Requires the cluster be joined or registered.` + promoteShort = `Promote resources from legacy clusters to karmada control plane` + promoteLong = `Promote resources from legacy clusters to karmada control plane. Requires the cluster be joined or registered.` + promoteExample = templates.Examples(` + # Promote deployment(default/nginx) from cluster1 to Karmada + %[1]s promote deployment nginx -n default -C cluster1 + + # Promote deployment(default/nginx) with gvk from cluster1 to Karmada + %[1]s promote deployment.v1.apps nginx -n default -C cluster1 + + # Dumps the artifacts but does not deploy them to Karmada, same as 'dry run' + %[1]s promote deployment nginx -n default -C cluster1 -o yaml|json + + # Promote secret(default/default-token) from cluster1 to Karmada + %[1]s promote secret default-token -n default -C cluster1 + + # Support to use '--cluster-kubeconfig' to specify the configuration of member cluster + %[1]s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig= + + # Support to use '--cluster-kubeconfig' and '--cluster-context' to specify the configuration of member cluster + %[1]s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig= --cluster-context=`) ) // NewCmdPromote defines the `promote` command that promote resources from legacy clusters @@ -43,7 +62,7 @@ func NewCmdPromote(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Com Use: "promote -n -C ", Short: promoteShort, Long: promoteLong, - Example: promoteExample(parentCommand), + Example: fmt.Sprintf(promoteExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -65,28 +84,6 @@ func NewCmdPromote(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Com return cmd } -func promoteExample(parentCommand string) string { - example := ` -# Promote deployment(default/nginx) from cluster1 to Karmada` + "\n" + - fmt.Sprintf("%s promote deployment nginx -n default -C cluster1", parentCommand) + ` - -# Promote deployment(default/nginx) with gvk from cluster1 to Karmada` + "\n" + - fmt.Sprintf("%s promote deployment.v1.apps nginx -n default -C cluster1", parentCommand) + ` - -# Dumps the artifacts but does not deploy them to Karmada, same as 'dry run'` + "\n" + - fmt.Sprintf("%s promote deployment nginx -n default -C cluster1 -o yaml|json", parentCommand) + ` - -# Promote secret(default/default-token) from cluster1 to Karmada` + "\n" + - fmt.Sprintf("%s promote secret default-token -n default -C cluster1", parentCommand) + ` - -# Support to use '--cluster-kubeconfig' to specify the configuration of member cluster` + "\n" + - fmt.Sprintf("%s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig=", parentCommand) + ` - -# Support to use '--cluster-kubeconfig' and '--cluster-context' to specify the configuration of member cluster` + "\n" + - fmt.Sprintf("%s promote deployment nginx -n default -C cluster1 --cluster-kubeconfig= --cluster-context=", parentCommand) - return example -} - // CommandPromoteOption holds all command options for promote type CommandPromoteOption struct { options.GlobalCommandOptions diff --git a/pkg/karmadactl/taint.go b/pkg/karmadactl/taint.go index 1d59107da..72dfc7134 100644 --- a/pkg/karmadactl/taint.go +++ b/pkg/karmadactl/taint.go @@ -17,6 +17,7 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/resource" cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" @@ -33,8 +34,21 @@ const ( ) var ( - taintShort = `Update the taints on one or more clusters` - taintLong = `Update the taints on one or more clusters.` + taintShort = `Update the taints on one or more clusters` + taintLong = `Update the taints on one or more clusters.` + taintExample = templates.Examples(` + # Update cluster 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule' + # If a taint with that key and effect already exists, its value is replaced as specified + %[1]s taint clusters foo dedicated=special-user:NoSchedule + + # Remove from cluster 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists + %[1]s taint clusters foo dedicated:NoSchedule- + + # Remove from cluster 'foo' all the taints with key 'dedicated' + %[1]s taint clusters foo dedicated- + + # Add to cluster 'foo' a taint with key 'bar' and no value + %[1]s taint clusters foo bar:NoSchedule`) ) // NewCmdTaint defines the `taint` command that mark cluster with taints @@ -45,7 +59,7 @@ func NewCmdTaint(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comma Use: "taint CLUSTER NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N", Short: taintShort, Long: taintLong, - Example: taintExample(parentCommand), + Example: fmt.Sprintf(taintExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -67,23 +81,6 @@ func NewCmdTaint(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comma return cmd } -func taintExample(parentCommand string) string { - example := ` -# Update cluster 'foo' with a taint with key 'dedicated' and value 'special-user' and effect 'NoSchedule' -# If a taint with that key and effect already exists, its value is replaced as specified` + "\n" + - fmt.Sprintf("%s taint clusters foo dedicated=special-user:NoSchedule", parentCommand) + ` - -# Remove from cluster 'foo' the taint with key 'dedicated' and effect 'NoSchedule' if one exists` + "\n" + - fmt.Sprintf("%s taint clusters foo dedicated:NoSchedule-", parentCommand) + ` - -# Remove from cluster 'foo' all the taints with key 'dedicated'` + "\n" + - fmt.Sprintf("%s taint clusters foo dedicated-", parentCommand) + ` - -# Add to cluster 'foo' a taint with key 'bar' and no value` + "\n" + - fmt.Sprintf("%s taint clusters foo bar:NoSchedule", parentCommand) - return example -} - // CommandTaintOption holds all command options for taint type CommandTaintOption struct { options.GlobalCommandOptions diff --git a/pkg/karmadactl/unjoin.go b/pkg/karmadactl/unjoin.go index accee7548..c92872383 100644 --- a/pkg/karmadactl/unjoin.go +++ b/pkg/karmadactl/unjoin.go @@ -14,6 +14,7 @@ import ( kubeclient "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/klog/v2" + "k8s.io/kubectl/pkg/util/templates" karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" "github.com/karmada-io/karmada/pkg/karmadactl/options" @@ -22,8 +23,17 @@ import ( ) var ( - unjoinShort = `Remove the registration of a cluster from control plane` - unjoinLong = `Unjoin removes the registration of a cluster from control plane.` + unjoinShort = `Remove the registration of a cluster from control plane` + unjoinLong = `Unjoin removes the registration of a cluster from control plane.` + unjoinExample = templates.Examples(` + # Unjoin cluster from karamada control plane, but not to remove resources created by karmada in the unjoining cluster + %[1]s unjoin CLUSTER_NAME + + # Unjoin cluster from karamada control plane and attempt to remove resources created by karmada in the unjoining cluster + %[1]s unjoin CLUSTER_NAME --cluster-kubeconfig= + + # Unjoin cluster from karamada control plane with timeout + %[1]s unjoin CLUSTER_NAME --cluster-kubeconfig= --wait 2m`) ) // NewCmdUnjoin defines the `unjoin` command that removes registration of a cluster from control plane. @@ -34,7 +44,7 @@ func NewCmdUnjoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comm Use: "unjoin CLUSTER_NAME --cluster-kubeconfig=", Short: unjoinShort, Long: unjoinLong, - Example: unjoinExample(parentCommand), + Example: fmt.Sprintf(unjoinExample, parentCommand), SilenceUsage: true, RunE: func(cmd *cobra.Command, args []string) error { if err := opts.Complete(args); err != nil { @@ -56,19 +66,6 @@ func NewCmdUnjoin(karmadaConfig KarmadaConfig, parentCommand string) *cobra.Comm return cmd } -func unjoinExample(parentCommand string) string { - example := ` -# Unjoin cluster from karamada control plane, but not to remove resources created by karmada in the unjoining cluster` + "\n" + - fmt.Sprintf("%s unjoin CLUSTER_NAME", parentCommand) + ` - -# Unjoin cluster from karamada control plane and attempt to remove resources created by karmada in the unjoining cluster` + "\n" + - fmt.Sprintf("%s unjoin CLUSTER_NAME --cluster-kubeconfig=", parentCommand) + ` - -# Unjoin cluster from karamada control plane with timeout` + "\n" + - fmt.Sprintf("%s unjoin CLUSTER_NAME --cluster-kubeconfig= --wait 2m", parentCommand) - return example -} - // CommandUnjoinOption holds all command options. type CommandUnjoinOption struct { options.GlobalCommandOptions diff --git a/pkg/version/sharedcommand/sharedcommand.go b/pkg/version/sharedcommand/sharedcommand.go index 7b58c4bcc..dd2e66bf7 100644 --- a/pkg/version/sharedcommand/sharedcommand.go +++ b/pkg/version/sharedcommand/sharedcommand.go @@ -5,6 +5,7 @@ import ( "os" "github.com/spf13/cobra" + "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/version" ) @@ -12,8 +13,9 @@ import ( var ( versionShort = `Print the version information` versionLong = `Print the version information.` - versionExample = ` # Print %s command version - %s version` + versionExample = templates.Examples(` + # Print %[1]s command version + %[1]s version`) ) // NewCmdVersion prints out the release version info for this command binary. @@ -23,7 +25,7 @@ func NewCmdVersion(parentCommand string) *cobra.Command { Use: "version", Short: versionShort, Long: versionLong, - Example: fmt.Sprintf(versionExample, parentCommand, parentCommand), + Example: fmt.Sprintf(versionExample, parentCommand), Run: func(cmd *cobra.Command, args []string) { fmt.Fprintf(os.Stdout, "%s version: %s\n", parentCommand, version.Get()) },