From 42902405cdb4dad6ac8a2bc44ec506099f3e8755 Mon Sep 17 00:00:00 2001 From: diamonwiggins Date: Mon, 2 May 2022 02:44:02 +0000 Subject: [PATCH] adding new runpod collector and refactoring old run collector to use new code --- .../troubleshoot/v1beta2/collector_shared.go | 28 ++- .../v1beta2/zz_generated.deepcopy.go | 28 ++- pkg/collect/collector.go | 10 + pkg/collect/run.go | 176 ++++++++++-------- 4 files changed, 159 insertions(+), 83 deletions(-) diff --git a/pkg/apis/troubleshoot/v1beta2/collector_shared.go b/pkg/apis/troubleshoot/v1beta2/collector_shared.go index 3acbc219..b52b92a1 100644 --- a/pkg/apis/troubleshoot/v1beta2/collector_shared.go +++ b/pkg/apis/troubleshoot/v1beta2/collector_shared.go @@ -76,7 +76,15 @@ type Run struct { ImagePullPolicy string `json:"imagePullPolicy,omitempty" yaml:"imagePullPolicy,omitempty"` ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"` ServiceAccountName string `json:"serviceAccountName,omitempty" yaml:"serviceAccountName,omitempty"` - PodSpec corev1.PodSpec `json:"podSpec,omitempty" yaml:"podSpec,omitempty"` +} + +type RunPod struct { + CollectorMeta `json:",inline" yaml:",inline"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + Namespace string `json:"namespace" yaml:"namespace"` + Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"` + ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"` + PodSpec corev1.PodSpec `json:"podSpec,omitempty" yaml:"podSpec,omitempty"` } type ImagePullSecrets struct { @@ -197,6 +205,7 @@ type Collect struct { ConfigMap *ConfigMap `json:"configMap,omitempty" yaml:"configMap,omitempty"` Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"` Run *Run `json:"run,omitempty" yaml:"run,omitempty"` + RunPod *RunPod `json:"runPod,omitempty" yaml:"runPod,omitempty"` Exec *Exec `json:"exec,omitempty" yaml:"exec,omitempty"` Data *Data `json:"data,omitempty" yaml:"data,omitempty"` Copy *Copy `json:"copy,omitempty" yaml:"copy,omitempty"` @@ -330,6 +339,19 @@ func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSub }, NonResourceAttributes: nil, }) + } else if c.RunPod != nil { + result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Namespace: pickNamespaceOrDefault(c.RunPod.Namespace, overrideNS), + Verb: "create", + Group: "", + Version: "", + Resource: "pods", + Subresource: "", + Name: "", + }, + NonResourceAttributes: nil, + }) } else if c.Exec != nil { result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{ ResourceAttributes: &authorizationv1.ResourceAttributes{ @@ -435,6 +457,10 @@ func (c *Collect) GetName() string { collector = "run" name = c.Run.CollectorName } + if c.RunPod != nil { + collector = "run-pod" + name = c.RunPod.CollectorName + } if c.Exec != nil { collector = "exec" name = c.Exec.CollectorName diff --git a/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go b/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go index b99dd1a3..713b37ea 100644 --- a/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go +++ b/pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go @@ -641,6 +641,11 @@ func (in *Collect) DeepCopyInto(out *Collect) { *out = new(Run) (*in).DeepCopyInto(*out) } + if in.RunPod != nil { + in, out := &in.RunPod, &out.RunPod + *out = new(RunPod) + (*in).DeepCopyInto(*out) + } if in.Exec != nil { in, out := &in.Exec, &out.Exec *out = new(Exec) @@ -3482,7 +3487,6 @@ func (in *Run) DeepCopyInto(out *Run) { *out = new(ImagePullSecrets) (*in).DeepCopyInto(*out) } - in.PodSpec.DeepCopyInto(&out.PodSpec) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Run. @@ -3495,6 +3499,28 @@ func (in *Run) DeepCopy() *Run { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunPod) DeepCopyInto(out *RunPod) { + *out = *in + out.CollectorMeta = in.CollectorMeta + if in.ImagePullSecret != nil { + in, out := &in.ImagePullSecret, &out.ImagePullSecret + *out = new(ImagePullSecrets) + (*in).DeepCopyInto(*out) + } + in.PodSpec.DeepCopyInto(&out.PodSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunPod. +func (in *RunPod) DeepCopy() *RunPod { + if in == nil { + return nil + } + out := new(RunPod) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Secret) DeepCopyInto(out *Secret) { *out = *in diff --git a/pkg/collect/collector.go b/pkg/collect/collector.go index b0c117b9..851c9dba 100644 --- a/pkg/collect/collector.go +++ b/pkg/collect/collector.go @@ -93,6 +93,14 @@ func (c *Collector) IsExcluded() bool { if isExcludedResult { return true } + } else if c.Collect.RunPod != nil { + isExcludedResult, err := isExcluded(c.Collect.RunPod.Exclude) + if err != nil { + return true + } + if isExcludedResult { + return true + } } else if c.Collect.Exec != nil { isExcludedResult, err := isExcluded(c.Collect.Exec.Exclude) if err != nil { @@ -221,6 +229,8 @@ func (c *Collector) RunCollectorSync(clientConfig *rest.Config, client kubernete result, err = Logs(c, c.Collect.Logs) } else if c.Collect.Run != nil { result, err = Run(c, c.Collect.Run) + } else if c.Collect.RunPod != nil { + result, err = RunPod(c, c.Collect.RunPod) } else if c.Collect.Exec != nil { result, err = Exec(c, c.Collect.Exec) } else if c.Collect.Data != nil { diff --git a/pkg/collect/run.go b/pkg/collect/run.go index 64003f44..8decf331 100644 --- a/pkg/collect/run.go +++ b/pkg/collect/run.go @@ -16,6 +16,48 @@ import ( ) func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult, error) { + podLabels := make(map[string]string) + podLabels["troubleshoot-role"] = "run-collector" + + pullPolicy := corev1.PullIfNotPresent + if runCollector.ImagePullPolicy != "" { + pullPolicy = corev1.PullPolicy(runCollector.ImagePullPolicy) + } + + namespace := "default" + if runCollector.Namespace != "" { + namespace = runCollector.Namespace + } + + serviceAccountName := "default" + if runCollector.ServiceAccountName != "" { + serviceAccountName = runCollector.ServiceAccountName + } + + runPodCollector := &troubleshootv1beta2.RunPod{ + Name: runCollector.CollectorName, + Namespace: namespace, + Timeout: runCollector.Timeout, + ImagePullSecret: runCollector.ImagePullSecret, + PodSpec: corev1.PodSpec{ + RestartPolicy: corev1.RestartPolicyNever, + ServiceAccountName: serviceAccountName, + Containers: []corev1.Container{ + { + Image: runCollector.Image, + ImagePullPolicy: pullPolicy, + Name: "collector", + Command: runCollector.Command, + Args: runCollector.Args, + }, + }, + }, + } + + return RunPod(c, runPodCollector) +} + +func RunPod(c *Collector, runCollector *troubleshootv1beta2.RunPod) (CollectorResult, error) { ctx := context.Background() client, err := kubernetes.NewForConfig(c.ClientConfig) @@ -23,7 +65,7 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult, return nil, errors.Wrap(err, "failed to create client from config") } - pod, err := runPod(ctx, client, runCollector, c.Namespace) + pod, err := runPodWithSpec(ctx, client, runCollector) if err != nil { return nil, errors.Wrap(err, "failed to run pod") } @@ -76,7 +118,52 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult, } } -func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCollector *troubleshootv1beta2.Run) (CollectorResult, error) { +func runPodWithSpec(ctx context.Context, client *kubernetes.Clientset, runCollector *troubleshootv1beta2.RunPod) (*corev1.Pod, error) { + podLabels := make(map[string]string) + podLabels["troubleshoot-role"] = "run-collector" + + namespace := "default" + if runCollector.Namespace != "" { + namespace = runCollector.Namespace + } + + podName := "run-pod" + if runCollector.CollectorName != "" { + podName = runCollector.CollectorName + } else if runCollector.Name != "" { + podName = runCollector.Name + } + + pod := corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: namespace, + Labels: podLabels, + }, + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Pod", + }, + Spec: runCollector.PodSpec, + } + + if runCollector.ImagePullSecret != nil && runCollector.ImagePullSecret.Data != nil { + secretName, err := createSecret(ctx, client, pod.Namespace, runCollector.ImagePullSecret) + if err != nil { + return nil, errors.Wrap(err, "failed to create secret") + } + pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: secretName}) + } + + created, err := client.CoreV1().Pods(namespace).Create(ctx, &pod, metav1.CreateOptions{}) + if err != nil { + return nil, errors.Wrap(err, "failed to create pod") + } + + return created, nil +} + +func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCollector *troubleshootv1beta2.RunPod) (CollectorResult, error) { client, err := kubernetes.NewForConfig(c.ClientConfig) if err != nil { return nil, errors.Wrap(err, "failed create client from config") @@ -104,10 +191,15 @@ func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCo output := NewResult() + collectorName := runCollector.Name + if collectorName == "" { + collectorName = runCollector.CollectorName + } + limits := troubleshootv1beta2.LogLimits{ MaxLines: 10000, } - podLogs, err := savePodLogs(ctx, c.BundlePath, client, *pod, runCollector.Name, "", &limits, true) + podLogs, err := savePodLogs(ctx, c.BundlePath, client, *pod, collectorName, "", &limits, true) if err != nil { return nil, errors.Wrap(err, "failed to get pod logs") } @@ -119,84 +211,6 @@ func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCo return output, nil } -func runPod(ctx context.Context, client *kubernetes.Clientset, runCollector *troubleshootv1beta2.Run, namespace string) (*corev1.Pod, error) { - podLabels := make(map[string]string) - podLabels["troubleshoot-role"] = "run-collector" - - pullPolicy := corev1.PullIfNotPresent - if runCollector.ImagePullPolicy != "" { - pullPolicy = corev1.PullPolicy(runCollector.ImagePullPolicy) - } - - if namespace == "" { - namespace = runCollector.Namespace - } - if namespace == "" { - namespace = "default" - } - - serviceAccountName := "default" - if runCollector.ServiceAccountName != "" { - serviceAccountName = runCollector.ServiceAccountName - } - - pod := corev1.Pod{} - if runCollector.PodSpec.Containers != nil { - pod = corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: runCollector.CollectorName, - Namespace: namespace, - Labels: podLabels, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - Spec: runCollector.PodSpec, - } - } else { - pod = corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: runCollector.CollectorName, - Namespace: namespace, - Labels: podLabels, - }, - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "Pod", - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - ServiceAccountName: serviceAccountName, - Containers: []corev1.Container{ - { - Image: runCollector.Image, - ImagePullPolicy: pullPolicy, - Name: "collector", - Command: runCollector.Command, - Args: runCollector.Args, - }, - }, - }, - } - - if runCollector.ImagePullSecret != nil && runCollector.ImagePullSecret.Data != nil { - secretName, err := createSecret(ctx, client, pod.Namespace, runCollector.ImagePullSecret) - if err != nil { - return nil, errors.Wrap(err, "failed to create secret") - } - pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: secretName}) - } - } - - created, err := client.CoreV1().Pods(namespace).Create(ctx, &pod, metav1.CreateOptions{}) - if err != nil { - return nil, errors.Wrap(err, "failed to create pod") - } - - return created, nil -} - func createSecret(ctx context.Context, client kubernetes.Interface, namespace string, imagePullSecret *troubleshootv1beta2.ImagePullSecrets) (string, error) { if imagePullSecret.Data == nil { return "", nil