Skip to content

Commit f204fa3

Browse files
authored
[resolution pt.2] required package variable source (#96)
* add bundle entity * add required package variable source Signed-off-by: perdasilva <[email protected]>
1 parent fffa59b commit f204fa3

File tree

3 files changed

+196
-1
lines changed

3 files changed

+196
-1
lines changed

internal/resolution/variable_sources/entity/bundle_entity_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import (
77
. "github.com/onsi/ginkgo/v2"
88
. "github.com/onsi/gomega"
99
"github.com/operator-framework/deppy/pkg/deppy/input"
10-
olmentity "github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
1110
"github.com/operator-framework/operator-registry/alpha/property"
11+
12+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
1213
)
1314

1415
func TestBundleEntity(t *testing.T) {
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package required_package
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/operator-framework/deppy/pkg/deppy"
8+
"github.com/operator-framework/deppy/pkg/deppy/constraint"
9+
"github.com/operator-framework/deppy/pkg/deppy/input"
10+
11+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
12+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/utils/predicates"
13+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/utils/sort"
14+
)
15+
16+
type RequiredPackageVariable struct {
17+
*input.SimpleVariable
18+
bundleEntities []*olmentity.BundleEntity
19+
}
20+
21+
func (r *RequiredPackageVariable) BundleEntities() []*olmentity.BundleEntity {
22+
return r.bundleEntities
23+
}
24+
25+
func NewRequiredPackageVariable(packageName string, bundleEntities []*olmentity.BundleEntity) *RequiredPackageVariable {
26+
id := deppy.IdentifierFromString(fmt.Sprintf("required package %s", packageName))
27+
var entityIDs []deppy.Identifier
28+
for _, bundle := range bundleEntities {
29+
entityIDs = append(entityIDs, bundle.ID)
30+
}
31+
return &RequiredPackageVariable{
32+
SimpleVariable: input.NewSimpleVariable(id, constraint.Mandatory(), constraint.Dependency(entityIDs...)),
33+
bundleEntities: bundleEntities,
34+
}
35+
}
36+
37+
var _ input.VariableSource = &RequiredPackageVariableSource{}
38+
39+
type RequiredPackageVariableSource struct {
40+
packageName string
41+
}
42+
43+
func NewRequiredPackage(packageName string) *RequiredPackageVariableSource {
44+
return &RequiredPackageVariableSource{
45+
packageName: packageName,
46+
}
47+
}
48+
49+
func (r *RequiredPackageVariableSource) GetVariables(ctx context.Context, entitySource input.EntitySource) ([]deppy.Variable, error) {
50+
resultSet, err := entitySource.Filter(ctx, predicates.WithPackageName(r.packageName))
51+
if err != nil {
52+
return nil, err
53+
}
54+
if len(resultSet) == 0 {
55+
return nil, fmt.Errorf("package '%s' not found", r.packageName)
56+
}
57+
resultSet = resultSet.Sort(sort.ByChannelAndVersion)
58+
var bundleEntities []*olmentity.BundleEntity
59+
for i := 0; i < len(resultSet); i++ {
60+
bundleEntities = append(bundleEntities, olmentity.NewBundleEntity(&resultSet[i]))
61+
}
62+
return []deppy.Variable{
63+
NewRequiredPackageVariable(r.packageName, bundleEntities),
64+
}, nil
65+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package required_package_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
. "github.com/onsi/ginkgo/v2"
9+
. "github.com/onsi/gomega"
10+
"github.com/operator-framework/deppy/pkg/deppy"
11+
"github.com/operator-framework/deppy/pkg/deppy/input"
12+
"github.com/operator-framework/operator-registry/alpha/property"
13+
14+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
15+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/required_package"
16+
)
17+
18+
func TestRequiredPackage(t *testing.T) {
19+
RegisterFailHandler(Fail)
20+
RunSpecs(t, "RequiredPackageVariableSource Suite")
21+
}
22+
23+
var _ = Describe("RequiredPackageVariable", func() {
24+
var (
25+
rpv *required_package.RequiredPackageVariable
26+
packageName string
27+
bundleEntities []*olmentity.BundleEntity
28+
)
29+
30+
BeforeEach(func() {
31+
packageName = "test-package"
32+
bundleEntities = []*olmentity.BundleEntity{
33+
olmentity.NewBundleEntity(input.NewEntity("bundle-1", map[string]string{
34+
property.TypePackage: `{"packageName": "test-package", "version": "1.0.0"}`,
35+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
36+
})),
37+
olmentity.NewBundleEntity(input.NewEntity("bundle-2", map[string]string{
38+
property.TypePackage: `{"packageName": "test-package", "version": "2.0.0"}`,
39+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
40+
})),
41+
olmentity.NewBundleEntity(input.NewEntity("bundle-3", map[string]string{
42+
property.TypePackage: `{"packageName": "test-package", "version": "3.0.0"}`,
43+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
44+
})),
45+
}
46+
rpv = required_package.NewRequiredPackageVariable(packageName, bundleEntities)
47+
})
48+
49+
It("should return the correct package name", func() {
50+
Expect(rpv.Identifier()).To(Equal(deppy.IdentifierFromString(fmt.Sprintf("required package %s", packageName))))
51+
})
52+
53+
It("should return the correct bundle entities", func() {
54+
Expect(rpv.BundleEntities()).To(Equal(bundleEntities))
55+
})
56+
57+
It("should contain both mandatory and dependency constraints", func() {
58+
// TODO: add this test once https://github.com/operator-framework/deppy/pull/85 gets merged
59+
// then we'll be able to inspect constraint types
60+
})
61+
})
62+
63+
var _ = Describe("RequiredPackageVariableSource", func() {
64+
var (
65+
rpvs *required_package.RequiredPackageVariableSource
66+
packageName string
67+
mockEntitySource input.EntitySource
68+
)
69+
70+
BeforeEach(func() {
71+
packageName = "test-package"
72+
rpvs = required_package.NewRequiredPackage(packageName)
73+
mockEntitySource = input.NewCacheQuerier(map[deppy.Identifier]input.Entity{
74+
"bundle-1": *input.NewEntity("bundle-1", map[string]string{
75+
property.TypePackage: `{"packageName": "test-package", "version": "1.0.0"}`,
76+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
77+
}),
78+
"bundle-2": *input.NewEntity("bundle-2", map[string]string{
79+
property.TypePackage: `{"packageName": "test-package", "version": "3.0.0"}`,
80+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
81+
}),
82+
"bundle-3": *input.NewEntity("bundle-3", map[string]string{
83+
property.TypePackage: `{"packageName": "test-package", "version": "2.0.0"}`,
84+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
85+
}),
86+
87+
// add some bundles from a different package
88+
"bundle-4": *input.NewEntity("bundle-4", map[string]string{
89+
property.TypePackage: `{"packageName": "test-package-2", "version": "1.0.0"}`,
90+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
91+
}),
92+
"bundle-5": *input.NewEntity("bundle-5", map[string]string{
93+
property.TypePackage: `{"packageName": "test-package-2", "version": "1.0.0"}`,
94+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
95+
}),
96+
})
97+
})
98+
99+
It("should return the correct package variable", func() {
100+
variables, err := rpvs.GetVariables(context.TODO(), mockEntitySource)
101+
Expect(err).NotTo(HaveOccurred())
102+
Expect(len(variables)).To(Equal(1))
103+
reqPackageVar, ok := variables[0].(*required_package.RequiredPackageVariable)
104+
Expect(ok).To(BeTrue())
105+
Expect(reqPackageVar.Identifier()).To(Equal(deppy.IdentifierFromString(fmt.Sprintf("required package %s", packageName))))
106+
107+
// ensure bundle entities are in version order
108+
Expect(reqPackageVar.BundleEntities()).To(Equal([]*olmentity.BundleEntity{
109+
olmentity.NewBundleEntity(input.NewEntity("bundle-2", map[string]string{
110+
property.TypePackage: `{"packageName": "test-package", "version": "3.0.0"}`,
111+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
112+
})),
113+
olmentity.NewBundleEntity(input.NewEntity("bundle-3", map[string]string{
114+
property.TypePackage: `{"packageName": "test-package", "version": "2.0.0"}`,
115+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
116+
})),
117+
olmentity.NewBundleEntity(input.NewEntity("bundle-1", map[string]string{
118+
property.TypePackage: `{"packageName": "test-package", "version": "1.0.0"}`,
119+
property.TypeChannel: `{"channelName":"stable","priority":0}`})),
120+
}))
121+
})
122+
123+
It("should return an error if package not found", func() {
124+
mockEntitySource := input.NewCacheQuerier(map[deppy.Identifier]input.Entity{})
125+
_, err := rpvs.GetVariables(context.TODO(), mockEntitySource)
126+
Expect(err).To(HaveOccurred())
127+
Expect(err.Error()).To(Equal("package 'test-package' not found"))
128+
})
129+
})

0 commit comments

Comments
 (0)