Skip to content

Commit 13ea200

Browse files
dtfranzawgreene
authored andcommitted
Pipe Solver Solution into BundleDeployments
Combines @perdasilva 's latest commits with a selection from @varshaprasad96 and @ankitathomas 's controller_prototype to enable the operator-controller to create bundledeployments using a (currently hard-coded) CatalogSource. Also adds additional Makefile targets to enable simpler installation of dependencies (cert-manager and rukpak). Signed-off-by: dtfranz <[email protected]>
1 parent 5541671 commit 13ea200

File tree

10 files changed

+519
-23
lines changed

10 files changed

+519
-23
lines changed

Makefile

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
export IMAGE_REPO ?= quay.io/operator-framework/operator-controller
66
export IMAGE_TAG ?= devel
77
export GO_BUILD_TAGS ?= upstream
8+
export CERT_MGR_VERSION ?= v1.9.0
9+
export WAIT_TIMEOUT ?= 60s
810
IMG?=$(IMAGE_REPO):$(IMAGE_TAG)
911

1012
OPERATOR_CONTROLLER_NAMESPACE ?= operator-controller-system
@@ -99,11 +101,11 @@ build: manifests generate fmt vet ## Build manager binary.
99101
go build -o bin/manager main.go
100102

101103
.PHONY: run
102-
run: docker-build kind-cluster kind-load install deploy wait ## Build the operator-controller then deploy it into a new kind cluster.
104+
run: docker-build kind-cluster kind-load cert-mgr rukpak install deploy wait ## Build the operator-controller then deploy it into a new kind cluster.
103105

104106
.PHONY: wait
105107
wait:
106-
kubectl wait --for=condition=Available --namespace=$(OPERATOR_CONTROLLER_NAMESPACE) deployment/operator-controller-controller-manager --timeout=60s
108+
kubectl wait --for=condition=Available --namespace=$(OPERATOR_CONTROLLER_NAMESPACE) deployment/operator-controller-controller-manager --timeout=$(WAIT_TIMEOUT)
107109

108110
# If you wish built the manager image targeting other platforms you can use the --platform flag.
109111
# (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it.
@@ -139,6 +141,17 @@ ifndef ignore-not-found
139141
ignore-not-found = false
140142
endif
141143

144+
## TODO dfranz: replace cert-mgr and rukpak targets with our chosen method of distribution when available
145+
.PHONY: cert-mgr
146+
cert-mgr: ## Install cert-manager
147+
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MGR_VERSION)/cert-manager.yaml
148+
kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=$(WAIT_TIMEOUT)
149+
150+
.PHONY: rukpak
151+
rukpak: ## Install rukpak
152+
kubectl apply -f https://github.com/operator-framework/rukpak/releases/latest/download/rukpak.yaml
153+
kubectl wait --for=condition=Available --namespace=rukpak-system deployment/core --timeout=$(WAIT_TIMEOUT)
154+
142155
.PHONY: install
143156
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
144157
$(KUSTOMIZE) build config/crd | kubectl apply -f -

config/rbac/role.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ metadata:
55
creationTimestamp: null
66
name: manager-role
77
rules:
8+
- apiGroups:
9+
- core.rukpak.io
10+
resources:
11+
- bundledeployments
12+
verbs:
13+
- create
14+
- get
15+
- list
16+
- patch
17+
- update
18+
- watch
819
- apiGroups:
920
- operators.operatorframework.io
1021
resources:

