Skip to content
This repository was archived by the owner on Jun 26, 2024. It is now read-only.

Rename to "applications" and "services" #348

Closed
wants to merge 19 commits into from

Conversation

sbose78
Copy link
Member

@sbose78 sbose78 commented Feb 23, 2020

( .. Based on @isutton 's ideas )

### This is a proposal and open for discussion/debate.

Motivation

  • Simplify the API, " connect applications to services "
  • Ensure 100% backward compatibility, no breaking changes in this PR

Changes

  • Rename spec.applicationSelector to spec.applications
  • Rename spec.backingServiceSelectors to spec.services
  • Support a list of apps : spec.applications
  • In order to maintain backward compatibility, spec.applications, spec.applicationSelector , spec.backingServiceSelector and spec.backingServiceSelectors are all optional. The appropriate parameters have been marked as deprecated.
  • In a future PR, when spec.applicationSelector,spec.backingServiceSelector and spec.backingServiceSelectors are removed, we will mark spec.applications and spec.services as mandatory. Doing so now will break integrations.
apiVersion: apps.openshift.io/v1alpha1
kind: ServiceBindingRequest

metadata:
  name: node-golang-todo-git

spec:

  applications:
  - resourceRef: node-todo-git
    group: apps
    version: v1
    resource: deployments

  services:
  - group: postgresql.baiju.dev
    version: v1alpha1
    kind: Database
    resourceRef: db-demo
  - group: etcd.database.coreos.com
    version: v1beta2
    kind: EtcdCluster
    resourceRef: etcd-demo

Here's how the API looked before:

apiVersion: apps.openshift.io/v1alpha1
kind: ServiceBindingRequest
metadata:
  name: node-todo-git
spec:
  applicationSelector:
    resourceRef: node-todo-git
    group: apps
    version: v1
    resource: deployments
  backingServiceSelectors:
  - group: postgresql.baiju.dev
    version: v1alpha1
    kind: Database
    resourceRef: db-demo
  - group: etcd.database.coreos.com
    version: v1beta2
    kind: EtcdCluster
    resourceRef: etcd-demo

Care is being taken to maintain backward compatibility.

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please assign sbose78
You can assign the PR to them by writing /assign @sbose78 in a comment when ready.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@codecov
Copy link

codecov bot commented Feb 23, 2020

Codecov Report

Merging #348 into master will increase coverage by 0.17%.
The diff coverage is 87.80%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #348      +/-   ##
==========================================
+ Coverage   64.95%   65.12%   +0.17%     
==========================================
  Files          21       21              
  Lines        1418     1431      +13     
==========================================
+ Hits          921      932      +11     
- Misses        372      373       +1     
- Partials      125      126       +1     
Impacted Files Coverage Δ
...troller/servicebindingrequest/custom_env_parser.go 71.42% <66.66%> (ø)
pkg/controller/servicebindingrequest/binder.go 61.07% <90.90%> (+0.79%) ⬆️
pkg/controller/servicebindingrequest/planner.go 93.93% <100.00%> (+0.18%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d8ca153...4a479d1. Read the comment docs.

@otaviof
Copy link
Member

otaviof commented Feb 24, 2020

Overall, I like the proposal, the ServiceBinding will look a lot cleaner this way! Thanks.

Removed support for label selectors in spec.applications

However, I think we should keep label selectors, since they are a general approach to handle Kubernetes based workloads. Therefore, users could choose on using a fully-qualified resource name or labels, should be up to final users.

@sbose78
Copy link
Member Author

sbose78 commented Feb 26, 2020

@isutton , thoughts on removing label selectors?

@isutton
Copy link
Contributor

isutton commented Feb 26, 2020

I've recently discussed about the labels topic with @otaviof and I'm fine supporting both direct references and label selectors for applications. The only question remaining is how to properly encode this information in the manifest.

One option might be keeping the applicationSelector field, but changing its internal fields to only represent or contain a Kubernetes' selector type, and introduce the applications field next to it containing a list of explicit application references.

This implies that watches should, if not already, be created to observe creation and updates of all supported applications' manifests in order to evaluate whether a binding should be applied to it or not.

@sbose78
Copy link
Member Author

sbose78 commented Feb 27, 2020

We could have the following then:

apiVersion: apps.openshift.io/v1alpha1
kind: ServiceBindingRequest

metadata:
  name: node-golang-todo-git

spec:

  applications:
  - group: apps
    version: v1
    resource: deployments
    labels: 
        environment: production
        app: nginx

And

apiVersion: apps.openshift.io/v1alpha1
kind: ServiceBindingRequest

metadata:
  name: node-golang-todo-git

spec:

  applications:
  - group: apps
    version: v1
    resource: deployments
    resourceRef: foo

@sbose78
Copy link
Member Author

sbose78 commented Feb 27, 2020

cc @arthurdm @bbrowning @pdettori
Would love to hear your feedback/thoughts too.

@arthurdm
Copy link
Member

hey @sbose78 - I like the new look of the CRD, cleaner and easier to understand! Assuming that #296 would also apply to applications, all good!

Side note (not meant to de-rail this PR, but since it also relates to updating the CRD)

We're looking to adopt (from the service binding spec) the ServiceBindingRequest CRD as the artifact by which applications use to request bindings. We have identified that we would likely need 2 new keys (per service):

  • one defining a service account to be used by the Service Binding Operator (SBO) to read the Secret exposed by the bindable service (secured with RBAC)
  • one defining the name of a Secret that contained complimentary binding data that SBO would combine with the data available from the bindable service. This is the case where an external subscription entity is used to fetch per-user API keys, or credentials/URI for a provisioned Db, and those are made available in a Secret. So SBO can combine it with the ones it finds, creating a single Secret (to optionally inject back into the app).

Probably this will make more sense once I write it down in a new PR to the spec, just fyi since you guys are thinking about changing the CRD with this PR. =)

The other thing is if apiVersion: apps.openshift.io/v1alpha1 could be made more generic so it doesn't necessarily tie into OpenShift? Some thoughts.

@pdettori
Copy link
Contributor

pdettori commented Feb 27, 2020

@sbose78 great, this looks definitely cleaner. Perhaps for another day/discussion, but have you thought about using a name for the CRD kind that looks more like a noun than an action ? That is, ServiceBinding rather than ServiceBindingRequest ? I think that would be more consistent with the way most CRDs are named in Kubernetes and with desired state based management. A 'Request' seems more like a one-off thing, which I would not expect to keep maintaining the state of the binding, while I suppose that here the Service Binding Operator would reconcile a change in the backing service with the credentials injected in the app.

@bbrowning
Copy link

+1 to applications and services as more concise names for the things being connected

@sbose78
Copy link
Member Author

sbose78 commented Feb 28, 2020

Hi, @arthurdm @pdettori , Thank you!

apiVersion: apps.openshift.io/v1alpha1

Yes, the group name must be changed. openshift must go from there. We'll track this and mark it for an openshift 4.5 timeframe because openshift consumes this API today.

but have you thought about using a name for the CRD kind that looks more like a noun than an action ? That is, ServiceBinding rather than ServiceBindingRequest ?

Yes! We did consider this and there seems to be significant consensus to start calling it servicebinding. I'll come up with a swift plan.

( field for a service to define a service account to be used by the Service Binding Operator (SBO) to read the Secret exposed by the bindable service (secured with RBAC)

This should be optional to handle a situation where the 'default' service account used by the service binding operator doesn't have the privileges to read a specific secret? I wonder if that situation would arise because the service binding operator's service account can read/write secrets in all namespaces.

one defining the name of a Secret that contained complimentary binding data that SBO would combine with the data available from the bindable service.

In this case, are you proposing we skip creating a separate binding secret and instead manage the one provided by the service, with additional information in it?

@arthurdm
Copy link
Member

Hey @sbose78 - thanks for the feedback. It's great to see these things are in motion.

This should be optional to handle a situation where the 'default' service account used by the service binding operator doesn't have the privileges to read a specific secret?

That's right.

I wonder if that situation would arise because the service binding operator's service account can read/write secrets in all namespaces.

Interesting. Is that something that could be configurable? Just thinking if customers would want to have a finer grained RBAC for this, so that everything doesn't become bindable by anyone?

In this case, are you proposing we skip creating a separate binding secret and instead manage the one provided by the service, with additional information in it?

Ya - probably populating the given Secret with anything missing / additional would be easiest. Another approach is to just copy the information from the given Secret into the one SBO creates/manages/injects.

@sbose78
Copy link
Member Author

sbose78 commented Feb 28, 2020

Interesting. Is that something that could be configurable? Just thinking if customers would want to have a finer grained RBAC for this, so that everything doesn't become bindable by anyone?

Custom service accounts would be hard since this operator needs to be watch all namespaces.

I propose a validation webhook & subject-access-review(SAR)-based design to ensure we validate "Does John have the privileges to modify deployment foo?"

What do you think?

@arthurdm
Copy link
Member

ya - perhaps there's 2 sides to this:
(a) does the requester have authority to create a binding to this bindable resource?
(b) (if application injection is not toggled off) does the requester have authority to modify the deployment with the binding data?

From a spec perspective It would be nice to have a single "thing" that we pass into the ServiceBindingRequest where implementations (in this case, SBO) could check for both (a) and (b). I was thinking a service-account was a native way to achieve it, but you bring up a good point that the SBO would already have permissions for all of them. In a validation / SAR design, what would be the artifact we pass around? (let me know if we should move this into a new issue 😄 )

@sbose78
Copy link
Member Author

sbose78 commented Mar 2, 2020

let me know if we should move this into a new issue

yes yes :)

@sbose78
Copy link
Member Author

sbose78 commented Mar 2, 2020

If both labels and resourceRef are present in applications[i], should we compile a cumulative list of

  • objects by resourceRef
  • objects by label selectors ?

@DhritiShikhar @isutton

@isutton
Copy link
Contributor

isutton commented Mar 20, 2020

The reason I prefer using pointers is that it helps our code distinguish between the following:

[snip]

  1. BackingServiceSelectors is used:

    • when [], the field might have been skipped in the CR. OR the user might have specified an empty list in the CR <-- this is an ambiguity.

I agree that some situations might require this approach (mostly when dealing with scalars and default values), but in this operator's particular case I'm unsure whether those precautions are required, since there are no semantic differences between an unpopulated or nil slice; additionally if any clean-up or amendment if necessary should be based on the differences between the previous state and the new desired state.

@sbose78
Copy link
Member Author

sbose78 commented Mar 20, 2020

I had actually moved out the change to a different PR because of a different observation as well #369 . This PR no longer introduces that change.

// different subresources owned by backing operator CR.
// +optional
DetectBindingResources bool `json:"detectBindingResources"`
ApplicationSelector *ApplicationSelector `json:"applicationSelector"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be omitempty

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed :)

@Avni-Sharma
Copy link
Contributor

/retest

2 similar comments
@sbose78
Copy link
Member Author

sbose78 commented Apr 1, 2020

/retest

@sbose78
Copy link
Member Author

sbose78 commented Apr 2, 2020

/retest

@sbose78
Copy link
Member Author

sbose78 commented Apr 2, 2020

/test 4.4-e2e

@ron1
Copy link

ron1 commented Apr 2, 2020

Up until now, it has been my understanding that a single ServiceBindingRequest CR was intended to bind one or more applications to a single backing service. The motivation for backingServiceSelectors being plural was to support complex backing services that had needed binding properties spread around in multiple resources. For example, a backing Kafka service has needed binding properties stored in both its KafkaCluster CR and its KafkaUser CR.

Is the name change from backingServiceSelectors to services intended to change the scope of the SBR CR such that now it binds one or more applications to multiple backing services rather than a single backing service? If so, then I think it would be good to have a discussion about the pros and cons of such a scope change. To me, this is much bigger than a simple name change.

OTOH, if this name change does not change the scope and a SBR CR still represents binding to a single backing service with potentially multiple selectors, then maybe the name change should be from backingServiceSelectors to the more simple serviceSelectors. With this name, it is more clear that a single service is the binding target resource and that multiple selectors may be required in order to capture all the binding information.

WDYT?

@isutton
Copy link
Contributor

isutton commented Apr 2, 2020 via email

@ron1
Copy link

ron1 commented Apr 2, 2020

@isutton Thanks for your reply.

In complex binding scenarios as is the case for Kafka with mutual TLS, the use of two independent service "entries" for the same Kafka service seems a bit unintuitive. In the binding secret at least, shouldn't the fact that I needed two service "entries" in order to bind to this one complex Kafka service be hidden? Is the thought that each service "entry" will have its own optional envvarprefix or id or mountpath and the two independent Kafka service "entries" will be associated with one another by assigning them the same envvarprefix/id/mountpath?

@isutton
Copy link
Contributor

isutton commented Apr 2, 2020 via email

@arthurdm
Copy link
Member

arthurdm commented Apr 3, 2020

we've been discussing the idea of
aggregate the configuration values collected from the services, and
grouping those accordingly.

@isutton - in this case, would you not just simply add the service's ID, as per this section? This section of the spec will apply also to injected values once this issue is written down, so it's consistent with mounted values. Would make sense to store these values with their IDs in the Secret.

@ron1
Copy link

ron1 commented Apr 3, 2020

My point is simply that Kafka and KafkaUser should.not be treated as separate services. Instead their properties should be globbed together in the binding secret. How does the SBR know to glob these two services together?

@arthurdm Would these two services share a common ID which would allow their properties to be globbed together in the binding secret.

@isutton
Copy link
Contributor

isutton commented Apr 3, 2020 via email

@isutton
Copy link
Contributor

isutton commented Apr 3, 2020 via email

@ron1
Copy link

ron1 commented Apr 3, 2020

I believe an intended goal is to provide a canonical Service Binding Schema for backing services. In the above example, Kafka is a single service but requires two service "entries" to accomplish its binding. Some of the binding schema elements are extracted from the Kafka CR and others are extracted from the KafkaUser CR. From a binding schema perspective, all binding properties for a single type=kafka should appear within a single "binding root" regardless of the CR from which they were extracted.

In other words, I do not want a Kafka "binding root" in the resulting binding secret that has the following subset of binding schema elements:

type - kafka
endpoints.<listener_name> - bootstrap server information for all listeners (TBD)
ca.p12 - CA certificate PKCS #12 archive file for storing certificates and keys (binding:env:object:secret:ca.p12)
ca.password - password for protecting the CA certficate PKCS #12 archive file (binding:env:object:secret:ca.password)

and another KafkaUser "binding root" that has the remaining subset of binding schema elements:

username - username for the consuming client (binding:env:object:secret:username)
user.p12 - user certificate for the consuming client PKCS #12 archive file for storing certificates and keys (binding:env:object:secret:user.p12)
user.password - password for protecting the user certficate PKCS #12 archive file (binding:env:object:secret:user.password)

Again, the resulting binding secret should have a single binding type=kafka that contains all the above properties. No binding type=kafkauser should be introduced.

If the service "entries" for Kafka and KafkaUser shared a common id, for example, that id could potentially serve as the "binding root" in the binding secret within which all the properties are located.

@isutton isutton mentioned this pull request Apr 3, 2020
service operator. Deprecation Notice: In the upcoming release, this
field would be depcreated. It would be mandatory to set "backingServiceSelectors".'
description: BackingServiceSelector is used to identify the backing
service operator. Deprecated. In the upcoming release, this field
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

backing service operator or any other k8s resource

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@@ -99,10 +99,78 @@ spec:
- resource
- version
type: object
applications:
description: Applications are used to identify the application connecting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

multiple applications

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is auto-generated from

        // Applications are used to identify the application connecting to the
	// backing service.
	// +optional
	Applications *[]ApplicationSelector `json:"applications,omitempty"`

@@ -251,8 +319,34 @@ spec:
description: EnvVarPrefix is the prefix for environment variables
type: string
mountPathPrefix:
description: MountPathPrefix is the prefix for volume mount
description: "Important: Run \"operator-sdk generate k8s\" to regenerate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

description here should not change, the previous one looks good MountPathPrefix is the prefix for volume mount

// DetectBindingResources is flag used to bind all non-bindable variables from
// different subresources owned by backing operator CR.
// +optional
DetectBindingResources bool `json:"detectBindingResources"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omitempty should be included for +optional fiellds

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind if I fixed it in a different PR, since the change isn't related?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@sbose78
Copy link
Member Author

sbose78 commented Apr 7, 2020

/retest

@@ -85,6 +85,9 @@ func (p *Planner) Plan() (*Plan, error) {
if p.sbr.Spec.BackingServiceSelectors != nil {
selectors = append(selectors, *p.sbr.Spec.BackingServiceSelectors...)
}
if p.sbr.Spec.Services != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A similar condition for p.sbr.Spec.Applications is missing that should be checked in a similar was as for https://github.com/redhat-developer/service-binding-operator/blob/master/pkg/controller/servicebindingrequest/planner.go#L83

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sbose78
Copy link
Member Author

sbose78 commented Apr 17, 2020

/hold

@sbose78
Copy link
Member Author

sbose78 commented May 27, 2020

Replaced by #495

@sbose78 sbose78 closed this May 27, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.