Skip to content
This repository was archived by the owner on Jan 30, 2026. It is now read-only.

Commit d7eadc5

Browse files
committed
Pretty-print discovery JSON by default
Signed-off-by: Caleb Xu <caxu@redhat.com>
1 parent f41b642 commit d7eadc5

3 files changed

Lines changed: 46 additions & 6 deletions

File tree

internal/cmd/discoverworkload/discoverworkload.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type config struct {
3333
KubeconfigPath string
3434
LabelSelector string
3535
FieldSelector string
36+
CompactOutput bool
3637
}
3738

3839
func NewCommand(ctx context.Context) *cobra.Command {
@@ -73,6 +74,10 @@ func NewCommand(ctx context.Context) *cobra.Command {
7374
go discover.StartNotifier(ctx, logger, 15*time.Second, 30*time.Second)
7475

7576
logger.Info("starting to watch for workloads", "duration", cfg.Timeout)
77+
78+
opts := discover.NewManifestJSONProcessorFnOptions{
79+
CompactOutput: cfg.CompactOutput,
80+
}
7681
err = discover.WatchForWorkloads(
7782
ctx,
7883
logger,
@@ -82,7 +87,7 @@ func NewCommand(ctx context.Context) *cobra.Command {
8287
FieldSelector: cfg.FieldSelector,
8388
},
8489
k8sclient,
85-
discover.NewManifestJSONProcessorFn(os.Stdout),
90+
discover.NewManifestJSONProcessorFn(os.Stdout, opts),
8691
)
8792
if err != nil {
8893
switch {
@@ -108,6 +113,7 @@ func NewCommand(ctx context.Context) *cobra.Command {
108113
flags.StringVarP(&cfg.KubeconfigPath, "kubeconfig", "k", clientcmd.RecommendedHomeFile, "The kubeconfig to use for cluster access.")
109114
flags.StringVarP(&cfg.LabelSelector, "selector", "l", "", "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
110115
flags.StringVar(&cfg.FieldSelector, "field-selector", "", "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.")
116+
flags.BoolVarP(&cfg.CompactOutput, "compact", "c", false, "Print JSON in compact format instead of pretty-printed output")
111117

112118
return c
113119
}

internal/discover/processor.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ import (
1313
"github.com/opdev/discover-workload/discovery"
1414
)
1515

16+
type NewManifestJSONProcessorFnOptions struct {
17+
CompactOutput bool
18+
}
19+
1620
// NewManifestJSONProcessorFn produces a ProcessingFunction that will write a
1721
// Manifest in JSON to out. This Processor finds all images from containers,
1822
// initContainers, and ephemeralContainers.
19-
func NewManifestJSONProcessorFn(out io.Writer) ProcessingFunction {
23+
func NewManifestJSONProcessorFn(out io.Writer, opts NewManifestJSONProcessorFnOptions) ProcessingFunction {
2024
return func(ctx context.Context, source <-chan *corev1.Pod, logger *slog.Logger) error {
2125
m := discovery.Manifest{}
2226

@@ -41,7 +45,14 @@ func NewManifestJSONProcessorFn(out io.Writer) ProcessingFunction {
4145
return nil
4246
}
4347

44-
manifestJSON, err := json.Marshal(m)
48+
var manifestJSON []byte
49+
var err error
50+
if opts.CompactOutput {
51+
manifestJSON, err = json.Marshal(m)
52+
} else {
53+
manifestJSON, err = json.MarshalIndent(m, "", " ")
54+
}
55+
4556
if err != nil {
4657
logger.Error("unable to convert output manifest to JSON", "errMsg", err)
4758
return err

internal/discover/processor_test.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/opdev/discover-workload/discovery"
1414
)
1515

16-
func TestManifestInsert(t *testing.T) {
16+
func TestManifestAppend(t *testing.T) {
1717
t.Parallel()
1818
testcases := map[string]struct {
1919
ctx context.Context
@@ -391,6 +391,7 @@ func TestManifestJSONProcessor(t *testing.T) {
391391
testcases := map[string]struct {
392392
ctx context.Context
393393
input []corev1.Pod
394+
compact bool
394395
expected []byte
395396
}{
396397
"initContainer only": {
@@ -408,7 +409,26 @@ func TestManifestJSONProcessor(t *testing.T) {
408409
},
409410
},
410411
},
411-
expected: []byte("{\"DiscoveredImages\":[{\"Image\":\"example.com/namespace/image:0.0.1\",\"Containers\":[{\"Name\":\"init-cname\",\"Type\":\"InitContainer\",\"Pod\":{\"Name\":\"init-podname\",\"Namespace\":\"\"}}]}]}\n"),
412+
compact: false,
413+
expected: []byte("{\n \"DiscoveredImages\": [\n {\n \"Image\": \"example.com/namespace/image:0.0.1\",\n \"Containers\": [\n {\n \"Name\": \"init-cname\",\n \"Type\": \"InitContainer\",\n \"Pod\": {\n \"Name\": \"init-podname\",\n \"Namespace\": \"\"\n }\n }\n ]\n }\n ]\n}\n"),
414+
},
415+
"with raw printed JSON": {
416+
ctx: context.TODO(),
417+
input: []corev1.Pod{
418+
{
419+
ObjectMeta: metav1.ObjectMeta{Name: "podname"},
420+
Spec: corev1.PodSpec{
421+
Containers: []corev1.Container{
422+
{
423+
Name: "cname",
424+
Image: "example.com/namespace/image:0.0.1",
425+
},
426+
},
427+
},
428+
},
429+
},
430+
compact: true,
431+
expected: []byte("{\"DiscoveredImages\":[{\"Image\":\"example.com/namespace/image:0.0.1\",\"Containers\":[{\"Name\":\"cname\",\"Type\":\"Container\",\"Pod\":{\"Name\":\"podname\",\"Namespace\":\"\"}}]}]}\n"),
412432
},
413433
}
414434

@@ -417,7 +437,10 @@ func TestManifestJSONProcessor(t *testing.T) {
417437
t.Run(description, func(t *testing.T) {
418438
t.Parallel()
419439
buffer := bytes.NewBuffer([]byte{})
420-
fn := NewManifestJSONProcessorFn(buffer)
440+
opts := NewManifestJSONProcessorFnOptions{
441+
CompactOutput: tc.compact,
442+
}
443+
fn := NewManifestJSONProcessorFn(buffer, opts)
421444

422445
ch := make(chan *corev1.Pod)
423446

0 commit comments

Comments
 (0)