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

Commit 54ddc0c

Browse files
authored
Add support for updated discovery.json (#33)
Signed-off-by: Jose R. Gonzalez <komish@flutes.dev>
1 parent 15e6920 commit 54ddc0c

File tree

6 files changed

+122
-13
lines changed

6 files changed

+122
-13
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/invopop/jsonschema v0.13.0
88
github.com/onsi/ginkgo/v2 v2.23.4
99
github.com/onsi/gomega v1.37.0
10-
github.com/opdev/discover-workload v0.0.0-20250115205614-3233d42da6d9
10+
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625
1111
github.com/spf13/cobra v1.9.1
1212
sigs.k8s.io/yaml v1.4.0
1313
)

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus
3535
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
3636
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
3737
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
38-
github.com/opdev/discover-workload v0.0.0-20250115205614-3233d42da6d9 h1:sLy7Kdnp5w+0GVQ6rYjLTpGR+kUCarfFnPcolLqJTKo=
39-
github.com/opdev/discover-workload v0.0.0-20250115205614-3233d42da6d9/go.mod h1:pYjtJEWZgLGKOM1/4aCxHVf297u00qJN/KMNN9uWMtM=
38+
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625 h1:kIvS4Q0WQJOg/TXGr7Web+krA9SZsINe8CUZ27zoF98=
39+
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625/go.mod h1:Evlxr5q2psdSnx1Fdf0WJouLvcXlGyETN5hdaDLh8Fo=
4040
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
4141
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
4242
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
{
22
"DiscoveredImages": [
33
{
4-
"PodName": "pod-1",
5-
"ContainerName": "container-1",
6-
"Image": "example.com/registry/namespace:tag"
4+
"Image": "example.com/registry/namespace:tag",
5+
"Containers": [
6+
{
7+
"Name": "container-1",
8+
"Type": "Container",
9+
"Pod": {
10+
"Name": "pod-1",
11+
"Namespace": "examplens"
12+
}
13+
}
14+
]
715
}
816
]
917
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package discovery
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
7+
discoverworkload "github.com/opdev/discover-workload/discovery"
8+
)
9+
10+
var _ = Describe("Discovery (internal)", func() {
11+
When("determining the most frequent container name in a container list", func() {
12+
var containers []discoverworkload.DiscoveredContainer
13+
14+
When("there one name present in the list is used more than onee", func() {
15+
BeforeEach(func() {
16+
containers = []discoverworkload.DiscoveredContainer{
17+
{Name: "container-1"},
18+
{Name: "container-1"},
19+
{Name: "container-2"},
20+
}
21+
})
22+
23+
It("should return the container name with the larger count", func() {
24+
actual, count, err := mostFrequentName(containers)
25+
Expect(err).ToNot(HaveOccurred())
26+
Expect(count).To(Equal(2))
27+
Expect(actual).To(Equal("container-1"))
28+
})
29+
})
30+
When("there are no containers", func() {
31+
BeforeEach(func() {
32+
containers = []discoverworkload.DiscoveredContainer{}
33+
})
34+
It("should return the expected error", func() {
35+
_, _, err := mostFrequentName(containers)
36+
Expect(err).To(MatchError(ErrNoContainers))
37+
})
38+
})
39+
40+
When("the containers input has malformed data", func() {
41+
BeforeEach(func() {
42+
containers = []discoverworkload.DiscoveredContainer{
43+
{Name: ""},
44+
}
45+
})
46+
It("should return the expected error", func() {
47+
_, _, err := mostFrequentName(containers)
48+
Expect(err).To(MatchError(ErrCountingContainerNameOccurrences))
49+
})
50+
})
51+
})
52+
})

internal/discovery/discovery.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ package discovery
66
import (
77
"errors"
88
"fmt"
9+
"maps"
910

1011
"github.com/opdev/discover-workload/discovery"
1112

1213
"github.com/opdev/productctl/internal/resource"
1314
)
1415

1516
var (
16-
ErrDuplicateComponentName = errors.New("duplicate component name")
17-
ErrNoImagesDiscovered = errors.New("no images found in discovery manifest")
17+
ErrDuplicateComponentName = errors.New("duplicate component name")
18+
ErrNoImagesDiscovered = errors.New("no images found in discovery manifest")
19+
ErrCountingContainerNameOccurrences = errors.New("failed counting container names")
20+
ErrNoContainers = errors.New("no containers in entry for image")
1821
)
1922