controllers/operator_controller.go

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ package controllers
1919
import (
2020
"context"
2121

22+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
2223
"k8s.io/apimachinery/pkg/api/equality"
2324
apimeta "k8s.io/apimachinery/pkg/api/meta"
2425
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2526
"k8s.io/apimachinery/pkg/runtime"
27+
"k8s.io/apimachinery/pkg/types"
2628
utilerrors "k8s.io/apimachinery/pkg/util/errors"
2729
ctrl "sigs.k8s.io/controller-runtime"
2830
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -41,10 +43,20 @@ type OperatorReconciler struct {
4143
resolver *resolution.OperatorResolver
4244
}
4345

46+
func NewOperatorReconciler(c client.Client, s *runtime.Scheme, r *resolution.OperatorResolver) *OperatorReconciler {
47+
return &OperatorReconciler{
48+
Client: c,
49+
Scheme: s,
50+
resolver: r,
51+
}
52+
}
53+
4454
//+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators,verbs=get;list;watch;create;update;patch;delete
4555
//+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/status,verbs=get;update;patch
4656
//+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators/finalizers,verbs=update
4757

58+
//+kubebuilder:rbac:groups=core.rukpak.io,resources=bundledeployments,verbs=get;list;watch;create;update;patch
59+
4860
// Reconcile is part of the main kubernetes reconciliation loop which aims to
4961
// move the current state of the cluster closer to the desired state.
5062
// TODO(user): Modify the Reconcile function to compare the state specified by
@@ -125,8 +137,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
125137
if err != nil {
126138
return ctrl.Result{}, err
127139
}
128-
// TODO(perdasilva): use bundlePath to stamp out bundle deployment
129-
_ = bundlePath
140+
dep, err := r.generateExpectedBundleDeployment(*op, bundlePath)
141+
if err != nil {
142+
return ctrl.Result{}, err
143+
}
144+
// Create bundleDeployment if not found or Update if needed
145+
if err := r.ensureBundleDeployment(ctx, dep); err != nil {
146+
return ctrl.Result{}, err
147+
}
130148
break
131149
}
132150
}
@@ -145,16 +163,71 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
145163
return ctrl.Result{}, nil
146164
}
147165

166+
func (r *OperatorReconciler) generateExpectedBundleDeployment(o operatorsv1alpha1.Operator, bundlePath string) (*rukpakv1alpha1.BundleDeployment, error) {
167+
dep := &rukpakv1alpha1.BundleDeployment{
168+
ObjectMeta: metav1.ObjectMeta{
169+
Name: o.GetName(),
170+
},
171+
Spec: rukpakv1alpha1.BundleDeploymentSpec{
172+
//TODO: Don't assume plain provisioner
173+
ProvisionerClassName: "core-rukpak-io-plain",
174+
Template: &rukpakv1alpha1.BundleTemplate{
175+
ObjectMeta: metav1.ObjectMeta{
176+
// TODO: Remove
177+
Labels: map[string]string{
178+
"app": "my-bundle",
179+
},
180+
},
181+
Spec: rukpakv1alpha1.BundleSpec{
182+
Source: rukpakv1alpha1.BundleSource{
183+
// TODO: Don't assume image type
184+
Type: rukpakv1alpha1.SourceTypeImage,
185+
Image: &rukpakv1alpha1.ImageSource{
186+
Ref: bundlePath,
187+
},
188+
},
189+
190+
//TODO: Don't assume registry provisioner
191+
ProvisionerClassName: "core-rukpak-io-registry",
192+
},
193+
},
194+
},
195+
}
196+
197+
if err := ctrl.SetControllerReference(&o, dep, r.Scheme); err != nil {
198+
return nil, err
199+
}
200+
return dep, nil
201+
}
202+
148203
// SetupWithManager sets up the controller with the Manager.
149204
func (r *OperatorReconciler) SetupWithManager(mgr ctrl.Manager) error {
150-
r.resolver = resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource)
151-
152205
err := ctrl.NewControllerManagedBy(mgr).
153206
For(&operatorsv1alpha1.Operator{}).
207+
Owns(&rukpakv1alpha1.BundleDeployment{}).
154208
Complete(r)
155209

156210
if err != nil {
157211
return err
158212
}
159213
return nil
160214
}
215+
216+
func (r *OperatorReconciler) ensureBundleDeployment(ctx context.Context, desiredBundleDeployment *rukpakv1alpha1.BundleDeployment) error {
217+
existingBundleDeployment := &rukpakv1alpha1.BundleDeployment{}
218+
err := r.Client.Get(ctx, types.NamespacedName{Name: desiredBundleDeployment.GetName()}, existingBundleDeployment)
219+
if err != nil {
220+
if client.IgnoreNotFound(err) != nil {
221+
return err
222+
}
223+
return r.Client.Create(ctx, desiredBundleDeployment)
224+
}
225+
226+
// Check if the existing bundleDeployment's spec needs to be updated
227+
if equality.Semantic.DeepEqual(existingBundleDeployment.Spec, desiredBundleDeployment.Spec) {
228+
return nil
229+
}
230+
231+
existingBundleDeployment.Spec = desiredBundleDeployment.Spec
232+
return r.Client.Update(ctx, existingBundleDeployment)
233+
}

