Skip to content

Instantly share code, notes, and snippets.

@isutton
Last active April 30, 2020 09:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isutton/12a20a8aa1f9a1469a963caa4fc13f3a to your computer and use it in GitHub Desktop.
Save isutton/12a20a8aa1f9a1469a963caa4fc13f3a to your computer and use it in GitHub Desktop.

Support arbitrary path to embed secret

The initial proposal is the following (excerpt from the issue above):

apiVersion: apps.openshift.io/v1alpha1
kind: ServiceBindingRequest
metadata:
  name: binding-request
  namespace: service-binding-demo
spec:
  applicationSelector:
    resourceRef: nodejs-rest-http-crud
    group: sources.eventing.knative.dev
    version: v1alpha1
    resource: KafkaSource
  bindingSecretPath: "spec.template.xyz.envFrom"
  backingServiceSelectors:
    - group: postgresql.baiju.dev
      version: v1alpha1
      kind: Database
      resourceRef: db-demo
    - group: another.group.dev
      version: v1alpha1
      kind: KafkaUser
      resourceRef: my-user-kafka-user

It is assumed that spec.applicationSelector.bindingSecretPath is the path that should be injected in all applications matching either resourceRef or matchLabels. This approach is likely to not work, since it can’t be assumed that an application matching matchLabels will 1) have declared the field in the object and 2) it is not guaranteed that matchLabels would return a list of only Deployment like objects.

There is a duality in applicationSelector itself: if matchLabels is given, then resourceRef and the GVK can be ignored (although I could not find any tests exercising this at the time of this writing).

Another point is that Deployment like objects couldn’t use the bindingSecretPath field to update its containers, meaning there’s actually two different functionalities in there:

  1. Application references, where the equivalent of an ObjectReference is stored; if the referred resource doesn’t exist, the binding can’t be performed nor considered successful.

  2. Application selector, which GVK can be used as predicate to collect the objects for the binding action. For example, using any complete GVK as predicate can result in a list with none or many objects of a specific GVK.

Approach

Given those separate functionalities, a possible approach is to specify strategies to inject secret data in the resolved Applications by mapping those to specific GVKs (the example is using apiVersion/kind for brevity):

- type: PodSpecSlice
  path: .spec.template.spec.containers
  resources:
    - deployments.apps/v1
    - replicasets.core/v1
- type: PodSpecSlice
  path: .spec.deploymentTemplate.spec.containers
  resources:
    - deploymentconfigs.openshift/v1
- type: SecretPath
  path: .spec.eventSourceSecret
  resources:
    - kafkasources.sources.eventing.knative.dev/v1alpha1

The secretInjection is a list of binding instructions, having the following fields:

Type

a valid, known injection type implemented and available in the Operator.

Resources

a list of GroupVersionResource specifying the objects that should be bound with the injector. This mapping decides how the secret data is bound to a particular object kind.

Path

the JSON representing the nodes where the injector should insert the secret.

We currently have implemented the PodSpecSlice injector, which basically assumes a manifest that contains container definitions in pre-defined nodes (for example, Deployment, ReplicaSet and DeploymentConfig all have the same structure).

Even though the contents of this particular example would be a hardcoded configuration, a user could, in theory, map resources to another entry in the secretInjection section to use the PodSpecSlice injection (for example, DeploymentConfig could be such a case, if we choose to support mainly Kubernetes and not have any dependency on OpenShift for the core functionality).

The other injector in the example is the SecretPath injector; the given path indicates the node the operator should inject the secret reference.

Specifying the mapping configuration in the ServiceBindingRequest manifest directly allows the SBO developers to support almost any object to be bound, as long as a compatible injector is available.

Observability

Since compatibility between resources and some injector is required, the case where this compatibility is not fulfilled this information will be propagated to the user through conditions in the ServiceBindingRequest manifest where the injector is defined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment