-
Notifications
You must be signed in to change notification settings - Fork 47
/
installed_package.go
84 lines (71 loc) · 3.25 KB
/
installed_package.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
package variablesources
import (
"context"
"fmt"
"github.com/operator-framework/deppy/pkg/deppy"
"github.com/operator-framework/deppy/pkg/deppy/input"
olmentity "github.com/operator-framework/operator-controller/internal/resolution/entities"
"github.com/operator-framework/operator-controller/internal/resolution/util/predicates"
"github.com/operator-framework/operator-controller/internal/resolution/util/sort"
"github.com/operator-framework/operator-controller/internal/resolution/variables"
)
var _ input.VariableSource = &InstalledPackageVariableSource{}
type InstalledPackageVariableSource struct {
bundleImage string
}
func (r *InstalledPackageVariableSource) GetVariables(ctx context.Context, entitySource input.EntitySource) ([]deppy.Variable, error) {
// find corresponding bundle entity for the installed content
resultSet, err := entitySource.Filter(ctx, predicates.WithBundleImage(r.bundleImage))
if err != nil {
return nil, err
}
if len(resultSet) == 0 {
return nil, r.notFoundError()
}
// sort by channel and version
// TODO: this is a bit of a hack and it assumes a well formed catalog.
// we currently have one entity per bundle/channel, i.e. if a bundle
// appears in multiple channels, we have multiple entities for it.
// this means that for a well formed catalog, we could get multiple entities
// back as a response to the filter above. For now, we sort by channel and version
// and take the top most element. Soon, we will add package and channel variables making
// this unnecessary.
// TODO: fast follow - we should check whether we are already supporting the channel attribute in the operator spec.
// if so, we should take the value from spec of the operator CR in the owner ref of the bundle deployment.
// If that channel is set, we need to update the filter above to filter by channel as well.
resultSet = resultSet.Sort(sort.ByChannelAndVersion)
installedBundle := olmentity.NewBundleEntity(&resultSet[0])
// now find the bundles that replace the installed bundle
// TODO: this algorithm does not yet consider skips and skipRange
// we simplify the process here by just searching for the bundle that replaces the installed bundle
packageName, err := installedBundle.PackageName()
if err != nil {
return nil, err
}
channelEntry, err := installedBundle.BundleChannelEntry()
if err != nil {
return nil, err
}
resultSet, err = entitySource.Filter(ctx, predicates.Replaces(channelEntry.Name))
if err != nil {
return nil, err
}
resultSet = resultSet.Sort(sort.ByChannelAndVersion)
upgradeEdges := make([]*olmentity.BundleEntity, 0, len(resultSet))
for i := range resultSet {
upgradeEdges = append(upgradeEdges, olmentity.NewBundleEntity(&resultSet[i]))
}
// you can always upgrade to yourself, i.e. not upgrade
upgradeEdges = append(upgradeEdges, installedBundle)
return []deppy.Variable{
variables.NewInstalledPackageVariable(packageName, upgradeEdges),
}, nil
}
func (r *InstalledPackageVariableSource) notFoundError() error {
return fmt.Errorf("bundleImage %q not found", r.bundleImage)
}
func NewInstalledPackageVariableSource(bundleImage string) (*InstalledPackageVariableSource, error) {
return &InstalledPackageVariableSource{
bundleImage: bundleImage,
}, nil
}