2023
// ComponentsFromDiscoveryManifest converts discovered workloads into Component
@@ -30,13 +33,17 @@ func ComponentsFromDiscoveryManifest(manifest discovery.Manifest) ([]*resource.C
3033

3134
components := make([]*resource.Component, 0, len(manifest.DiscoveredImages))
3235
for _, image := range manifest.DiscoveredImages {
36+
mostCommonContainerName, _, err := mostFrequentName(image.Containers)
37+
if err != nil {
38+
return nil, err
39+
}
3340
c := resource.Component{
3441
Container: &resource.ContainerComponent{
3542
DistributionMethod: resource.ContainerDistributionExternal,
3643
OSContentType: resource.ContentTypeUBI,
3744
Type: resource.ContainerTypeContainer,
3845
},
39-
Name: image.ContainerName,
46+
Name: mostCommonContainerName,
4047
ProjectStatus: resource.ProjectStatusActive,
4148
Type: resource.ComponentTypeContainer,
4249
}
@@ -52,3 +59,37 @@ func ComponentsFromDiscoveryManifest(manifest discovery.Manifest) ([]*resource.C
5259

5360
return components, nil
5461
}
62+
63+
// mostFrequentName returns the most frequent discovered container name for
64+
// items in containers, with a goal of providing the user with a likely name to
65+
// use for a certification component for the specified container. Returned is
66+
// the actual container name and how many times it was found in the input data.
67+
func mostFrequentName(containers []discovery.DiscoveredContainer) (string, int, error) {
68+
if len(containers) == 0 {
69+
return "", 0, ErrNoContainers
70+
}
71+
72+
count := map[string]int{}
73+
for _, c := range containers {
74+
if _, exists := count[c.Name]; !exists {
75+
count[c.Name] = 0
76+
}
77+
count[c.Name] += 1
78+
}
79+
80+
keys := maps.Keys(count)
81+
var mostFrequent string
82+
occurrences := 0
83+
for key := range keys {
84+
if count[key] > occurrences {
85+
mostFrequent = key
86+
occurrences = count[key]
87+
}
88+
}
89+
90+
if mostFrequent == "" || occurrences == 0 {
91+
return "", 0, ErrCountingContainerNameOccurrences
92+
}
93+
94+
return mostFrequent, occurrences, nil
95+
}

internal/discovery/discovery_test.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ import (
1111

1212
var _ = Describe("Discovery", func() {
1313
When("converting workload discovery manifest to component resources", func() {
14+
It("should return an error if there are images with malformed container data", func() {
15+
_, err := libdiscovery.ComponentsFromDiscoveryManifest(discovery.Manifest{
16+
DiscoveredImages: []discovery.DiscoveredImage{
17+
{Containers: []discovery.DiscoveredContainer{}},
18+
},
19+
})
20+
Expect(err).To(MatchError(libdiscovery.ErrNoContainers))
21+
})
1422
It("should return an error when discovery manifest contains no entries", func() {
1523
_, err := libdiscovery.ComponentsFromDiscoveryManifest(discovery.Manifest{})
1624
Expect(err).To(MatchError(libdiscovery.ErrNoImagesDiscovered))
@@ -19,8 +27,8 @@ var _ = Describe("Discovery", func() {
1927
It("should return an error for duplicate component names", func() {
2028
manifestWithDuplicateNames := discovery.Manifest{
2129
DiscoveredImages: []discovery.DiscoveredImage{
22-
{ContainerName: "component1"},
23-
{ContainerName: "component1"},
30+
{Containers: []discovery.DiscoveredContainer{{Name: "component1"}}},
31+
{Containers: []discovery.DiscoveredContainer{{Name: "component1"}}},
2432
},
2533
}
2634
_, err := libdiscovery.ComponentsFromDiscoveryManifest(manifestWithDuplicateNames)
@@ -30,8 +38,8 @@ var _ = Describe("Discovery", func() {
3038
It("should return components for valid manifest", func() {
3139
manifest := discovery.Manifest{
3240
DiscoveredImages: []discovery.DiscoveredImage{
33-
{ContainerName: "component1"},
34-
{ContainerName: "component2"},
41+
{Containers: []discovery.DiscoveredContainer{{Name: "component1"}}},
42+
{Containers: []discovery.DiscoveredContainer{{Name: "component2"}}},
3543
},
3644
}
3745
components, err := libdiscovery.ComponentsFromDiscoveryManifest(manifest)

0 commit comments

Comments
 (0)