Skip to content

Commit cd1511a

Browse files
authored
fix(collectors): store unhealthy pod logs correctly (#909)
The symlinking logs feature led to a regression where symlinks of unhealthy pods were overwritting logs in the support bundle. This fix allows the cluster resources collector to instruct the logs collector not to symlink logs, which in turn ensures logs are not overwritten. Fixes: #908
1 parent 9c77a0e commit cd1511a

File tree

4 files changed

+30
-15
lines changed

4 files changed

+30
-15
lines changed

pkg/collect/cluster_resources.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,21 +167,16 @@ func (c *CollectClusterResources) Collect(progressChan chan<- interface{}) (Coll
167167
for _, pod := range unhealthyPods {
168168
allContainers := append(pod.Spec.InitContainers, pod.Spec.Containers...)
169169
for _, container := range allContainers {
170-
logsRoot := ""
171-
if c.BundlePath != "" {
172-
logsRoot = path.Join(c.BundlePath, "cluster-resources", "pods", "logs", pod.Namespace)
173-
}
174170
limits := &troubleshootv1beta2.LogLimits{
175171
MaxLines: 500,
176172
}
177-
podLogs, err := savePodLogs(ctx, logsRoot, client, &pod, "", container.Name, limits, false)
173+
podLogs, err := savePodLogs(ctx, c.BundlePath, client, &pod, "", container.Name, limits, false, false)
178174
if err != nil {
179175
errPath := filepath.Join("cluster-resources", "pods", "logs", pod.Namespace, pod.Name, fmt.Sprintf("%s-logs-errors.log", container.Name))
180176
output.SaveResult(c.BundlePath, errPath, bytes.NewBuffer([]byte(err.Error())))
181177
}
182-
for k, v := range podLogs {
183-
output[filepath.Join("cluster-resources", "pods", "logs", pod.Namespace, k)] = v
184-
}
178+
// Add logs collector results to the rest of the output
179+
output.AddResult(podLogs)
185180
}
186181
}
187182

pkg/collect/logs.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (c *CollectLogs) Collect(progressChan chan<- interface{}) (CollectorResult,
7171
}
7272

7373
for _, containerName := range containerNames {
74-
podLogs, err := savePodLogs(ctx, c.BundlePath, client, &pod, c.Collector.Name, containerName, c.Collector.Limits, false)
74+
podLogs, err := savePodLogs(ctx, c.BundlePath, client, &pod, c.Collector.Name, containerName, c.Collector.Limits, false, true)
7575
if err != nil {
7676
key := fmt.Sprintf("%s/%s-errors.json", c.Collector.Name, pod.Name)
7777
if containerName != "" {
@@ -89,7 +89,7 @@ func (c *CollectLogs) Collect(progressChan chan<- interface{}) (CollectorResult,
8989
}
9090
} else {
9191
for _, container := range c.Collector.ContainerNames {
92-
containerLogs, err := savePodLogs(ctx, c.BundlePath, client, &pod, c.Collector.Name, container, c.Collector.Limits, false)
92+
containerLogs, err := savePodLogs(ctx, c.BundlePath, client, &pod, c.Collector.Name, container, c.Collector.Limits, false, true)
9393
if err != nil {
9494
key := fmt.Sprintf("%s/%s/%s-errors.json", c.Collector.Name, pod.Name, container)
9595
err := output.SaveResult(c.BundlePath, key, marshalErrors([]string{err.Error()}))
@@ -132,8 +132,9 @@ func savePodLogs(
132132
collectorName, container string,
133133
limits *troubleshootv1beta2.LogLimits,
134134
follow bool,
135+
createSymLinks bool,
135136
) (CollectorResult, error) {
136-
return savePodLogsWithInterface(ctx, bundlePath, client, pod, collectorName, container, limits, follow)
137+
return savePodLogsWithInterface(ctx, bundlePath, client, pod, collectorName, container, limits, follow, createSymLinks)
137138
}
138139

139140
func savePodLogsWithInterface(
@@ -144,6 +145,7 @@ func savePodLogsWithInterface(
144145
collectorName, container string,
145146
limits *troubleshootv1beta2.LogLimits,
146147
follow bool,
148+
createSymLinks bool,
147149
) (CollectorResult, error) {
148150
podLogOpts := corev1.PodLogOptions{
149151
Follow: follow,
@@ -185,7 +187,9 @@ func savePodLogsWithInterface(
185187
return nil, errors.Wrap(err, "failed to get log writer")
186188
}
187189
// NOTE: deferred calls are executed in LIFO order i.e called in reverse order
188-
defer result.SymLinkResult(bundlePath, linkRelPathPrefix+".log", filePathPrefix+".log")
190+
if createSymLinks {
191+
defer result.SymLinkResult(bundlePath, linkRelPathPrefix+".log", filePathPrefix+".log")
192+
}
189193
defer result.CloseWriter(bundlePath, filePathPrefix+".log", logWriter)
190194

191195
_, err = io.Copy(logWriter, podLogs)
@@ -207,7 +211,9 @@ func savePodLogsWithInterface(
207211
return nil, errors.Wrap(err, "failed to get previous log writer")
208212
}
209213
// NOTE: deferred calls are executed in LIFO order i.e called in reverse order
210-
defer result.SymLinkResult(bundlePath, linkRelPathPrefix+"-previous.log", filePathPrefix+"-previous.log")
214+
if createSymLinks {
215+
defer result.SymLinkResult(bundlePath, linkRelPathPrefix+"-previous.log", filePathPrefix+"-previous.log")
216+
}
211217
defer result.CloseWriter(bundlePath, filePathPrefix+"-previous.log", logWriter)
212218

213219
_, err = io.Copy(prevLogWriter, podLogs)

pkg/collect/logs_test.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,14 @@ func Test_savePodLogs(t *testing.T) {
8585
name string
8686
withContainerName bool
8787
collectorName string
88+
createSymLinks bool
8889
want CollectorResult
8990
}{
9091
{
9192
name: "with container name",
9293
withContainerName: true,
9394
collectorName: "all-logs",
95+
createSymLinks: true,
9496
want: CollectorResult{
9597
"all-logs/test-pod/nginx.log": []byte("fake logs"),
9698
"all-logs/test-pod/nginx-previous.log": []byte("fake logs"),
@@ -102,6 +104,7 @@ func Test_savePodLogs(t *testing.T) {
102104
name: "without container name",
103105
withContainerName: false,
104106
collectorName: "all-logs",
107+
createSymLinks: true,
105108
want: CollectorResult{
106109
"all-logs/test-pod.log": []byte("fake logs"),
107110
"all-logs/test-pod-previous.log": []byte("fake logs"),
@@ -112,13 +115,24 @@ func Test_savePodLogs(t *testing.T) {
112115
{
113116
name: "without container or collector names",
114117
withContainerName: false,
118+
createSymLinks: true,
115119
want: CollectorResult{
116120
"/test-pod.log": []byte("fake logs"),
117121
"/test-pod-previous.log": []byte("fake logs"),
118122
"cluster-resources/pods/logs/my-namespace/test-pod/nginx.log": []byte("fake logs"),
119123
"cluster-resources/pods/logs/my-namespace/test-pod/nginx-previous.log": []byte("fake logs"),
120124
},
121125
},
126+
{
127+
name: "without sym links",
128+
withContainerName: true,
129+
collectorName: "all-logs",
130+
createSymLinks: false,
131+
want: CollectorResult{
132+
"cluster-resources/pods/logs/my-namespace/test-pod/nginx.log": []byte("fake logs"),
133+
"cluster-resources/pods/logs/my-namespace/test-pod/nginx-previous.log": []byte("fake logs"),
134+
},
135+
},
122136
}
123137
for _, tt := range tests {
124138
t.Run(tt.name, func(t *testing.T) {
@@ -144,7 +158,7 @@ func Test_savePodLogs(t *testing.T) {
144158
if !tt.withContainerName {
145159
containerName = ""
146160
}
147-
got, err := savePodLogsWithInterface(ctx, "", client, pod, tt.collectorName, containerName, limits, false)
161+
got, err := savePodLogsWithInterface(ctx, "", client, pod, tt.collectorName, containerName, limits, false, tt.createSymLinks)
148162
assert.NoError(t, err)
149163
assert.Equal(t, tt.want, got)
150164
})

pkg/collect/run_pod.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func runWithoutTimeout(ctx context.Context, bundlePath string, clientConfig *res
179179
limits := troubleshootv1beta2.LogLimits{
180180
MaxLines: 10000,
181181
}
182-
podLogs, err := savePodLogs(ctx, bundlePath, client, pod, collectorName, "", &limits, true)
182+
podLogs, err := savePodLogs(ctx, bundlePath, client, pod, collectorName, "", &limits, true, true)
183183
if err != nil {
184184
return nil, errors.Wrap(err, "failed to get pod logs")
185185
}

0 commit comments

Comments
 (0)