<commit_before>/*
 Copyright 2017 Crunchy Data Solutions, Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

// Package cmd provides the command line functions of the crunchy CLI
package cmd

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/crunchydata/postgres-operator/tpr"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"k8s.io/apimachinery/pkg/api/errors"
	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"time"
)

var backupCmd = &cobra.Command{
	Use:   "backup",
	Short: "perform a Backup",
	Long: `BACKUP performs a Backup, for example:
			pgo backup mycluster`,
	Run: func(cmd *cobra.Command, args []string) {
		log.Debug("backup called")
		if len(args) == 0 {
			fmt.Println(`You must specify the cluster to backup.`)
		} else {
			createBackup(args)
		}

	},
}

func init() {
	RootCmd.AddCommand(backupCmd)
}

func showBackup(args []string) {
	log.Debugf("showBackup called %v\n", args)

	//show pod information for job
	for _, arg := range args {
		log.Debug("show backup called for " + arg)
		//pg-database=basic or
		//pgbackup=true
		if arg == "all" {
			lo := meta_v1.ListOptions{LabelSelector: "pgbackup=true"}
			log.Debug("label selector is " + lo.LabelSelector)
			pods, err2 := Clientset.CoreV1().Pods(Namespace).List(lo)
			if err2 != nil {
				log.Error(err2.Error())
				return
			}
			for _, pod := range pods.Items {
				showBackupInfo(pod.ObjectMeta.Labels["pg-database"])
			}

		} else {
			showBackupInfo(arg)

		}

	}

}
func showBackupInfo(name string) {
	fmt.Println("\nbackup information for " + name + "...")
	//print the pgbackups TPR if it exists
	result := tpr.PgBackup{}
	err := Tprclient.Get().
		Resource(tpr.BACKUP_RESOURCE).
		Namespace(Namespace).
		Name(name).
		Do().
		Into(&result)
	if err == nil {
		printBackupTPR(&result)
	} else if errors.IsNotFound(err) {
		fmt.Println("\npgbackup TPR not found ")
	} else {
		log.Errorf("\npgbackup %s\n", name+" lookup error ")
		log.Error(err.Error())
		return
	}

	//print the backup jobs if any exists
	lo := meta_v1.ListOptions{LabelSelector: "pgbackup=true,pg-database=" + name}
	log.Debug("label selector is " + lo.LabelSelector)
	pods, err2 := Clientset.CoreV1().Pods(Namespace).List(lo)
	if err2 != nil {
		log.Error(err2.Error())
	}
	fmt.Printf("\nbackup job pods for database %s\n", name+"...")

	pvcMap := make(map[string]string)

	for _, p := range pods.Items {

		//get the pgdata volume info
		for _, v := range p.Spec.Volumes {
			if v.Name == "pgdata" {
				fmt.Printf("%s%s (pvc %s)\n\n", TREE_TRUNK, p.Name, v.VolumeSource.PersistentVolumeClaim.ClaimName)
				pvcMap[v.VolumeSource.PersistentVolumeClaim.ClaimName] = v.VolumeSource.PersistentVolumeClaim.ClaimName
			}
		}
		fmt.Println("")

	}

	log.Debugf("ShowPVC is %v\n", ShowPVC)

	if ShowPVC {
		//print pvc information for all jobs
		for key, _ := range pvcMap {
			PrintPVCListing(key)
		}
	}
}

func printBackupTPR(result *tpr.PgBackup) {
	fmt.Printf("%s%s\n", "", "")
	fmt.Printf("%s%s\n", "", "pgbackup : "+result.Spec.Name)

	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Name:\t"+result.Spec.StorageSpec.PvcName)
	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Access Mode:\t"+result.Spec.StorageSpec.PvcAccessMode)
	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Size:\t\t"+result.Spec.StorageSpec.PvcSize)
	fmt.Printf("%s%s\n", TREE_BRANCH, "CCP_IMAGE_TAG:\t"+result.Spec.CCP_IMAGE_TAG)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Status:\t"+result.Spec.BACKUP_STATUS)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Host:\t"+result.Spec.BACKUP_HOST)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup User:\t"+result.Spec.BACKUP_USER)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Pass:\t"+result.Spec.BACKUP_PASS)
	fmt.Printf("%s%s\n", TREE_TRUNK, "Backup Port:\t"+result.Spec.BACKUP_PORT)

}

func createBackup(args []string) {
	log.Debugf("createBackup called %v\n", args)

	var err error
	var newInstance *tpr.PgBackup

	for _, arg := range args {<commit_msg>add selector flag to backup command<commit_after>/*
 Copyright 2017 Crunchy Data Solutions, Inc.
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

// Package cmd provides the command line functions of the crunchy CLI
package cmd

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	"github.com/crunchydata/postgres-operator/tpr"
	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/labels"

	"github.com/spf13/viper"
	"k8s.io/apimachinery/pkg/api/errors"
	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"time"
)

var backupCmd = &cobra.Command{
	Use:   "backup",
	Short: "perform a Backup",
	Long: `BACKUP performs a Backup, for example:
			pgo backup mycluster`,
	Run: func(cmd *cobra.Command, args []string) {
		log.Debug("backup called")
		if len(args) == 0 && Selector == "" {
			fmt.Println(`You must specify the cluster to backup or a selector flag.`)
		} else {
			createBackup(args)
		}

	},
}

func init() {
	RootCmd.AddCommand(backupCmd)

	backupCmd.Flags().StringVarP(&Selector, "selector", "s", "", "The selector to use for cluster filtering ")
}

func showBackup(args []string) {
	log.Debugf("showBackup called %v\n", args)

	//show pod information for job
	for _, arg := range args {
		log.Debug("show backup called for " + arg)
		//pg-database=basic or
		//pgbackup=true
		if arg == "all" {
			lo := meta_v1.ListOptions{LabelSelector: "pgbackup=true"}
			log.Debug("label selector is " + lo.LabelSelector)
			pods, err2 := Clientset.CoreV1().Pods(Namespace).List(lo)
			if err2 != nil {
				log.Error(err2.Error())
				return
			}
			for _, pod := range pods.Items {
				showBackupInfo(pod.ObjectMeta.Labels["pg-database"])
			}

		} else {
			showBackupInfo(arg)

		}

	}

}
func showBackupInfo(name string) {
	fmt.Println("\nbackup information for " + name + "...")
	//print the pgbackups TPR if it exists
	result := tpr.PgBackup{}
	err := Tprclient.Get().
		Resource(tpr.BACKUP_RESOURCE).
		Namespace(Namespace).
		Name(name).
		Do().
		Into(&result)
	if err == nil {
		printBackupTPR(&result)
	} else if errors.IsNotFound(err) {
		fmt.Println("\npgbackup TPR not found ")
	} else {
		log.Errorf("\npgbackup %s\n", name+" lookup error ")
		log.Error(err.Error())
		return
	}

	//print the backup jobs if any exists
	lo := meta_v1.ListOptions{LabelSelector: "pgbackup=true,pg-database=" + name}
	log.Debug("label selector is " + lo.LabelSelector)
	pods, err2 := Clientset.CoreV1().Pods(Namespace).List(lo)
	if err2 != nil {
		log.Error(err2.Error())
	}
	fmt.Printf("\nbackup job pods for database %s\n", name+"...")

	pvcMap := make(map[string]string)

	for _, p := range pods.Items {

		//get the pgdata volume info
		for _, v := range p.Spec.Volumes {
			if v.Name == "pgdata" {
				fmt.Printf("%s%s (pvc %s)\n\n", TREE_TRUNK, p.Name, v.VolumeSource.PersistentVolumeClaim.ClaimName)
				pvcMap[v.VolumeSource.PersistentVolumeClaim.ClaimName] = v.VolumeSource.PersistentVolumeClaim.ClaimName
			}
		}
		fmt.Println("")

	}

	log.Debugf("ShowPVC is %v\n", ShowPVC)

	if ShowPVC {
		//print pvc information for all jobs
		for key, _ := range pvcMap {
			PrintPVCListing(key)
		}
	}
}

func printBackupTPR(result *tpr.PgBackup) {
	fmt.Printf("%s%s\n", "", "")
	fmt.Printf("%s%s\n", "", "pgbackup : "+result.Spec.Name)

	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Name:\t"+result.Spec.StorageSpec.PvcName)
	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Access Mode:\t"+result.Spec.StorageSpec.PvcAccessMode)
	fmt.Printf("%s%s\n", TREE_BRANCH, "PVC Size:\t\t"+result.Spec.StorageSpec.PvcSize)
	fmt.Printf("%s%s\n", TREE_BRANCH, "CCP_IMAGE_TAG:\t"+result.Spec.CCP_IMAGE_TAG)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Status:\t"+result.Spec.BACKUP_STATUS)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Host:\t"+result.Spec.BACKUP_HOST)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup User:\t"+result.Spec.BACKUP_USER)
	fmt.Printf("%s%s\n", TREE_BRANCH, "Backup Pass:\t"+result.Spec.BACKUP_PASS)
	fmt.Printf("%s%s\n", TREE_TRUNK, "Backup Port:\t"+result.Spec.BACKUP_PORT)

}

func createBackup(args []string) {
	log.Debugf("createBackup called %v\n", args)

	var err error
	var newInstance *tpr.PgBackup

	if Selector != "" {
		//use the selector instead of an argument list to filter on

		myselector, err := labels.Parse(Selector)
		if err != nil {
			log.Error("could not parse selector flag")
			return
		}

		//get the clusters list
		clusterList := tpr.PgClusterList{}
		err = Tprclient.Get().
			Resource(tpr.CLUSTER_RESOURCE).
			Namespace(Namespace).
			LabelsSelectorParam(myselector).
			Do().
			Into(&clusterList)
		if err != nil {
			log.Error("error getting cluster list" + err.Error())
			return
		}

		if len(clusterList.Items) == 0 {
			log.Debug("no clusters found")
		} else {
			newargs := make([]string, 0)
			for _, cluster := range clusterList.Items {
				newargs = append(newargs, cluster.Spec.Name)
			}
			args = newargs
		}

	}

	for _, arg := range args {
{'fraction_non_alphanumeric': 0.15034285129464742, 'fraction_numerical': 0.005833589192508443, 'mean_word_length': 3.947848101265823, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '616976', 'n_tokens_mistral': 3778, 'n_tokens_neox': 3592, 'n_words': 835}