-
Notifications
You must be signed in to change notification settings - Fork 53
/
bundle.go
91 lines (76 loc) · 3.06 KB
/
bundle.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package variablesources
import (
"fmt"
"sort"
"github.com/operator-framework/deppy/pkg/deppy"
"k8s.io/apimachinery/pkg/util/sets"
"github.com/operator-framework/operator-controller/internal/catalogmetadata"
catalogfilter "github.com/operator-framework/operator-controller/internal/catalogmetadata/filter"
catalogsort "github.com/operator-framework/operator-controller/internal/catalogmetadata/sort"
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
)
func MakeBundleVariables(
allBundles []*catalogmetadata.Bundle,
requiredPackages []*olmvariables.RequiredPackageVariable,
installedPackages []*olmvariables.InstalledPackageVariable,
) ([]*olmvariables.BundleVariable, error) {
var bundleQueue []*catalogmetadata.Bundle
for _, variable := range requiredPackages {
bundleQueue = append(bundleQueue, variable.Bundles()...)
}
for _, variable := range installedPackages {
bundleQueue = append(bundleQueue, variable.Bundles()...)
}
// build bundle and dependency variables
var result []*olmvariables.BundleVariable
visited := sets.Set[deppy.Identifier]{}
for len(bundleQueue) > 0 {
// pop head of queue
var head *catalogmetadata.Bundle
head, bundleQueue = bundleQueue[0], bundleQueue[1:]
id := olmvariables.BundleVariableID(head)
// ignore bundles that have already been processed
if visited.Has(id) {
continue
}
visited.Insert(id)
// get bundle dependencies
dependencies, err := filterBundleDependencies(allBundles, head)
if err != nil {
return nil, fmt.Errorf("could not determine dependencies for bundle %q from package %q in catalog %q: %s", head.Name, head.Package, head.CatalogName, err)
}
// add bundle dependencies to queue for processing
bundleQueue = append(bundleQueue, dependencies...)
// create variable
result = append(result, olmvariables.NewBundleVariable(head, dependencies))
}
return result, nil
}
func filterBundleDependencies(allBundles []*catalogmetadata.Bundle, bundle *catalogmetadata.Bundle) ([]*catalogmetadata.Bundle, error) {
var dependencies []*catalogmetadata.Bundle
added := sets.Set[deppy.Identifier]{}
// gather required package dependencies
requiredPackages, _ := bundle.RequiredPackages()
for _, requiredPackage := range requiredPackages {
packageDependencyBundles := catalogfilter.Filter(allBundles, catalogfilter.And(
catalogfilter.WithPackageName(requiredPackage.PackageName),
catalogfilter.InBlangSemverRange(requiredPackage.SemverRange),
))
if len(packageDependencyBundles) == 0 {
return nil, fmt.Errorf("no bundles found matching required package %q in range %q", requiredPackage.PackageName, requiredPackage.VersionRange)
}
for i := 0; i < len(packageDependencyBundles); i++ {
bundle := packageDependencyBundles[i]
id := olmvariables.BundleVariableID(bundle)
if !added.Has(id) {
dependencies = append(dependencies, bundle)
added.Insert(id)
}
}
}
// sort bundles in version order
sort.SliceStable(dependencies, func(i, j int) bool {
return catalogsort.ByVersion(dependencies[i], dependencies[j])
})
return dependencies, nil
}