Skip to content

Commit ebc5cfe

Browse files
Mikalai Radchukm1kola
authored andcommitted
Split variables and variable sources
Signed-off-by: Mikalai Radchuk <[email protected]>
1 parent a747143 commit ebc5cfe

13 files changed

+281
-209
lines changed

internal/controllers/operator_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import (
4242
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
4343
"github.com/operator-framework/operator-controller/internal/controllers/validators"
4444
"github.com/operator-framework/operator-controller/internal/resolution/entities"
45-
"github.com/operator-framework/operator-controller/internal/resolution/variablesources"
45+
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
4646
)
4747

4848
// OperatorReconciler reconciles a Operator object
@@ -247,7 +247,7 @@ func mapBDStatusToInstalledCondition(existingTypedBundleDeployment *rukpakv1alph
247247
func (r *OperatorReconciler) getBundleEntityFromSolution(solution *solver.Solution, packageName string) (*entities.BundleEntity, error) {
248248
for _, variable := range solution.SelectedVariables() {
249249
switch v := variable.(type) {
250-
case *variablesources.BundleVariable:
250+
case *olmvariables.BundleVariable:
251251
entityPkgName, err := v.BundleEntity().PackageName()
252252
if err != nil {
253253
return nil, err
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package variables
2+
3+
import (
4+
"github.com/operator-framework/deppy/pkg/deppy"
5+
"github.com/operator-framework/deppy/pkg/deppy/constraint"
6+
"github.com/operator-framework/deppy/pkg/deppy/input"
7+
8+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
9+
)
10+
11+
var _ deppy.Variable = &BundleVariable{}
12+
13+
type BundleVariable struct {
14+
*input.SimpleVariable
15+
bundleEntity *olmentity.BundleEntity
16+
dependencies []*olmentity.BundleEntity
17+
}
18+
19+
func (b *BundleVariable) BundleEntity() *olmentity.BundleEntity {
20+
return b.bundleEntity
21+
}
22+
23+
func (b *BundleVariable) Dependencies() []*olmentity.BundleEntity {
24+
return b.dependencies
25+
}
26+
27+
func NewBundleVariable(bundleEntity *olmentity.BundleEntity, dependencyBundleEntities []*olmentity.BundleEntity) *BundleVariable {
28+
dependencyIDs := make([]deppy.Identifier, 0, len(dependencyBundleEntities))
29+
for _, bundle := range dependencyBundleEntities {
30+
dependencyIDs = append(dependencyIDs, bundle.ID)
31+
}
32+
var constraints []deppy.Constraint
33+
if len(dependencyIDs) > 0 {
34+
constraints = append(constraints, constraint.Dependency(dependencyIDs...))
35+
}
36+
return &BundleVariable{
37+
SimpleVariable: input.NewSimpleVariable(bundleEntity.ID, constraints...),
38+
bundleEntity: bundleEntity,
39+
dependencies: dependencyBundleEntities,
40+
}
41+
}
42+
43+
var _ deppy.Variable = &BundleUniquenessVariable{}
44+
45+
type BundleUniquenessVariable struct {
46+
*input.SimpleVariable
47+
}
48+
49+
// NewBundleUniquenessVariable creates a new variable that instructs the resolver to choose at most a single bundle
50+
// from the input 'atMostID'. Examples:
51+
// 1. restrict the solution to at most a single bundle per package
52+
// 2. restrict the solution to at most a single bundler per provided gvk
53+
// this guarantees that no two operators provide the same gvk and no two version of the same operator are running at the same time
54+
func NewBundleUniquenessVariable(id deppy.Identifier, atMostIDs ...deppy.Identifier) *BundleUniquenessVariable {
55+
return &BundleUniquenessVariable{
56+
SimpleVariable: input.NewSimpleVariable(id, constraint.AtMost(1, atMostIDs...)),
57+
}
58+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package variables_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
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+
"github.com/operator-framework/operator-registry/alpha/property"
11+
12+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
13+
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
14+
)
15+
16+
var _ = Describe("BundleVariable", func() {
17+
var (
18+
bv *olmvariables.BundleVariable
19+
bundleEntity *olmentity.BundleEntity
20+
dependencies []*olmentity.BundleEntity
21+
)
22+
23+
BeforeEach(func() {
24+
bundleEntity = olmentity.NewBundleEntity(input.NewEntity("bundle-1", map[string]string{
25+
property.TypePackage: `{"packageName": "test-package", "version": "1.0.0"}`,
26+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
27+
}))
28+
dependencies = []*olmentity.BundleEntity{
29+
olmentity.NewBundleEntity(input.NewEntity("bundle-2", map[string]string{
30+
property.TypePackage: `{"packageName": "test-package-2", "version": "2.0.0"}`,
31+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
32+
})),
33+
olmentity.NewBundleEntity(input.NewEntity("bundle-3", map[string]string{
34+
property.TypePackage: `{"packageName": "test-package-3", "version": "2.0.0"}`,
35+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
36+
})),
37+
}
38+
bv = olmvariables.NewBundleVariable(bundleEntity, dependencies)
39+
})
40+
41+
It("should return the correct bundle entity", func() {
42+
Expect(bv.BundleEntity()).To(Equal(bundleEntity))
43+
})
44+
45+
It("should return the correct dependencies", func() {
46+
Expect(bv.Dependencies()).To(Equal(dependencies))
47+
})
48+
})
49+
50+
var _ = Describe("BundleUniquenessVariable", func() {
51+
var (
52+
id deppy.Identifier
53+
atMostIDs []deppy.Identifier
54+
globalConstraintVariable *olmvariables.BundleUniquenessVariable
55+
)
56+
57+
BeforeEach(func() {
58+
id = deppy.IdentifierFromString("test-id")
59+
atMostIDs = []deppy.Identifier{
60+
deppy.IdentifierFromString("test-at-most-id-1"),
61+
deppy.IdentifierFromString("test-at-most-id-2"),
62+
}
63+
globalConstraintVariable = olmvariables.NewBundleUniquenessVariable(id, atMostIDs...)
64+
})
65+
66+
It("should initialize a new global constraint variable", func() {
67+
Expect(globalConstraintVariable.Identifier()).To(Equal(id))
68+
Expect(globalConstraintVariable.Constraints()).To(Equal([]deppy.Constraint{constraint.AtMost(1, atMostIDs...)}))
69+
})
70+
})
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package variables
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/operator-framework/deppy/pkg/deppy"
7+
"github.com/operator-framework/deppy/pkg/deppy/constraint"
8+
"github.com/operator-framework/deppy/pkg/deppy/input"
9+
10+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
11+
)
12+
13+
var _ deppy.Variable = &RequiredPackageVariable{}
14+
15+
type RequiredPackageVariable struct {
16+
*input.SimpleVariable
17+
bundleEntities []*olmentity.BundleEntity
18+
}
19+
20+
func (r *RequiredPackageVariable) BundleEntities() []*olmentity.BundleEntity {
21+
return r.bundleEntities
22+
}
23+
24+
func NewRequiredPackageVariable(packageName string, bundleEntities []*olmentity.BundleEntity) *RequiredPackageVariable {
25+
id := deppy.IdentifierFromString(fmt.Sprintf("required package %s", packageName))
26+
entityIDs := make([]deppy.Identifier, 0, len(bundleEntities))
27+
for _, bundle := range bundleEntities {
28+
entityIDs = append(entityIDs, bundle.ID)
29+
}
30+
return &RequiredPackageVariable{
31+
SimpleVariable: input.NewSimpleVariable(id, constraint.Mandatory(), constraint.Dependency(entityIDs...)),
32+
bundleEntities: bundleEntities,
33+
}
34+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package variables_test
2+
3+
import (
4+
"fmt"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
9+
"github.com/operator-framework/deppy/pkg/deppy"
10+
"github.com/operator-framework/deppy/pkg/deppy/input"
11+
"github.com/operator-framework/operator-registry/alpha/property"
12+
13+
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
14+
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
15+
)
16+
17+
var _ = Describe("RequiredPackageVariable", func() {
18+
var (
19+
rpv *olmvariables.RequiredPackageVariable
20+
packageName string
21+
bundleEntities []*olmentity.BundleEntity
22+
)
23+
24+
BeforeEach(func() {
25+
packageName = "test-package"
26+
bundleEntities = []*olmentity.BundleEntity{
27+
olmentity.NewBundleEntity(input.NewEntity("bundle-1", map[string]string{
28+
property.TypePackage: `{"packageName": "test-package", "version": "1.0.0"}`,
29+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
30+
})),
31+
olmentity.NewBundleEntity(input.NewEntity("bundle-2", map[string]string{
32+
property.TypePackage: `{"packageName": "test-package", "version": "2.0.0"}`,
33+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
34+
})),
35+
olmentity.NewBundleEntity(input.NewEntity("bundle-3", map[string]string{
36+
property.TypePackage: `{"packageName": "test-package", "version": "3.0.0"}`,
37+
property.TypeChannel: `{"channelName":"stable","priority":0}`,
38+
})),
39+
}
40+
rpv = olmvariables.NewRequiredPackageVariable(packageName, bundleEntities)
41+
})
42+
43+
It("should return the correct package name", func() {
44+
Expect(rpv.Identifier()).To(Equal(deppy.IdentifierFromString(fmt.Sprintf("required package %s", packageName))))
45+
})
46+
47+
It("should return the correct bundle entities", func() {
48+
Expect(rpv.BundleEntities()).To(Equal(bundleEntities))
49+
})
50+
51+
It("should contain both mandatory and dependency constraints", func() {
52+
// TODO: add this test once https://github.com/operator-framework/deppy/pull/85 gets merged
53+
// then we'll be able to inspect constraint types
54+
})
55+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package variables_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestVariableSources(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Variables Suite")
13+
}

internal/resolution/variablesources/bundles_and_dependencies.go

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,14 @@ import (
77

88
"github.com/blang/semver/v4"
99
"github.com/operator-framework/deppy/pkg/deppy"
10-
"github.com/operator-framework/deppy/pkg/deppy/constraint"
1110
"github.com/operator-framework/deppy/pkg/deppy/input"
1211

1312
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
1413
"github.com/operator-framework/operator-controller/internal/resolution/util/predicates"
1514
entitysort "github.com/operator-framework/operator-controller/internal/resolution/util/sort"
15+
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
1616
)
1717

18-
type BundleVariable struct {
19-
*input.SimpleVariable
20-
bundleEntity *olmentity.BundleEntity
21-
dependencies []*olmentity.BundleEntity
22-
}
23-
24-
func (b *BundleVariable) BundleEntity() *olmentity.BundleEntity {
25-
return b.bundleEntity
26-
}
27-
28-
func (b *BundleVariable) Dependencies() []*olmentity.BundleEntity {
29-
return b.dependencies
30-
}
31-
32-
func NewBundleVariable(bundleEntity *olmentity.BundleEntity, dependencyBundleEntities []*olmentity.BundleEntity) *BundleVariable {
33-
dependencyIDs := make([]deppy.Identifier, 0, len(dependencyBundleEntities))
34-
for _, bundle := range dependencyBundleEntities {
35-
dependencyIDs = append(dependencyIDs, bundle.ID)
36-
}
37-
var constraints []deppy.Constraint
38-
if len(dependencyIDs) > 0 {
39-
constraints = append(constraints, constraint.Dependency(dependencyIDs...))
40-
}
41-
return &BundleVariable{
42-
SimpleVariable: input.NewSimpleVariable(bundleEntity.ID, constraints...),
43-
bundleEntity: bundleEntity,
44-
dependencies: dependencyBundleEntities,
45-
}
46-
}
47-
4818
var _ input.VariableSource = &BundlesAndDepsVariableSource{}
4919

5020
type BundlesAndDepsVariableSource struct {
@@ -73,7 +43,7 @@ func (b *BundlesAndDepsVariableSource) GetVariables(ctx context.Context, entityS
7343
var bundleEntityQueue []*olmentity.BundleEntity
7444
for _, variable := range variables {
7545
switch v := variable.(type) {
76-
case *RequiredPackageVariable:
46+
case *olmvariables.RequiredPackageVariable:
7747
bundleEntityQueue = append(bundleEntityQueue, v.BundleEntities()...)
7848
}
7949
}
@@ -101,7 +71,7 @@ func (b *BundlesAndDepsVariableSource) GetVariables(ctx context.Context, entityS
10171
bundleEntityQueue = append(bundleEntityQueue, dependencyEntityBundles...)
10272

10373
// create variable
104-
variables = append(variables, NewBundleVariable(head, dependencyEntityBundles))
74+
variables = append(variables, olmvariables.NewBundleVariable(head, dependencyEntityBundles))
10575
}
10676

10777
return variables, nil

0 commit comments

Comments
 (0)