operator-framework / catalogd

On-cluster FBC catalog content server
Apache License 2.0
16 stars 32 forks source link

Use FBC as the only API for exposing catalog content on cluster #38

Closed anik120 closed 1 year ago

anik120 commented 1 year ago

Motivation:

Right now, the content of a file-based catalog(distributed in an OCI container image) is exposed on cluster using Package and BundleMetadata APIs. However, this translation layer adds another layer of APIs, that must be maintained and supported, besides the FBC API, without adding any extra value to the goal of exposing the catalog metadata on cluster. Since the FBC API itself is a) Already an API we will be maintaining and providing support guarantees for b) Is sufficient to communicate all of the information in the catalog to the on-cluster consumers (as opposed to the legacy sqlite db API that needed the translation in order to be interpretable/consumable)

the FBC API should be exposed without any translation on cluster.

Goal:

One way to go about this is consolidating the Package/BundleMetadata APIs to a single CatalogMetadata API, that contains the schemas in it's spec field.

For eg, for a package foo that has bundles foo.v0.1.0 and foo.v0.2.0, the following CatalogMetadata objects would be created:

kind: CatalogMetdata 
metadata: 
    labels: 
       catalog: bar
       name: foo.v0.1.0
       package: foo
       schema: olm.bundle
    name: foo.v0.1.0
spec:
   catalog: bar
   package: foo
   schema: olm.bundle
   content: 
      <fbc blob rendered as yaml>
       .
       .
kind: CatalogMetdata 
metadata: 
    labels: 
       catalog: bar
       name: foo.v0.2.0
       package: foo
       schema: olm.bundle
    name: foo.v0.2.0
spec:
   catalog: bar
   package: foo
   schema: olm.bundle
   content: 
      <fbc blob rendered as yaml>
       .
       .
kind: CatalogMetdata 
metadata: 
    labels: 
       catalog: bar
       name: foo.v0.1.0
       package: foo
       schema: olm.package
    name: foo
spec:
   catalog: bar
   package: foo
   schema: olm.package
   content: 
      <fbc blob rendered as yaml>
       .
       .

This would allow clients to query for the content on cluster in a kube native way by taking advantage of the label selectors, and read the content off of the CatalogMetadata objects.

$ kubectl get catalogmetadata -l package=foo
NAME         CATALOG       SCHEMA        PACKAGE              
foo           bar         olm.package    foo   
foo.v0.1.0    bar         olm.bundle     foo 
foo.v0.2.0    bar         olm.bundle     foo   

Acceptance Criteria:

oceanc80 commented 1 year ago

@joelanford's POC that can be used as a resource/reference: https://github.com/joelanford/catalogd Relevant parts are about label selectors.

anik120 commented 1 year ago

Another thing to note for this new API, the current BundleMetadata CRs get built using the values for properties from declCfg as they are, which ends up looking something like this:

spec:
  catalogSource: catalogsource-sample
  image: quay.io/operatorhubio/argocd-operator@sha256:5f4533de114e9301e836155190dc2c66a969f55085af03a4959a2fb0af74e1f4
  package: argocd-operator
  properties:
  - type: olm.gvk
    value: ewogICAgICAgICAgICAgICAgImdyb3VwIjogImFyZ29wcm9qLmlvIiwKICAgICAgICAgICAgICAgICJraW5kIjogIkFwcFByb2plY3QiLAogICAgICAgICAgICAgICAgInZlcnNpb24iOiAidjFhbHBoYTEiCiAgICAgICAgICAgIH0=
  - type: olm.gvk
    value: ewogICAgICAgICAgICAgICAgImdyb3VwIjogImFyZ29wcm9qLmlvIiwKICAgICAgICAgICAgICAgICJraW5kIjogIkFwcGxpY2F0aW9uIiwKICAgICAgICAgICAgICAgICJ2ZXJzaW9uIjogInYxYWxwaGExIgogICAgICAgICAgICB9
  - type: olm.gvk
    value: ewogICAgICAgICAgICAgICAgImdyb3VwIjogImFyZ29wcm9qLmlvIiwKICAgICAgICAgICAgICAgICJraW5kIjogIkFwcGxpY2F0aW9uU2V0IiwKICAgICAgICAgICAgICAgICJ2ZXJzaW9uIjogInYxYWxwaGExIgogICAgICAgICAgICB9
  - type: olm.gvk
    value: ewogICAgICAgICAgICAgICAgImdyb3VwIjogImFyZ29wcm9qLmlvIiwKICAgICAgICAgICAgICAgICJraW5kIjogIkFyZ29DRCIsCiAgICAgICAgICAgICAgICAidmVyc2lvbiI6ICJ2MWFscGhhMSIKICAgICAgICAgICAgfQ==
  - type: olm.gvk
    value: ewogICAgICAgICAgICAgICAgImdyb3VwIjogImFyZ29wcm9qLmlvIiwKICAgICAgICAgICAgICAgICJraW5kIjogIkFyZ29DREV4cG9ydCIsCiAgICAgICAgICAgICAgICAidmVyc2lvbiI6ICJ2MWFscGhhMSIKICAgICAgICAgICAgfQ==
  - type: olm.package
    value: ewogICAgICAgICAgICAgICAgInBhY2thZ2VOYW1lIjogImFyZ29jZC1vcGVyYXRvciIsCiAgICAgICAgICAgICAgICAidmVyc2lvbiI6ICIwLjUuMCIKICAgICAgICAgICAgfQ==
  relatedImages:
  - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0
    name: ""
  - image: quay.io/argoprojlabs/argocd-operator@sha256:2f5c0d4567607266ccacb91d8c2e3b18c2afe0edaf55855dcb1a06b02173b520
    name: ""
  - image: quay.io/operatorhubio/argocd-operator@sha256:5f4533de114e9301e836155190dc2c66a969f55085af03a4959a2fb0af74e1f4
    name: ""

New API should unmarshall these content to make sure they're not base64 encoded data.

joelanford commented 1 year ago

CRs get built using the values for properties from declCfg as they are, which ends up looking something like this

@anik120 I wonder if this is because something is interpreting them as []byte values? If you JSON marshal a []byte, it ends up being base64 encoded. To avoid that, the values need to be treated as json.RawMessage (which is how they are in operator-registry)

everettraven commented 1 year ago

I wonder if this is because something is interpreting them as []byte values? If you JSON marshal a []byte, it ends up being base64 encoded. To avoid that, the values need to be treated as json.RawMessage (which is how they are in operator-registry)

This is the case as we are doing this here: https://github.com/operator-framework/catalogd/blob/8ec44671ac7404d9bf335ecd0eb8389d255e4975/pkg/apis/core/v1beta1/bundlemetadata_types.go#L71-L78

IIRC there were some problems using the types in operator-registry in a CR that would require some changes in operator-registry itself so we rolled our own implementation for the time being. I remember trying to use the json.RawMessage type but for some reason kept running into a weird unmarshalling error so I just set it as []byte with the intention of updating it in the future (that future likely being the PR that resolves this issue)

joelanford commented 1 year ago

Ok, it should be doable in a CR with runtime.RawExtension. Here's how we do it in rukpak: https://github.com/operator-framework/rukpak/blob/0876db6a30de0aaa6ce5651e2e24f5f6d5766e22/api/v1alpha1/bundledeployment_types.go#L51-L53