Skip to content

Commit d6a1795

Browse files
Merge pull request #564 from replicatedhq/diamonwiggins/sc-44286/run-pod-spec
RunPod Collector
2 parents 2c9a37a + 9f527ee commit d6a1795

File tree

4 files changed

+162
-69
lines changed

4 files changed

+162
-69
lines changed

pkg/apis/troubleshoot/v1beta2/collector_shared.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/replicatedhq/troubleshoot/pkg/multitype"
88
authorizationv1 "k8s.io/api/authorization/v1"
9+
corev1 "k8s.io/api/core/v1"
910
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1011
)
1112

@@ -77,6 +78,15 @@ type Run struct {
7778
ServiceAccountName string `json:"serviceAccountName,omitempty" yaml:"serviceAccountName,omitempty"`
7879
}
7980

81+
type RunPod struct {
82+
CollectorMeta `json:",inline" yaml:",inline"`
83+
Name string `json:"name,omitempty" yaml:"name,omitempty"`
84+
Namespace string `json:"namespace" yaml:"namespace"`
85+
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
86+
ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"`
87+
PodSpec corev1.PodSpec `json:"podSpec,omitempty" yaml:"podSpec,omitempty"`
88+
}
89+
8090
type ImagePullSecrets struct {
8191
Name string `json:"name,omitempty" yaml:"name,omitempty"`
8292
Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"`
@@ -196,6 +206,7 @@ type Collect struct {
196206
ConfigMap *ConfigMap `json:"configMap,omitempty" yaml:"configMap,omitempty"`
197207
Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"`
198208
Run *Run `json:"run,omitempty" yaml:"run,omitempty"`
209+
RunPod *RunPod `json:"runPod,omitempty" yaml:"runPod,omitempty"`
199210
Exec *Exec `json:"exec,omitempty" yaml:"exec,omitempty"`
200211
Data *Data `json:"data,omitempty" yaml:"data,omitempty"`
201212
Copy *Copy `json:"copy,omitempty" yaml:"copy,omitempty"`
@@ -329,6 +340,19 @@ func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSub
329340
},
330341
NonResourceAttributes: nil,
331342
})
343+
} else if c.RunPod != nil {
344+
result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{
345+
ResourceAttributes: &authorizationv1.ResourceAttributes{
346+
Namespace: pickNamespaceOrDefault(c.RunPod.Namespace, overrideNS),
347+
Verb: "create",
348+
Group: "",
349+
Version: "",
350+
Resource: "pods",
351+
Subresource: "",
352+
Name: "",
353+
},
354+
NonResourceAttributes: nil,
355+
})
332356
} else if c.Exec != nil {
333357
result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{
334358
ResourceAttributes: &authorizationv1.ResourceAttributes{
@@ -434,6 +458,10 @@ func (c *Collect) GetName() string {
434458
collector = "run"
435459
name = c.Run.CollectorName
436460
}
461+
if c.RunPod != nil {
462+
collector = "run-pod"
463+
name = c.RunPod.CollectorName
464+
}
437465
if c.Exec != nil {
438466
collector = "exec"
439467
name = c.Exec.CollectorName

pkg/apis/troubleshoot/v1beta2/zz_generated.deepcopy.go

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/collect/collector.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ func (c *Collector) IsExcluded() bool {
9797
if isExcludedResult {
9898
return true
9999
}
100+
} else if c.Collect.RunPod != nil {
101+
isExcludedResult, err := isExcluded(c.Collect.RunPod.Exclude)
102+
if err != nil {
103+
return true
104+
}
105+
if isExcludedResult {
106+
return true
107+
}
100108
} else if c.Collect.Exec != nil {
101109
isExcludedResult, err := isExcluded(c.Collect.Exec.Exclude)
102110
if err != nil {
@@ -225,6 +233,8 @@ func (c *Collector) RunCollectorSync(clientConfig *rest.Config, client kubernete
225233
result, err = Logs(c, c.Collect.Logs)
226234
} else if c.Collect.Run != nil {
227235
result, err = Run(c, c.Collect.Run)
236+
} else if c.Collect.RunPod != nil {
237+
result, err = RunPod(c, c.Collect.RunPod)
228238
} else if c.Collect.Exec != nil {
229239
result, err = Exec(c, c.Collect.Exec)
230240
} else if c.Collect.Data != nil {

pkg/collect/run.go

Lines changed: 97 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,53 @@ import (
1616
)
1717

1818
func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult, error) {
19+
pullPolicy := corev1.PullIfNotPresent
20+
if runCollector.ImagePullPolicy != "" {
21+
pullPolicy = corev1.PullPolicy(runCollector.ImagePullPolicy)
22+
}
23+
24+
namespace := "default"
25+
if runCollector.Namespace != "" {
26+
namespace = runCollector.Namespace
27+
}
28+
29+
serviceAccountName := "default"
30+
if runCollector.ServiceAccountName != "" {
31+
serviceAccountName = runCollector.ServiceAccountName
32+
}
33+
34+
runPodCollector := &troubleshootv1beta2.RunPod{
35+
Name: runCollector.CollectorName,
36+
Namespace: namespace,
37+
Timeout: runCollector.Timeout,
38+
ImagePullSecret: runCollector.ImagePullSecret,
39+
PodSpec: corev1.PodSpec{
40+
RestartPolicy: corev1.RestartPolicyNever,
41+
ServiceAccountName: serviceAccountName,
42+
Containers: []corev1.Container{
43+
{
44+
Image: runCollector.Image,
45+
ImagePullPolicy: pullPolicy,
46+
Name: "collector",
47+
Command: runCollector.Command,
48+
Args: runCollector.Args,
49+
},
50+
},
51+
},
52+
}
53+
54+
return RunPod(c, runPodCollector)
55+
}
56+
57+
func RunPod(c *Collector, runPodCollector *troubleshootv1beta2.RunPod) (CollectorResult, error) {
1958
ctx := context.Background()
2059

2160
client, err := kubernetes.NewForConfig(c.ClientConfig)
2261
if err != nil {
2362
return nil, errors.Wrap(err, "failed to create client from config")
2463
}
2564

26-
pod, err := runPod(ctx, client, runCollector, c.Namespace)
65+
pod, err := runPodWithSpec(ctx, client, runPodCollector)
2766
if err != nil {
2867
return nil, errors.Wrap(err, "failed to run pod")
2968
}
@@ -33,7 +72,7 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult,
3372
logger.Printf("Failed to delete pod %s: %v", pod.Name, err)
3473
}
3574
}()
36-
if runCollector.ImagePullSecret != nil && runCollector.ImagePullSecret.Data != nil {
75+
if runPodCollector.ImagePullSecret != nil && runPodCollector.ImagePullSecret.Data != nil {
3776
defer func() {
3877
for _, k := range pod.Spec.ImagePullSecrets {
3978
if err := client.CoreV1().Secrets(pod.Namespace).Delete(ctx, k.Name, metav1.DeleteOptions{}); err != nil {
@@ -42,11 +81,11 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult,
4281
}
4382
}()
4483
}
45-
if runCollector.Timeout == "" {
46-
return runWithoutTimeout(ctx, c, pod, runCollector)
84+
if runPodCollector.Timeout == "" {
85+
return runWithoutTimeout(ctx, c, pod, runPodCollector)
4786
}
4887

49-
timeout, err := time.ParseDuration(runCollector.Timeout)
88+
timeout, err := time.ParseDuration(runPodCollector.Timeout)
5089
if err != nil {
5190
return nil, errors.Wrap(err, "failed to parse timeout")
5291
}
@@ -58,7 +97,7 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult,
5897
defer cancel()
5998

6099
go func() {
61-
b, err := runWithoutTimeout(timeoutCtx, c, pod, runCollector)
100+
b, err := runWithoutTimeout(timeoutCtx, c, pod, runPodCollector)
62101
if err != nil {
63102
errCh <- err
64103
} else {
@@ -76,7 +115,52 @@ func Run(c *Collector, runCollector *troubleshootv1beta2.Run) (CollectorResult,
76115
}
77116
}
78117

79-
func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCollector *troubleshootv1beta2.Run) (CollectorResult, error) {
118+
func runPodWithSpec(ctx context.Context, client *kubernetes.Clientset, runPodCollector *troubleshootv1beta2.RunPod) (*corev1.Pod, error) {
119+
podLabels := make(map[string]string)
120+
podLabels["troubleshoot-role"] = "run-collector"
121+
122+
namespace := "default"
123+
if runPodCollector.Namespace != "" {
124+
namespace = runPodCollector.Namespace
125+
}
126+
127+
podName := "run-pod"
128+
if runPodCollector.CollectorName != "" {
129+
podName = runPodCollector.CollectorName
130+
} else if runPodCollector.Name != "" {
131+
podName = runPodCollector.Name
132+
}
133+
134+
pod := corev1.Pod{
135+
ObjectMeta: metav1.ObjectMeta{
136+
Name: podName,
137+
Namespace: namespace,
138+
Labels: podLabels,
139+
},
140+
TypeMeta: metav1.TypeMeta{
141+
APIVersion: "v1",
142+
Kind: "Pod",
143+
},
144+
Spec: runPodCollector.PodSpec,
145+
}
146+
147+
if runPodCollector.ImagePullSecret != nil && runPodCollector.ImagePullSecret.Data != nil {
148+
secretName, err := createSecret(ctx, client, pod.Namespace, runPodCollector.ImagePullSecret)
149+
if err != nil {
150+
return nil, errors.Wrap(err, "failed to create secret")
151+
}
152+
pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: secretName})
153+
}
154+
155+
created, err := client.CoreV1().Pods(namespace).Create(ctx, &pod, metav1.CreateOptions{})
156+
if err != nil {
157+
return nil, errors.Wrap(err, "failed to create pod")
158+
}
159+
160+
return created, nil
161+
}
162+
163+
func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runPodCollector *troubleshootv1beta2.RunPod) (CollectorResult, error) {
80164
client, err := kubernetes.NewForConfig(c.ClientConfig)
81165
if err != nil {
82166
return nil, errors.Wrap(err, "failed create client from config")
@@ -104,10 +188,15 @@ func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCo
104188

105189
output := NewResult()
106190

191+
collectorName := runPodCollector.Name
192+
if collectorName == "" {
193+
collectorName = runPodCollector.CollectorName
194+
}
195+
107196
limits := troubleshootv1beta2.LogLimits{
108197
MaxLines: 10000,
109198
}
110-
podLogs, err := savePodLogs(ctx, c.BundlePath, client, *pod, runCollector.Name, "", &limits, true)
199+
podLogs, err := savePodLogs(ctx, c.BundlePath, client, *pod, collectorName, "", &limits, true)
111200
if err != nil {
112201
return nil, errors.Wrap(err, "failed to get pod logs")
113202
}
@@ -119,67 +208,6 @@ func runWithoutTimeout(ctx context.Context, c *Collector, pod *corev1.Pod, runCo
119208
return output, nil
120209
}
121210

122-
func runPod(ctx context.Context, client *kubernetes.Clientset, runCollector *troubleshootv1beta2.Run, namespace string) (*corev1.Pod, error) {
123-
podLabels := make(map[string]string)
124-
podLabels["troubleshoot-role"] = "run-collector"
125-
126-
pullPolicy := corev1.PullIfNotPresent
127-
if runCollector.ImagePullPolicy != "" {
128-
pullPolicy = corev1.PullPolicy(runCollector.ImagePullPolicy)
129-
}
130-
131-
if namespace == "" {
132-
namespace = runCollector.Namespace
133-
}
134-
if namespace == "" {
135-
namespace = "default"
136-
}
137-
138-
serviceAccountName := "default"
139-
if runCollector.ServiceAccountName != "" {
140-
serviceAccountName = runCollector.ServiceAccountName
141-
}
142-
143-
pod := corev1.Pod{
144-
ObjectMeta: metav1.ObjectMeta{
145-
Name: runCollector.CollectorName,
146-
Namespace: namespace,
147-
Labels: podLabels,
148-
},
149-
TypeMeta: metav1.TypeMeta{
150-
APIVersion: "v1",
151-
Kind: "Pod",
152-
},
153-
Spec: corev1.PodSpec{
154-
RestartPolicy: corev1.RestartPolicyNever,
155-
ServiceAccountName: serviceAccountName,
156-
Containers: []corev1.Container{
157-
{
158-
Image: runCollector.Image,
159-
ImagePullPolicy: pullPolicy,
160-
Name: "collector",
161-
Command: runCollector.Command,
162-
Args: runCollector.Args,
163-
},
164-
},
165-
},
166-
}
167-
168-
if runCollector.ImagePullSecret != nil && runCollector.ImagePullSecret.Data != nil {
169-
secretName, err := createSecret(ctx, client, pod.Namespace, runCollector.ImagePullSecret)
170-
if err != nil {
171-
return nil, errors.Wrap(err, "failed to create secret")
172-
}
173-
pod.Spec.ImagePullSecrets = append(pod.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: secretName})
174-
}
175-
created, err := client.CoreV1().Pods(namespace).Create(ctx, &pod, metav1.CreateOptions{})
176-
if err != nil {
177-
return nil, errors.Wrap(err, "failed to create pod")
178-
}
179-
180-
return created, nil
181-
}
182-
183211
func createSecret(ctx context.Context, client kubernetes.Interface, namespace string, imagePullSecret *troubleshootv1beta2.ImagePullSecrets) (string, error) {
184212
if imagePullSecret.Data == nil {
185213
return "", nil

0 commit comments

Comments
 (0)