Skip to content

Commit 9d41d4a

Browse files
authored
Fix getting pod details for new support bundle formats (#543)
1 parent e248ab0 commit 9d41d4a

File tree

2 files changed

+267
-8
lines changed

2 files changed

+267
-8
lines changed

pkg/supportbundle/parse.go

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,44 @@ var (
1919
SupportBundleNameRegex = regexp.MustCompile(`^\/?support-bundle-(\d{4})-(\d{2})-(\d{2})T(\d{2})_(\d{2})_(\d{2})\/?`)
2020
)
2121

22-
func GetPodDetails(bundleArchive string, podNamespace string, podName string) (*types.PodDetails, error) {
23-
podDetails := types.PodDetails{}
22+
func getPodsFilePath(namespace string) string {
23+
return filepath.Join("cluster-resources", "pods", fmt.Sprintf("%s.json", namespace))
24+
}
25+
26+
func getContainerLogsFilePath(namespace string, podName string, containerName string) string {
27+
return filepath.Join("cluster-resources", "pods", "logs", namespace, podName, fmt.Sprintf("%s.log", containerName))
28+
}
29+
30+
func getEventsFilePath(namespace string) string {
31+
return filepath.Join("cluster-resources", "events", fmt.Sprintf("%s.json", namespace))
32+
}
2433

25-
nsPodsFilePath := filepath.Join("cluster-resources", "pods", fmt.Sprintf("%s.json", podNamespace))
26-
nsEventsFilePath := filepath.Join("cluster-resources", "events", fmt.Sprintf("%s.json", podNamespace))
34+
func GetPodDetails(bundleArchive string, podNamespace string, podName string) (*types.PodDetails, error) {
35+
nsPodsFilePath := getPodsFilePath(podNamespace)
36+
nsEventsFilePath := getEventsFilePath(podNamespace)
2737

2838
files, err := GetFilesContents(bundleArchive, []string{nsPodsFilePath, nsEventsFilePath})
2939
if err != nil {
3040
return nil, errors.Wrap(err, "failed to get files contents")
3141
}
3242

43+
return getPodDetailsFromFiles(files, podNamespace, podName)
44+
}
45+
46+
func getPodDetailsFromFiles(files map[string][]byte, podNamespace string, podName string) (*types.PodDetails, error) {
47+
podDetails := types.PodDetails{}
48+
49+
nsPodsFilePath := getPodsFilePath(podNamespace)
50+
nsEventsFilePath := getEventsFilePath(podNamespace)
51+
3352
var nsEvents []corev1.Event
3453
if err := json.Unmarshal(files[nsEventsFilePath], &nsEvents); err != nil {
35-
return nil, errors.Wrap(err, "failed to unmarshal events")
54+
// try new format
55+
var nsEventsList corev1.EventList
56+
if err := json.Unmarshal(files[nsEventsFilePath], &nsEventsList); err != nil {
57+
return nil, errors.Wrap(err, "failed to unmarshal events")
58+
}
59+
nsEvents = nsEventsList.Items
3660
}
3761
podEvents := []corev1.Event{}
3862
for _, event := range nsEvents {
@@ -44,7 +68,12 @@ func GetPodDetails(bundleArchive string, podNamespace string, podName string) (*
4468

4569
var podsArr []corev1.Pod
4670
if err := json.Unmarshal(files[nsPodsFilePath], &podsArr); err != nil {
47-
return nil, errors.Wrap(err, "failed to unmarshal pods")
71+
// try new format
72+
var podsList corev1.PodList
73+
if err := json.Unmarshal(files[nsPodsFilePath], &podsList); err != nil {
74+
return nil, errors.Wrap(err, "failed to unmarshal pods")
75+
}
76+
podsArr = podsList.Items
4877
}
4978
for _, pod := range podsArr {
5079
if pod.Name == podName && pod.Namespace == podNamespace {
@@ -53,14 +82,14 @@ func GetPodDetails(bundleArchive string, podNamespace string, podName string) (*
5382
for _, i := range pod.Spec.InitContainers {
5483
podDetails.PodContainers = append(podDetails.PodContainers, types.PodContainer{
5584
Name: i.Name,
56-
LogsFilePath: filepath.Join("cluster-resources", "pods", "logs", pod.Namespace, pod.Name, fmt.Sprintf("%s.log", i.Name)),
85+
LogsFilePath: getContainerLogsFilePath(pod.Namespace, pod.Name, i.Name),
5786
IsInitContainer: true,
5887
})
5988
}
6089
for _, c := range pod.Spec.Containers {
6190
podDetails.PodContainers = append(podDetails.PodContainers, types.PodContainer{
6291
Name: c.Name,
63-
LogsFilePath: filepath.Join("cluster-resources", "pods", "logs", pod.Namespace, pod.Name, fmt.Sprintf("%s.log", c.Name)),
92+
LogsFilePath: getContainerLogsFilePath(pod.Namespace, pod.Name, c.Name),
6493
IsInitContainer: false,
6594
})
6695
}

pkg/supportbundle/parse_test.go

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
package supportbundle
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
types "github.com/replicatedhq/troubleshoot/pkg/supportbundle/types"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
corev1 "k8s.io/api/core/v1"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
)
13+
14+
func Test_getPodDetails(t *testing.T) {
15+
podNamespace := "default"
16+
podName := "hello-27436131-pxhk9"
17+
18+
podsFileContentOldFormat := `[
19+
{
20+
"kind": "Pod",
21+
"apiVersion": "v1",
22+
"metadata": {
23+
"name": "hello-27436131-pxhk9",
24+
"namespace": "default"
25+
},
26+
"spec": {
27+
"initContainers": [
28+
{
29+
"name": "remove-lost-found"
30+
}
31+
],
32+
"containers": [
33+
{
34+
"name": "hello"
35+
}
36+
]
37+
}
38+
}
39+
]`
40+
41+
podsFileContentNewFormat := fmt.Sprintf(`{
42+
"kind": "PodList",
43+
"apiVersion": "v1",
44+
"metadata": {
45+
"resourceVersion": "5389414"
46+
},
47+
"items": %s
48+
}`, podsFileContentOldFormat)
49+
50+
eventsFileContentOldFormat := `[
51+
{
52+
"kind": "Event",
53+
"apiVersion": "v1",
54+
"metadata": {
55+
"name": "example-nginx.16d85cebe302a9b1",
56+
"namespace": "default"
57+
},
58+
"involvedObject": {
59+
"kind": "Deployment",
60+
"namespace": "default",
61+
"name": "example-nginx"
62+
}
63+
},
64+
{
65+
"kind": "Event",
66+
"apiVersion": "v1",
67+
"metadata": {
68+
"name": "hello-27436131-pxhk9.16d85cf27380b4fa",
69+
"namespace": "default"
70+
},
71+
"involvedObject": {
72+
"kind": "Pod",
73+
"namespace": "default",
74+
"name": "hello-27436131-pxhk9"
75+
}
76+
}
77+
]`
78+
79+
eventsFileContentNewFormat := fmt.Sprintf(`{
80+
"kind": "EventList",
81+
"apiVersion": "v1",
82+
"metadata": {
83+
"resourceVersion": "5389515"
84+
},
85+
"items": %s
86+
}`, eventsFileContentOldFormat)
87+
88+
removeLostAndFoundInitContainerLogs := `some logs here`
89+
helloContainerLogs := `Tue Mar 1 20:53:00 UTC 2022 Hello`
90+
91+
tests := []struct {
92+
name string
93+
files map[string][]byte
94+
expect *types.PodDetails
95+
}{
96+
{
97+
name: "old support bundle format",
98+
files: map[string][]byte{
99+
getPodsFilePath(podNamespace): []byte(podsFileContentOldFormat),
100+
getEventsFilePath(podNamespace): []byte(eventsFileContentOldFormat),
101+
getContainerLogsFilePath(podNamespace, podName, "remove-lost-found"): []byte(removeLostAndFoundInitContainerLogs),
102+
getContainerLogsFilePath(podNamespace, podName, "hello"): []byte(helloContainerLogs),
103+
},
104+
expect: &types.PodDetails{
105+
PodDefinition: corev1.Pod{
106+
TypeMeta: metav1.TypeMeta{
107+
APIVersion: "v1",
108+
Kind: "Pod",
109+
},
110+
ObjectMeta: metav1.ObjectMeta{
111+
Name: podName,
112+
Namespace: podNamespace,
113+
},
114+
Spec: corev1.PodSpec{
115+
InitContainers: []corev1.Container{
116+
{
117+
Name: "remove-lost-found",
118+
},
119+
},
120+
Containers: []corev1.Container{
121+
{
122+
Name: "hello",
123+
},
124+
},
125+
},
126+
},
127+
PodEvents: []corev1.Event{
128+
{
129+
TypeMeta: metav1.TypeMeta{
130+
APIVersion: "v1",
131+
Kind: "Event",
132+
},
133+
ObjectMeta: metav1.ObjectMeta{
134+
Name: "hello-27436131-pxhk9.16d85cf27380b4fa",
135+
Namespace: podNamespace,
136+
},
137+
InvolvedObject: corev1.ObjectReference{
138+
Kind: "Pod",
139+
Namespace: podNamespace,
140+
Name: podName,
141+
},
142+
},
143+
},
144+
PodContainers: []types.PodContainer{
145+
{
146+
Name: "remove-lost-found",
147+
LogsFilePath: getContainerLogsFilePath(podNamespace, podName, "remove-lost-found"),
148+
IsInitContainer: true,
149+
},
150+
{
151+
Name: "hello",
152+
LogsFilePath: getContainerLogsFilePath(podNamespace, podName, "hello"),
153+
},
154+
},
155+
},
156+
},
157+
{
158+
name: "new support bundle format",
159+
files: map[string][]byte{
160+
getPodsFilePath(podNamespace): []byte(podsFileContentNewFormat),
161+
getEventsFilePath(podNamespace): []byte(eventsFileContentNewFormat),
162+
getContainerLogsFilePath(podNamespace, podName, "remove-lost-found"): []byte(removeLostAndFoundInitContainerLogs),
163+
getContainerLogsFilePath(podNamespace, podName, "hello"): []byte(helloContainerLogs),
164+
},
165+
expect: &types.PodDetails{
166+
PodDefinition: corev1.Pod{
167+
TypeMeta: metav1.TypeMeta{
168+
APIVersion: "v1",
169+
Kind: "Pod",
170+
},
171+
ObjectMeta: metav1.ObjectMeta{
172+
Name: podName,
173+
Namespace: podNamespace,
174+
},
175+
Spec: corev1.PodSpec{
176+
InitContainers: []corev1.Container{
177+
{
178+
Name: "remove-lost-found",
179+
},
180+
},
181+
Containers: []corev1.Container{
182+
{
183+
Name: "hello",
184+
},
185+
},
186+
},
187+
},
188+
PodEvents: []corev1.Event{
189+
{
190+
TypeMeta: metav1.TypeMeta{
191+
APIVersion: "v1",
192+
Kind: "Event",
193+
},
194+
ObjectMeta: metav1.ObjectMeta{
195+
Name: "hello-27436131-pxhk9.16d85cf27380b4fa",
196+
Namespace: podNamespace,
197+
},
198+
InvolvedObject: corev1.ObjectReference{
199+
Kind: "Pod",
200+
Namespace: podNamespace,
201+
Name: podName,
202+
},
203+
},
204+
},
205+
PodContainers: []types.PodContainer{
206+
{
207+
Name: "remove-lost-found",
208+
LogsFilePath: getContainerLogsFilePath(podNamespace, podName, "remove-lost-found"),
209+
IsInitContainer: true,
210+
},
211+
{
212+
Name: "hello",
213+
LogsFilePath: getContainerLogsFilePath(podNamespace, podName, "hello"),
214+
},
215+
},
216+
},
217+
},
218+
}
219+
220+
for _, test := range tests {
221+
t.Run(test.name, func(t *testing.T) {
222+
req := require.New(t)
223+
224+
actual, err := getPodDetailsFromFiles(test.files, podNamespace, podName)
225+
req.NoError(err)
226+
227+
assert.Equal(t, test.expect, actual)
228+
})
229+
}
230+
}

0 commit comments

Comments
 (0)