Skip to content

Commit bdb76b4

Browse files
author
Mikalai Radchuk
committed
Resolution POC
Signed-off-by: Mikalai Radchuk <[email protected]>
1 parent d8de4f8 commit bdb76b4

File tree

4 files changed

+237
-28
lines changed

4 files changed

+237
-28
lines changed

cmd/resolutioncli/main.go

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
Copyright 2022.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"context"
21+
"errors"
22+
"flag"
23+
"fmt"
24+
"os"
25+
26+
"github.com/operator-framework/deppy/pkg/deppy/solver"
27+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
28+
"k8s.io/apimachinery/pkg/runtime"
29+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
30+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
31+
_ "k8s.io/client-go/plugin/pkg/client/auth"
32+
"sigs.k8s.io/controller-runtime/pkg/client"
33+
"sigs.k8s.io/controller-runtime/pkg/client/config"
34+
35+
catalogd "github.com/operator-framework/catalogd/pkg/apis/core/v1beta1"
36+
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
37+
"github.com/operator-framework/operator-controller/internal/resolution/entitysources"
38+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/bundles_and_dependencies"
39+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
40+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/olm"
41+
)
42+
43+
var (
44+
scheme = runtime.NewScheme()
45+
)
46+
47+
func init() {
48+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
49+
utilruntime.Must(operatorsv1alpha1.AddToScheme(scheme))
50+
utilruntime.Must(rukpakv1alpha1.AddToScheme(scheme))
51+
utilruntime.Must(catalogd.AddToScheme(scheme))
52+
}
53+
54+
func main() {
55+
var packageName string
56+
var packageVersion string
57+
var packageChannel string
58+
flag.StringVar(&packageName, "package-name", "", "Name of the package to resolve")
59+
flag.StringVar(&packageVersion, "package-version", "", "Version of the package")
60+
flag.StringVar(&packageChannel, "package-channel", "", "Channel of the package")
61+
flag.Parse()
62+
63+
if err := validateFlags(packageName); err != nil {
64+
fmt.Println(err)
65+
flag.Usage()
66+
os.Exit(1)
67+
}
68+
69+
err := run(packageName, packageVersion, packageChannel)
70+
if err != nil {
71+
fmt.Println(err)
72+
os.Exit(1)
73+
}
74+
}
75+
76+
func validateFlags(packageName string) error {
77+
if packageName == "" {
78+
return errors.New("missing required -package-name flag")
79+
}
80+
81+
return nil
82+
}
83+
84+
func run(packageName, packageVersion, packageChannel string) error {
85+
ctx := context.Background()
86+
client, err := client.New(config.GetConfigOrDie(), client.Options{Scheme: scheme})
87+
if err != nil {
88+
return fmt.Errorf("failed to create client: %w", err)
89+
}
90+
91+
packageVariableSource := NewPackageVariableSource(packageName, packageVersion, packageChannel)
92+
resolver := solver.NewDeppySolver(
93+
entitysources.NewCatalogdEntitySource(client),
94+
append(olm.NestedVariableSource{packageVariableSource}, olm.NewOLMVariableSource(client)...),
95+
)
96+
97+
bundleImage, err := resolve(ctx, resolver, packageName)
98+
if err != nil {
99+
return err
100+
}
101+
102+
fmt.Println(bundleImage)
103+
return nil
104+
}
105+
106+
func resolve(ctx context.Context, resolver *solver.DeppySolver, packageName string) (string, error) {
107+
solution, err := resolver.Solve(ctx)
108+
if err != nil {
109+
return "", err
110+
}
111+
112+
bundleEntity, err := getBundleEntityFromSolution(solution, packageName)
113+
if err != nil {
114+
return "", err
115+
}
116+
117+
// Get the bundle image reference for the bundle
118+
bundleImage, err := bundleEntity.BundlePath()
119+
if err != nil {
120+
return "", err
121+
}
122+
123+
return bundleImage, nil
124+
}
125+
126+
func getBundleEntityFromSolution(solution *solver.Solution, packageName string) (*entity.BundleEntity, error) {
127+
for _, variable := range solution.SelectedVariables() {
128+
switch v := variable.(type) {
129+
case *bundles_and_dependencies.BundleVariable:
130+
entityPkgName, err := v.BundleEntity().PackageName()
131+
if err != nil {
132+
return nil, err
133+
}
134+
if packageName == entityPkgName {
135+
return v.BundleEntity(), nil
136+
}
137+
}
138+
}
139+
return nil, fmt.Errorf("entity for package %q not found in solution", packageName)
140+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import (
4+
"github.com/operator-framework/deppy/pkg/deppy/input"
5+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/olm"
6+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/required_package"
7+
)
8+
9+
func NewPackageVariableSource(packageName, packageVersion, packageChannel string) func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
10+
return func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
11+
pkgSource, err := required_package.NewRequiredPackage(
12+
packageName,
13+
required_package.InVersionRange(packageVersion),
14+
required_package.InChannel(packageChannel),
15+
)
16+
if err != nil {
17+
return nil, err
18+
}
19+
20+
sliceSource := olm.SliceVariableSource{pkgSource}
21+
if inputVariableSource != nil {
22+
sliceSource = append(sliceSource, inputVariableSource)
23+
}
24+
25+
return sliceSource, nil
26+
}
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package olm
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"github.com/operator-framework/deppy/pkg/deppy"
8+
"github.com/operator-framework/deppy/pkg/deppy/input"
9+
)
10+
11+
var _ input.VariableSource = &SliceVariableSource{}
12+
var _ input.VariableSource = &NestedVariableSource{}
13+
14+
type NestedVariableSource []func(inputVariableSource input.VariableSource) (input.VariableSource, error)
15+
16+
func (s NestedVariableSource) GetVariables(ctx context.Context, entitySource input.EntitySource) ([]deppy.Variable, error) {
17+
if len(s) == 0 {
18+
return nil, errors.New("empty nested variable sources")
19+
}
20+
21+
var variableSource input.VariableSource
22+
var err error
23+
for _, constructor := range s {
24+
variableSource, err = constructor(variableSource)
25+
if err != nil {
26+
return nil, err
27+
}
28+
}
29+
30+
return variableSource.GetVariables(ctx, entitySource)
31+
}
32+
33+
type SliceVariableSource []input.VariableSource
34+
35+
func (s SliceVariableSource) GetVariables(ctx context.Context, entitySource input.EntitySource) ([]deppy.Variable, error) {
36+
var variables []deppy.Variable
37+
for _, variableSource := range s {
38+
inputVariables, err := variableSource.GetVariables(ctx, entitySource)
39+
if err != nil {
40+
return nil, err
41+
}
42+
variables = append(variables, inputVariables...)
43+
}
44+
45+
return variables, nil
46+
}

