github.com/operator-framework/operator-lifecycle-manager@v0.30.0/doc/contributors/design-proposals/pull-bundle-on-a-cluster.md (about)

     1  # Pull Bundle on a Cluster
     2  
     3  The purpose of this proposal is to allow bundle data to be pulled at install time. At a high level, this starts with launching the bundle inside a pod and then writing the data found inside of the container into a configmap.
     4  
     5  ## Launching a bundle image for data extraction
     6  
     7  The function to call for launching the bundle looks like:
     8  
     9  LaunchBundleImage(kubeclient kubernetes.Interface, bundleImage, initImage, namespace string) (*corev1.ConfigMap, *batchv1.Job, error)
    10  
    11  Here the bundle image, init image, and namespace are the core parameters. Note that it is a requirement that the service account have permissions to update configmaps in the specified namespace. In the expected usage however, the namespace of OLM will be used and permissions will not be a problem. The configmap and job are returned for the caller to delete when done.
    12  
    13  Within the launch function a job is called using a spec simliar to what is described below. Unique random names are able to be depended upon by using generateName for both the job and configmap.
    14  
    15  ```yaml
    16  apiVersion: batch/v1
    17  kind: Job
    18  metadata:
    19    generateName: deploy-bundle-image-
    20  spec:
    21    #ttlSecondsAfterFinished: 0 # alpha feature - https://github.com/kubernetes/enhancements/issues/592, https://github.com/kubernetes/kubernetes/pull/82082
    22    template:
    23      metadata:
    24        name: bundle-image
    25      spec:
    26        containers:
    27        - name: bundle-image
    28          image: &image bundle-image
    29          command: ['/injected/operator-registry', 'serve']
    30          env:
    31            - name: CONTAINER_IMAGE
    32              value: *image
    33          volumeMounts:
    34          - name: copydir
    35            mountPath: /injected
    36        initContainers:
    37        - name: copy-binary
    38          image: init-operator-manifest
    39          imagePullPolicy: Never
    40          command: ['/bin/cp', '/operator-registry', '/copy-dest']
    41          volumeMounts:
    42          - name: copydir
    43            mountPath: /copy-dest
    44        volumes:
    45        - name: copydir
    46          emptyDir: {}
    47        restartPolicy: OnFailure
    48  ```
    49  
    50  ## Serving the bundle data
    51  
    52  A new command will be made in operator-registry to provide functionality for traversing the directies of the bundle image for writing to a configmap (example above is "operator-registry serve"). The configmap format is described in more detail in the next section. The pre-generated configmap name is specified to be updated with the bundle data. As previously noted, after the configmap data has been read it is the responsibility of the caller to delete both the job and configmap. As a sanity check, the configmap is also updated with the image name as an annotation (olm.imageSource).
    53  
    54  ## Store a bundle in a `ConfigMap`
    55  Below is the directory layout of the operator bundle inside the image.
    56  ```bash
    57  $ tree
    58  /
    59  ├── manifests
    60  │   ├── testbackup.crd.yaml
    61  │   ├── testcluster.crd.yaml
    62  │   ├── testoperator.v0.1.0.clusterserviceversion.yaml
    63  │   └── testrestore.crd.yaml
    64  └── metadata
    65      └── annotations.yaml
    66      
    67  $ cat /annotations.yaml
    68  annotations:
    69    operators.coreos.com.bundle.resources: "manifests+metadata"
    70    operators.coreos.com.bundle.mediatype: "operator-registry+v1"
    71  ```
    72  
    73  The following `ConfigMap` maps to the above operator bundle
    74  ```yaml
    75  apiVersion: v1
    76  kind: ConfigMap
    77  metadata:
    78    name: test
    79    namespace: test
    80    annotations:
    81      operators.coreos.com.bundle.resources: "manifests+metadata"
    82      operators.coreos.com.bundle.mediatype: "registry+v1"
    83  data:
    84    testbackup.crd.yaml: content of testbackup.crd.yaml
    85    testcluster.crd.yaml: content of testcluster.crd.yaml
    86    testoperator.v0.1.0.clusterserviceversion.yaml: content oftestoperator.v0.1.0.clusterserviceversion.yaml
    87    testrestore.crd.yaml: content of testrestore.crd.yaml
    88  ```
    89  
    90  The `key` of a `ConfigMap` has the following format
    91  ```go
    92  	// Data contains the configuration data.
    93  	// Each key must consist of alphanumeric characters, '-', '_' or '.'.
    94  	// Values with non-UTF-8 byte sequences must use the BinaryData field.
    95  	// The keys stored in Data must not overlap with the keys in
    96  	// the BinaryData field, this is enforced during validation process.
    97  	// +optional
    98  	Data map[string]string `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"`
    99  ```
   100  
   101  Notes:
   102  * The resource file name needs to be manipulated if it contains special characters.
   103  * The consumer of the `ConfigMap` does not use the key name in `Data` section to identify the type of resource. It should inspect the content.
   104  * The consumer will iterate through the `Data` section and and add each resource to the bundle.
   105  * The annotations from the `annotations.yaml` file is copied to `metadata.annotations` to the `ConfigMap`.
   106  * The `ConfigMap` may have a resource that contains a `PackageManifest` resource. The consumer needs to handle this properly.
   107  
   108  
   109  ## Build a Bundle from ConfigMap
   110  ```go
   111  import (
   112  	"github.com/operator-framework/operator-registry/pkg/registry"
   113  	corev1 "k8s.io/api/core/v1"
   114  )
   115  
   116  // Manifest contains a bundle and a PackageManifest.
   117  type Manifest struct {
   118  	Bundle          *registry.Bundle
   119  	PackageManifest *registry.PackageManifest
   120  }
   121  
   122  type Loader interface {
   123  	Load(cm *corev1.ConfigMap) (manifest *Manifest, err error)
   124  }
   125  ```
   126  
   127  ## Managing Lifecycle of the `ConfigMap`
   128  
   129  ## Things that Happen after reading the configmap
   130  
   131