-
Notifications
You must be signed in to change notification settings - Fork 48
/
crd_constraints.go
76 lines (64 loc) · 2.99 KB
/
crd_constraints.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package variablesources
import (
"context"
"fmt"
"github.com/operator-framework/deppy/pkg/deppy"
"github.com/operator-framework/deppy/pkg/deppy/input"
"github.com/operator-framework/operator-controller/internal/catalogmetadata"
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
)
var _ input.VariableSource = &CRDUniquenessConstraintsVariableSource{}
// CRDUniquenessConstraintsVariableSource produces variables that constraint the solution to
// 1. at most 1 bundle per package
// 2. at most 1 bundle per gvk (provided by the bundle)
// these variables guarantee that no two operators provide the same gvk and no two version of
// the same operator are running at the same time.
// This variable source does not itself reach out to catalog metadata. It produces its variables
// by searching for BundleVariables that are produced by its 'inputVariableSource' and working out
// which bundles correspond to which package and which gvks are provided by which bundle
type CRDUniquenessConstraintsVariableSource struct {
inputVariableSource input.VariableSource
}
// NewCRDUniquenessConstraintsVariableSource creates a new instance of the CRDUniquenessConstraintsVariableSource.
// its purpose if to provide variables with constraints that restrict the solutions to bundle sets where
// no two bundles come from the same package and not two bundles provide the same gvk
func NewCRDUniquenessConstraintsVariableSource(inputVariableSource input.VariableSource) *CRDUniquenessConstraintsVariableSource {
return &CRDUniquenessConstraintsVariableSource{
inputVariableSource: inputVariableSource,
}
}
func (g *CRDUniquenessConstraintsVariableSource) GetVariables(ctx context.Context) ([]deppy.Variable, error) {
variables, err := g.inputVariableSource.GetVariables(ctx)
if err != nil {
return nil, err
}
// todo(perdasilva): better handle cases where a provided gvk is not found
// not all packages will necessarily export a CRD
pkgToBundleMap := map[string]map[deppy.Identifier]struct{}{}
for _, variable := range variables {
switch v := variable.(type) {
case *olmvariables.BundleVariable:
bundles := []*catalogmetadata.Bundle{v.Bundle()}
bundles = append(bundles, v.Dependencies()...)
for _, bundle := range bundles {
id := olmvariables.BundleVariableID(bundle)
// get bundleID package and update map
packageName := bundle.Package
if _, ok := pkgToBundleMap[packageName]; !ok {
pkgToBundleMap[packageName] = map[deppy.Identifier]struct{}{}
}
pkgToBundleMap[packageName][id] = struct{}{}
}
}
}
// create global constraint variables
for packageName, bundleIDMap := range pkgToBundleMap {
var bundleIDs []deppy.Identifier
for bundleID := range bundleIDMap {
bundleIDs = append(bundleIDs, bundleID)
}
varID := deppy.IdentifierFromString(fmt.Sprintf("%s package uniqueness", packageName))
variables = append(variables, olmvariables.NewBundleUniquenessVariable(varID, bundleIDs...))
}
return variables, nil
}