Skip to content

Commit f757b84

Browse files
committed
Review: Add tests to confirm expected files are created for each job
1 parent 4e6d035 commit f757b84

File tree

2 files changed

+762
-0
lines changed

2 files changed

+762
-0
lines changed

pkg/jobs/common_job_list_test.go

Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package jobs
33
import (
44
"bytes"
55
"context"
6+
"encoding/json"
67
"fmt"
78
"log"
89
"path/filepath"
@@ -14,6 +15,8 @@ import (
1415
"github.com/nginxinc/nginx-k8s-supportpkg/pkg/mock"
1516
"github.com/stretchr/testify/assert"
1617
"go.uber.org/mock/gomock"
18+
corev1 "k8s.io/api/core/v1"
19+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1720
"k8s.io/apimachinery/pkg/runtime"
1821
"k8s.io/client-go/kubernetes/fake"
1922
k8stesting "k8s.io/client-go/testing" // Add this line
@@ -142,3 +145,370 @@ func TestCommonJobList_PodListError(t *testing.T) {
142145
assert.Nil(t, result.Error) // The job itself doesn't fail, just logs errors
143146
}
144147
}
148+
149+
func TestCommonJobList_FileCreation(t *testing.T) {
150+
tests := []struct {
151+
name string
152+
jobName string
153+
jobIndex int
154+
expectedFiles []string
155+
setupMockObjects func() []runtime.Object
156+
verifyFileContent func(t *testing.T, files map[string][]byte, tmpDir string)
157+
}{
158+
{
159+
name: "pod-list creates pods.json files",
160+
jobName: "pod-list",
161+
jobIndex: 0,
162+
expectedFiles: []string{
163+
"resources/default/pods.json",
164+
"resources/test-ns/pods.json",
165+
},
166+
setupMockObjects: func() []runtime.Object {
167+
return []runtime.Object{
168+
&corev1.Pod{
169+
ObjectMeta: metav1.ObjectMeta{Name: "test-pod", Namespace: "default"},
170+
},
171+
}
172+
},
173+
verifyFileContent: func(t *testing.T, files map[string][]byte, tmpDir string) {
174+
// Verify JSON structure
175+
for path, content := range files {
176+
if strings.Contains(path, "pods.json") {
177+
var podList corev1.PodList
178+
err := json.Unmarshal(content, &podList)
179+
assert.NoError(t, err, "Should be valid JSON")
180+
assert.GreaterOrEqual(t, len(podList.Items), 0, "Should contain pod items")
181+
}
182+
}
183+
},
184+
},
185+
// Add more test cases for other jobs...
186+
}
187+
188+
for _, tt := range tests {
189+
t.Run(tt.name, func(t *testing.T) {
190+
tmpDir := t.TempDir()
191+
var logOutput bytes.Buffer
192+
193+
// Setup mock objects
194+
mockObjects := tt.setupMockObjects()
195+
client := fake.NewSimpleClientset(mockObjects...)
196+
197+
dc := &data_collector.DataCollector{
198+
BaseDir: tmpDir,
199+
Namespaces: []string{"default", "test-ns"},
200+
Logger: log.New(&logOutput, "", 0),
201+
K8sCoreClientSet: client,
202+
}
203+
204+
// Execute the specific job
205+
jobs := CommonJobList()
206+
job := jobs[tt.jobIndex]
207+
assert.Equal(t, tt.jobName, job.Name)
208+
209+
ctx := context.Background()
210+
ch := make(chan JobResult, 1)
211+
job.Execute(dc, ctx, ch)
212+
213+
result := <-ch
214+
215+
// Verify expected number of files
216+
assert.Len(t, result.Files, len(tt.expectedFiles),
217+
"Should create expected number of files")
218+
219+
// Verify each expected file exists
220+
for _, expectedFile := range tt.expectedFiles {
221+
expectedPath := filepath.Join(tmpDir, expectedFile)
222+
content, exists := result.Files[expectedPath]
223+
assert.True(t, exists, "Expected file should exist: %s", expectedFile)
224+
assert.NotEmpty(t, content, "File content should not be empty: %s", expectedFile)
225+
}
226+
227+
// Custom content verification
228+
if tt.verifyFileContent != nil {
229+
tt.verifyFileContent(t, result.Files, tmpDir)
230+
}
231+
232+
// Verify no errors for successful operations
233+
if len(tt.expectedFiles) > 0 {
234+
assert.Nil(t, result.Error, "Should not have errors for successful execution")
235+
}
236+
})
237+
}
238+
}
239+
240+
func TestCommonJobList_ResourceListJobs(t *testing.T) {
241+
resourceTests := []struct {
242+
jobName string
243+
jobIndex int
244+
resourceType string
245+
fileName string
246+
setupObjects func() []runtime.Object
247+
}{
248+
{
249+
jobName: "pod-list",
250+
jobIndex: 0,
251+
resourceType: "pods",
252+
fileName: "pods.json",
253+
setupObjects: func() []runtime.Object {
254+
return []runtime.Object{
255+
&corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "test-pod", Namespace: "default"}},
256+
}
257+
},
258+
},
259+
{
260+
jobName: "service-list",
261+
jobIndex: 9,
262+
resourceType: "services",
263+
fileName: "services.json",
264+
setupObjects: func() []runtime.Object {
265+
return []runtime.Object{
266+
&corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: "test-svc", Namespace: "default"}},
267+
}
268+
},
269+
},
270+
{
271+
jobName: "configmap-list",
272+
jobIndex: 8,
273+
resourceType: "configmaps",
274+
fileName: "configmaps.json",
275+
setupObjects: func() []runtime.Object {
276+
return []runtime.Object{
277+
&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "test-cm", Namespace: "default"}},
278+
}
279+
},
280+
},
281+
}
282+
283+
for _, tt := range resourceTests {
284+
t.Run(tt.jobName, func(t *testing.T) {
285+
tmpDir := t.TempDir()
286+
var logOutput bytes.Buffer
287+
288+
client := fake.NewSimpleClientset(tt.setupObjects()...)
289+
290+
dc := &data_collector.DataCollector{
291+
BaseDir: tmpDir,
292+
Namespaces: []string{"default"},
293+
Logger: log.New(&logOutput, "", 0),
294+
K8sCoreClientSet: client,
295+
}
296+
297+
jobs := CommonJobList()
298+
job := jobs[tt.jobIndex]
299+
300+
ctx := context.Background()
301+
ch := make(chan JobResult, 1)
302+
job.Execute(dc, ctx, ch)
303+
304+
result := <-ch
305+
306+
// Verify file creation
307+
expectedPath := filepath.Join(tmpDir, "resources/default", tt.fileName)
308+
content, exists := result.Files[expectedPath]
309+
assert.True(t, exists, "Expected %s file should exist", tt.fileName)
310+
assert.NotEmpty(t, content, "File content should not be empty")
311+
312+
// Verify JSON structure
313+
var jsonData map[string]interface{}
314+
err := json.Unmarshal(content, &jsonData)
315+
assert.NoError(t, err, "Content should be valid JSON")
316+
assert.Contains(t, jsonData, "items", "Should contain 'items' field")
317+
})
318+
}
319+
}
320+
321+
func TestCommonJobList_CollectPodsLogs_FileCreation(t *testing.T) {
322+
tmpDir := t.TempDir()
323+
var logOutput bytes.Buffer
324+
325+
testPod := &corev1.Pod{
326+
ObjectMeta: metav1.ObjectMeta{
327+
Name: "nginx-pod",
328+
Namespace: "default",
329+
},
330+
Spec: corev1.PodSpec{
331+
Containers: []corev1.Container{
332+
{Name: "nginx", Image: "nginx:latest"},
333+
{Name: "sidecar", Image: "busybox:latest"},
334+
},
335+
},
336+
}
337+
338+
client := fake.NewSimpleClientset(testPod)
339+
340+
dc := &data_collector.DataCollector{
341+
BaseDir: tmpDir,
342+
Namespaces: []string{"default"},
343+
Logger: log.New(&logOutput, "", 0),
344+
K8sCoreClientSet: client,
345+
}
346+
347+
jobs := CommonJobList()
348+
collectLogsJob := jobs[1] // collect-pods-logs
349+
350+
ctx := context.Background()
351+
ch := make(chan JobResult, 1)
352+
collectLogsJob.Execute(dc, ctx, ch)
353+
354+
result := <-ch
355+
356+
// Expected log files (will fail with fake client, but we can verify the attempt)
357+
expectedLogFiles := []string{
358+
"logs/default/nginx-pod__nginx.txt",
359+
"logs/default/nginx-pod__sidecar.txt",
360+
}
361+
362+
// Verify expected file paths would be constructed correctly
363+
for _, expectedFile := range expectedLogFiles {
364+
expectedFullPath := filepath.Join(tmpDir, expectedFile)
365+
_, exists := result.Files[expectedFullPath]
366+
assert.True(t, exists, "Expected file should exist: %s", expectedFile)
367+
}
368+
}
369+
370+
func TestCommonJobList_ClusterLevelJobs(t *testing.T) {
371+
clusterTests := []struct {
372+
name string
373+
jobName string
374+
jobIndex int
375+
expectedFile string
376+
}{
377+
{
378+
name: "k8s-version creates version.json",
379+
jobName: "k8s-version",
380+
jobIndex: 18,
381+
expectedFile: "k8s/version.json",
382+
},
383+
{
384+
name: "clusterroles-info creates clusterroles.json",
385+
jobName: "clusterroles-info",
386+
jobIndex: 20,
387+
expectedFile: "k8s/rbac/clusterroles.json",
388+
},
389+
{
390+
name: "nodes-info creates nodes.json and platform_info.json",
391+
jobName: "nodes-info",
392+
jobIndex: 22,
393+
expectedFile: "k8s/nodes.json",
394+
},
395+
}
396+
397+
for _, tt := range clusterTests {
398+
t.Run(tt.name, func(t *testing.T) {
399+
tmpDir := t.TempDir()
400+
var logOutput bytes.Buffer
401+
402+
// Setup mock objects based on job type
403+
var mockObjects []runtime.Object
404+
if tt.jobName == "nodes-info" {
405+
mockObjects = []runtime.Object{
406+
&corev1.Node{
407+
ObjectMeta: metav1.ObjectMeta{
408+
Name: "test-node",
409+
Labels: map[string]string{
410+
"node-role.kubernetes.io/control-plane": "",
411+
},
412+
},
413+
Status: corev1.NodeStatus{
414+
NodeInfo: corev1.NodeSystemInfo{
415+
OSImage: "Ubuntu 20.04",
416+
OperatingSystem: "linux",
417+
Architecture: "amd64",
418+
},
419+
},
420+
},
421+
}
422+
}
423+
424+
client := fake.NewSimpleClientset(mockObjects...)
425+
426+
dc := &data_collector.DataCollector{
427+
BaseDir: tmpDir,
428+
Namespaces: []string{"default"},
429+
Logger: log.New(&logOutput, "", 0),
430+
K8sCoreClientSet: client,
431+
}
432+
433+
jobs := CommonJobList()
434+
job := jobs[tt.jobIndex]
435+
assert.Equal(t, tt.jobName, job.Name)
436+
437+
ctx := context.Background()
438+
ch := make(chan JobResult, 1)
439+
job.Execute(dc, ctx, ch)
440+
441+
result := <-ch
442+
443+
// Verify main file creation
444+
expectedPath := filepath.Join(tmpDir, tt.expectedFile)
445+
content, exists := result.Files[expectedPath]
446+
assert.True(t, exists, "Expected file should exist: %s", tt.expectedFile)
447+
assert.NotEmpty(t, content, "File content should not be empty")
448+
449+
// Special case for nodes-info which creates additional platform_info.json
450+
if tt.jobName == "nodes-info" {
451+
platformInfoPath := filepath.Join(tmpDir, "platform_info.json")
452+
platformContent, platformExists := result.Files[platformInfoPath]
453+
assert.True(t, platformExists, "platform_info.json should exist")
454+
assert.NotEmpty(t, platformContent, "Platform info should not be empty")
455+
456+
// Verify platform info structure
457+
var platformInfo data_collector.PlatformInfo
458+
err := json.Unmarshal(platformContent, &platformInfo)
459+
assert.NoError(t, err, "Platform info should be valid JSON")
460+
assert.NotEmpty(t, platformInfo.PlatformType, "Platform type should be set")
461+
assert.NotEmpty(t, platformInfo.Hostname, "Hostname should be set")
462+
}
463+
})
464+
}
465+
}
466+
467+
func TestCommonJobList_AllJobsFileCreation(t *testing.T) {
468+
dc := mock.SetupMockDataCollector(t)
469+
jobs := CommonJobList()
470+
471+
// Track all created files across all jobs
472+
allFiles := make(map[string][]byte)
473+
474+
for i, job := range jobs {
475+
t.Run(fmt.Sprintf("job_%d_%s", i, job.Name), func(t *testing.T) {
476+
ctx := context.Background()
477+
ch := make(chan JobResult, 1)
478+
job.Execute(dc, ctx, ch)
479+
480+
result := <-ch
481+
482+
// Collect files from this job
483+
for path, content := range result.Files {
484+
allFiles[path] = content
485+
}
486+
487+
// Verify files are within base directory
488+
for filePath := range result.Files {
489+
assert.True(t, strings.HasPrefix(filePath, dc.BaseDir),
490+
"File should be within base directory: %s", filePath)
491+
}
492+
})
493+
}
494+
495+
// Verify overall file structure
496+
t.Run("verify_overall_structure", func(t *testing.T) {
497+
// Check that we have files in expected directories
498+
expectedDirs := []string{"resources", "k8s", "k8s/rbac"}
499+
500+
for _, expectedDir := range expectedDirs {
501+
found := false
502+
for filePath := range allFiles {
503+
if strings.Contains(filePath, expectedDir) {
504+
found = true
505+
break
506+
}
507+
}
508+
assert.True(t, found, "Should have files in directory: %s", expectedDir)
509+
}
510+
511+
// Verify minimum number of files created
512+
assert.Greater(t, len(allFiles), 10, "Should create multiple files across all jobs")
513+
})
514+
}

0 commit comments

Comments
 (0)