operator-framework / operator-sdk

SDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.
https://sdk.operatorframework.io
Apache License 2.0
7.25k stars 1.75k forks source link

Unify the commands `operator-sdk add api ` and `operator-sdk add controller` #1741

Closed camilamacedo86 closed 5 years ago

camilamacedo86 commented 5 years ago

Feature Request

Is your feature request related to a problem? Please describe. Lead and make easier the understatement of the concepts for developers built the operator projects. We can find many projects where we have many CR/CRDs using the same controller and/or not representing each one an object.

My current understanding is that an operator project is designed to have resources where each type of resource(CR/CRD) has its own controller and you can indeed manage any resource in any controller since the resources impl in your operator project works in exactly the same way that the API resources as "corev1.Service" for example.

So, when a CR/CRD is created/defined means a new resource/class(representation) with these attributes. So, if we use the same class to define all the different sorts of resources, we may be hurting concepts such as encapsulation, single resposanbilty principle and almost for sure cohesion that may cause unexpected sides effects such difficulty to read, maintain/improve and extend, to mention a few. Just to clarify my POV, it is the same as defining a user class which will have attributes related to other objects as fruits and furniture for example.

Describe the solution you'd like

Unify the commands operator-sdk add api and operator-sdk add controller in order to make more clear the purpose and lead developers following the controller-runtime design.

E.g $ operator-sdk add --api-version=redhat-operator.example.com/v1alpha1 --kind=App will do all actions that is done currently in operator-sdk add api --api-version=redhat-operator.example.com/v1alpha1 --kind=App + operator-sdk add controller --api-version=redhat-operator.example.com/v1alpha1 --kind=App which could be removed from the project in order of we just keep one command.

camilamacedo86 commented 5 years ago

Hi, @shawn-hurley @jmrodri @hasbro17 wdyt?

tony-clarke-amdocs commented 5 years ago

@camilamacedo86 I can imagine there are use cases where you the controller to API (CRD) is not one to one. Maybe you want one controller to own two CRDS because otherwise they are managing some common resources.

camilamacedo86 commented 5 years ago

Hi @tony-clarke-amdocs in my understand it goes implicitly against the design of the controller-runtime. Also, note that you can manage any object in any controller no matter if it is our own api and/or k8s, and/or openshift one.

See here: https://github.com/operator-framework/operator-sdk/issues/1383#issuecomment-489604367 as well.

hasbro17 commented 5 years ago

@camilamacedo86 You're right that having a controller reconcile multiple CR types is an anti pattern.

However you would still want the ability to define a new API type in your project, without necessarily reconciling it as a primary type in your controller. For e.g the prometheus-operator's controller only reconciles the Prometheus resource but it still has the ServiceMonitor defined as the secondary API type which is watched, but is not the primary resource that the operator gets reconcile requests for. That is still a valid operator pattern.

Or if you already have an API type e.g Kind=AppService Group/Version=app.example.com/v1 defined. And you want to define v2 of the same Group and Kind. You don't need to add a controller in that case as well.

So while your rationale is correct that the add api and add controller operations are most commonly performed together, that is not always the case.

So even if we replace the two commands with a single command of add api, we will still need to keep around a flag e.g --controller=true/false to dictate whether we want a controller scaffolded with that API or not.

$ operator-sdk add api --api-version=app.example.com/v1alpha1 --kind=AppService --controller=true

So I don't know if there is much to gain from replacing the add controller subcommand with an optional flag --controller flag if users still have to distinguish when and when not to scaffold a controller. Both are equivalent UX wise, in my opinion.

camilamacedo86 commented 5 years ago

Hi @hasbro17,

Really tks for your input and ideas. My idea with this RFE is we try to make the design implicit for its users and lead them to use it in the best way as possible.

Wdyt over we resolve the v2 scenario programmatically? I mean before the unified command creates the controller we check if the kind has already a controller created for it? Or what about doing as you suggested by using a flag but just when the controller should not be created? I mean, by default the controller will be always created unless we use something like --no-controller or --controller=false

hasbro17 commented 5 years ago

Closing this as we're not considering UX changes before we explore the Kubebuilder integration. All of the above may come about as a result of that integration. https://github.com/kubernetes-sigs/kubebuilder/blob/master/designs/integrating-kubebuilder-and-osdk.md

1955