controllers/suite_test.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ import (
3838

3939
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
4040
"github.com/operator-framework/operator-controller/controllers"
41+
"github.com/operator-framework/operator-controller/internal/resolution"
4142
operatorutil "github.com/operator-framework/operator-controller/internal/util"
43+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
4244
//+kubebuilder:scaffold:imports
4345
)
4446

@@ -63,7 +65,9 @@ var _ = BeforeSuite(func() {
6365

6466
By("bootstrapping test environment")
6567
testEnv = &envtest.Environment{
66-
CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
68+
CRDDirectoryPaths: []string{
69+
filepath.Join("..", "config", "crd", "bases"),
70+
filepath.Join("..", "testdata", "crds")},
6771
ErrorIfCRDPathMissing: true,
6872
}
6973

@@ -76,6 +80,9 @@ var _ = BeforeSuite(func() {
7680
err = operatorsv1alpha1.AddToScheme(scheme.Scheme)
7781
Expect(err).NotTo(HaveOccurred())
7882

83+
err = rukpakv1alpha1.AddToScheme(scheme.Scheme)
84+
Expect(err).NotTo(HaveOccurred())
85+
7986
//+kubebuilder:scaffold:scheme
8087

8188
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
@@ -87,10 +94,11 @@ var _ = BeforeSuite(func() {
8794
})
8895
Expect(err).ToNot(HaveOccurred())
8996

90-
err = (&controllers.OperatorReconciler{
91-
Client: k8sManager.GetClient(),
92-
Scheme: k8sManager.GetScheme(),
93-
}).SetupWithManager(k8sManager)
97+
err = controllers.NewOperatorReconciler(
98+
k8sManager.GetClient(),
99+
k8sManager.GetScheme(),
100+
resolution.NewOperatorResolver(k8sManager.GetClient(), resolution.HardcodedEntitySource),
101+
).SetupWithManager(k8sManager)
94102
Expect(err).ToNot(HaveOccurred())
95103

96104
ctx, cancel = context.WithCancel(context.Background())

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/onsi/gomega v1.22.1
99
github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f
1010
github.com/operator-framework/operator-registry v1.26.2
11+
github.com/operator-framework/rukpak v0.11.0
1112
k8s.io/apimachinery v0.25.0
1213
k8s.io/client-go v0.25.0
1314
sigs.k8s.io/controller-runtime v0.13.1
@@ -42,7 +43,7 @@ require (
4243
github.com/golang/protobuf v1.5.2 // indirect
4344
github.com/google/gnostic v0.5.7-v3refs // indirect
4445
github.com/google/go-cmp v0.5.8 // indirect
45-
github.com/google/gofuzz v1.1.0 // indirect
46+
github.com/google/gofuzz v1.2.0 // indirect
4647
github.com/google/uuid v1.2.0 // indirect
4748
github.com/imdario/mergo v0.3.12 // indirect
4849
github.com/josharian/intern v1.0.0 // indirect

go.sum

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
203203
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
204204
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
205205
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
206-
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
207-
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
206+
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
207+
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
208208
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
209209
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
210210
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -291,6 +291,8 @@ github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f h1:YxUZyQ
291291
github.com/operator-framework/deppy v0.0.0-20230125110717-dc02e928470f/go.mod h1:JaF7sX6tn7mpXcOehYjSHiKM1Y0z09vEfC6dca4AVuo=
292292
github.com/operator-framework/operator-registry v1.26.2 h1:kQToR/hPqdivljaRXM0olPllNIcc/GUk1VBoGwagJmk=
293293
github.com/operator-framework/operator-registry v1.26.2/go.mod h1:Z7XIb/3ZkhBQCvMD/rJphyuY4LmU/eWpZS+o0Mm1WAk=
294+
github.com/operator-framework/rukpak v0.11.0 h1:D2UAlYkmCl/i6zWE+yP9oIzOScVu9VwtqJKKt+dklWw=
295+
github.com/operator-framework/rukpak v0.11.0/go.mod h1:n8oYwfz4a50Oh9hYnPgxiD2wa+xLbPq3cI67wapcL4Y=
294296
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
295297
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
296298
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -336,8 +338,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
336338
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
337339
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
338340
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
339-
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
340341
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
342+
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
341343
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
342344
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
343345
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

main.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import (
3333

3434
operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
3535
"github.com/operator-framework/operator-controller/controllers"
36+
"github.com/operator-framework/operator-controller/internal/resolution"
37+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
3638
//+kubebuilder:scaffold:imports
3739
)
3840

@@ -45,6 +47,7 @@ func init() {
4547
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
4648

4749
utilruntime.Must(operatorsv1alpha1.AddToScheme(scheme))
50+
utilruntime.Must(rukpakv1alpha1.AddToScheme(scheme))
4851
//+kubebuilder:scaffold:scheme
4952
}
5053

@@ -89,10 +92,11 @@ func main() {
8992
os.Exit(1)
9093
}
9194

92-
if err = (&controllers.OperatorReconciler{
93-
Client: mgr.GetClient(),
94-
Scheme: mgr.GetScheme(),
95-
}).SetupWithManager(mgr); err != nil {
95+
if err = controllers.NewOperatorReconciler(
96+
mgr.GetClient(),
97+
mgr.GetScheme(),
98+
resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource),
99+
).SetupWithManager(mgr); err != nil {
96100
setupLog.Error(err, "unable to create controller", "controller", "Operator")
97101
os.Exit(1)
98102
}

test/e2e/e2e_suite_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"sigs.k8s.io/controller-runtime/pkg/client"
1313

1414
operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
15+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
1516
)
1617

1718
var (
@@ -33,6 +34,9 @@ var _ = BeforeSuite(func() {
3334
err := operatorv1alpha1.AddToScheme(scheme)
3435
Expect(err).To(Not(HaveOccurred()))
3536

37+
err = rukpakv1alpha1.AddToScheme(scheme)
38+
Expect(err).To(Not(HaveOccurred()))
39+
3640
c, err = client.New(cfg, client.Options{Scheme: scheme})
3741
Expect(err).To(Not(HaveOccurred()))
3842
})

test/e2e/install_test.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
. "github.com/onsi/ginkgo/v2"
1313
. "github.com/onsi/gomega"
1414
operatorv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1"
15+
rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1"
1516
)
1617

1718
const (
@@ -22,11 +23,12 @@ const (
2223
var _ = Describe("Operator Install", func() {
2324
It("resolves the specified package with correct bundle path", func() {
2425
var (
25-
ctx context.Context = context.Background()
26-
pkgName string = "prometheus"
27-
operator *operatorv1alpha1.Operator = &operatorv1alpha1.Operator{
26+
ctx context.Context = context.Background()
27+
pkgName string = "prometheus"
28+
operatorName string = fmt.Sprintf("operator-%s", rand.String(8))
29+
operator *operatorv1alpha1.Operator = &operatorv1alpha1.Operator{
2830
ObjectMeta: metav1.ObjectMeta{
29-
Name: fmt.Sprintf("operator-%s", rand.String(8)),
31+
Name: operatorName,
3032
},
3133
Spec: operatorv1alpha1.OperatorSpec{
3234
PackageName: pkgName,
@@ -48,6 +50,16 @@ var _ = Describe("Operator Install", func() {
4850
g.Expect(operator.Status.Conditions[0].Message).To(Equal("resolution was successful"))
4951
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
5052

53+
By("eventually installing the package successfully")
54+
Eventually(func(g Gomega) {
55+
bd := rukpakv1alpha1.BundleDeployment{}
56+
err = c.Get(ctx, types.NamespacedName{Name: operatorName}, &bd)
57+
g.Expect(err).ToNot(HaveOccurred())
58+
g.Expect(len(bd.Status.Conditions)).To(Equal(2))
59+
g.Expect(bd.Status.Conditions[0].Reason).To(Equal("UnpackSuccessful"))
60+
g.Expect(bd.Status.Conditions[1].Reason).To(Equal("InstallationSucceeded"))
61+
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
62+
5163
By("deleting the Operator resource")
5264
err = c.Delete(ctx, operator)
5365
Expect(err).ToNot(HaveOccurred())

0 commit comments

Comments
 (0)