// Module included in the following assemblies:
//
// * operators/operator_sdk/golang/osdk-golang-quickstart.adoc
// * operators/operator_sdk/ansible/osdk-ansible-quickstart.adoc
// * operators/operator_sdk/helm/osdk-helm-quickstart.adoc

ifeval::["{context}" == "osdk-golang-quickstart"]
:golang:
:type: Go
:app-proper: Memcached
:app: memcached
:group: cache
endif::[]
ifeval::["{context}" == "osdk-ansible-quickstart"]
:ansible:
:type: Ansible
:app-proper: Memcached
:app: memcached
:group: cache
endif::[]
ifeval::["{context}" == "osdk-helm-quickstart"]
:helm:
:type: Helm
:app-proper: Nginx
:app: nginx
:group: demo
endif::[]
ifeval::["{context}" == "osdk-java-quickstart"]
:java:
:type: Java
:app-proper: Memcached
:app: memcached
:group: cache
endif::[]

:_mod-docs-content-type: PROCEDURE
[id="osdk-quickstart_{context}"]
= Creating and deploying {type}-based Operators

You can build and deploy a simple {type}-based Operator for {app-proper} by using the Operator SDK.

.Procedure

. *Create a project.*

.. Create your project directory:
+
[source,terminal,subs="attributes+"]
----
$ mkdir {app}-operator
----

.. Change into the project directory:
+
[source,terminal,subs="attributes+"]
----
$ cd {app}-operator
----

.. Run the `operator-sdk init` command
ifdef::ansible[]
with the `ansible` plugin
endif::[]
ifdef::helm[]
with the `helm` plugin
endif::[]
ifdef::java[]
with the `quarkus` plugin
endif::[]
to initialize the project:
+
[source,terminal,subs="attributes+"]
ifdef::golang[]
----
$ operator-sdk init \
    --domain=example.com \
    --repo=github.com/example-inc/{app}-operator
----
+
The command uses the Go plugin by default.
endif::[]
ifdef::ansible[]
----
$ operator-sdk init \
    --plugins=ansible \
    --domain=example.com
----
endif::[]
ifdef::helm[]
----
$ operator-sdk init \
    --plugins=helm
----
endif::[]
ifdef::java[]
----
$ operator-sdk init \
    --plugins=quarkus \
    --domain=example.com \
    --project-name=memcached-operator
----
endif::[]

. *Create an API.*
+
Create a simple {app-proper} API:
+
[source,terminal,subs="attributes+"]
ifdef::golang[]
----
$ operator-sdk create api \
    --resource=true \
    --controller=true \
    --group {group} \
    --version v1 \
    --kind {app-proper}
----
endif::[]
ifdef::ansible[]
----
$ operator-sdk create api \
    --group {group} \
    --version v1 \
    --kind {app-proper} \
    --generate-role <1>
----
<1> Generates an Ansible role for the API.
endif::[]
ifdef::helm[]
----
$ operator-sdk create api \
    --group {group} \
    --version v1 \
    --kind {app-proper}
----
+
This API uses the built-in Helm chart boilerplate from the `helm create` command.
endif::[]
ifdef::java[]
----
$ operator-sdk create api \
    --plugins quarkus \
    --group {group} \
    --version v1 \
    --kind {app-proper}
----
endif::[]

. *Build and push the Operator image.*
+
Use the default `Makefile` targets to build and push your Operator. Set `IMG` with a pull spec for your image that uses a registry you can push to:
+
[source,terminal]
----
$ make docker-build docker-push IMG=<registry>/<user>/<image_name>:<tag>
----

. *Run the Operator.*

.. Install the CRD:
+
[source,terminal]
----
$ make install
----

.. Deploy the project to the cluster. Set `IMG` to the image that you pushed:
+
[source,terminal]
----
$ make deploy IMG=<registry>/<user>/<image_name>:<tag>
----

ifdef::helm[]
. *Add a security context constraint (SCC).*
+
The {app-proper} service account requires privileged access to run in {product-title}. Add the following SCC to the service account for the `{app}-sample` pod:
+
[source,terminal,subs="attributes+"]
----
$ oc adm policy add-scc-to-user \
    anyuid system:serviceaccount:{app}-operator-system:{app}-sample
----
endif::[]

. *Create a sample custom resource (CR).*

.. Create a sample CR:
+
[source,terminal,subs="attributes+"]
----
$ oc apply -f config/samples/{group}_v1_{app}.yaml \
    -n {app}-operator-system
----

.. Watch for the CR to reconcile the Operator:
+
[source,terminal,subs="attributes+"]
----
$ oc logs deployment.apps/{app}-operator-controller-manager \
    -c manager \
    -n {app}-operator-system
----
ifdef::ansible[]
+
.Example output
[source,terminal]
----
...
I0205 17:48:45.881666       7 leaderelection.go:253] successfully acquired lease memcached-operator-system/memcached-operator
{"level":"info","ts":1612547325.8819902,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting EventSource","source":"kind source: cache.example.com/v1, Kind=Memcached"}
{"level":"info","ts":1612547325.98242,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting Controller"}
{"level":"info","ts":1612547325.9824686,"logger":"controller-runtime.manager.controller.memcached-controller","msg":"Starting workers","worker count":4}
{"level":"info","ts":1612547348.8311093,"logger":"runner","msg":"Ansible-runner exited successfully","job":"4037200794235010051","name":"memcached-sample","namespace":"memcached-operator-system"}
----
endif::[]

. *Delete a CR.*
+
Delete a CR by running the following command:
+
[source,terminal,subs="attributes+"]
----
$ oc delete -f config/samples/{group}_v1_{app}.yaml -n {app}-operator-system
----

. *Clean up.*
+
Run the following command to clean up the resources that have been created as part of this procedure:
+
[source,terminal]
----
$ make undeploy
----

ifeval::["{context}" == "osdk-golang-quickstart"]
:!golang:
:!type:
:!app-proper:
:!app:
endif::[]
ifeval::["{context}" == "osdk-ansible-quickstart"]
:!ansible:
:!type:
:!app-proper:
:!app:
endif::[]
ifeval::["{context}" == "osdk-helm-quickstart"]
:!helm:
:!type:
:!app-proper:
:!app:
endif::[]
ifeval::["{context}" == "osdk-java-quickstart"]
:!java:
:!type:
:!app-proper:
:!app:
endif::[]
