github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/cli/cmd/backuprepo/list.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package backuprepo
    21  
    22  import (
    23  	"fmt"
    24  	"sort"
    25  
    26  	"github.com/spf13/cobra"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/cli-runtime/pkg/genericiooptions"
    30  	"k8s.io/client-go/dynamic"
    31  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    32  	"k8s.io/kubectl/pkg/util/templates"
    33  
    34  	dpv1alpha1 "github.com/1aal/kubeblocks/apis/dataprotection/v1alpha1"
    35  	"github.com/1aal/kubeblocks/pkg/cli/list"
    36  	"github.com/1aal/kubeblocks/pkg/cli/printer"
    37  	"github.com/1aal/kubeblocks/pkg/cli/types"
    38  	"github.com/1aal/kubeblocks/pkg/cli/util"
    39  )
    40  
    41  var (
    42  	listExample = templates.Examples(`
    43  	# List all backup repositories
    44  	kbcli backuprepo list
    45  	`)
    46  )
    47  
    48  type listBackupRepoOptions struct {
    49  	dynamic dynamic.Interface
    50  	*list.ListOptions
    51  }
    52  
    53  func newListCommand(f cmdutil.Factory, streams genericiooptions.IOStreams) *cobra.Command {
    54  	o := &listBackupRepoOptions{
    55  		ListOptions: list.NewListOptions(f, streams, types.BackupRepoGVR()),
    56  	}
    57  	cmd := &cobra.Command{
    58  		Use:               "list",
    59  		Short:             "List Backup Repositories.",
    60  		Aliases:           []string{"ls"},
    61  		Example:           listExample,
    62  		ValidArgsFunction: util.ResourceNameCompletionFunc(f, types.BackupRepoGVR()),
    63  		Run: func(cmd *cobra.Command, args []string) {
    64  			o.Names = args
    65  			cmdutil.CheckErr(o.Complete())
    66  			cmdutil.CheckErr(printBackupRepoList(o))
    67  		},
    68  	}
    69  	o.AddFlags(cmd)
    70  	return cmd
    71  }
    72  
    73  func (o *listBackupRepoOptions) Complete() error {
    74  	var err error
    75  	o.dynamic, err = o.Factory.DynamicClient()
    76  	if err != nil {
    77  		return err
    78  	}
    79  	return nil
    80  }
    81  
    82  func printBackupRepoList(o *listBackupRepoOptions) error {
    83  	// if format is JSON or YAML, use default printer to output the result.
    84  	if o.Format == printer.JSON || o.Format == printer.YAML {
    85  		_, err := o.Run()
    86  		return err
    87  	}
    88  
    89  	// get and output the result
    90  	o.Print = false
    91  	r, err := o.Run()
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	infos, err := r.Infos()
    97  	if err != nil {
    98  		return err
    99  	}
   100  
   101  	if len(infos) == 0 {
   102  		fmt.Fprintln(o.IOStreams.Out, "No backup repository found")
   103  		return nil
   104  	}
   105  
   106  	backupRepos := make([]*dpv1alpha1.BackupRepo, 0)
   107  	for _, info := range infos {
   108  		backupRepo := &dpv1alpha1.BackupRepo{}
   109  		obj := info.Object.(*unstructured.Unstructured)
   110  		if err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, backupRepo); err != nil {
   111  			return err
   112  		}
   113  		backupRepos = append(backupRepos, backupRepo)
   114  	}
   115  
   116  	printRows := func(tbl *printer.TablePrinter) error {
   117  		// sort BackupRepos with isDefault, then phase and name
   118  		sort.SliceStable(backupRepos, func(i, j int) bool {
   119  			iBackupRepo := backupRepos[i]
   120  			jBackupRepo := backupRepos[j]
   121  			if iBackupRepo.Status.IsDefault != jBackupRepo.Status.IsDefault {
   122  				return iBackupRepo.Status.IsDefault
   123  			}
   124  			if iBackupRepo.Status.Phase == jBackupRepo.Status.Phase {
   125  				return iBackupRepo.GetName() < jBackupRepo.GetName()
   126  			}
   127  			return iBackupRepo.Status.Phase < jBackupRepo.Status.Phase
   128  		})
   129  		for _, backupRepo := range backupRepos {
   130  			backups, backupSize, err := countBackupNumsAndSize(o.dynamic, backupRepo)
   131  			if err != nil {
   132  				return err
   133  			}
   134  			tbl.AddRow(backupRepo.Name,
   135  				backupRepo.Status.Phase,
   136  				backupRepo.Spec.StorageProviderRef,
   137  				backupRepo.Spec.AccessMethod,
   138  				backupRepo.Status.IsDefault,
   139  				fmt.Sprintf("%d", backups),
   140  				backupSize,
   141  			)
   142  		}
   143  		return nil
   144  	}
   145  
   146  	if err = printer.PrintTable(o.Out, nil, printRows,
   147  		"NAME", "STATUS", "STORAGE-PROVIDER", "ACCESS-METHOD", "DEFAULT", "BACKUPS", "TOTAL-SIZE"); err != nil {
   148  		return err
   149  	}
   150  	return nil
   151  }