diff --git a/cli/cmd/capture/capture.go b/cli/cmd/capture/capture.go index b32ce49605..be24da8f25 100644 --- a/cli/cmd/capture/capture.go +++ b/cli/cmd/capture/capture.go @@ -9,7 +9,10 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions" ) -var name string +var opts = struct { + genericclioptions.ConfigFlags + Name *string +}{} const defaultName = "retina-capture" @@ -20,7 +23,7 @@ var capture = &cobra.Command{ func init() { cmd.Retina.AddCommand(capture) - configFlags = genericclioptions.NewConfigFlags(true) - configFlags.AddFlags(capture.PersistentFlags()) - capture.PersistentFlags().StringVar(&name, "name", defaultName, "The name of the Retina Capture") + opts.ConfigFlags = *genericclioptions.NewConfigFlags(true) + opts.AddFlags(capture.PersistentFlags()) + capture.PersistentFlags().StringVar(opts.Name, "name", defaultName, "The name of the Retina Capture") } diff --git a/cli/cmd/capture/create.go b/cli/cmd/capture/create.go index a508666077..a2f57fe949 100644 --- a/cli/cmd/capture/create.go +++ b/cli/cmd/capture/create.go @@ -17,7 +17,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" @@ -32,8 +31,6 @@ import ( ) var ( - configFlags *genericclioptions.ConfigFlags - blobUpload string debug bool duration time.Duration @@ -111,7 +108,7 @@ var createCapture = &cobra.Command{ Short: "Create a Retina Capture", Example: createExample, RunE: func(*cobra.Command, []string) error { - kubeConfig, err := configFlags.ToRESTConfig() + kubeConfig, err := opts.ToRESTConfig() if err != nil { return errors.Wrap(err, "failed to compose k8s rest config") } @@ -134,10 +131,10 @@ var createCapture = &cobra.Command{ if nowait { retinacmd.Logger.Info("Please manually delete all capture jobs") if capture.Spec.OutputConfiguration.BlobUpload != nil { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload)) + retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload)) } if capture.Spec.OutputConfiguration.S3Upload != nil && capture.Spec.OutputConfiguration.S3Upload.SecretName != "" { - retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName)) + retinacmd.Logger.Info("Please manually delete capture secret", zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName)) } printCaptureResult(jobsCreated) return nil @@ -154,19 +151,19 @@ var createCapture = &cobra.Command{ retinacmd.Logger.Info("Deleting jobs as all jobs are completed") jobsFailedToDelete := deleteJobs(kubeClient, jobsCreated) if len(jobsFailedToDelete) != 0 { - retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ","))) + retinacmd.Logger.Info("Please manually delete capture jobs failed to delete", zap.String("namespace", *opts.Namespace), zap.String("job list", strings.Join(jobsFailedToDelete, ","))) } err = deleteSecret(kubeClient, capture.Spec.OutputConfiguration.BlobUpload) if err != nil { retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", - zap.String("namespace", namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err)) + zap.String("namespace", *opts.Namespace), zap.String("secret name", *capture.Spec.OutputConfiguration.BlobUpload), zap.Error(err)) } err = deleteSecret(kubeClient, &capture.Spec.OutputConfiguration.S3Upload.SecretName) if err != nil { retinacmd.Logger.Error("Failed to delete capture secret, please manually delete it", - zap.String("namespace", namespace), + zap.String("namespace", *opts.Namespace), zap.String("secret name", capture.Spec.OutputConfiguration.S3Upload.SecretName), zap.Error(err), ) @@ -180,7 +177,7 @@ var createCapture = &cobra.Command{ retinacmd.Logger.Info("Not all job are completed in the given time") retinacmd.Logger.Info("Please manually delete the Capture") - return getCaptureAndPrintCaptureResult(kubeClient, capture.Name, namespace) + return getCaptureAndPrintCaptureResult(kubeClient, capture.Name, *opts.Namespace) }, } @@ -199,7 +196,7 @@ func createSecretFromBlobUpload(kubeClient kubernetes.Interface, blobUpload, cap captureConstants.CaptureOutputLocationBlobUploadSecretKey: []byte(blobUpload), }, } - secret, err := kubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{}) + secret, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{}) if err != nil { return "", err } @@ -218,7 +215,7 @@ func createSecretFromS3Upload(kubeClient kubernetes.Interface, s3AccessKeyID, s3 captureConstants.CaptureOutputLocationS3UploadSecretAccessKey: []byte(s3SecretAccessKey), }, } - secret, err := kubeClient.CoreV1().Secrets(namespace).Create(context.TODO(), secret, metav1.CreateOptions{}) + secret, err := kubeClient.CoreV1().Secrets(*opts.Namespace).Create(context.TODO(), secret, metav1.CreateOptions{}) if err != nil { return "", fmt.Errorf("failed to create s3 upload secret: %w", err) } @@ -230,14 +227,14 @@ func deleteSecret(kubeClient kubernetes.Interface, secretName *string) error { return nil } - return kubeClient.CoreV1().Secrets(namespace).Delete(context.TODO(), *secretName, metav1.DeleteOptions{}) + return kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(context.TODO(), *secretName, metav1.DeleteOptions{}) //nolint:wrapcheck //internal return } func createCaptureF(kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, error) { capture := &retinav1alpha1.Capture{ ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, + Name: *opts.Name, + Namespace: *opts.Namespace, }, Spec: retinav1alpha1.CaptureSpec{ CaptureConfiguration: retinav1alpha1.CaptureConfiguration{ @@ -322,7 +319,7 @@ func createCaptureF(kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, e if len(blobUpload) != 0 { // Mount blob url as secret onto the capture pod for security concern if blob url is not empty. - secretName, err := createSecretFromBlobUpload(kubeClient, blobUpload, name) + secretName, err := createSecretFromBlobUpload(kubeClient, blobUpload, *opts.Name) if err != nil { return nil, err } @@ -330,7 +327,7 @@ func createCaptureF(kubeClient kubernetes.Interface) (*retinav1alpha1.Capture, e } if s3Bucket != "" { - secretName, err := createSecretFromS3Upload(kubeClient, s3AccessKeyID, s3SecretAccessKey, name) + secretName, err := createSecretFromS3Upload(kubeClient, s3AccessKeyID, s3SecretAccessKey, *opts.Name) if err != nil { return nil, fmt.Errorf("failed to create s3 upload secret: %w", err) } @@ -379,12 +376,12 @@ func createJobs(kubeClient kubernetes.Interface, capture *retinav1alpha1.Capture jobsCreated := []batchv1.Job{} for _, job := range jobs { - jobCreated, err := kubeClient.BatchV1().Jobs(namespace).Create(context.TODO(), job, metav1.CreateOptions{}) + jobCreated, err := kubeClient.BatchV1().Jobs(*opts.Namespace).Create(context.TODO(), job, metav1.CreateOptions{}) if err != nil { return nil, err } jobsCreated = append(jobsCreated, *jobCreated) - retinacmd.Logger.Info("Packet capture job is created", zap.String("namespace", namespace), zap.String("capture job", jobCreated.Name)) + retinacmd.Logger.Info("Packet capture job is created", zap.String("namespace", *opts.Namespace), zap.String("capture job", jobCreated.Name)) } return jobsCreated, nil } @@ -428,7 +425,7 @@ func waitUntilJobsComplete(kubeClient kubernetes.Interface, jobs []batchv1.Job) if len(jobsIncompleted) != 0 { retinacmd.Logger.Info("Not all jobs are completed", - zap.String("namespace", namespace), + zap.String("namespace", *opts.Namespace), zap.String("Completed jobs", strings.Join(jobsCompleted, ",")), zap.String("Uncompleted packet capture jobs", strings.Join(jobsIncompleted, ",")), ) diff --git a/cli/cmd/capture/delete.go b/cli/cmd/capture/delete.go index b672f7c04b..88c5e7020d 100644 --- a/cli/cmd/capture/delete.go +++ b/cli/cmd/capture/delete.go @@ -30,7 +30,7 @@ var deleteCapture = &cobra.Command{ Short: "Delete a Retina capture", Example: deleteExample, RunE: func(*cobra.Command, []string) error { - kubeConfig, err := configFlags.ToRESTConfig() + kubeConfig, err := opts.ToRESTConfig() if err != nil { return errors.Wrap(err, "") } @@ -42,7 +42,7 @@ var deleteCapture = &cobra.Command{ captureJobSelector := &metav1.LabelSelector{ MatchLabels: map[string]string{ - label.CaptureNameLabel: name, + label.CaptureNameLabel: *opts.Name, label.AppLabel: captureConstants.CaptureAppname, }, } @@ -51,12 +51,12 @@ var deleteCapture = &cobra.Command{ LabelSelector: labelSelector.String(), } - jobList, err := kubeClient.BatchV1().Jobs(namespace).List(context.TODO(), jobListOpt) + jobList, err := kubeClient.BatchV1().Jobs(*opts.Namespace).List(context.TODO(), jobListOpt) if err != nil { return errors.Wrap(err, "failed to list capture jobs") } if len(jobList.Items) == 0 { - return errors.Errorf("capture %s in namespace %s was not found", name, namespace) + return errors.Errorf("capture %s in namespace %s was not found", *opts.Name, *opts.Namespace) } for _, job := range jobList.Items { @@ -70,13 +70,13 @@ var deleteCapture = &cobra.Command{ for _, volume := range jobList.Items[0].Spec.Template.Spec.Volumes { if volume.Secret != nil { - if err := kubeClient.CoreV1().Secrets(namespace).Delete(context.TODO(), volume.Secret.SecretName, metav1.DeleteOptions{}); err != nil { + if err := kubeClient.CoreV1().Secrets(*opts.Namespace).Delete(context.TODO(), volume.Secret.SecretName, metav1.DeleteOptions{}); err != nil { return errors.Wrap(err, "failed to delete capture secret") } break } } - retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", name)) + retinacmd.Logger.Info(fmt.Sprintf("Retina Capture %q delete", *opts.Name)) return nil }, diff --git a/cli/cmd/capture/download.go b/cli/cmd/capture/download.go index 227916f33b..00142b7f75 100644 --- a/cli/cmd/capture/download.go +++ b/cli/cmd/capture/download.go @@ -45,14 +45,14 @@ var downloadCapture = &cobra.Command{ splitPath := strings.SplitN(containerPath, "/", 2) //nolint:gomnd // TODO string splitting probably isn't the right way to parse this URL? containerName := splitPath[0] - params := storage.ListBlobsParameters{Prefix: name} + params := storage.ListBlobsParameters{Prefix: *opts.Name} blobList, err := blobService.GetContainerReference(containerName).ListBlobs(params) if err != nil { return errors.Wrap(err, "failed to list blobstore ") } if len(blobList.Blobs) == 0 { - return errors.Errorf("no blobs found with prefix: %s", name) + return errors.Errorf("no blobs found with prefix: %s", *opts.Name) } for _, v := range blobList.Blobs { diff --git a/cli/cmd/capture/list.go b/cli/cmd/capture/list.go index 04f02c67af..a95cefd2c4 100644 --- a/cli/cmd/capture/list.go +++ b/cli/cmd/capture/list.go @@ -26,7 +26,7 @@ var listCaptures = &cobra.Command{ Short: "List Retina Captures", Example: listExample, RunE: func(*cobra.Command, []string) error { - kubeConfig, err := configFlags.ToRESTConfig() + kubeConfig, err := opts.ToRESTConfig() if err != nil { return errors.Wrap(err, "failed to compose k8s rest config") } @@ -36,7 +36,7 @@ var listCaptures = &cobra.Command{ return errors.Wrap(err, "failed to initialize kubernetes client") } - captureNamespace := namespace + captureNamespace := *opts.Namespace if allNamespaces { captureNamespace = "" } @@ -46,7 +46,6 @@ var listCaptures = &cobra.Command{ func init() { capture.AddCommand(listCaptures) - listCaptures.Flags().StringVarP(&namespace, "namespace", "n", "default", "Namespace to host capture job") listCaptures.Flags().BoolVarP(&allNamespaces, "all-namespaces", "A", allNamespaces, "If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.") }