Skip to content

doc/proposal: Ansible Operator proposal #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions doc/proposals/ansible-operator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
## Ansible Operator Proposal

### Background

Not everyone is a golang developer, and therefore gaining adoption for the operator-sdk is capped by the number of golang developers. Also, tooling for kubernetes in other languages is lacking support for things such as informers, caches, and listers.

Operators purpose is to codify the operations of an application on kubernetes. [Ansible](https://www.ansible.com/) is already an industry standard tool for automation and is a good fit for the kind of work that kubernetes operators need to do. Adding the ability for users of the SDK to choose which between ansible and golang to follow will increase the number of potential users, and will grant existing users even more behavior.

### Goals

The goal of the Ansible Operator will be to create a fully functional framework for Ansible developers to create operators. It will also expose a library for golang users to use ansible in their operator if they so choose. These two goals in conjunction will allow users to select the best technology for their project or skillset.

### New Operator Type

This proposal creates a new type of operator called `ansible`. The new type is used to tell the tooling to act on that type of operator.

### Package Structure
Packages will be added to the operator-sdk. These packages are designed to be usable by the end user if they choose to and should have a well documented public API. The proposed packages are:
* /operator-sdk/pkg/ansible/controller
* Will contain the ansible operator controller.
* Will contain a exposed reconciler. But the default `Add` method will use this reconciler.
Copy link
Contributor

Choose a reason for hiding this comment

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

But the default Add method will use this reconciler

@shawn-hurley Just so I understand this correctly, this controller is expected to be added to the manager in the hybrid case right?
likely in cmd/manager/main.go:

import ac "github.com/operator-framework/operator-sdk/pkg/ansible/controller"
...
// Add the manage
ac.Add(mgr, ac.Options{...})

So users can either call Add() to add the default ansible controller to their manager.
Or create their own controller and use the default reconciler (AnsibleOperatorReconciler from #461 )

Copy link
Contributor

Choose a reason for hiding this comment

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

*an exposed

Copy link
Contributor

Choose a reason for hiding this comment

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

My bad I just realized this controller pkg is being used by up local's manager to run the ansible-operator locally.
Although this can still be used in the hybrid case as well I think.

Copy link
Member Author

Choose a reason for hiding this comment

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

@hasbro17 that is what we are thinking as well +1

* /operator-sdk/pkg/ansible/runner
* Contains the runner types and interfaces
* Implementation is behind an internal package (/operator-sdk/pkg/ansible/runner/internal)
* New Methods are exposed and are the main way a user interacts with the package
* Runner interface for running ansible from the operator.
* NewForWatchers - the method that returns a map of GVK to Runner types based on the watchers file.
* NewPlaybookRunner - the method that returns a new Runner for a playbook.
* NewRoleRunner - the method that returns a new Runner for a role.
* This contains the events API code and public methods. Implementation should probably be in the internal package. The events API is used for recieving events from ansible runner.

* /operator-sdk/pkg/ansible/proxy
* This is a reverse proxy for the kubernetes API that is used for owner reference injection.
* /operator-sdk/pkg/ansible/proxy/kubeconfig
* Code needed to generate the kubeconfig for the proxy.
* /operator-sdk/pkg/ansible/events
* Package for event handlers from ansible runner events.
* Default has only the event logger.


### Commands
We are adding and updating existing commands to accommodate the ansible operator. Changes to the `cmd` package as well as changes to the generator are needed.

`operator-sdk new <project-name> --type ansible --kind <kind> --api-version <group/version>` This will be a new generation command under the hood. We will:
* Create a new ansible role in the roles directory
* Create a new watchers file. The role and GVK are defaulted based on input to the command.
* A CRD is generated. This CRD does not have any validations defined.
* A dockerfile is created using the watchers file and the ansible role with the base image being the ansible operator base image.

The resulting structure should be
```
|- Dockerfile
|
|- roles
\ | - <kind>
| \ | - generated ansible role
|
| - watchers.yaml
Copy link
Contributor

Choose a reason for hiding this comment

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

@shawn-hurley shouldn't this be watches.yaml?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, oops 🤦‍♂️

Copy link
Contributor

Choose a reason for hiding this comment

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

cool.. thought it was me :)

|
| - deploy
\ | - <kind>-CRD.yaml
| | - rbac.yaml
| | - operator.yaml
| | - cr.yaml
```

`operator-sdk generate crd <api-version> <kind> ` This will be used to generate new CRDs based on ansible code. The command helps when a user wants to watch more than one CRD for their operator.
Copy link
Contributor

Choose a reason for hiding this comment

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

We probably want to have this functionality for the go operator as well. I think once we switch to controller runtime, we can do that for the go operator. The question I am having now is that how do we generate additional CRDs for both go type and ansible type?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think there is already an operator-sdk generate k8s which will generate the code for custom resources. The ansible only needs the CRD. Therefore I suggest that operator-sdk generate k8s both generates the go structures and a CRD, while this command only generates the CRD.

Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

while this command (operator-sdk generate crd <api-version> <kind>) only generates the CRD.

as long as it can generate a CRD regardless whether the operator is a Go one or Ansible one. I think this command makes sense.

Args:
Required kind - the kind for the object.
Required api-version - the <group>/<version> for the CRD.
Flags:
Optional: --defaults-file - A path to the defaults file to use to generate a new CRD.yaml. If this is not defined, then an empty CRD is created.

`operator-sdk up local` - This should use the known structure and the ansible operator code to run the operator from this location. This will need to be changed to determine if it is an ansible operator or a golang operator. The command works by running the operator-sdk binary, which includes the ansible operator code, as the operator process. This is slightly different than the current up local command.

Copy link
Contributor

Choose a reason for hiding this comment

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

running the operator-sdk binary, which includes the ansible operator code

Sorry if I'm rehashing this again but how exactly does the operator-sdk run the user's local ansible code?
In a Golang project it would just run the main entry point from the local project exec.Command("go run cmd/manager/main.go").

And for a pure ansible project up local is just going to run the main function inside its own process right? i.e start a new manager, read the local watches.yaml and create a controller for each gvk.

Basically up local would run this internally.
https://github.com/water-hole/ansible-operator/blob/master/cmd/ansible-operator/main.go#L29-L78

Is that right?

Copy link
Member

Choose a reason for hiding this comment

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

In a pure ansible operator, up local would run the code you linked to, which would be already compiled into the operator-sdk binary.

In a "hybrid" operator, up local would just treat it like any other golang operator.

Copy link
Member Author

Choose a reason for hiding this comment

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

That is correct!

`operator-sdk build <image-name>` - This builds the operator image. This will need to be changed to determine if ansbile operator or golang operator.