github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/velero/velero.go (about)

     1  package velero
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/jenkins-x/jx-logging/pkg/log"
     8  	"github.com/jenkins-x/jx/v2/pkg/util"
     9  	"github.com/pkg/errors"
    10  	apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"k8s.io/client-go/kubernetes"
    13  )
    14  
    15  type veleroSchedule struct {
    16  	Metadata veleroScheduleMetadata `json:"metadata"`
    17  }
    18  
    19  type veleroScheduleMetadata struct {
    20  	Name string `json:"name"`
    21  }
    22  
    23  type veleroScheduleList struct {
    24  	Items []veleroSchedule `json:"items"`
    25  }
    26  
    27  type veleroBackupMetadata struct {
    28  	Name string `json:"name"`
    29  }
    30  
    31  type veleroBackup struct {
    32  	Metadata veleroBackupMetadata `json:"metadata"`
    33  }
    34  
    35  type veleroBackupList struct {
    36  	Items []veleroBackup `json:"items"`
    37  }
    38  
    39  var (
    40  	veleroBackupsResource   = "backups.velero.io"
    41  	veleroSchedulesResource = "schedules.velero.io"
    42  )
    43  
    44  // RestoreFromBackup restores from a named velero backup
    45  func RestoreFromBackup(apiClient apiextensionsclientset.Interface, kubeClient kubernetes.Interface, namespace string, backupName string) error {
    46  	if backupName == "" {
    47  		return errors.Errorf("")
    48  	}
    49  	log.Logger().Infof("Using backup '%s'", backupName)
    50  
    51  	args := []string{"create", "restore", "--from-backup", backupName, "--namespace", namespace}
    52  	cmd := util.Command{
    53  		Name: "velero",
    54  		Args: args,
    55  	}
    56  
    57  	output, err := cmd.RunWithoutRetry()
    58  	if err != nil {
    59  		return errors.Wrap(err, fmt.Sprintf("executing '%s %v' command", cmd.Name, cmd.Args))
    60  	}
    61  
    62  	log.Logger().Infof(output)
    63  
    64  	return nil
    65  }
    66  
    67  // DoesVeleroBackupScheduleExist checks whether a velero schedule exists
    68  func DoesVeleroBackupScheduleExist(apiClient apiextensionsclientset.Interface, namespace string) (bool, error) {
    69  
    70  	if doesVeleroSchedulesResourceExist(apiClient) {
    71  		// kubectl get schedules.velero.io -n velero -o json
    72  		args := []string{"get", veleroSchedulesResource, "-n", namespace, "-o", "json"}
    73  		cmd := util.Command{
    74  			Name: "kubectl",
    75  			Args: args,
    76  		}
    77  
    78  		output, err := cmd.RunWithoutRetry()
    79  		if err != nil {
    80  			return false, errors.Wrap(err, fmt.Sprintf("executing kubectl get %s command", veleroSchedulesResource))
    81  		}
    82  
    83  		var veleroShedules veleroScheduleList
    84  		err = json.Unmarshal([]byte(output), &veleroShedules)
    85  		if err != nil {
    86  			return false, errors.Wrap(err, "unmarshalling kubectl response")
    87  		}
    88  
    89  		if len(veleroShedules.Items) > 0 {
    90  			return true, nil
    91  		}
    92  		return false, nil
    93  	}
    94  	return false, nil
    95  }
    96  
    97  func doesVeleroBackupsResourceExist(apiClient apiextensionsclientset.Interface) bool {
    98  	listOptions := metav1.ListOptions{
    99  		FieldSelector: fmt.Sprintf("metadata.name=%s", veleroBackupsResource),
   100  	}
   101  	backupList, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(listOptions)
   102  	if err != nil {
   103  		return false
   104  	}
   105  
   106  	if len(backupList.Items) > 0 {
   107  		return true
   108  	}
   109  	return false
   110  }
   111  
   112  func doesVeleroSchedulesResourceExist(apiClient apiextensionsclientset.Interface) bool {
   113  	listOptions := metav1.ListOptions{
   114  		FieldSelector: fmt.Sprintf("metadata.name=%s", veleroSchedulesResource),
   115  	}
   116  	schedulesList, err := apiClient.ApiextensionsV1beta1().CustomResourceDefinitions().List(listOptions)
   117  	if err != nil {
   118  		return false
   119  	}
   120  
   121  	if len(schedulesList.Items) > 0 {
   122  		return true
   123  	}
   124  	return false
   125  }
   126  
   127  // GetBackupsFromBackupResource returns a list of all velero backups
   128  func GetBackupsFromBackupResource(apiClient apiextensionsclientset.Interface, namespace string) ([]string, error) {
   129  
   130  	if doesVeleroBackupsResourceExist(apiClient) {
   131  		// kubectl get backups.velero.io -n velero -o json
   132  		args := []string{"get", veleroBackupsResource, "-n", namespace, "-o", "json"}
   133  		cmd := util.Command{
   134  			Name: "kubectl",
   135  			Args: args,
   136  		}
   137  
   138  		output, err := cmd.RunWithoutRetry()
   139  		if err != nil {
   140  			return []string{}, errors.Wrap(err, fmt.Sprintf("executing '%s %v' command", cmd.Name, cmd.Args))
   141  		}
   142  
   143  		var veleroBackups veleroBackupList
   144  		err = json.Unmarshal([]byte(output), &veleroBackups)
   145  		if err != nil {
   146  			return []string{}, errors.Wrap(err, "unmarshalling kubectl response for backups")
   147  		}
   148  
   149  		if len(veleroBackups.Items) > 0 {
   150  			backups := make([]string, len(veleroBackups.Items))
   151  			// there must be a nicer way to do this
   152  			for index, veleroBackup := range veleroBackups.Items {
   153  				backups[index] = veleroBackup.Metadata.Name
   154  			}
   155  			return backups, nil
   156  		}
   157  		return []string{}, nil
   158  	}
   159  	return []string{}, nil
   160  }
   161  
   162  // GetLatestBackupFromBackupResource returns the latest velero backup name
   163  func GetLatestBackupFromBackupResource(apiClient apiextensionsclientset.Interface, namespace string) (string, error) {
   164  
   165  	if doesVeleroBackupsResourceExist(apiClient) {
   166  
   167  		backups, err := GetBackupsFromBackupResource(apiClient, namespace)
   168  		if err != nil {
   169  			return "", errors.Wrap(err, "when attempting to retrieve velero backup list")
   170  		}
   171  
   172  		return backups[len(backups)-1], nil
   173  	}
   174  	return "", nil
   175  }