From 21ba18e296621951f531a6498e926508c3e20075 Mon Sep 17 00:00:00 2001 From: Bryce Palmer Date: Fri, 15 Sep 2023 16:57:11 -0400 Subject: [PATCH] (refactor): Remove deprecated CatalogMetadata and associated code (#169) * (refactor): Remove deprecated CatalogMetadata and associated code Signed-off-by: Bryce Palmer * go mod tidy Signed-off-by: Bryce Palmer --------- Signed-off-by: Bryce Palmer --- README.md | 92 +++++------ api/core/v1alpha1/catalogmetadata_types.go | 64 -------- api/core/v1alpha1/zz_generated.deepcopy.go | 80 ---------- ....operatorframework.io_catalogmetadata.yaml | 69 -------- config/crd/kustomization.yaml | 1 - config/default/manager_auth_proxy_patch.yaml | 2 +- config/rbac/role.yaml | 12 -- go.mod | 2 +- hack/scripts/generate-asciidemo.sh | 28 ++-- pkg/controllers/core/catalog_controller.go | 150 +----------------- .../core/catalog_controller_test.go | 93 +---------- pkg/features/features.go | 8 +- test/e2e/unpack_test.go | 94 ----------- 13 files changed, 63 insertions(+), 632 deletions(-) delete mode 100644 api/core/v1alpha1/catalogmetadata_types.go delete mode 100644 config/crd/bases/catalogd.operatorframework.io_catalogmetadata.yaml diff --git a/README.md b/README.md index 9b7c329b..7e78c16f 100644 --- a/README.md +++ b/README.md @@ -91,81 +91,69 @@ Catalogd helps customers discover installable content by hosting catalog metadat Events: ``` +1. Port forward the `catalogd-catalogserver` service in the `catalogd-system` namespace: + ```sh + $ kubectl -n catalogd-system port-forward svc/catalogd-catalogserver 8080:80 + ``` + 1. Run the following command to get a list of packages: ```sh - $ kubectl get catalogmetadata -l schema=olm.package + $ curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.package") | .name' ``` *Example output* ```sh - NAME AGE - operatorhubio-olm.package-ack-acm-controller 18m - operatorhubio-olm.package-ack-apigatewayv2-controller 18m - operatorhubio-olm.package-ack-applicationautoscaling-controller 18m - operatorhubio-olm.package-ack-cloudtrail-controller 18m - operatorhubio-olm.package-ack-cloudwatch-controller 18m - operatorhubio-olm.package-ack-dynamodb-controller 18m - operatorhubio-olm.package-ack-ec2-controller 18m - operatorhubio-olm.package-ack-ecr-controller 18m - operatorhubio-olm.package-ack-eks-controller 18m - operatorhubio-olm.package-ack-elasticache-controller 18m - operatorhubio-olm.package-ack-emrcontainers-controller 18m - operatorhubio-olm.package-ack-eventbridge-controller 18m - operatorhubio-olm.package-ack-iam-controller 18m - operatorhubio-olm.package-ack-kinesis-controller 18m + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 112M 0 --:--:-- --:--:-- --:--:-- 112M + "ack-acm-controller" + "ack-apigatewayv2-controller" + "ack-applicationautoscaling-controller" + "ack-cloudtrail-controller" + "ack-cloudwatch-controller" + "ack-dynamodb-controller" + "ack-ec2-controller" + "ack-ecr-controller" + "ack-eks-controller" + "ack-elasticache-controller" + "ack-emrcontainers-controller" + "ack-eventbridge-controller" + "ack-iam-controller" + "ack-kinesis-controller" ... ``` -1. Run the following command to get a list of channels: +1. Run the following command to get a list of channels for the `ack-acm-controller` package: ```sh - $ kubectl get catalogmetadata -l olm.channel + $ curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.channel") | select(.package == "ack-acm-controller") | .name' ``` *Example output* ```sh - NAME AGE - operatorhubio-olm.channel-ack-acm-controller-alpha 21m - operatorhubio-olm.channel-ack-apigatewayv2-controller-alpha 21m - operatorhubio-olm.channel-ack-applicationautoscaling-controller-alpha 21m - operatorhubio-olm.channel-ack-cloudtrail-controller-alpha 21m - operatorhubio-olm.channel-ack-cloudwatch-controller-alpha 21m - operatorhubio-olm.channel-ack-dynamodb-controller-alpha 21m - operatorhubio-olm.channel-ack-ec2-controller-alpha 21m - operatorhubio-olm.channel-ack-ecr-controller-alpha 21m - operatorhubio-olm.channel-ack-eks-controller-alpha 21m - operatorhubio-olm.channel-ack-elasticache-controller-alpha 21m - operatorhubio-olm.channel-ack-emrcontainers-controller-alpha 21m - operatorhubio-olm.channel-ack-eventbridge-controller-alpha 21m - operatorhubio-olm.channel-ack-iam-controller-alpha 21m - operatorhubio-olm.channel-ack-kinesis-controller-alpha 21m - ... + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 115M 0 --:--:-- --:--:-- --:--:-- 116M + "alpha" ``` -1. Run the following command to get a list of bundles: +1. Run the following command to get a list of bundles belonging to the `ack-acm-controller` package: ```sh - $ kubectl get catalogmetadata -l olm.bundle + $ curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == "olm.bundle") | select(.package == "ack-acm-controller") | .name' ``` *Example output* ```sh - NAME AGE - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.1 19m - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.2 19m - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.4 19m - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.5 19m - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.6 19m - operatorhubio-olm.bundle-ack-acm-controller-ack-acm-controller.v0.0.7 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.10 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.11 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.12 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.13 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.14 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.15 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.16 19m - operatorhubio-olm.bundle-ack-apigatewayv2-controller-ack-apigatewayv2-controller.v0.0.17 19m - ... + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 110M 100 110M 0 0 122M 0 --:--:-- --:--:-- --:--:-- 122M + "ack-acm-controller.v0.0.1" + "ack-acm-controller.v0.0.2" + "ack-acm-controller.v0.0.4" + "ack-acm-controller.v0.0.5" + "ack-acm-controller.v0.0.6" + "ack-acm-controller.v0.0.7" ``` ## Contributing diff --git a/api/core/v1alpha1/catalogmetadata_types.go b/api/core/v1alpha1/catalogmetadata_types.go deleted file mode 100644 index 117105d3..00000000 --- a/api/core/v1alpha1/catalogmetadata_types.go +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2023. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - "encoding/json" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// CatalogMetadataSpec defines the desired state of CatalogMetadata. -// It is based on the `Meta` schema defined in Operator Registry (https://olm.operatorframework.io/docs/reference/file-based-catalogs/#schema) -// and it adheres to the format of `Meta` schema that contains fields such as `Schema` (Required), `Package` (Optional), `Name` (Optional) and `Blob`. -// The `CatalogMetadataSpec` is an extension of the `Meta` schema that additionally contains a `Catalog` field which references the Catalog and a `Content` field -// which is a JSON representation of the File-Based Catalog blob. -type CatalogMetadataSpec struct { - Catalog corev1.LocalObjectReference `json:"catalog"` - Schema string `json:"schema"` - Package string `json:"package,omitempty"` - Name string `json:"name,omitempty"` - // +kubebuilder:validation:Schemaless - // +kubebuilder:pruning:PreserveUnknownFields - // +kubebuilder:validation:Type=object - Content json.RawMessage `json:"content,omitempty"` -} - -//+kubebuilder:object:root=true -//+kubebuilder:resource:scope=Cluster - -// CatalogMetadata is the Schema for the catalogs API -type CatalogMetadata struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec CatalogMetadataSpec `json:"spec,omitempty"` -} - -//+kubebuilder:object:root=true - -// CatalogMetadataList contains a list of CatalogMetadata -type CatalogMetadataList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []CatalogMetadata `json:"items"` -} - -func init() { - SchemeBuilder.Register(&CatalogMetadata{}, &CatalogMetadataList{}) -} diff --git a/api/core/v1alpha1/zz_generated.deepcopy.go b/api/core/v1alpha1/zz_generated.deepcopy.go index 3b4d2ed7..6d85fd21 100644 --- a/api/core/v1alpha1/zz_generated.deepcopy.go +++ b/api/core/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,6 @@ limitations under the License. package v1alpha1 import ( - "encoding/json" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -86,85 +85,6 @@ func (in *CatalogList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CatalogMetadata) DeepCopyInto(out *CatalogMetadata) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogMetadata. -func (in *CatalogMetadata) DeepCopy() *CatalogMetadata { - if in == nil { - return nil - } - out := new(CatalogMetadata) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CatalogMetadata) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CatalogMetadataList) DeepCopyInto(out *CatalogMetadataList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]CatalogMetadata, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogMetadataList. -func (in *CatalogMetadataList) DeepCopy() *CatalogMetadataList { - if in == nil { - return nil - } - out := new(CatalogMetadataList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *CatalogMetadataList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CatalogMetadataSpec) DeepCopyInto(out *CatalogMetadataSpec) { - *out = *in - out.Catalog = in.Catalog - if in.Content != nil { - in, out := &in.Content, &out.Content - *out = make(json.RawMessage, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CatalogMetadataSpec. -func (in *CatalogMetadataSpec) DeepCopy() *CatalogMetadataSpec { - if in == nil { - return nil - } - out := new(CatalogMetadataSpec) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CatalogSource) DeepCopyInto(out *CatalogSource) { *out = *in diff --git a/config/crd/bases/catalogd.operatorframework.io_catalogmetadata.yaml b/config/crd/bases/catalogd.operatorframework.io_catalogmetadata.yaml deleted file mode 100644 index 3a6c4c89..00000000 --- a/config/crd/bases/catalogd.operatorframework.io_catalogmetadata.yaml +++ /dev/null @@ -1,69 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.0 - name: catalogmetadata.catalogd.operatorframework.io -spec: - group: catalogd.operatorframework.io - names: - kind: CatalogMetadata - listKind: CatalogMetadataList - plural: catalogmetadata - singular: catalogmetadata - scope: Cluster - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: CatalogMetadata is the Schema for the catalogs API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: CatalogMetadataSpec defines the desired state of CatalogMetadata. - It is based on the `Meta` schema defined in Operator Registry (https://olm.operatorframework.io/docs/reference/file-based-catalogs/#schema) - and it adheres to the format of `Meta` schema that contains fields such - as `Schema` (Required), `Package` (Optional), `Name` (Optional) and - `Blob`. The `CatalogMetadataSpec` is an extension of the `Meta` schema - that additionally contains a `Catalog` field which references the Catalog - and a `Content` field which is a JSON representation of the File-Based - Catalog blob. - properties: - catalog: - description: LocalObjectReference contains enough information to let - you locate the referenced object inside the same namespace. - properties: - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - type: object - x-kubernetes-map-type: atomic - content: - type: object - x-kubernetes-preserve-unknown-fields: true - name: - type: string - package: - type: string - schema: - type: string - required: - - catalog - - schema - type: object - type: object - served: true - storage: true diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 41af6421..fc01b245 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -3,7 +3,6 @@ # It should be run by config/default resources: - bases/catalogd.operatorframework.io_catalogs.yaml -- bases/catalogd.operatorframework.io_catalogmetadata.yaml #+kubebuilder:scaffold:crdkustomizeresource patches: diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml index b24c81b9..9fde74dd 100644 --- a/config/default/manager_auth_proxy_patch.yaml +++ b/config/default/manager_auth_proxy_patch.yaml @@ -51,5 +51,5 @@ spec: - "--metrics-bind-address=127.0.0.1:8080" - "--leader-elect" - "--catalogs-storage-dir=/var/cache/catalogs" - - "--feature-gates=CatalogMetadataAPI=true,HTTPServer=true" + - "--feature-gates=HTTPServer=true" diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index de78dd1c..d18c70b6 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -4,18 +4,6 @@ kind: ClusterRole metadata: name: manager-role rules: -- apiGroups: - - catalogd.operatorframework.io - resources: - - catalogmetadata - verbs: - - create - - delete - - get - - list - - patch - - update - - watch - apiGroups: - catalogd.operatorframework.io resources: diff --git a/go.mod b/go.mod index a6e9782a..2f6e832d 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( k8s.io/apimachinery v0.26.1 k8s.io/client-go v0.26.1 k8s.io/component-base v0.26.1 - k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 sigs.k8s.io/controller-runtime v0.14.4 ) @@ -84,6 +83,7 @@ require ( k8s.io/apiextensions-apiserver v0.26.1 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect diff --git a/hack/scripts/generate-asciidemo.sh b/hack/scripts/generate-asciidemo.sh index c0af41c1..ccc80c61 100755 --- a/hack/scripts/generate-asciidemo.sh +++ b/hack/scripts/generate-asciidemo.sh @@ -18,7 +18,7 @@ function run() { sleep 10 typeline "make install" sleep 10 - # inspect crds (catalog, catalogmetadata) + # inspect crds (catalog) typeline 'kubectl get crds -A' typeline -x "# create a catalog" @@ -26,18 +26,20 @@ function run() { typeline "kubectl get catalog -A" # shows catalog-sample typeline -x "# waiting for catalog to report ready status" typeline "time kubectl wait --for=condition=Unpacked catalog/operatorhubio --timeout=1h" - # inspect packages, and then details on one package - typeline -x "# check what 'packages' are available in this catalog and then inspect the content of one of the packages" - typeline "kubectl get catalogmetadata -l schema=olm.package" - typeline "kubectl get catalogmetadata operatorhubio-olm.package-wavefront -o yaml" - # inspect channels, and then details on one channel - typeline -x "# check what channels are included in the wavefront package and then inspect the content of the alpha channel" - typeline "kubectl get catalogmetadata -l schema=olm.channel,package=wavefront" - typeline "kubectl get catalogmetadata operatorhubio-olm.channel-wavefront-alpha -o yaml" - # inspect bundles, and then details on one bundle - typeline -x "# check what bundles are included in the wavefront package and then inspect the content of the wavefront-operator.v0.1.0 bundle" - typeline "kubectl get catalogmetadata -l schema=olm.bundle,package=wavefront" - typeline "kubectl get catalogmetadata operatorhubio-olm.bundle-wavefront-wavefront-operator.v0.1.0 -o yaml" + + # port forward the catalogd-catalogserver service + typeline -x "# port forward the catalogd-catalogserver service to interact with the HTTP server serving catalog contents" + typline "kubectl -n catalogd-system port-forward svc/catalogd-catalogserver 8080:80" + + # inspect packages + typeline -x "# check what 'packages' are available in this catalog" + typeline "curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == \"olm.package\") | .name'" + # inspect channels + typeline -x "# check what channels are included in the wavefront package" + typeline "curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == \"olm.channel\") | select(.package == \"wavefront\") | .name'" + # inspect bundles + typeline -x "# check what bundles are included in the wavefront package" + typeline "curl http://localhost:8080/catalogs/operatorhubio/all.json | jq -s '.[] | select(.schema == \"olm.bundle\") | select(.package == \"ack-acm-controller\") | .name'" } run diff --git a/pkg/controllers/core/catalog_controller.go b/pkg/controllers/core/catalog_controller.go index 31b4ca82..7b4bb881 100644 --- a/pkg/controllers/core/catalog_controller.go +++ b/pkg/controllers/core/catalog_controller.go @@ -17,29 +17,20 @@ limitations under the License. package core import ( - "context" - "crypto/sha1" // #nosec - "encoding/hex" - "encoding/json" + "context" // #nosec "fmt" - "io/fs" - "github.com/operator-framework/operator-registry/alpha/declcfg" - "github.com/operator-framework/operator-registry/alpha/property" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apimacherrors "k8s.io/apimachinery/pkg/util/errors" - "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" "github.com/operator-framework/catalogd/api/core/v1alpha1" - "github.com/operator-framework/catalogd/internal/k8sutil" "github.com/operator-framework/catalogd/internal/source" "github.com/operator-framework/catalogd/pkg/features" "github.com/operator-framework/catalogd/pkg/storage" @@ -57,7 +48,6 @@ type CatalogReconciler struct { //+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogs,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogs/status,verbs=get;update;patch //+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogs/finalizers,verbs=update -//+kubebuilder:rbac:groups=catalogd.operatorframework.io,resources=catalogmetadata,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=core,resources=pods,verbs=create;update;patch;delete;get;list;watch //+kubebuilder:rbac:groups=core,resources=pods/log,verbs=get;list;watch @@ -146,11 +136,6 @@ func (r *CatalogReconciler) reconcile(ctx context.Context, catalog *v1alpha1.Cat return ctrl.Result{}, updateStatusStorageError(&catalog.Status, fmt.Errorf("error storing fbc: %v", err)) } } - if features.CatalogdFeatureGate.Enabled(features.CatalogMetadataAPI) { - if err = r.syncCatalogMetadata(ctx, unpackResult.FS, catalog); err != nil { - return ctrl.Result{}, updateStatusUnpackFailing(&catalog.Status, fmt.Errorf("create catalog metadata objects: %v", err)) - } - } updateStatusUnpacked(&catalog.Status, unpackResult) return ctrl.Result{}, nil @@ -225,136 +210,3 @@ func updateStatusStorageDeleteError(status *v1alpha1.CatalogStatus, err error) e }) return err } - -// syncCatalogMetadata will sync all of the catalog contents to `CatalogMetadata` objects -// by creating, updating and deleting the objects as necessary. Returns an -// error if any are encountered. -func (r *CatalogReconciler) syncCatalogMetadata(ctx context.Context, fsys fs.FS, catalog *v1alpha1.Catalog) error { - newCatalogMetadataObjs := map[string]*v1alpha1.CatalogMetadata{} - - err := declcfg.WalkMetasFS(fsys, func(path string, meta *declcfg.Meta, err error) error { - if err != nil { - return fmt.Errorf("error in parsing catalog content files in the filesystem: %w", err) - } - - packageOrName := meta.Package - if packageOrName == "" { - packageOrName = meta.Name - } - - var objName string - if objName, err = generateCatalogMetadataName(ctx, catalog.Name, meta); err != nil { - return fmt.Errorf("error in generating catalog metadata name: %w", err) - } - - blob := meta.Blob - if meta.Schema == declcfg.SchemaBundle { - var b declcfg.Bundle - if err := json.Unmarshal(blob, &b); err != nil { - return fmt.Errorf("error unmarshalling bundle: %w", err) - } - properties := b.Properties[:0] - for _, p := range b.Properties { - if p.Type == property.TypeBundleObject { - continue - } - properties = append(properties, p) - } - b.Properties = properties - blob, err = json.Marshal(b) - if err != nil { - return fmt.Errorf("error marshalling bundle: %w", err) - } - } - - catalogMetadata := &v1alpha1.CatalogMetadata{ - TypeMeta: metav1.TypeMeta{ - APIVersion: v1alpha1.GroupVersion.String(), - Kind: "CatalogMetadata", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: objName, - Labels: map[string]string{ - "catalog": catalog.Name, - "schema": meta.Schema, - "package": meta.Package, - "name": meta.Name, - "packageOrName": packageOrName, - }, - OwnerReferences: []metav1.OwnerReference{{ - APIVersion: v1alpha1.GroupVersion.String(), - Kind: "Catalog", - Name: catalog.Name, - UID: catalog.UID, - BlockOwnerDeletion: pointer.Bool(true), - Controller: pointer.Bool(true), - }}, - }, - Spec: v1alpha1.CatalogMetadataSpec{ - Catalog: corev1.LocalObjectReference{Name: catalog.Name}, - Name: meta.Name, - Schema: meta.Schema, - Package: meta.Package, - Content: blob, - }, - } - - newCatalogMetadataObjs[catalogMetadata.Name] = catalogMetadata - - return nil - }) - if err != nil { - return fmt.Errorf("unable to parse declarative config into CatalogMetadata API: %w", err) - } - - var existingCatalogMetadataObjs v1alpha1.CatalogMetadataList - if err := r.List(ctx, &existingCatalogMetadataObjs, &client.MatchingLabels{"catalog": catalog.Name}); err != nil { - return fmt.Errorf("list existing catalog metadata: %v", err) - } - for i, existingCatalogMetadata := range existingCatalogMetadataObjs.Items { - if _, ok := newCatalogMetadataObjs[existingCatalogMetadata.Name]; !ok { - // delete existing catalog metadata - err := r.Delete(ctx, &existingCatalogMetadataObjs.Items[i]) - if err != nil { - return fmt.Errorf("delete existing catalog metadata %q: %v", existingCatalogMetadata.Name, err) - } - } - } - - ordered := sets.List(sets.KeySet(newCatalogMetadataObjs)) - for _, catalogMetadataName := range ordered { - newcatalogMetadata := newCatalogMetadataObjs[catalogMetadataName] - if err := r.Client.Patch(ctx, newcatalogMetadata, client.Apply, &client.PatchOptions{Force: pointer.Bool(true), FieldManager: "catalog-controller"}); err != nil { - return fmt.Errorf("applying catalog metadata %q: %w", newcatalogMetadata.Name, err) - } - } - - return nil -} - -// generateCatalogMetadataName will generate unique names for the CatalogMetadata objects that are constructed with the -// catalog name and `meta.Schema`. Additionally, if the `meta.Package` and `meta.Name` exist, they are appended to the CatalogMetadata name. -// In the place of the empty `meta.Name`, it computes a hash of `meta.Blob` to prevent multiple FBC blobs colliding on the the object name. -// Possible outcomes are: "{catalogName}-{meta.Schema}-{meta.Name}", "{catalogName}-{meta.Schema}-{meta.Package}-{meta.Name}", -// "{catalogName}-{meta.Schema}-{hash{meta.Blob}}", "{catalogName}-{meta.Schema}-{meta.Package}-{hash{meta.Blob}}". -// Characters that would result in an invalid DNS name are replaced with dashes. -func generateCatalogMetadataName(_ context.Context, catalogName string, meta *declcfg.Meta) (string, error) { - objName := fmt.Sprintf("%s-%s", catalogName, meta.Schema) - if meta.Package != "" { - objName = fmt.Sprintf("%s-%s", objName, meta.Package) - } - if meta.Name != "" { - objName = fmt.Sprintf("%s-%s", objName, meta.Name) - } else { - metaJSON, err := json.Marshal(meta.Blob) - if err != nil { - return "", fmt.Errorf("JSON marshal error: %v", err) - } - // #nosec - h := sha1.New() - h.Write(metaJSON) - objName = fmt.Sprintf("%s-%s", objName, hex.EncodeToString(h.Sum(nil))) - } - objName, _ = k8sutil.MetadataName(objName) - return objName, nil -} diff --git a/pkg/controllers/core/catalog_controller_test.go b/pkg/controllers/core/catalog_controller_test.go index 624b2064..89f9f274 100644 --- a/pkg/controllers/core/catalog_controller_test.go +++ b/pkg/controllers/core/catalog_controller_test.go @@ -300,8 +300,7 @@ var _ = Describe("Catalogd Controller Test", func() { When("HTTPServer feature gate is enabled", func() { BeforeEach(func() { Expect(features.CatalogdFeatureGate.SetFromMap(map[string]bool{ - string(features.CatalogMetadataAPI): false, - string(features.HTTPServer): true, + string(features.HTTPServer): true, })).NotTo(HaveOccurred()) // call reconciler so that initial finalizer setup is done here res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: catalogKey}) @@ -373,92 +372,6 @@ var _ = Describe("Catalogd Controller Test", func() { }) }) }) - When("the CatalogMetadataAPI feature gate is enabled", func() { - BeforeEach(func() { - Expect(features.CatalogdFeatureGate.SetFromMap(map[string]bool{ - string(features.CatalogMetadataAPI): true, - string(features.HTTPServer): false, - })).NotTo(HaveOccurred()) - - // reconcile - res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: catalogKey}) - Expect(res).To(Equal(ctrl.Result{})) - Expect(err).ToNot(HaveOccurred()) - }) - - AfterEach(func() { - // clean up catalogmetadata - Expect(cl.DeleteAllOf(ctx, &v1alpha1.CatalogMetadata{})).To(Succeed()) - Expect(features.CatalogdFeatureGate.SetFromMap(map[string]bool{ - string(features.CatalogMetadataAPI): false, - })).NotTo(HaveOccurred()) - }) - - // TODO (rashmigottipati): Add testing of CatalogMetadata sync process. - It("should create CatalogMetadata resources", func() { - catalogMetadatas := &v1alpha1.CatalogMetadataList{} - Expect(cl.List(ctx, catalogMetadatas)).To(Succeed()) - Expect(catalogMetadatas.Items).To(HaveLen(3)) - for _, catalogMetadata := range catalogMetadatas.Items { - Expect(catalogMetadata.Name).To(ContainSubstring(catalogKey.Name)) - Expect(catalogMetadata.Kind).To(Equal("CatalogMetadata")) - Expect(catalogMetadata.OwnerReferences).To(HaveLen(1)) - Expect(catalogMetadata.OwnerReferences[0].Name).To(Equal(catalogKey.Name)) - Expect(catalogMetadata.Spec.Catalog.Name).To(Equal(catalogKey.Name)) - } - }) - - When("creating another Catalog", func() { - var ( - tempCatalog *v1alpha1.Catalog - ) - BeforeEach(func() { - tempCatalog = &v1alpha1.Catalog{ - ObjectMeta: metav1.ObjectMeta{Name: "tempedout"}, - Spec: v1alpha1.CatalogSpec{ - Source: v1alpha1.CatalogSource{ - Type: "image", - Image: &v1alpha1.ImageSource{ - Ref: "somecatalog:latest", - }, - }, - }, - } - - Expect(cl.Create(ctx, tempCatalog)).To(Succeed()) - res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{Name: "tempedout"}}) - Expect(res).To(Equal(ctrl.Result{})) - Expect(err).ToNot(HaveOccurred()) - }) - - AfterEach(func() { - Expect(cl.Delete(ctx, tempCatalog)).NotTo(HaveOccurred()) - }) - - It("should not delete CatalogMetadata belonging to a different catalog", func() { - catalogMetadatas := &v1alpha1.CatalogMetadataList{} - Expect(cl.List(ctx, catalogMetadatas)).To(Succeed()) - Expect(catalogMetadatas.Items).To(HaveLen(6)) - for _, catalogMetadata := range catalogMetadatas.Items { - for _, or := range catalogMetadata.GetOwnerReferences() { - if or.Kind == "Catalog" { - if or.Name == catalogKey.Name { - Expect(catalogMetadata.Name).To(ContainSubstring(catalogKey.Name)) - Expect(catalogMetadata.Kind).To(Equal("CatalogMetadata")) - Expect(catalogMetadata.Spec.Catalog.Name).To(Equal(catalogKey.Name)) - break - } else if or.Name == tempCatalog.Name { - Expect(catalogMetadata.Name).To(ContainSubstring(tempCatalog.Name)) - Expect(catalogMetadata.Kind).To(Equal("CatalogMetadata")) - Expect(catalogMetadata.Spec.Catalog.Name).To(Equal(tempCatalog.Name)) - break - } - } - } - } - }) - }) - }) }) }) }) @@ -470,8 +383,8 @@ var _ = Describe("Catalogd Controller Test", func() { // To learn more about File-Based Catalogs and the different objects, view the // documentation at https://olm.operatorframework.io/docs/reference/file-based-catalogs/. // The reasoning behind having these as a template is to parameterize different -// fields to use custom values during testing and verifying to ensure that the CatalogMetadata -// resources created by the Catalog controller have the appropriate values. +// fields to use custom values during testing and verifying to ensure that the catalog +// metadata served after the Catalog resource has been reconciled have the appropriate values. // Having the parameterized fields allows us to easily change the values that are used in // the tests by changing them in one place as opposed to manually changing many string literals // throughout the code. diff --git a/pkg/features/features.go b/pkg/features/features.go index 8204f388..2e20f5ac 100644 --- a/pkg/features/features.go +++ b/pkg/features/features.go @@ -9,18 +9,14 @@ const ( // Add new feature gates constants (strings) // Ex: SomeFeature featuregate.Feature = "SomeFeature" - CatalogMetadataAPI featuregate.Feature = "CatalogMetadataAPI" - HTTPServer featuregate.Feature = "HTTPServer" + HTTPServer featuregate.Feature = "HTTPServer" ) var catalogdFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ // Add new feature gate definitions // Ex: SomeFeature: {...} - // Marking the CatalogMetadataAPI feature gate as Deprecated in the interest of introducing - // the HTTP Server functionality in the future and use it as a default method of serving the catalog contents. - CatalogMetadataAPI: {Default: false, PreRelease: featuregate.Deprecated}, - HTTPServer: {Default: false, PreRelease: featuregate.Alpha}, + HTTPServer: {Default: false, PreRelease: featuregate.Alpha}, } var CatalogdFeatureGate featuregate.MutableFeatureGate = featuregate.NewFeatureGate() diff --git a/test/e2e/unpack_test.go b/test/e2e/unpack_test.go index 444e0230..73939365 100644 --- a/test/e2e/unpack_test.go +++ b/test/e2e/unpack_test.go @@ -2,7 +2,6 @@ package e2e import ( "context" - "encoding/json" "fmt" "io" "os" @@ -10,7 +9,6 @@ import ( "github.com/google/go-cmp/cmp" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/operator-framework/operator-registry/alpha/declcfg" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -18,7 +16,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest/komega" catalogd "github.com/operator-framework/catalogd/api/core/v1alpha1" ) @@ -82,97 +79,6 @@ var _ = Describe("Catalog Unpacking", func() { g.Expect(cond.Status).To(Equal(metav1.ConditionTrue)) g.Expect(cond.Reason).To(Equal(catalogd.ReasonUnpackSuccessful)) }).Should(Succeed()) - catalogOwnerRef := metav1.NewControllerRef(catalog, catalogd.GroupVersion.WithKind("Catalog")) - - By("Ensuring the expected number of CatalogMetadata objects exist") - catalogMetadataList := &catalogd.CatalogMetadataList{} - err := c.List(ctx, catalogMetadataList) - Expect(err).ToNot(HaveOccurred()) - Expect(catalogMetadataList.Items).To(HaveLen(3)) - - By("Validating the expected CatalogMetadata olm.package object exists") - pack := &catalogd.CatalogMetadata{} - expectedPack := &catalogd.CatalogMetadata{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-%s", catalog.Name, declcfg.SchemaPackage, pkg), - Labels: map[string]string{ - "schema": "olm.package", - "catalog": "test-catalog", - "name": "prometheus", - "package": "", - "packageOrName": "prometheus", - }, - OwnerReferences: []metav1.OwnerReference{*catalogOwnerRef}, - }, - Spec: catalogd.CatalogMetadataSpec{ - Catalog: corev1.LocalObjectReference{ - Name: catalogName, - }, - Schema: declcfg.SchemaPackage, - Name: pkg, - Package: "", - Content: json.RawMessage(`{"defaultChannel":"beta","name":"prometheus","schema":"olm.package"}`), - }, - } - err = c.Get(ctx, client.ObjectKeyFromObject(expectedPack), pack) - Expect(err).ToNot(HaveOccurred()) - Expect(expectedPack).To(komega.EqualObject(pack, komega.IgnoreAutogeneratedMetadata)) - - By("Validating the expected CatalogMetadata olm.channel object exists") - ch := &catalogd.CatalogMetadata{} - expectedCh := &catalogd.CatalogMetadata{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-%s-%s", catalog.Name, declcfg.SchemaChannel, pkg, channel), - Labels: map[string]string{ - "schema": declcfg.SchemaChannel, - "catalog": catalog.Name, - "name": channel, - "package": pkg, - "packageOrName": pkg, - }, - OwnerReferences: []metav1.OwnerReference{*catalogOwnerRef}, - }, - Spec: catalogd.CatalogMetadataSpec{ - Catalog: corev1.LocalObjectReference{ - Name: catalogName, - }, - Schema: declcfg.SchemaChannel, - Name: channel, - Package: pkg, - Content: json.RawMessage(`{"entries":[{"name":"prometheus-operator.0.47.0"}],"name":"beta","package":"prometheus","schema":"olm.channel"}`), - }, - } - err = c.Get(ctx, client.ObjectKeyFromObject(expectedCh), ch) - Expect(err).ToNot(HaveOccurred()) - Expect(expectedCh).To(komega.EqualObject(ch, komega.IgnoreAutogeneratedMetadata)) - - By("Validating the expected CatalogMetadata olm.bundle object exists") - bndl := &catalogd.CatalogMetadata{} - expectedBndl := &catalogd.CatalogMetadata{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s-%s-%s", catalog.Name, declcfg.SchemaBundle, pkg, bundle), - Labels: map[string]string{ - "schema": declcfg.SchemaBundle, - "catalog": catalog.Name, - "name": bundle, - "package": pkg, - "packageOrName": pkg, - }, - OwnerReferences: []metav1.OwnerReference{*catalogOwnerRef}, - }, - Spec: catalogd.CatalogMetadataSpec{ - Catalog: corev1.LocalObjectReference{ - Name: catalogName, - }, - Schema: declcfg.SchemaBundle, - Name: bundle, - Package: pkg, - Content: json.RawMessage(`{"image":"localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0","name":"prometheus-operator.0.47.0","package":"prometheus","properties":[{"type":"olm.package","value":{"packageName":"prometheus","version":"0.47.0"}}],"schema":"olm.bundle"}`), - }, - } - err = c.Get(ctx, client.ObjectKeyFromObject(expectedBndl), bndl) - Expect(err).ToNot(HaveOccurred()) - Expect(expectedBndl).To(komega.EqualObject(bndl, komega.IgnoreAutogeneratedMetadata)) By("Making sure the catalog content is available via the http server") // (TODO): Get the URL from the CR once https://github.com/operator-framework/catalogd/issues/119 is done