Skip to content

Commit

Permalink
Refactor controller variable source
Browse files Browse the repository at this point in the history
Signed-off-by: Mikalai Radchuk <mradchuk@redhat.com>
  • Loading branch information
m1kola committed Oct 31, 2023
1 parent 1ba218a commit 3267301
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 15 deletions.
88 changes: 73 additions & 15 deletions internal/controllers/variable_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,84 @@ limitations under the License.
package controllers

import (
"context"

"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/operator-framework/deppy/pkg/deppy/input"
"github.com/operator-framework/deppy/pkg/deppy"
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"

operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
"github.com/operator-framework/operator-controller/internal/catalogmetadata"
"github.com/operator-framework/operator-controller/internal/resolution/variablesources"
)

func NewVariableSource(cl client.Client, catalogClient variablesources.BundleProvider) variablesources.NestedVariableSource {
return variablesources.NestedVariableSource{
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
return variablesources.NewOperatorVariableSource(cl, catalogClient, inputVariableSource), nil
},
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
return variablesources.NewBundleDeploymentVariableSource(cl, catalogClient, inputVariableSource), nil
},
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
return variablesources.NewBundlesAndDepsVariableSource(catalogClient, inputVariableSource), nil
},
func(inputVariableSource input.VariableSource) (input.VariableSource, error) {
return variablesources.NewCRDUniquenessConstraintsVariableSource(inputVariableSource), nil
},
// BundleProvider provides the way to retrieve a list of Bundles from a source,
// generally from a catalog client of some kind.
type BundleProvider interface {
Bundles(ctx context.Context) ([]*catalogmetadata.Bundle, error)
}

type OLMVariableSource struct {
client client.Client
catalogClient BundleProvider
}

func NewVariableSource(cl client.Client, catalogClient BundleProvider) *OLMVariableSource {
return &OLMVariableSource{
client: cl,
catalogClient: catalogClient,
}
}

func (o *OLMVariableSource) GetVariables(ctx context.Context) ([]deppy.Variable, error) {
operatorList := operatorsv1alpha1.OperatorList{}
if err := o.client.List(ctx, &operatorList); err != nil {
return nil, err
}

bundleDeploymentList := rukpakv1alpha1.BundleDeploymentList{}
if err := o.client.List(ctx, &bundleDeploymentList); err != nil {
return nil, err
}

allBundles, err := o.catalogClient.Bundles(ctx)
if err != nil {
return nil, err
}

requiredPackages, err := variablesources.MakeRequiredPackageVariables(allBundles, operatorList.Items)
if err != nil {
return nil, err
}

installedPackages, err := variablesources.MakeInstalledPackageVariables(allBundles, bundleDeploymentList.Items)
if err != nil {
return nil, err
}

bundles, err := variablesources.MakeBundleVariables(allBundles, requiredPackages, installedPackages)
if err != nil {
return nil, err
}

bundleUniqueness, err := variablesources.MakeBundleUniquenessVariables(bundles)
if err != nil {
return nil, err
}

result := []deppy.Variable{}
for _, v := range requiredPackages {
result = append(result, v)
}
for _, v := range installedPackages {
result = append(result, v)
}
for _, v := range bundles {
result = append(result, v)
}
for _, v := range bundleUniqueness {
result = append(result, v)
}
return result, nil
}
114 changes: 114 additions & 0 deletions internal/controllers/variable_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package controllers_test

import (
"context"
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/rand"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client/fake"

"github.com/operator-framework/operator-registry/alpha/declcfg"
"github.com/operator-framework/operator-registry/alpha/property"
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"

operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
"github.com/operator-framework/operator-controller/internal/catalogmetadata"
"github.com/operator-framework/operator-controller/internal/controllers"
olmvariables "github.com/operator-framework/operator-controller/internal/resolution/variables"
testutil "github.com/operator-framework/operator-controller/test/util"
)

func TestOLMVariableSource(t *testing.T) {
sch := runtime.NewScheme()
utilruntime.Must(operatorsv1alpha1.AddToScheme(sch))
utilruntime.Must(rukpakv1alpha1.AddToScheme(sch))

stableChannel := catalogmetadata.Channel{Channel: declcfg.Channel{
Name: "stable",
Entries: []declcfg.ChannelEntry{
{
Name: "packageA.v2.0.0",
},
},
}}
testBundleList := []*catalogmetadata.Bundle{
{
Bundle: declcfg.Bundle{
Name: "packageA.v2.0.0",
Package: "packageA",
Image: "foo.io/packageA/packageA:v2.0.0",
Properties: []property.Property{
{Type: property.TypePackage, Value: json.RawMessage(`{"packageName":"packageA","version":"2.0.0"}`)},
},
},
CatalogName: "fake-catalog",
InChannels: []*catalogmetadata.Channel{&stableChannel},
},
}

pkgName := "packageA"
opName := fmt.Sprintf("operator-test-%s", rand.String(8))
operator := &operatorsv1alpha1.Operator{
ObjectMeta: metav1.ObjectMeta{Name: opName},
Spec: operatorsv1alpha1.OperatorSpec{
PackageName: pkgName,
Channel: "stable",
Version: "2.0.0",
},
}

bd := &rukpakv1alpha1.BundleDeployment{
ObjectMeta: metav1.ObjectMeta{
Name: opName,
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: operatorsv1alpha1.GroupVersion.String(),
Kind: "Operator",
Name: operator.Name,
UID: operator.UID,
Controller: pointer.Bool(true),
BlockOwnerDeletion: pointer.Bool(true),
},
},
},
Spec: rukpakv1alpha1.BundleDeploymentSpec{
ProvisionerClassName: "core-rukpak-io-plain",
Template: &rukpakv1alpha1.BundleTemplate{
Spec: rukpakv1alpha1.BundleSpec{
ProvisionerClassName: "core-rukpak-io-registry",
Source: rukpakv1alpha1.BundleSource{
Type: rukpakv1alpha1.SourceTypeImage,
Image: &rukpakv1alpha1.ImageSource{
Ref: "foo.io/packageA/packageA:v2.0.0",
},
},
},
},
},
}
fakeClient := fake.NewClientBuilder().WithScheme(sch).WithObjects(operator, bd).Build()
fakeCatalogClient := testutil.NewFakeCatalogClient(testBundleList)

vs := controllers.NewVariableSource(fakeClient, &fakeCatalogClient)

vars, err := vs.GetVariables(context.Background())
require.NoError(t, err)

require.Len(t, vars, 4)
assert.Equal(t, "required package packageA", vars[0].Identifier().String())
assert.IsType(t, &olmvariables.RequiredPackageVariable{}, vars[0])
assert.Equal(t, "installed package packageA", vars[1].Identifier().String())
assert.IsType(t, &olmvariables.InstalledPackageVariable{}, vars[1])
assert.Equal(t, "fake-catalog-packageA-packageA.v2.0.0", vars[2].Identifier().String())
assert.IsType(t, &olmvariables.BundleVariable{}, vars[2])
assert.Equal(t, "packageA package uniqueness", vars[3].Identifier().String())
assert.IsType(t, &olmvariables.BundleUniquenessVariable{}, vars[3])
}

0 comments on commit 3267301

Please sign in to comment.