diff --git a/go.mod b/go.mod index f47c51bb1..99ca231ae 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( k8s.io/client-go v0.30.3 k8s.io/component-base v0.30.3 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + package-operator.run/apis v1.12.0 sigs.k8s.io/controller-runtime v0.18.4 sigs.k8s.io/yaml v1.4.0 ) @@ -243,7 +244,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiserver v0.30.3 // indirect - k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/klog/v2 v2.130.0 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/kubectl v0.30.0 // indirect oras.land/oras-go v1.2.5 // indirect diff --git a/go.sum b/go.sum index 13fe9a1a3..d48f36097 100644 --- a/go.sum +++ b/go.sum @@ -651,8 +651,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -1069,8 +1069,8 @@ k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s= k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.130.0 h1:5nB3+3HpqKqXJIXNtJdtxcDCfaa9KL8StJgMzGJkUkM= +k8s.io/klog/v2 v2.130.0/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/kubectl v0.30.0 h1:xbPvzagbJ6RNYVMVuiHArC1grrV5vSmmIcSZuCdzRyk= @@ -1079,6 +1079,8 @@ k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1 k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= oras.land/oras-go v1.2.5 h1:XpYuAwAb0DfQsunIyMfeET92emK8km3W4yEzZvUbsTo= oras.land/oras-go v1.2.5/go.mod h1:PuAwRShRZCsZb7g8Ar3jKKQR/2A/qN+pkYxIOd/FAoo= +package-operator.run/apis v1.12.0 h1:IY7RanX9m2VAkWWDhLScZ9fEn/ameB77Ez7EKlgpiNo= +package-operator.run/apis v1.12.0/go.mod h1:9/KuG+JVx+mOYc6d6yqry2tAVelw0dVMECEOeiesgWc= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 h1:/U5vjBbQn3RChhv7P11uhYvCSm5G2GaIi5AIGBS6r4c= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0/go.mod h1:z7+wmGM2dfIiLRfrC6jb5kV2Mq/sK1ZP303cxzkV5Y4= diff --git a/internal/controllers/clusterextension_controller.go b/internal/controllers/clusterextension_controller.go index 1867e2c00..1cb9345f7 100644 --- a/internal/controllers/clusterextension_controller.go +++ b/internal/controllers/clusterextension_controller.go @@ -43,6 +43,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" apimachyaml "k8s.io/apimachinery/pkg/util/yaml" + pkocorev1alpha1 "package-operator.run/apis/core/v1alpha1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/cache" @@ -278,6 +279,14 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp ext.Status.ResolvedBundle = bundleutil.MetadataFor(resolvedBundle.Name, *resolvedBundleVersion) setResolvedStatusConditionSuccess(ext, fmt.Sprintf("resolved to %q", resolvedBundle.Image)) + if ext.Annotations != nil && ext.Annotations["package-operator.run/take-this"] == "True" { + pkoReconciler := &pkoReconciler{ + client: r.Client, + scheme: r.Scheme(), + } + return pkoReconciler.Reconcile(ctx, ext, resolvedBundle) + } + bundleSource := &rukpaksource.BundleSource{ Type: rukpaksource.SourceTypeImage, Image: &rukpaksource.ImageSource{ @@ -511,6 +520,7 @@ func SetDeprecationStatus(ext *ocv1alpha1.ClusterExtension, bundleName string, d func (r *ClusterExtensionReconciler) SetupWithManager(mgr ctrl.Manager) error { controller, err := ctrl.NewControllerManagedBy(mgr). For(&ocv1alpha1.ClusterExtension{}). + Owns(&pkocorev1alpha1.ClusterPackage{}). Watches(&catalogd.ClusterCatalog{}, crhandler.EnqueueRequestsFromMapFunc(clusterExtensionRequestsForCatalog(mgr.GetClient(), mgr.GetLogger())), builder.WithPredicates(predicate.Funcs{ diff --git a/internal/controllers/pko_reconciler.go b/internal/controllers/pko_reconciler.go new file mode 100644 index 000000000..55bc44668 --- /dev/null +++ b/internal/controllers/pko_reconciler.go @@ -0,0 +1,98 @@ +package controllers + +import ( + "context" + "encoding/json" + "fmt" + + ocv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/declcfg" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + pkocorev1alpha1 "package-operator.run/apis/core/v1alpha1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +// Uses Package Operator to reconcile a bundle on the cluster and get status information. +type pkoReconciler struct { + client client.Client + scheme *runtime.Scheme +} + +func (r *pkoReconciler) Reconcile(ctx context.Context, cext *ocv1alpha1.ClusterExtension, bundle *declcfg.Bundle) ( + res ctrl.Result, err error, +) { + configJson, err := json.Marshal(map[string]interface{}{ + "namespace": cext.Spec.InstallNamespace, + }) + if err != nil { + return res, err + } + desiredPkg := &pkocorev1alpha1.ClusterPackage{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "package-operator.run/v1alpha1", + Kind: "ClusterPackage", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: cext.Name, + Labels: map[string]string{ + "olm.operatorframework.io/owner-kind": "ClusterExtension", + }, + }, + Spec: pkocorev1alpha1.PackageSpec{ + Image: bundle.Image, + Config: &runtime.RawExtension{ + Raw: configJson, + }, + }, + } + if err := controllerutil.SetControllerReference(cext, desiredPkg, r.scheme); err != nil { + return res, fmt.Errorf("set controller ref: %w", err) + } + if err := r.client.Patch(ctx, desiredPkg, client.Apply, client.FieldOwner("olm-operator-controller")); err != nil { + return res, fmt.Errorf("patching ClusterPackage: %w", err) + } + + // Status reporting + currentPkg := &pkocorev1alpha1.ClusterPackage{} + if err := r.client.Get(ctx, client.ObjectKeyFromObject(desiredPkg), currentPkg); err != nil { + return res, fmt.Errorf("getting ClusterPackage: %w", err) + } + + availableCond := meta.FindStatusCondition(currentPkg.Status.Conditions, pkocorev1alpha1.PackageAvailable) + if availableCond != nil && availableCond.ObservedGeneration == currentPkg.Generation { + meta.SetStatusCondition(&cext.Status.Conditions, metav1.Condition{ + Type: "package-operator.run/Available", + Status: availableCond.Status, + Reason: availableCond.Reason, + Message: availableCond.Message, + ObservedGeneration: currentPkg.Generation, + }) + } + + progressingCond := meta.FindStatusCondition(currentPkg.Status.Conditions, pkocorev1alpha1.PackageProgressing) + if progressingCond != nil && progressingCond.ObservedGeneration == currentPkg.Generation { + meta.SetStatusCondition(&cext.Status.Conditions, metav1.Condition{ + Type: "package-operator.run/Progressing", + Status: progressingCond.Status, + Reason: progressingCond.Reason, + Message: progressingCond.Message, + ObservedGeneration: currentPkg.Generation, + }) + } + + unpackedCond := meta.FindStatusCondition(currentPkg.Status.Conditions, pkocorev1alpha1.PackageUnpacked) + if unpackedCond != nil && unpackedCond.ObservedGeneration == currentPkg.Generation { + meta.SetStatusCondition(&cext.Status.Conditions, metav1.Condition{ + Type: "package-operator.run/Unpacked", + Status: unpackedCond.Status, + Reason: unpackedCond.Reason, + Message: unpackedCond.Message, + ObservedGeneration: currentPkg.Generation, + }) + } + return +} diff --git a/pkg/scheme/scheme.go b/pkg/scheme/scheme.go index 933d89b05..90b8239f6 100644 --- a/pkg/scheme/scheme.go +++ b/pkg/scheme/scheme.go @@ -10,6 +10,7 @@ import ( catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1" ocv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" + pkocorev1alpha1 "package-operator.run/apis/core/v1alpha1" ) var Scheme = runtime.NewScheme() @@ -20,5 +21,6 @@ func init() { utilruntime.Must(catalogd.AddToScheme(Scheme)) utilruntime.Must(appsv1.AddToScheme(Scheme)) utilruntime.Must(corev1.AddToScheme(Scheme)) + utilruntime.Must(pkocorev1alpha1.AddToScheme(Scheme)) //+kubebuilder:scaffold:scheme }