internal/resolution/variable_sources/olm/olm.go

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package olm
33
import (
44
"context"
55

6-
"github.com/operator-framework/deppy/pkg/deppy"
76
"github.com/operator-framework/deppy/pkg/deppy/input"
87
"sigs.k8s.io/controller-runtime/pkg/client"
98

@@ -13,47 +12,44 @@ import (
1312
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/required_package"
1413
)
1514

16-
var _ input.VariableSource = &OLMVariableSource{}
17-
18-
type OLMVariableSource struct {
19-
client client.Client
15+
func NewOLMVariableSource(cl client.Client) NestedVariableSource {
16+
return NestedVariableSource{
17+
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
18+
return NewOperatorVariableSource(cl, inputVariableSource)
19+
},
20+
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
21+
return bundles_and_dependencies.NewBundlesAndDepsVariableSource(inputVariableSource), nil
22+
},
23+
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
24+
return crd_constraints.NewCRDUniquenessConstraintsVariableSource(inputVariableSource), nil
25+
},
26+
}
2027
}
2128

22-
func NewOLMVariableSource(cl client.Client) *OLMVariableSource {
23-
return &OLMVariableSource{
24-
client: cl,
29+
func NewOperatorVariableSource(cl client.Client, inputVariableSource input.VariableSource) (SliceVariableSource, error) {
30+
inputVariableSources := SliceVariableSource{}
31+
if inputVariableSource != nil {
32+
inputVariableSources = append(inputVariableSources, inputVariableSource)
2533
}
26-
}
2734

28-
func (o *OLMVariableSource) GetVariables(ctx context.Context, entitySource input.EntitySource) ([]deppy.Variable, error) {
2935
operatorList := operatorsv1alpha1.OperatorList{}
30-
if err := o.client.List(ctx, &operatorList); err != nil {
36+
// TODO: Maybe?
37+
if err := cl.List(context.TODO(), &operatorList); err != nil {
3138
return nil, err
3239
}
3340

34-
var inputVariableSources []input.VariableSource
35-
3641
// build required package variable sources
3742
for _, operator := range operatorList.Items {
38-
rps, err := o.requiredPackageFromOperator(&operator)
43+
rps, err := required_package.NewRequiredPackage(
44+
operator.Spec.PackageName,
45+
required_package.InVersionRange(operator.Spec.Version),
46+
required_package.InChannel(operator.Spec.Channel),
47+
)
3948
if err != nil {
4049
return nil, err
4150
}
4251
inputVariableSources = append(inputVariableSources, rps)
4352
}
4453

45-
// build variable source pipeline
46-
variableSource := crd_constraints.NewCRDUniquenessConstraintsVariableSource(bundles_and_dependencies.NewBundlesAndDepsVariableSource(inputVariableSources...))
47-
return variableSource.GetVariables(ctx, entitySource)
48-
}
49-
50-
func (o *OLMVariableSource) requiredPackageFromOperator(operator *operatorsv1alpha1.Operator) (*required_package.RequiredPackageVariableSource, error) {
51-
var opts []required_package.RequiredPackageOption
52-
if operator.Spec.Version != "" {
53-
opts = append(opts, required_package.InVersionRange(operator.Spec.Version))
54-
}
55-
if operator.Spec.Channel != "" {
56-
opts = append(opts, required_package.InChannel(operator.Spec.Channel))
57-
}
58-
return required_package.NewRequiredPackage(operator.Spec.PackageName, opts...)
54+
return inputVariableSources, nil
5955
}

0 commit comments

Comments
 (0)