Explorar o código

add porter run cleanup subcommand

Mohammed Nafees %!s(int64=4) %!d(string=hai) anos
pai
achega
3c84ff7e15
Modificáronse 2 ficheiros con 118 adicións e 1 borrados
  1. 105 1
      cli/cmd/run.go
  2. 13 0
      cli/cmd/utils/prompt.go

+ 105 - 1
cli/cmd/run.go

@@ -48,6 +48,20 @@ var runCmd = &cobra.Command{
 	},
 }
 
+// cleanupCmd represents the "porter run cleanup" subcommand
+var cleanupCmd = &cobra.Command{
+	Use:   "cleanup",
+	Args:  cobra.NoArgs,
+	Short: "Delete any lingering ephemeral pods that were created with \"porter run\".",
+	Run: func(cmd *cobra.Command, args []string) {
+		err := checkLoginAndRun(args, cleanup)
+
+		if err != nil {
+			os.Exit(1)
+		}
+	},
+}
+
 var existingPod bool
 
 func init() {
@@ -75,6 +89,8 @@ func init() {
 		false,
 		"whether to print verbose output",
 	)
+
+	runCmd.AddCommand(cleanupCmd)
 }
 
 func run(_ *types.GetAuthenticatedUserResponse, client *api.Client, args []string) error {
@@ -148,6 +164,94 @@ func run(_ *types.GetAuthenticatedUserResponse, client *api.Client, args []strin
 	return executeRunEphemeral(config, namespace, selectedPod.Name, selectedContainerName, args[1:])
 }
 
+func cleanup(_ *types.GetAuthenticatedUserResponse, client *api.Client, _ []string) error {
+	config := &PorterRunSharedConfig{
+		Client: client,
+	}
+
+	err := config.setSharedConfig()
+	if err != nil {
+		return fmt.Errorf("Could not retrieve kube credentials: %s", err.Error())
+	}
+
+	proceed, err := utils.PromptSelect(
+		fmt.Sprintf("You have chosen the '%s' namespace for cleanup. Do you want to proceed?", namespace),
+		[]string{"Yes", "No", "All namespaces"},
+	)
+	if err != nil {
+		return err
+	}
+
+	if proceed == "No" {
+		return nil
+	}
+
+	var podNames []string
+
+	color.New(color.FgGreen).Println("Fetching ephemeral pods for cleanup")
+
+	if proceed == "All namespaces" {
+		namespaces, err := config.Clientset.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
+		if err != nil {
+			return err
+		}
+
+		for _, namespace := range namespaces.Items {
+			if pods, err := getEphemeralPods(namespace.Name, config.Clientset); err == nil {
+				podNames = append(podNames, pods...)
+			} else {
+				return err
+			}
+		}
+	} else {
+		if pods, err := getEphemeralPods(namespace, config.Clientset); err == nil {
+			podNames = append(podNames, pods...)
+		} else {
+			return err
+		}
+	}
+
+	if len(podNames) == 0 {
+		color.New(color.FgBlue).Println("No ephemeral pods to delete")
+		return nil
+	}
+
+	selectedPods, err := utils.PromptMultiselect("Select ephemeral pods to delete", podNames)
+	if err != nil {
+		return err
+	}
+
+	for _, podName := range selectedPods {
+		color.New(color.FgBlue).Printf("Deleting ephemeral pod: %s\n", podName)
+
+		err = config.Clientset.CoreV1().Pods(namespace).Delete(
+			context.Background(), podName, metav1.DeleteOptions{},
+		)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func getEphemeralPods(namespace string, clientset *kubernetes.Clientset) ([]string, error) {
+	var podNames []string
+
+	pods, err := clientset.CoreV1().Pods(namespace).List(
+		context.Background(), metav1.ListOptions{LabelSelector: "porter/ephemeral-pod"},
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, pod := range pods.Items {
+		podNames = append(podNames, pod.Name)
+	}
+
+	return podNames, nil
+}
+
 type PorterRunSharedConfig struct {
 	Client     *api.Client
 	RestConf   *rest.Config
@@ -423,7 +527,7 @@ func checkForPodDeletionCronJob(config *PorterRunSharedConfig) error {
 			Name: "porter-ephemeral-pod-deletion-cronjob",
 		},
 		Spec: batchv1.CronJobSpec{
-			Schedule: "* 6 * * *",
+			Schedule: "0 * * * *",
 			JobTemplate: batchv1.JobTemplateSpec{
 				Spec: batchv1.JobSpec{
 					Template: v1.PodTemplateSpec{

+ 13 - 0
cli/cmd/utils/prompt.go

@@ -79,3 +79,16 @@ func PromptSelect(prompt string, options []string) (string, error) {
 
 	return ans.Response, err
 }
+
+func PromptMultiselect(prompt string, options []string) ([]string, error) {
+	query := &survey.MultiSelect{
+		Message: prompt,
+		Options: options,
+	}
+
+	var ans []string
+
+	err := survey.AskOne(query, &ans)
+
+	return ans, err
+}