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

Commit f41b642

Browse files
committed
De-duplicate images in final discovery output
This change modifies DiscoveredImage to store the name/type of one or more containers which use the image, and it also adds a new appendToManifest function, which acts similarly to the built-in append except duplicate entries are merged into the existing DiscoveredImage instance in the list. Signed-off-by: Caleb Xu <caxu@redhat.com>
1 parent 30d6c29 commit f41b642

3 files changed

Lines changed: 539 additions & 42 deletions

File tree

discovery/discovery.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,42 @@ type Manifest struct {
55
DiscoveredImages []DiscoveredImage
66
}
77

8-
// DiscoveredImage is a container image that' been discovered based on the
9-
// workload watchers.
8+
// DiscoveredImage is a container image which was discovered in one or more workloads.
109
type DiscoveredImage struct {
11-
// PodName is the pod.metadata.name value where the image was discovered.
12-
PodName string
13-
// ContainerName represents the container in the pod that had the image.
14-
ContainerName string
1510
// Image is a fully qualified container image name and tag or digest.
1611
Image string
12+
13+
// Containers is a list of DiscoveredContainer objects which are using
14+
// the discovered image.
15+
Containers []DiscoveredContainer
16+
}
17+
18+
// DiscoveredContainer is a container which was observed during the discovery process.
19+
type DiscoveredContainer struct {
20+
// Name is the name of a container in a pod.
21+
Name string
22+
23+
// Type is the ContainerType of the container in its pod.
24+
Type ContainerType
25+
26+
// Pod is the DiscoveredPod which this container is a part of.
27+
Pod DiscoveredPod
28+
}
29+
30+
// ContainerType is the type of a container in a pod.
31+
type ContainerType = string
32+
33+
const (
34+
ContainerTypeStandard ContainerType = "Container"
35+
ContainerTypeInit ContainerType = "InitContainer"
36+
ContainerTypeEphemeral ContainerType = "EphemeralContainer"
37+
)
38+
39+
// DiscoveredPod is a pod that contains a discovered image.
40+
type DiscoveredPod struct {
41+
// Name is the pod.metadata.name value where the image was discovered.
42+
Name string
43+
44+
// Namespace is the pod.metadata.namespace value of the pod.
45+
Namespace string
1746
}

internal/discover/processor.go

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"log/slog"
9+
"slices"
910

1011
corev1 "k8s.io/api/core/v1"
1112

@@ -28,7 +29,7 @@ func NewManifestJSONProcessorFn(out io.Writer) ProcessingFunction {
2829
continueRunning = false
2930
break
3031
}
31-
m.DiscoveredImages = append(m.DiscoveredImages, processContainers(p, logger)...)
32+
m = appendToManifest(m, processContainers(p, logger)...)
3233
case <-ctx.Done():
3334
logger.Debug("processorFn completing because the context completed")
3435
continueRunning = false
@@ -64,9 +65,17 @@ func processContainers(
6465
found = append(
6566
found,
6667
discovery.DiscoveredImage{
67-
PodName: p.Name,
68-
ContainerName: c.Name,
69-
Image: c.Image,
68+
Image: c.Image,
69+
Containers: []discovery.DiscoveredContainer{
70+
{
71+
Name: c.Name,
72+
Type: discovery.ContainerTypeStandard,
73+
Pod: discovery.DiscoveredPod{
74+
Name: p.Name,
75+
Namespace: p.Namespace,
76+
},
77+
},
78+
},
7079
},
7180
)
7281
}
@@ -76,9 +85,17 @@ func processContainers(
7685
found = append(
7786
found,
7887
discovery.DiscoveredImage{
79-
PodName: p.Name,
80-
ContainerName: c.Name,
81-
Image: c.Image,
88+
Image: c.Image,
89+
Containers: []discovery.DiscoveredContainer{
90+
{
91+
Name: c.Name,
92+
Type: discovery.ContainerTypeInit,
93+
Pod: discovery.DiscoveredPod{
94+
Name: p.Name,
95+
Namespace: p.Namespace,
96+
},
97+
},
98+
},
8299
},
83100
)
84101
}
@@ -88,12 +105,45 @@ func processContainers(
88105
found = append(
89106
found,
90107
discovery.DiscoveredImage{
91-
PodName: p.Name,
92-
ContainerName: c.Name,
93-
Image: c.Image,
108+
Image: c.Image,
109+
Containers: []discovery.DiscoveredContainer{
110+
{
111+
Name: c.Name,
112+
Type: discovery.ContainerTypeEphemeral,
113+
Pod: discovery.DiscoveredPod{
114+
Name: p.Name,
115+
Namespace: p.Namespace,
116+
},
117+
},
118+
},
94119
},
95120
)
96121
}
97122

98123
return found
99124
}
125+
126+
func appendToManifest(m discovery.Manifest, images ...discovery.DiscoveredImage) discovery.Manifest {
127+
for _, image := range images {
128+
idx := slices.IndexFunc(m.DiscoveredImages, func(i discovery.DiscoveredImage) bool {
129+
return i.Image == image.Image
130+
})
131+
132+
if idx == -1 {
133+
m.DiscoveredImages = append(m.DiscoveredImages, image)
134+
continue
135+
}
136+
137+
for _, container := range image.Containers {
138+
if !slices.Contains(m.DiscoveredImages[idx].Containers, container) {
139+
m.DiscoveredImages[idx].Containers = append(m.DiscoveredImages[idx].Containers, container)
140+
}
141+
}
142+
}
143+
144+
return m
145+
}
146+
147+
func imagesEqual(i1, i2 discovery.DiscoveredImage) bool {
148+
return i1.Image == i2.Image && slices.Equal(i1.Containers, i2.Containers)
149+
}

0 commit comments

Comments
 (0)