├── .generate └── gen-all.sh ├── .gitignore ├── LICENSE ├── README.md ├── ansible ├── .generate │ ├── defaults_main.yml │ ├── gen-ansible-memcached.sh │ ├── role_main.yml │ ├── size_podcount_test.yml │ └── test-molecule.sh ├── README.md └── memcached-operator │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── README.md │ ├── bundle.Dockerfile │ ├── bundle │ ├── manifests │ │ ├── cache.example.com_memcacheds.yaml │ │ ├── memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml │ │ └── memcached-operator.clusterserviceversion.yaml │ ├── metadata │ │ └── annotations.yaml │ └── tests │ │ └── scorecard │ │ └── config.yaml │ ├── config │ ├── crd │ │ ├── bases │ │ │ └── cache.example.com_memcacheds.yaml │ │ └── kustomization.yaml │ ├── default │ │ ├── kustomization.yaml │ │ └── manager_auth_proxy_patch.yaml │ ├── manager │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── manifests │ │ ├── bases │ │ │ └── memcached-operator.clusterserviceversion.yaml │ │ └── kustomization.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── memcached_editor_role.yaml │ │ ├── memcached_viewer_role.yaml │ │ ├── role.yaml │ │ └── role_binding.yaml │ ├── samples │ │ ├── cache_v1alpha1_memcached.yaml │ │ └── kustomization.yaml │ ├── scorecard │ │ ├── bases │ │ │ └── config.yaml │ │ ├── kustomization.yaml │ │ └── patches │ │ │ ├── basic.config.yaml │ │ │ └── olm.config.yaml │ └── testing │ │ ├── debug_logs_patch.yaml │ │ ├── kustomization.yaml │ │ ├── manager_image.yaml │ │ └── pull_policy │ │ ├── Always.yaml │ │ ├── IfNotPresent.yaml │ │ └── Never.yaml │ ├── molecule │ ├── default │ │ ├── converge.yml │ │ ├── create.yml │ │ ├── destroy.yml │ │ ├── kustomize.yml │ │ ├── molecule.yml │ │ ├── prepare.yml │ │ ├── tasks │ │ │ ├── memcached_test.yml │ │ │ └── size_podcount_test.yml │ │ └── verify.yml │ └── kind │ │ ├── converge.yml │ │ ├── create.yml │ │ ├── destroy.yml │ │ └── molecule.yml │ ├── playbooks │ └── .placeholder │ ├── requirements.yml │ ├── roles │ ├── .placeholder │ └── memcached │ │ ├── README.md │ │ ├── defaults │ │ └── main.yml │ │ ├── files │ │ └── .placeholder │ │ ├── handlers │ │ └── main.yml │ │ ├── meta │ │ └── main.yml │ │ ├── tasks │ │ └── main.yml │ │ ├── templates │ │ └── .placeholder │ │ └── vars │ │ └── main.yml │ └── watches.yaml ├── go ├── .generate │ └── gen-go-sample.sh ├── .gitignore ├── README.md ├── doc │ └── README.md └── memcached-operator │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ └── v1alpha1 │ │ ├── groupversion_info.go │ │ ├── memcached_types.go │ │ ├── memcached_webhook.go │ │ └── zz_generated.deepcopy.go │ ├── bundle.Dockerfile │ ├── bundle │ ├── manifests │ │ ├── cache.example.com_memcacheds.yaml │ │ ├── memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml │ │ └── memcached-operator.clusterserviceversion.yaml │ ├── metadata │ │ └── annotations.yaml │ └── tests │ │ └── scorecard │ │ └── config.yaml │ ├── config │ ├── certmanager │ │ ├── certificate.yaml │ │ ├── kustomization.yaml │ │ └── kustomizeconfig.yaml │ ├── crd │ │ ├── bases │ │ │ └── cache.example.com_memcacheds.yaml │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ └── patches │ │ │ ├── cainjection_in_memcacheds.yaml │ │ │ └── webhook_in_memcacheds.yaml │ ├── default │ │ ├── kustomization.yaml │ │ ├── manager_auth_proxy_patch.yaml │ │ ├── manager_webhook_patch.yaml │ │ └── webhookcainjection_patch.yaml │ ├── manager │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── manifests │ │ ├── bases │ │ │ └── memcached-operator.clusterserviceversion.yaml │ │ └── kustomization.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── memcached_editor_role.yaml │ │ ├── memcached_viewer_role.yaml │ │ ├── role.yaml │ │ └── role_binding.yaml │ ├── samples │ │ ├── cache_v1alpha1_memcached.yaml │ │ └── kustomization.yaml │ ├── scorecard │ │ ├── bases │ │ │ └── config.yaml │ │ ├── kustomization.yaml │ │ └── patches │ │ │ ├── basic.config.yaml │ │ │ └── olm.config.yaml │ └── webhook │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ ├── manifests.yaml │ │ └── service.yaml │ ├── controllers │ ├── memcached_controller.go │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ └── boilerplate.go.txt │ ├── main.go │ └── packagemanifests │ ├── 0.0.1 │ ├── cache.example.com_memcacheds.yaml │ ├── memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml │ └── memcached-operator.clusterserviceversion.yaml │ └── memcached-operator.package.yaml └── helm ├── .generate ├── gen-helm-memcached.sh └── policy-role.yaml ├── README.md └── memcached-operator ├── .gitignore ├── Dockerfile ├── Makefile ├── PROJECT ├── bundle.Dockerfile ├── bundle ├── manifests │ ├── cache.example.com_memcacheds.yaml │ ├── memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml │ └── memcached-operator.clusterserviceversion.yaml ├── metadata │ └── annotations.yaml └── tests │ └── scorecard │ └── config.yaml ├── config ├── crd │ ├── bases │ │ └── cache.example.com_memcacheds.yaml │ └── kustomization.yaml ├── default │ ├── kustomization.yaml │ └── manager_auth_proxy_patch.yaml ├── manager │ ├── kustomization.yaml │ └── manager.yaml ├── manifests │ ├── bases │ │ └── memcached-operator.clusterserviceversion.yaml │ └── kustomization.yaml ├── prometheus │ ├── kustomization.yaml │ └── monitor.yaml ├── rbac │ ├── auth_proxy_client_clusterrole.yaml │ ├── auth_proxy_role.yaml │ ├── auth_proxy_role_binding.yaml │ ├── auth_proxy_service.yaml │ ├── kustomization.yaml │ ├── leader_election_role.yaml │ ├── leader_election_role_binding.yaml │ ├── memcached_editor_role.yaml │ ├── memcached_viewer_role.yaml │ ├── role.yaml │ └── role_binding.yaml ├── samples │ ├── cache_v1alpha1_memcached.yaml │ └── kustomization.yaml └── scorecard │ ├── bases │ └── config.yaml │ ├── kustomization.yaml │ └── patches │ ├── basic.config.yaml │ └── olm.config.yaml ├── helm-charts └── memcached │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── pdb.yaml │ ├── servicemonitor.yaml │ ├── statefulset.yaml │ └── svc.yaml │ └── values.yaml └── watches.yaml /.generate/gen-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 The Operator-SDK Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Before run this script ensure that you have helm installed locally 18 | # with the stable repo as well. The helm sample will use the memcached chart 19 | # from helm repository. 20 | # To install: https://helm.sh/docs/intro/install/ 21 | # To add the repo run `helm repo add stable https://charts.helm.sh/stable` 22 | 23 | set -o errexit 24 | set -o pipefail 25 | 26 | # Turn colors in this script off by setting the NO_COLOR variable in your 27 | # environment to any value: 28 | # 29 | # $ NO_COLOR=1 test.sh 30 | NO_COLOR=${NO_COLOR:-""} 31 | if [ -z "$NO_COLOR" ]; then 32 | header=$'\e[1;33m' 33 | reset=$'\e[0m' 34 | else 35 | header='' 36 | reset='' 37 | fi 38 | 39 | #=================================================================== 40 | # FUNCTION trap_add () 41 | # 42 | # Purpose: prepends a command to a trap 43 | # 44 | # - 1st arg: code to add 45 | # - remaining args: names of traps to modify 46 | # 47 | # Example: trap_add 'echo "in trap DEBUG"' DEBUG 48 | # 49 | # See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal 50 | #=================================================================== 51 | 52 | function trap_add() { 53 | trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error" 54 | new_cmd= 55 | for trap_add_name in "$@"; do 56 | # Grab the currently defined trap commands for this trap 57 | existing_cmd=`trap -p "${trap_add_name}" | awk -F"'" '{print $2}'` # Define default command 58 | [ -z "${existing_cmd}" ] && existing_cmd="echo exiting @ `date`" # Generate the new command 59 | new_cmd="${trap_add_cmd};${existing_cmd}" # Assign the test 60 | trap "${new_cmd}" "${trap_add_name}" || \ 61 | fatal "unable to add to trap ${trap_add_name}" 62 | done 63 | } 64 | function header_text { 65 | echo "$header$*$reset" 66 | } 67 | # edit the release version before execute the script 68 | RELEASE_VERSION=v1.1.0 69 | function install_bin() { 70 | header_text "installing the SDK version ${RELEASE_VERSION}" 71 | TMPDIR="$(mktemp -d)" 72 | trap_add 'rm -rf $TMPDIR' EXIT 73 | pushd "$TMPDIR" 74 | git clone https://github.com/operator-framework/operator-sdk 75 | cd operator-sdk 76 | git checkout ${RELEASE_VERSION} 77 | git checkout -b generate-release-${RELEASE_VERSION} 78 | make tidy 79 | make install 80 | operator-sdk version 81 | } 82 | 83 | ROOTDIR="$(pwd)" 84 | 85 | install_bin 86 | 87 | header_text "updating samples" 88 | 89 | cd $ROOTDIR 90 | cd ../go/.generate/ 91 | ./gen-go-sample.sh 92 | 93 | cd $ROOTDIR 94 | cd ../helm/.generate/ 95 | ./gen-helm-memcached.sh 96 | 97 | cd $ROOTDIR 98 | cd ../ansible/.generate/ 99 | ./gen-ansible-memcached.sh 100 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | */.idea/ 3 | */*/.idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [DEPRECATED] Operator SDK Samples 2 | 3 | This repository has been deprecated. The sample operator projects have been moved to `testdata/` in [Operator SDK](https://github.com/operator-framework/operator-sdk/) repository. For more info see the [enhancement proposal](https://github.com/operator-framework/enhancements/blob/master/enhancements/samples-generation.md) for automatic sample generation using Go. 4 | 5 | This project is a component of the [Operator Framework](https://github.com/operator-framework), an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post](https://coreos.com/blog/introducing-operator-framework). 6 | 7 | Note that, the latest SDK released version used to update the samples is 1.1.0. 8 | 9 | ## Overview 10 | 11 | This repo contains samples of operators built using the [operator-sdk][operator_sdk]. 12 | 13 | To view operators which leverage Go, Ansible, or Helm for deployment, see the [Go][go_examples], [Ansible][ansible_examples], or [Helm][helm_examples] samples sections, respectively. 14 | 15 | **NOTE:** For examples of other operators, see the [Awesome Operators][awesome-operators] repo. However, note that not all of these operators were written using [operator-sdk][operator_sdk]. 16 | 17 | [operator_sdk]:https://github.com/operator-framework/operator-sdk 18 | [go_examples]:./go/ 19 | [ansible_examples]:./ansible/ 20 | [helm_examples]:./helm/ 21 | [awesome-operators]:https://github.com/operator-framework/awesome-operators 22 | -------------------------------------------------------------------------------- /ansible/.generate/defaults_main.yml: -------------------------------------------------------------------------------- 1 | # Update file in operator-sdk-samples/ansible/generate/defaults_main.yml 2 | size: 1 3 | -------------------------------------------------------------------------------- /ansible/.generate/gen-ansible-memcached.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | 6 | # NO_COLOR=1 # Uncomment to disable color. 7 | NO_COLOR=${NO_COLOR:-""} 8 | if [ -z "$NO_COLOR" ]; then 9 | header=$'\e[1;33m' 10 | reset=$'\e[0m' 11 | else 12 | header='' 13 | reset='' 14 | fi 15 | 16 | operatorName="memcached-operator" 17 | operIMG="quay.io/example-inc/memcached-operator:v0.0.1" 18 | bundleIMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" 19 | 20 | function header_text { 21 | echo "$header$*$reset" 22 | } 23 | 24 | function gen_ansible_memcached { 25 | header_text "Regenerating Ansible Memcached sample." 26 | 27 | header_text "Removing previous sample." 28 | cd .. 29 | mv $operatorName/README.md .generate/README-BAK.md 30 | rm -rf $operatorName 31 | 32 | header_text "creating $operatorName" 33 | mkdir $operatorName 34 | cd $operatorName 35 | operator-sdk init --plugins=ansible --group=cache --domain=example.com --version=v1alpha1 --kind=Memcached --generate-role 36 | 37 | 38 | header_text "Customizing for Memcached" 39 | cd ../.generate 40 | 41 | header_text "... adding README" 42 | mv README-BAK.md ../$operatorName/README.md 43 | 44 | header_text "... adding Ansible task and variable" 45 | cat role_main.yml >> ../$operatorName/roles/memcached/tasks/main.yml 46 | cat defaults_main.yml >> ../$operatorName/roles/memcached/defaults/main.yml 47 | sed -i 's|foo: bar|size: 1|g' ../$operatorName/config/samples/cache_v1alpha1_memcached.yaml 48 | 49 | header_text "... adding molecule test for Ansible task" 50 | sed -i 's/false/true/' ../$operatorName/molecule/default/tasks/memcached_test.yml 51 | cp size_podcount_test.yml ../$operatorName/molecule/default/tasks/size_podcount_test.yml 52 | 53 | header_text "bulding the project ..." 54 | cd ../$operatorName/ 55 | make docker-build IMG=$operIMG 56 | 57 | header_text "integrating with OLM ..." 58 | sed -i".bak" -E -e 's/operator-sdk generate kustomize manifests/operator-sdk generate kustomize manifests --interactive=false/g' Makefile; rm -f Makefile.bak 59 | 60 | header_text "generating bundle and building the image $bundleIMG ..." 61 | make bundle IMG=$operIMG 62 | make bundle-build BUNDLE_IMG=$bundleIMG 63 | } 64 | 65 | gen_ansible_memcached 66 | 67 | -------------------------------------------------------------------------------- /ansible/.generate/role_main.yml: -------------------------------------------------------------------------------- 1 | # Update file in operator-sdk-samples/ansible/generate/role_main.yml 2 | - name: start memcached 3 | community.kubernetes.k8s: 4 | definition: 5 | kind: Deployment 6 | apiVersion: apps/v1 7 | metadata: 8 | name: '{{ ansible_operator_meta.name }}-memcached' 9 | namespace: '{{ ansible_operator_meta.namespace }}' 10 | spec: 11 | replicas: "{{size}}" 12 | selector: 13 | matchLabels: 14 | app: memcached 15 | template: 16 | metadata: 17 | labels: 18 | app: memcached 19 | spec: 20 | containers: 21 | - name: memcached 22 | command: 23 | - memcached 24 | - -m=64 25 | - -o 26 | - modern 27 | - -v 28 | image: "docker.io/memcached:1.4.36-alpine" 29 | ports: 30 | - containerPort: 11211 31 | -------------------------------------------------------------------------------- /ansible/.generate/size_podcount_test.yml: -------------------------------------------------------------------------------- 1 | # Update file in operator-sdk-samples/ansible/generate/size_podcount_test.yml 2 | --- 3 | - name: Create the cache.example.com/v1alpha1.Memcached 4 | k8s: 5 | state: present 6 | namespace: "{{ namespace }}" 7 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 8 | wait: yes 9 | wait_timeout: 300 10 | wait_condition: 11 | type: Running 12 | reason: Successful 13 | status: "True" 14 | vars: 15 | cr_file: 'cache_v1alpha1_memcached.yaml' 16 | 17 | - name: Wait 2 minutes for memcached pod to start 18 | k8s_info: 19 | kind: "Pod" 20 | api_version: "v1" 21 | namespace: "osdk-test" 22 | label_selectors: 23 | - app = memcached 24 | register: pod_list 25 | until: 26 | - pod_list.resources is defined 27 | - pod_list.resources|length == 1 28 | retries: 12 29 | delay: 10 30 | 31 | - name: Delete memcached pod 32 | community.kubernetes.k8s: 33 | state: absent 34 | definition: 35 | kind: Pod 36 | api_version: v1 37 | metadata: 38 | namespace: "{{ namespace }}" 39 | name: "{{ item.metadata.name }}" 40 | loop: "{{ pod_list.resources }}" 41 | 42 | - name: pause 43 | pause: 44 | seconds: 10 45 | 46 | - name: Wait 2 minutes for memcached pod to restart 47 | k8s_info: 48 | kind: "Pod" 49 | api_version: "v1" 50 | namespace: "osdk-test" 51 | label_selectors: 52 | - app = memcached 53 | register: pod_list 54 | until: 55 | - pod_list.resources is defined 56 | - pod_list.resources|length == 1 57 | retries: 12 58 | delay: 10 59 | 60 | 61 | - name: Edit Memcached size 62 | k8s: 63 | state: present 64 | namespace: "{{ namespace }}" 65 | definition: 66 | apiVersion: cache.example.com/v1alpha1 67 | kind: Memcached 68 | metadata: 69 | name: memcached-sample 70 | spec: 71 | size: 3 72 | 73 | - name: Wait 2 minutes for 3 memcached pods 74 | k8s_info: 75 | kind: "Pod" 76 | api_version: "v1" 77 | namespace: "osdk-test" 78 | label_selectors: 79 | - app = memcached 80 | register: pod_list 81 | until: 82 | - pod_list.resources is defined 83 | - pod_list.resources|length == 1 84 | retries: 12 85 | delay: 10 86 | -------------------------------------------------------------------------------- /ansible/.generate/test-molecule.sh: -------------------------------------------------------------------------------- 1 | source ~/.virtualenvs/molecule/bin/activate 2 | 3 | cd ../memcached-operator 4 | export IMG='quay.io/asmacdo/example-operator:v0.0.1' 5 | export OPERATOR_IMAGE=${IMG} 6 | make docker-build docker-push 7 | time molecule test -s kind 8 | -------------------------------------------------------------------------------- /ansible/README.md: -------------------------------------------------------------------------------- 1 | This project is a component of the [Operator 2 | Framework](https://github.com/operator-framework), an open source 3 | toolkit to manage Kubernetes native applications, called Operators, in 4 | an effective, automated, and scalable way. Read more in the 5 | [introduction blog 6 | post](https://coreos.com/blog/introducing-operator-framework). 7 | 8 | # Operator SDK Samples - Ansible 9 | This directory contains samples of operators powered by Ansible built 10 | using the [operator-sdk][operator_sdk]. To learn more about creating an 11 | operator that leverages Ansible, check out the [Ansible tutorial][ansible_tutorial]. 12 | 13 | [operator_sdk]:https://github.com/operator-framework/operator-sdk 14 | [ansible_tutorial]:https://sdk.operatorframework.io/docs/building-operators/ansible/tutorial/ 15 | -------------------------------------------------------------------------------- /ansible/memcached-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # editor and IDE paraphernalia 11 | .idea 12 | *.swp 13 | *.swo 14 | *~ 15 | -------------------------------------------------------------------------------- /ansible/memcached-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/operator-framework/ansible-operator:v1.1.0 2 | 3 | COPY requirements.yml ${HOME}/requirements.yml 4 | RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ 5 | && chmod -R ug+rwx ${HOME}/.ansible 6 | 7 | COPY watches.yaml ${HOME}/watches.yaml 8 | COPY roles/ ${HOME}/roles/ 9 | COPY playbooks/ ${HOME}/playbooks/ 10 | -------------------------------------------------------------------------------- /ansible/memcached-operator/Makefile: -------------------------------------------------------------------------------- 1 | # Current Operator version 2 | VERSION ?= 0.0.1 3 | # Default bundle image tag 4 | BUNDLE_IMG ?= controller-bundle:$(VERSION) 5 | # Options for 'bundle-build' 6 | ifneq ($(origin CHANNELS), undefined) 7 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 8 | endif 9 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 10 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 11 | endif 12 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 13 | 14 | # Image URL to use all building/pushing image targets 15 | IMG ?= controller:latest 16 | 17 | all: docker-build 18 | 19 | # Run against the configured Kubernetes cluster in ~/.kube/config 20 | run: ansible-operator 21 | $(ANSIBLE_OPERATOR) run 22 | 23 | # Install CRDs into a cluster 24 | install: kustomize 25 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 26 | 27 | # Uninstall CRDs from a cluster 28 | uninstall: kustomize 29 | $(KUSTOMIZE) build config/crd | kubectl delete -f - 30 | 31 | # Deploy controller in the configured Kubernetes cluster in ~/.kube/config 32 | deploy: kustomize 33 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 34 | $(KUSTOMIZE) build config/default | kubectl apply -f - 35 | 36 | # Undeploy controller in the configured Kubernetes cluster in ~/.kube/config 37 | undeploy: kustomize 38 | $(KUSTOMIZE) build config/default | kubectl delete -f - 39 | 40 | # Build the docker image 41 | docker-build: 42 | docker build . -t ${IMG} 43 | 44 | # Push the docker image 45 | docker-push: 46 | docker push ${IMG} 47 | 48 | PATH := $(PATH):$(PWD)/bin 49 | SHELL := env PATH=$(PATH) /bin/sh 50 | OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') 51 | ARCH = $(shell uname -m | sed 's/x86_64/amd64/') 52 | OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') 53 | ARCHOPER = $(shell uname -m ) 54 | 55 | kustomize: 56 | ifeq (, $(shell which kustomize 2>/dev/null)) 57 | @{ \ 58 | set -e ;\ 59 | mkdir -p bin ;\ 60 | curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ 61 | } 62 | KUSTOMIZE=$(realpath ./bin/kustomize) 63 | else 64 | KUSTOMIZE=$(shell which kustomize) 65 | endif 66 | 67 | ansible-operator: 68 | ifeq (, $(shell which ansible-operator 2>/dev/null)) 69 | @{ \ 70 | set -e ;\ 71 | mkdir -p bin ;\ 72 | curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.1.0/ansible-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ;\ 73 | mv ansible-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ 74 | chmod +x ./bin/ansible-operator ;\ 75 | } 76 | ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) 77 | else 78 | ANSIBLE_OPERATOR=$(shell which ansible-operator) 79 | endif 80 | 81 | # Generate bundle manifests and metadata, then validate generated files. 82 | .PHONY: bundle 83 | bundle: kustomize 84 | operator-sdk generate kustomize manifests --interactive=false -q 85 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 86 | $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 87 | operator-sdk bundle validate ./bundle 88 | 89 | # Build the bundle image. 90 | .PHONY: bundle-build 91 | bundle-build: 92 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 93 | -------------------------------------------------------------------------------- /ansible/memcached-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: example.com 2 | layout: ansible.sdk.operatorframework.io/v1 3 | projectName: memcached-operator 4 | resources: 5 | - group: cache 6 | kind: Memcached 7 | version: v1alpha1 8 | version: 3-alpha 9 | -------------------------------------------------------------------------------- /ansible/memcached-operator/README.md: -------------------------------------------------------------------------------- 1 | # Memcached Operator 2 | 3 | ## Overview 4 | 5 | This Memcached operator is a simple example operator for the [Operator SDK][operator_sdk]. It includes: 6 | * A Custom Resource Definition for `Memcached` resources 7 | * An Ansible-based controller to respond to `Memcached` resources 8 | * Molecule-based tests for the Ansible role. 9 | 10 | ## Prerequisites 11 | 12 | - [docker][docker_tool] version 17.03+ 13 | - [kubectl][kubectl_tool] v1.14.1+ 14 | - [operator_sdk][operator_install] 15 | - Access to a Kubernetes v1.14.1+ cluster 16 | 17 | ## Getting Started 18 | 19 | ### Cloning the repository 20 | 21 | Checkout this Memcached Operator repository 22 | 23 | ``` 24 | git clone https://github.com/operator-framework/operator-sdk-samples.git 25 | cd operator-sdk-samples/ansible/memcached-operator 26 | ``` 27 | 28 | ### Building the operator 29 | 30 | Build the Memcached operator image and push it to a public registry, such as quay.io: 31 | 32 | ```sh 33 | export IMG=quay.io/example-inc/memcached-operator:v0.0.1 34 | docker push IMG=$IMG 35 | ``` 36 | 37 | **NOTE** To allow the cluster pull the image the repository needs to be set as public or you must configure an image pull secret. 38 | 39 | ### Run the operator 40 | 41 | Deploy the project to the cluster. Set `IMG` with `make deploy` to use the image you just pushed: 42 | 43 | ### Create a `Memcached` resource 44 | 45 | Apply the sample Custom Resource: 46 | 47 | ```sh 48 | kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml -n memcached-operator-system 49 | ``` 50 | 51 | Run the following command to verify that the installation was successful: 52 | 53 | ```console 54 | $ kubectl get all -n memcached-operator-system 55 | 56 | NAME READY STATUS RESTARTS AGE 57 | pod/memcached-operator-controller-manager-f896cd75b-v5jqc 2/2 Running 0 19s 58 | pod/memcached-sample-memcached-6456bdd5fc-hwgnd 1/1 Running 0 12s 59 | 60 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 61 | service/memcached-operator-controller-manager-metrics-service ClusterIP 10.102.107.68 8443/TCP 19s 62 | 63 | NAME READY UP-TO-DATE AVAILABLE AGE 64 | deployment.apps/memcached-operator-controller-manager 1/1 1 1 19s 65 | deployment.apps/memcached-sample-memcached 1/1 1 1 12s 66 | 67 | NAME DESIRED CURRENT READY AGE 68 | replicaset.apps/memcached-operator-controller-manager-f896cd75b 1 1 1 19s 69 | replicaset.apps/memcached-sample-memcached-6456bdd5fc 1 1 1 12s 70 | ``` 71 | 72 | ### Cleanup 73 | 74 | To leave the operator, but remove the memcached sample pods, delete the 75 | CR. 76 | 77 | ```sh 78 | kubectl delete -f config/samples/cache_v1alpha1_memcached.yaml -n memcached-operator-system 79 | ``` 80 | 81 | To clean up everything: 82 | 83 | ```sh 84 | make undeploy 85 | ``` 86 | ### Troubleshooting 87 | 88 | Run the following command to check the operator logs. 89 | 90 | ```sh 91 | kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager 92 | ``` 93 | 94 | ### Extras 95 | 96 | This project was created by using the [gen-ansible-memcached.sh][gen-ansible-memcached.sh] script. 97 | 98 | For mor information see the [Ansible-based operator docs][ansible-docs]. 99 | 100 | [kubectl_tool]: https://kubernetes.io/docs/tasks/tools/install-kubectl/ 101 | [docker_tool]: https://docs.docker.com/install/ 102 | [operator_install]: https://sdk.operatorframework.io/docs/install-operator-sdk/ 103 | [ansible-docs]: https://sdk.operatorframework.io/docs/building-operators/ansible/ 104 | [gen-ansible-memcached.sh]: .generate/gen-helm-memcached.sh 105 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | 3 | LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 4 | LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ 5 | LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ 6 | LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator 7 | LABEL operators.operatorframework.io.bundle.channels.v1=alpha 8 | LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0 9 | LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 10 | LABEL operators.operatorframework.io.metrics.project_layout=ansible.sdk.operatorframework.io/v1 11 | LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ 12 | LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 13 | COPY bundle/manifests /manifests/ 14 | COPY bundle/metadata /metadata/ 15 | COPY bundle/tests/scorecard /tests/scorecard/ 16 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | creationTimestamp: null 5 | name: memcacheds.cache.example.com 6 | spec: 7 | group: cache.example.com 8 | names: 9 | kind: Memcached 10 | listKind: MemcachedList 11 | plural: memcacheds 12 | singular: memcached 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: Memcached is the Schema for the memcacheds API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 22 | type: string 23 | kind: 24 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 25 | type: string 26 | metadata: 27 | type: object 28 | spec: 29 | description: Spec defines the desired state of Memcached 30 | type: object 31 | x-kubernetes-preserve-unknown-fields: true 32 | status: 33 | description: Status defines the observed state of Memcached 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | type: object 37 | served: true 38 | storage: true 39 | subresources: 40 | status: {} 41 | status: 42 | acceptedNames: 43 | kind: "" 44 | plural: "" 45 | conditions: null 46 | storedVersions: null 47 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: memcached-operator-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - /metrics 9 | verbs: 10 | - get 11 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: |- 6 | [ 7 | { 8 | "apiVersion": "cache.example.com/v1alpha1", 9 | "kind": "Memcached", 10 | "metadata": { 11 | "name": "memcached-sample" 12 | }, 13 | "spec": { 14 | "size": 1 15 | } 16 | } 17 | ] 18 | capabilities: Basic Install 19 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 20 | operators.operatorframework.io/project_layout: ansible.sdk.operatorframework.io/v1 21 | name: memcached-operator.v0.0.1 22 | namespace: placeholder 23 | spec: 24 | apiservicedefinitions: {} 25 | customresourcedefinitions: 26 | owned: 27 | - kind: Memcached 28 | name: memcacheds.cache.example.com 29 | version: v1alpha1 30 | description: Memcached Operator description. TODO. 31 | displayName: Memcached Operator 32 | icon: 33 | - base64data: "" 34 | mediatype: "" 35 | install: 36 | spec: 37 | clusterPermissions: 38 | - rules: 39 | - apiGroups: 40 | - "" 41 | resources: 42 | - secrets 43 | - pods 44 | - pods/exec 45 | - pods/log 46 | verbs: 47 | - create 48 | - delete 49 | - get 50 | - list 51 | - patch 52 | - update 53 | - watch 54 | - apiGroups: 55 | - apps 56 | resources: 57 | - deployments 58 | - daemonsets 59 | - replicasets 60 | - statefulsets 61 | verbs: 62 | - create 63 | - delete 64 | - get 65 | - list 66 | - patch 67 | - update 68 | - watch 69 | - apiGroups: 70 | - cache.example.com 71 | resources: 72 | - memcacheds 73 | - memcacheds/status 74 | - memcacheds/finalizers 75 | verbs: 76 | - create 77 | - delete 78 | - get 79 | - list 80 | - patch 81 | - update 82 | - watch 83 | - apiGroups: 84 | - authentication.k8s.io 85 | resources: 86 | - tokenreviews 87 | verbs: 88 | - create 89 | - apiGroups: 90 | - authorization.k8s.io 91 | resources: 92 | - subjectaccessreviews 93 | verbs: 94 | - create 95 | serviceAccountName: default 96 | deployments: 97 | - name: memcached-operator-controller-manager 98 | spec: 99 | replicas: 1 100 | selector: 101 | matchLabels: 102 | control-plane: controller-manager 103 | strategy: {} 104 | template: 105 | metadata: 106 | labels: 107 | control-plane: controller-manager 108 | spec: 109 | containers: 110 | - args: 111 | - --secure-listen-address=0.0.0.0:8443 112 | - --upstream=http://127.0.0.1:8080/ 113 | - --logtostderr=true 114 | - --v=10 115 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 116 | name: kube-rbac-proxy 117 | ports: 118 | - containerPort: 8443 119 | name: https 120 | resources: {} 121 | - args: 122 | - --metrics-addr=127.0.0.1:8080 123 | - --enable-leader-election 124 | - --leader-election-id=memcached-operator 125 | env: 126 | - name: ANSIBLE_GATHERING 127 | value: explicit 128 | image: quay.io/example-inc/memcached-operator:v0.0.1 129 | name: manager 130 | resources: {} 131 | terminationGracePeriodSeconds: 10 132 | permissions: 133 | - rules: 134 | - apiGroups: 135 | - "" 136 | resources: 137 | - configmaps 138 | verbs: 139 | - get 140 | - list 141 | - watch 142 | - create 143 | - update 144 | - patch 145 | - delete 146 | - apiGroups: 147 | - "" 148 | resources: 149 | - events 150 | verbs: 151 | - create 152 | - patch 153 | serviceAccountName: default 154 | strategy: deployment 155 | installModes: 156 | - supported: false 157 | type: OwnNamespace 158 | - supported: false 159 | type: SingleNamespace 160 | - supported: false 161 | type: MultiNamespace 162 | - supported: true 163 | type: AllNamespaces 164 | keywords: 165 | - memcached-operator 166 | links: 167 | - name: Memcached Operator 168 | url: https://memcached-operator.domain 169 | maintainers: 170 | - email: your@email.com 171 | name: Maintainer Name 172 | maturity: alpha 173 | provider: 174 | name: Provider Name 175 | url: https://your.domain 176 | version: 0.0.1 177 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle/metadata/annotations.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | operators.operatorframework.io.bundle.channels.v1: alpha 3 | operators.operatorframework.io.bundle.manifests.v1: manifests/ 4 | operators.operatorframework.io.bundle.mediatype.v1: registry+v1 5 | operators.operatorframework.io.bundle.metadata.v1: metadata/ 6 | operators.operatorframework.io.bundle.package.v1: memcached-operator 7 | operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 9 | operators.operatorframework.io.metrics.project_layout: ansible.sdk.operatorframework.io/v1 10 | operators.operatorframework.io.test.config.v1: tests/scorecard/ 11 | operators.operatorframework.io.test.mediatype.v1: scorecard+v1 12 | -------------------------------------------------------------------------------- /ansible/memcached-operator/bundle/tests/scorecard/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: 8 | - entrypoint: 9 | - scorecard-test 10 | - basic-check-spec 11 | image: quay.io/operator-framework/scorecard-test:v1.1.0 12 | labels: 13 | suite: basic 14 | test: basic-check-spec-test 15 | - entrypoint: 16 | - scorecard-test 17 | - olm-bundle-validation 18 | image: quay.io/operator-framework/scorecard-test:v1.1.0 19 | labels: 20 | suite: olm 21 | test: olm-bundle-validation-test 22 | - entrypoint: 23 | - scorecard-test 24 | - olm-crds-have-validation 25 | image: quay.io/operator-framework/scorecard-test:v1.1.0 26 | labels: 27 | suite: olm 28 | test: olm-crds-have-validation-test 29 | - entrypoint: 30 | - scorecard-test 31 | - olm-crds-have-resources 32 | image: quay.io/operator-framework/scorecard-test:v1.1.0 33 | labels: 34 | suite: olm 35 | test: olm-crds-have-resources-test 36 | - entrypoint: 37 | - scorecard-test 38 | - olm-spec-descriptors 39 | image: quay.io/operator-framework/scorecard-test:v1.1.0 40 | labels: 41 | suite: olm 42 | test: olm-spec-descriptors-test 43 | - entrypoint: 44 | - scorecard-test 45 | - olm-status-descriptors 46 | image: quay.io/operator-framework/scorecard-test:v1.1.0 47 | labels: 48 | suite: olm 49 | test: olm-status-descriptors-test 50 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: memcacheds.cache.example.com 6 | spec: 7 | group: cache.example.com 8 | names: 9 | kind: Memcached 10 | listKind: MemcachedList 11 | plural: memcacheds 12 | singular: memcached 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: Memcached is the Schema for the memcacheds API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of Memcached 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of Memcached 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/cache.example.com_memcacheds.yaml 6 | # +kubebuilder:scaffold:crdkustomizeresource 7 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: memcached-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: memcached-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 20 | #- ../prometheus 21 | 22 | patchesStrategicMerge: 23 | # Protect the /metrics endpoint by putting it behind auth. 24 | # If you want your controller-manager to expose the /metrics 25 | # endpoint w/o any authn/z, please comment the following line. 26 | - manager_auth_proxy_patch.yaml 27 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--metrics-addr=127.0.0.1:8080" 25 | - "--enable-leader-election" 26 | - "--leader-election-id=memcached-operator" 27 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: quay.io/example-inc/memcached-operator 8 | newTag: v0.0.1 9 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | containers: 26 | - name: manager 27 | args: 28 | - "--enable-leader-election" 29 | - "--leader-election-id=memcached-operator" 30 | env: 31 | - name: ANSIBLE_GATHERING 32 | value: explicit 33 | image: controller:latest 34 | terminationGracePeriodSeconds: 10 35 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: '[]' 6 | capabilities: Basic Install 7 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io/project_layout: ansible.sdk.operatorframework.io/v1 9 | name: memcached-operator.vX.Y.Z 10 | namespace: placeholder 11 | spec: 12 | apiservicedefinitions: {} 13 | customresourcedefinitions: {} 14 | description: Memcached Operator description. TODO. 15 | displayName: Memcached Operator 16 | icon: 17 | - base64data: "" 18 | mediatype: "" 19 | install: 20 | spec: 21 | deployments: null 22 | strategy: "" 23 | installModes: 24 | - supported: false 25 | type: OwnNamespace 26 | - supported: false 27 | type: SingleNamespace 28 | - supported: false 29 | type: MultiNamespace 30 | - supported: true 31 | type: AllNamespaces 32 | keywords: 33 | - memcached-operator 34 | links: 35 | - name: Memcached Operator 36 | url: https://memcached-operator.domain 37 | maintainers: 38 | - email: your@email.com 39 | name: Maintainer Name 40 | maturity: alpha 41 | provider: 42 | name: Provider Name 43 | url: https://your.domain 44 | version: 0.0.0 45 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | - ../samples 4 | - ../scorecard 5 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | selector: 15 | matchLabels: 16 | control-plane: controller-manager 17 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - role_binding.yaml 4 | - leader_election_role.yaml 5 | - leader_election_role_binding.yaml 6 | # Comment the following 4 lines if you want to disable 7 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 8 | # which protects your /metrics endpoint. 9 | - auth_proxy_service.yaml 10 | - auth_proxy_role.yaml 11 | - auth_proxy_role_binding.yaml 12 | - auth_proxy_client_clusterrole.yaml 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - patch 26 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/memcached_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-editor-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - cache.example.com 21 | resources: 22 | - memcacheds/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/memcached_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-viewer-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - cache.example.com 17 | resources: 18 | - memcacheds/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: manager-role 6 | rules: 7 | ## 8 | ## Base operator rules 9 | ## 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - secrets 14 | - pods 15 | - pods/exec 16 | - pods/log 17 | verbs: 18 | - create 19 | - delete 20 | - get 21 | - list 22 | - patch 23 | - update 24 | - watch 25 | - apiGroups: 26 | - apps 27 | resources: 28 | - deployments 29 | - daemonsets 30 | - replicasets 31 | - statefulsets 32 | verbs: 33 | - create 34 | - delete 35 | - get 36 | - list 37 | - patch 38 | - update 39 | - watch 40 | ## 41 | ## Rules for cache.example.com/v1alpha1, Kind: Memcached 42 | ## 43 | - apiGroups: 44 | - cache.example.com 45 | resources: 46 | - memcacheds 47 | - memcacheds/status 48 | - memcacheds/finalizers 49 | verbs: 50 | - create 51 | - delete 52 | - get 53 | - list 54 | - patch 55 | - update 56 | - watch 57 | # +kubebuilder:scaffold:rules 58 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: manager-rolebinding 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: manager-role 10 | subjects: 11 | - kind: ServiceAccount 12 | name: default 13 | namespace: system 14 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cache.example.com/v1alpha1 2 | kind: Memcached 3 | metadata: 4 | name: memcached-sample 5 | spec: 6 | size: 1 7 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - cache_v1alpha1_memcached.yaml 4 | # +kubebuilder:scaffold:manifestskustomizesamples 5 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | # +kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.1.0 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.1.0 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.1.0 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.1.0 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/debug_logs_patch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | env: 13 | - name: ANSIBLE_DEBUG_LOGS 14 | value: "TRUE" 15 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: osdk-test 3 | 4 | namePrefix: osdk- 5 | 6 | # Labels to add to all resources and selectors. 7 | #commonLabels: 8 | # someName: someValue 9 | 10 | patchesStrategicMerge: 11 | - manager_image.yaml 12 | - debug_logs_patch.yaml 13 | - ../default/manager_auth_proxy_patch.yaml 14 | 15 | apiVersion: kustomize.config.k8s.io/v1beta1 16 | kind: Kustomization 17 | resources: 18 | - ../crd 19 | - ../rbac 20 | - ../manager 21 | images: 22 | - name: testing 23 | newName: testing-operator 24 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/manager_image.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | image: testing 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/pull_policy/Always.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: Always 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/pull_policy/IfNotPresent.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: IfNotPresent 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/config/testing/pull_policy/Never.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: controller-manager 6 | namespace: system 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | imagePullPolicy: Never 13 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | collections: 7 | - community.kubernetes 8 | 9 | tasks: 10 | - name: Create Namespace 11 | k8s: 12 | api_version: v1 13 | kind: Namespace 14 | name: '{{ namespace }}' 15 | 16 | - import_tasks: kustomize.yml 17 | vars: 18 | state: present 19 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | tasks: [] 7 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/destroy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Destroy 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | collections: 7 | - community.kubernetes 8 | 9 | tasks: 10 | - import_tasks: kustomize.yml 11 | vars: 12 | state: absent 13 | 14 | - name: Destroy Namespace 15 | k8s: 16 | api_version: v1 17 | kind: Namespace 18 | name: '{{ namespace }}' 19 | state: absent 20 | 21 | - name: Unset pull policy 22 | command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' 23 | args: 24 | chdir: '{{ config_dir }}/testing' 25 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/kustomize.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Build kustomize testing overlay 3 | # load_restrictor must be set to none so we can load patch files from the default overlay 4 | command: '{{ kustomize }} build --load_restrictor none .' 5 | args: 6 | chdir: '{{ config_dir }}/testing' 7 | register: resources 8 | changed_when: false 9 | 10 | - name: Set resources to {{ state }} 11 | k8s: 12 | definition: '{{ item }}' 13 | state: '{{ state }}' 14 | wait: yes 15 | loop: '{{ resources.stdout | from_yaml_all | list }}' 16 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: delegated 6 | lint: | 7 | set -e 8 | yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . 9 | platforms: 10 | - name: cluster 11 | groups: 12 | - k8s 13 | provisioner: 14 | name: ansible 15 | lint: | 16 | set -e 17 | ansible-lint 18 | inventory: 19 | group_vars: 20 | all: 21 | namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} 22 | host_vars: 23 | localhost: 24 | ansible_python_interpreter: '{{ ansible_playbook_python }}' 25 | config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config 26 | samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples 27 | operator_image: ${OPERATOR_IMAGE:-""} 28 | operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"} 29 | kustomize: ${KUSTOMIZE_PATH:-kustomize} 30 | env: 31 | K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"} 32 | verifier: 33 | name: ansible 34 | lint: | 35 | set -e 36 | ansible-lint 37 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | 7 | tasks: 8 | - name: Ensure operator image is set 9 | fail: 10 | msg: | 11 | You must specify the OPERATOR_IMAGE environment variable in order to run the 12 | 'default' scenario 13 | when: not operator_image 14 | 15 | - name: Set testing image 16 | command: '{{ kustomize }} edit set image testing={{ operator_image }}' 17 | args: 18 | chdir: '{{ config_dir }}/testing' 19 | 20 | - name: Set pull policy 21 | command: '{{ kustomize }} edit add patch pull_policy/{{ operator_pull_policy }}.yaml' 22 | args: 23 | chdir: '{{ config_dir }}/testing' 24 | 25 | - name: Set testing namespace 26 | command: '{{ kustomize }} edit set namespace {{ namespace }}' 27 | args: 28 | chdir: '{{ config_dir }}/testing' 29 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/tasks/memcached_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create the cache.example.com/v1alpha1.Memcached 3 | k8s: 4 | state: present 5 | namespace: '{{ namespace }}' 6 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 7 | wait: yes 8 | wait_timeout: 300 9 | wait_condition: 10 | type: Running 11 | reason: Successful 12 | status: "True" 13 | vars: 14 | cr_file: 'cache_v1alpha1_memcached.yaml' 15 | 16 | - name: Add assertions here 17 | assert: 18 | that: true 19 | fail_msg: FIXME Add real assertions for your operator 20 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/tasks/size_podcount_test.yml: -------------------------------------------------------------------------------- 1 | # Update file in operator-sdk-samples/ansible/generate/size_podcount_test.yml 2 | --- 3 | - name: Create the cache.example.com/v1alpha1.Memcached 4 | k8s: 5 | state: present 6 | namespace: "{{ namespace }}" 7 | definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" 8 | wait: yes 9 | wait_timeout: 300 10 | wait_condition: 11 | type: Running 12 | reason: Successful 13 | status: "True" 14 | vars: 15 | cr_file: 'cache_v1alpha1_memcached.yaml' 16 | 17 | - name: Wait 2 minutes for memcached pod to start 18 | k8s_info: 19 | kind: "Pod" 20 | api_version: "v1" 21 | namespace: "osdk-test" 22 | label_selectors: 23 | - app = memcached 24 | register: pod_list 25 | until: 26 | - pod_list.resources is defined 27 | - pod_list.resources|length == 1 28 | retries: 12 29 | delay: 10 30 | 31 | - name: Delete memcached pod 32 | community.kubernetes.k8s: 33 | state: absent 34 | definition: 35 | kind: Pod 36 | api_version: v1 37 | metadata: 38 | namespace: "{{ namespace }}" 39 | name: "{{ item.metadata.name }}" 40 | loop: "{{ pod_list.resources }}" 41 | 42 | - name: pause 43 | pause: 44 | seconds: 10 45 | 46 | - name: Wait 2 minutes for memcached pod to restart 47 | k8s_info: 48 | kind: "Pod" 49 | api_version: "v1" 50 | namespace: "osdk-test" 51 | label_selectors: 52 | - app = memcached 53 | register: pod_list 54 | until: 55 | - pod_list.resources is defined 56 | - pod_list.resources|length == 1 57 | retries: 12 58 | delay: 10 59 | 60 | 61 | - name: Edit Memcached size 62 | k8s: 63 | state: present 64 | namespace: "{{ namespace }}" 65 | definition: 66 | apiVersion: cache.example.com/v1alpha1 67 | kind: Memcached 68 | metadata: 69 | name: memcached-sample 70 | spec: 71 | size: 3 72 | 73 | - name: Wait 2 minutes for 3 memcached pods 74 | k8s_info: 75 | kind: "Pod" 76 | api_version: "v1" 77 | namespace: "osdk-test" 78 | label_selectors: 79 | - app = memcached 80 | register: pod_list 81 | until: 82 | - pod_list.resources is defined 83 | - pod_list.resources|length == 1 84 | retries: 12 85 | delay: 10 86 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | collections: 7 | - community.kubernetes 8 | 9 | vars: 10 | ctrl_label: control-plane=controller-manager 11 | 12 | tasks: 13 | - block: 14 | - name: Import all test files from tasks/ 15 | include_tasks: '{{ item }}' 16 | with_fileglob: 17 | - tasks/*_test.yml 18 | rescue: 19 | - name: Retrieve relevant resources 20 | k8s_info: 21 | api_version: '{{ item.api_version }}' 22 | kind: '{{ item.kind }}' 23 | namespace: '{{ namespace }}' 24 | loop: 25 | - api_version: v1 26 | kind: Pod 27 | - api_version: apps/v1 28 | kind: Deployment 29 | - api_version: v1 30 | kind: Secret 31 | - api_version: v1 32 | kind: ConfigMap 33 | register: debug_resources 34 | 35 | - name: Retrieve Pod logs 36 | k8s_log: 37 | name: '{{ item.metadata.name }}' 38 | namespace: '{{ namespace }}' 39 | container: manager 40 | loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}" 41 | register: debug_logs 42 | 43 | - name: Output gathered resources 44 | debug: 45 | var: debug_resources 46 | 47 | - name: Output gathered logs 48 | debug: 49 | var: item.log_lines 50 | loop: '{{ debug_logs.results }}' 51 | 52 | - name: Re-emit failure 53 | vars: 54 | failed_task: 55 | result: '{{ ansible_failed_result }}' 56 | fail: 57 | msg: '{{ failed_task }}' 58 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/kind/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: localhost 4 | connection: local 5 | gather_facts: no 6 | 7 | tasks: 8 | - name: Build operator image 9 | docker_image: 10 | build: 11 | path: '{{ project_dir }}' 12 | pull: no 13 | name: '{{ operator_image }}' 14 | tag: latest 15 | push: no 16 | source: build 17 | force_source: yes 18 | 19 | - name: Load image into kind cluster 20 | command: kind load docker-image --name osdk-test '{{ operator_image }}' 21 | register: result 22 | changed_when: '"not yet present" in result.stdout' 23 | 24 | - import_playbook: ../default/converge.yml 25 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/kind/create.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | tasks: 7 | - name: Create test kind cluster 8 | command: kind create cluster --name osdk-test --kubeconfig {{ kubeconfig }} 9 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/kind/destroy.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Destroy 3 | hosts: localhost 4 | connection: local 5 | gather_facts: false 6 | collections: 7 | - community.kubernetes 8 | 9 | tasks: 10 | - name: Destroy test kind cluster 11 | command: kind delete cluster --name osdk-test --kubeconfig {{ kubeconfig }} 12 | 13 | - name: Unset pull policy 14 | command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' 15 | args: 16 | chdir: '{{ config_dir }}/testing' 17 | -------------------------------------------------------------------------------- /ansible/memcached-operator/molecule/kind/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: delegated 6 | lint: | 7 | set -e 8 | yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . 9 | platforms: 10 | - name: cluster 11 | groups: 12 | - k8s 13 | provisioner: 14 | name: ansible 15 | playbooks: 16 | prepare: ../default/prepare.yml 17 | verify: ../default/verify.yml 18 | lint: | 19 | set -e 20 | ansible-lint 21 | inventory: 22 | group_vars: 23 | all: 24 | namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} 25 | host_vars: 26 | localhost: 27 | ansible_python_interpreter: '{{ ansible_playbook_python }}' 28 | config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config 29 | samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples 30 | project_dir: ${MOLECULE_PROJECT_DIRECTORY} 31 | operator_image: testing-operator 32 | operator_pull_policy: "Never" 33 | kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" 34 | kustomize: ${KUSTOMIZE_PATH:-kustomize} 35 | env: 36 | K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig 37 | KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig 38 | verifier: 39 | name: ansible 40 | lint: | 41 | set -e 42 | ansible-lint 43 | -------------------------------------------------------------------------------- /ansible/memcached-operator/playbooks/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operator-framework/operator-sdk-samples/caf90347ff2e40ae9511d651d6fef4bb42c891af/ansible/memcached-operator/playbooks/.placeholder -------------------------------------------------------------------------------- /ansible/memcached-operator/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - name: community.kubernetes 4 | version: "<1.0.0" 5 | - operator_sdk.util 6 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operator-framework/operator-sdk-samples/caf90347ff2e40ae9511d651d6fef4bb42c891af/ansible/memcached-operator/roles/.placeholder -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/README.md: -------------------------------------------------------------------------------- 1 | Role Name 2 | ========= 3 | 4 | A brief description of the role goes here. 5 | 6 | Requirements 7 | ------------ 8 | 9 | Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, 10 | if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. 11 | 12 | Role Variables 13 | -------------- 14 | 15 | A description of the settable variables for this role should go here, including any variables that are in 16 | defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables 17 | that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well 18 | 19 | Dependencies 20 | ------------ 21 | 22 | A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set 23 | for other roles, or variables that are used from other roles. 24 | 25 | Example Playbook 26 | ---------------- 27 | 28 | Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for 29 | users too: 30 | 31 | - hosts: servers 32 | roles: 33 | - { role: username.rolename, x: 42 } 34 | 35 | License 36 | ------- 37 | 38 | BSD 39 | 40 | Author Information 41 | ------------------ 42 | 43 | An optional section for the role authors to include contact information, or a website (HTML is not allowed). 44 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for Memcached 3 | # Update file in operator-sdk-samples/ansible/generate/defaults_main.yml 4 | size: 1 5 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/files/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operator-framework/operator-sdk-samples/caf90347ff2e40ae9511d651d6fef4bb42c891af/ansible/memcached-operator/roles/memcached/files/.placeholder -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for Memcached 3 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: your name 4 | description: your description 5 | company: your company (optional) 6 | 7 | # If the issue tracker for your role is not on github, uncomment the 8 | # next line and provide a value 9 | # issue_tracker_url: http://example.com/issue/tracker 10 | 11 | # Some suggested licenses: 12 | # - BSD (default) 13 | # - MIT 14 | # - GPLv2 15 | # - GPLv3 16 | # - Apache 17 | # - CC-BY 18 | license: license (GPLv2, CC-BY, etc) 19 | 20 | min_ansible_version: 2.9 21 | 22 | # If this a Container Enabled role, provide the minimum Ansible Container version. 23 | # min_ansible_container_version: 24 | 25 | # Optionally specify the branch Galaxy will use when accessing the GitHub 26 | # repo for this role. During role install, if no tags are available, 27 | # Galaxy will use this branch. During import Galaxy will access files on 28 | # this branch. If Travis integration is configured, only notifications for this 29 | # branch will be accepted. Otherwise, in all cases, the repo's default branch 30 | # (usually master) will be used. 31 | #github_branch: 32 | 33 | # 34 | # Provide a list of supported platforms, and for each platform a list of versions. 35 | # If you don't wish to enumerate all versions for a particular platform, use 'all'. 36 | # To view available platforms and versions (or releases), visit: 37 | # https://galaxy.ansible.com/api/v1/platforms/ 38 | # 39 | # platforms: 40 | # - name: Fedora 41 | # versions: 42 | # - all 43 | # - 25 44 | # - name: SomePlatform 45 | # versions: 46 | # - all 47 | # - 1.0 48 | # - 7 49 | # - 99.99 50 | 51 | galaxy_tags: [] 52 | # List tags for your role here, one per line. A tag is a keyword that describes 53 | # and categorizes the role. Users find roles by searching for tags. Be sure to 54 | # remove the '[]' above, if you add tags to this list. 55 | # 56 | # NOTE: A tag is limited to a single word comprised of alphanumeric characters. 57 | # Maximum 20 tags per role. 58 | 59 | dependencies: [] 60 | # List your role dependencies here, one per line. Be sure to remove the '[]' above, 61 | # if you add dependencies to this list. 62 | collections: 63 | - operator_sdk.util 64 | - community.kubernetes 65 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for Memcached 3 | # Update file in operator-sdk-samples/ansible/generate/role_main.yml 4 | - name: start memcached 5 | community.kubernetes.k8s: 6 | definition: 7 | kind: Deployment 8 | apiVersion: apps/v1 9 | metadata: 10 | name: '{{ ansible_operator_meta.name }}-memcached' 11 | namespace: '{{ ansible_operator_meta.namespace }}' 12 | spec: 13 | replicas: "{{size}}" 14 | selector: 15 | matchLabels: 16 | app: memcached 17 | template: 18 | metadata: 19 | labels: 20 | app: memcached 21 | spec: 22 | containers: 23 | - name: memcached 24 | command: 25 | - memcached 26 | - -m=64 27 | - -o 28 | - modern 29 | - -v 30 | image: "docker.io/memcached:1.4.36-alpine" 31 | ports: 32 | - containerPort: 11211 33 | -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/templates/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/operator-framework/operator-sdk-samples/caf90347ff2e40ae9511d651d6fef4bb42c891af/ansible/memcached-operator/roles/memcached/templates/.placeholder -------------------------------------------------------------------------------- /ansible/memcached-operator/roles/memcached/vars/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # vars file for Memcached 3 | -------------------------------------------------------------------------------- /ansible/memcached-operator/watches.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Use the 'create api' subcommand to add watches to this file. 3 | - version: v1alpha1 4 | group: cache.example.com 5 | kind: Memcached 6 | role: memcached 7 | # +kubebuilder:scaffold:watch 8 | -------------------------------------------------------------------------------- /go/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | *.swp 23 | *.swo 24 | *~ 25 | -------------------------------------------------------------------------------- /go/README.md: -------------------------------------------------------------------------------- 1 | This project is a component of the [Operator Framework](https://github.com/operator-framework), an open source toolkit to manage Kubernetes native applications, called Operators, in an effective, automated, and scalable way. Read more in the [introduction blog post](https://coreos.com/blog/introducing-operator-framework). 2 | 3 | # Operator SDK Samples - Go 4 | This directory contains samples of operators powered by Go built using the [operator-sdk][operator_sdk]. To learn more about creating an operator that leverages Golang, check out the [user guide][user_guide]. 5 | 6 | [operator_sdk]:https://github.com/operator-framework/operator-sdk 7 | [user_guide]:https://sdk.operatorframework.io/docs/building-operators/golang/quickstart/ 8 | -------------------------------------------------------------------------------- /go/doc/README.md: -------------------------------------------------------------------------------- 1 | # Memcached Go Operator 2 | 3 | ## Overview 4 | 5 | This Memcached operator is a simple example operator using the [Operator SDK][operator_sdk] CLI tool and controller-runtime library API. 6 | For more detailed information on project creation, please refer [Quickstart][quickstart]. 7 | 8 | ## Prerequisites 9 | 10 | - [go][go_tool] version v1.13+. 11 | - [docker][docker_tool] version 17.03+ 12 | - [kubectl][kubectl_tool] v1.11.3+ 13 | - [kustomize][kustomize] v3.1.0+ 14 | - [operator-sdk][operator_install] 15 | - Access to a Kubernetes v1.11.3+ cluster 16 | 17 | ## Getting Started 18 | 19 | ### Cloning the repository 20 | 21 | Checkout this Memcached Operator repository 22 | 23 | ``` 24 | $ mkdir -p $GOPATH/src/github.com/operator-framework 25 | $ cd $GOPATH/src/github.com/operator-framework 26 | $ git clone https://github.com/operator-framework/operator-sdk-samples.git 27 | $ cd operator-sdk-samples/go/kubebuilder/memcached-operator 28 | ``` 29 | ### Pulling the dependencies 30 | 31 | Run the following command 32 | 33 | ``` 34 | $ go mod tidy 35 | ``` 36 | ***NOTE*** As this example showcases validation webhook creation, please follow [this][certmanager] guide to install cert-mamager into cluster prior to deployment. 37 | 38 | ### Building the operator 39 | 40 | Build the Memcached operator image and push it to a public registry, such as quay.io: 41 | 42 | ```shell 43 | $ export IMG=quay.io/example/memcached-operator:v0.0.1 44 | $ make docker-build docker-push IMG=$IMG 45 | ``` 46 | 47 | **NOTE** The `quay.io/example/memcached-operator:v0.0.1` is an example. You should build and push the image for your repository. 48 | 49 | ### Instaling Operator API 50 | 51 | Install the CRDs into the cluster: 52 | 53 | ```shell 54 | $ make install 55 | ``` 56 | ### Deploying your operator 57 | 58 | Deploy the Memcached Operator to the cluster with image specified by IMG 59 | 60 | ```shell 61 | $ make deploy IMG=$IMG 62 | ``` 63 | 64 | ### Create memcached-sample instances. 65 | 66 | ```shell 67 | $ kubectl create -f config/samples/cache_v1alpha1_memcached.yaml -n memcached-operator-system 68 | ``` 69 | 70 | Please verify expected result. 71 | 72 | ```shell 73 | 74 | $ kubectl get all -n memcached-operator-system 75 | NAME READY STATUS RESTARTS AGE 76 | pod/memcached-operator-controller-manager-864f7c75d4-7cf47 2/2 Running 0 118s 77 | pod/memcached-sample-68b656fbd4-2pnl8 1/1 Running 0 53s 78 | pod/memcached-sample-68b656fbd4-464xk 1/1 Running 0 53s 79 | pod/memcached-sample-68b656fbd4-gzz5l 1/1 Running 0 53s 80 | 81 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 82 | service/memcached-operator-controller-manager-metrics-service ClusterIP 10.96.171.209 8443/TCP 118s 83 | 84 | NAME READY UP-TO-DATE AVAILABLE AGE 85 | deployment.apps/memcached-operator-controller-manager 1/1 1 1 118s 86 | deployment.apps/memcached-sample 3/3 3 3 53s 87 | 88 | NAME DESIRED CURRENT READY AGE 89 | replicaset.apps/memcached-operator-controller-manager-864f7c75d4 1 1 1 118s 90 | ``` 91 | 92 | ### Verifying the validating webhook 93 | 94 | The following command attempts to increase the CR's `spec.size` to an even number. It should throw an error like that shown below, as the validating webhook does not allow an even `spec.size`. 95 | 96 | ```console 97 | $ kubectl patch memcached memcached-sample -p '{"spec":{"size": 4}}' --type=merge -n memcached-operator-system 98 | 99 | Error from server (Cluster size must be an odd number): admission webhook "vmemcached.kb.io" denied the request: Cluster size must be an odd number 100 | ``` 101 | 102 | ### Uninstalling 103 | 104 | To uninstall all that was performed in the above step run `make uninstall`. 105 | 106 | ### Troubleshooting 107 | 108 | Use the following command to check the operator logs. 109 | 110 | ```shell 111 | $ kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager 112 | 113 | ``` 114 | 115 | ### Extras 116 | This project was created using the [gen-go-sample.sh][generate_script] script. If you would like to build golang-based operators using SDK, please refer to [quickstart][go_guide], 117 | 118 | 119 | [go_tool]: https://golang.org/dl/ 120 | [kubectl_tool]: https://kubernetes.io/docs/tasks/tools/install-kubectl/ 121 | [docker_tool]: https://docs.docker.com/install/ 122 | [kustomize]: https://github.com/kubernetes-sigs/kustomize/blob/master/docs/INSTALL.md 123 | [operator_sdk]: https://github.com/operator-framework/operator-sdk 124 | [operator_install]: https://sdk.operatorframework.io/docs/install-operator-sdk/ 125 | [quickstart]: https://github.com/operator-framework/operator-sdk/blob/master/website/content/en/docs/kubebuilder/quickstart.md#implement-the-controller 126 | [certmanager]: https://cert-manager.io/docs/installation/kubernetes/ 127 | [generate_script]: .generate/gen-go-sample.sh 128 | [go_guide]: https://sdk.operatorframework.io/docs/building-operators/golang/quickstart/ 129 | 130 | -------------------------------------------------------------------------------- /go/memcached-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # Test binary, build with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Kubernetes Generated files - skip generated files, except for vendored files 17 | 18 | !vendor/**/zz_generated.* 19 | 20 | # editor and IDE paraphernalia 21 | .idea 22 | *.swp 23 | *.swo 24 | *~ 25 | -------------------------------------------------------------------------------- /go/memcached-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.13 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | COPY go.mod go.mod 7 | COPY go.sum go.sum 8 | # cache deps before building and copying source so that we don't need to re-download as much 9 | # and so that source changes don't invalidate our downloaded layer 10 | RUN go mod download 11 | 12 | # Copy the go source 13 | COPY main.go main.go 14 | COPY api/ api/ 15 | COPY controllers/ controllers/ 16 | 17 | # Build 18 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 19 | 20 | # Use distroless as minimal base image to package the manager binary 21 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 22 | FROM gcr.io/distroless/static:nonroot 23 | WORKDIR / 24 | COPY --from=builder /workspace/manager . 25 | USER nonroot:nonroot 26 | 27 | ENTRYPOINT ["/manager"] 28 | -------------------------------------------------------------------------------- /go/memcached-operator/Makefile: -------------------------------------------------------------------------------- 1 | # Current Operator version 2 | VERSION ?= 0.0.1 3 | # Default bundle image tag 4 | BUNDLE_IMG ?= controller-bundle:$(VERSION) 5 | # Options for 'bundle-build' 6 | ifneq ($(origin CHANNELS), undefined) 7 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 8 | endif 9 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 10 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 11 | endif 12 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 13 | 14 | # Image URL to use all building/pushing image targets 15 | IMG ?= controller:latest 16 | # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) 17 | CRD_OPTIONS ?= "crd:trivialVersions=true" 18 | 19 | # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) 20 | ifeq (,$(shell go env GOBIN)) 21 | GOBIN=$(shell go env GOPATH)/bin 22 | else 23 | GOBIN=$(shell go env GOBIN) 24 | endif 25 | 26 | all: manager 27 | 28 | # Run tests 29 | ENVTEST_ASSETS_DIR=$(shell pwd)/testbin 30 | ENVTEST_ASSETS_DIR = $(shell pwd)/testbin 31 | test: generate fmt vet manifests 32 | mkdir -p $(ENVTEST_ASSETS_DIR) 33 | test -f $(ENVTEST_ASSETS_DIR)/setup-envtest.sh || curl -sSLo $(ENVTEST_ASSETS_DIR)/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.6.3/hack/setup-envtest.sh 34 | source $(ENVTEST_ASSETS_DIR)/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); mkdir -p ${ENVTEST_ASSETS_DIR} 35 | test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/master/hack/setup-envtest.sh 36 | source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out 37 | 38 | # Build manager binary 39 | manager: generate fmt vet 40 | go build -o bin/manager main.go 41 | 42 | # Run against the configured Kubernetes cluster in ~/.kube/config 43 | run: generate fmt vet manifests 44 | go run ./main.go 45 | 46 | # Install CRDs into a cluster 47 | install: manifests kustomize 48 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 49 | 50 | # Uninstall CRDs from a cluster 51 | uninstall: manifests kustomize 52 | $(KUSTOMIZE) build config/crd | kubectl delete -f - 53 | 54 | # Deploy controller in the configured Kubernetes cluster in ~/.kube/config 55 | deploy: manifests kustomize 56 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 57 | $(KUSTOMIZE) build config/default | kubectl apply -f - 58 | 59 | # Generate manifests e.g. CRD, RBAC etc. 60 | manifests: controller-gen 61 | $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases 62 | 63 | # Run go fmt against code 64 | fmt: 65 | go fmt ./... 66 | 67 | # Run go vet against code 68 | vet: 69 | go vet ./... 70 | 71 | # Generate code 72 | generate: controller-gen 73 | $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." 74 | 75 | # Build the docker image 76 | docker-build: test 77 | docker build . -t ${IMG} 78 | 79 | # Push the docker image 80 | docker-push: 81 | docker push ${IMG} 82 | 83 | # find or download controller-gen 84 | # download controller-gen if necessary 85 | controller-gen: 86 | ifeq (, $(shell which controller-gen)) 87 | @{ \ 88 | set -e ;\ 89 | CONTROLLER_GEN_TMP_DIR=$$(mktemp -d) ;\ 90 | cd $$CONTROLLER_GEN_TMP_DIR ;\ 91 | go mod init tmp ;\ 92 | go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.3.0 ;\ 93 | rm -rf $$CONTROLLER_GEN_TMP_DIR ;\ 94 | } 95 | CONTROLLER_GEN=$(GOBIN)/controller-gen 96 | else 97 | CONTROLLER_GEN=$(shell which controller-gen) 98 | endif 99 | 100 | kustomize: 101 | ifeq (, $(shell which kustomize)) 102 | @{ \ 103 | set -e ;\ 104 | KUSTOMIZE_GEN_TMP_DIR=$$(mktemp -d) ;\ 105 | cd $$KUSTOMIZE_GEN_TMP_DIR ;\ 106 | go mod init tmp ;\ 107 | go get sigs.k8s.io/kustomize/kustomize/v3@v3.5.4 ;\ 108 | rm -rf $$KUSTOMIZE_GEN_TMP_DIR ;\ 109 | } 110 | KUSTOMIZE=$(GOBIN)/kustomize 111 | else 112 | KUSTOMIZE=$(shell which kustomize) 113 | endif 114 | 115 | # Generate bundle manifests and metadata, then validate generated files. 116 | .PHONY: bundle 117 | bundle: manifests 118 | operator-sdk generate kustomize manifests --interactive=false -q 119 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 120 | $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 121 | operator-sdk bundle validate ./bundle 122 | 123 | # Build the bundle image. 124 | .PHONY: bundle-build 125 | bundle-build: 126 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 127 | 128 | # UnDeploy controller from the configured Kubernetes cluster in ~/.kube/config 129 | # Note that it was added for we are allowed to uninstall the files. However, it will be present by default in the future 130 | # versions. 131 | undeploy: 132 | $(KUSTOMIZE) build config/default | kubectl delete -f - 133 | 134 | 135 | # Options for "packagemanifests". 136 | ifneq ($(origin CHANNEL), undefined) 137 | PKG_CHANNELS := --channel=$(CHANNEL) 138 | endif 139 | ifeq ($(IS_CHANNEL_DEFAULT), 1) 140 | PKG_IS_DEFAULT_CHANNEL := --default-channel 141 | endif 142 | PKG_MAN_OPTS ?= $(PKG_CHANNELS) $(PKG_IS_DEFAULT_CHANNEL) 143 | # Generate package manifests. 144 | packagemanifests: kustomize manifests 145 | operator-sdk generate kustomize manifests --interactive=false -q --interactive=false 146 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 147 | $(KUSTOMIZE) build config/manifests | operator-sdk generate packagemanifests -q --version $(VERSION) $(PKG_MAN_OPTS) 148 | -------------------------------------------------------------------------------- /go/memcached-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: example.com 2 | layout: go.kubebuilder.io/v2 3 | projectName: memcached-operator 4 | repo: github.com/example/memcached-operator 5 | resources: 6 | - group: cache 7 | kind: Memcached 8 | version: v1alpha1 9 | version: 3-alpha 10 | plugins: 11 | go.sdk.operatorframework.io/v2-alpha: {} 12 | -------------------------------------------------------------------------------- /go/memcached-operator/api/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains API Schema definitions for the cache v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=cache.example.com 20 | package v1alpha1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "cache.example.com", Version: "v1alpha1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /go/memcached-operator/api/v1alpha1/memcached_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 24 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 25 | 26 | // MemcachedSpec defines the desired state of Memcached 27 | type MemcachedSpec struct { 28 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 29 | // Important: Run "make" to regenerate code after modifying this file 30 | 31 | Size int32 `json:"size"` 32 | } 33 | 34 | // MemcachedStatus defines the observed state of Memcached 35 | type MemcachedStatus struct { 36 | Nodes []string `json:"nodes"` 37 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 38 | // Important: Run "make" to regenerate code after modifying this file 39 | } 40 | 41 | // +kubebuilder:object:root=true 42 | // +kubebuilder:subresource:status 43 | 44 | // Memcached is the Schema for the memcacheds API 45 | type Memcached struct { 46 | metav1.TypeMeta `json:",inline"` 47 | metav1.ObjectMeta `json:"metadata,omitempty"` 48 | 49 | Spec MemcachedSpec `json:"spec,omitempty"` 50 | Status MemcachedStatus `json:"status,omitempty"` 51 | } 52 | 53 | // +kubebuilder:object:root=true 54 | 55 | // MemcachedList contains a list of Memcached 56 | type MemcachedList struct { 57 | metav1.TypeMeta `json:",inline"` 58 | metav1.ListMeta `json:"metadata,omitempty"` 59 | Items []Memcached `json:"items"` 60 | } 61 | 62 | func init() { 63 | SchemeBuilder.Register(&Memcached{}, &MemcachedList{}) 64 | } 65 | -------------------------------------------------------------------------------- /go/memcached-operator/api/v1alpha1/memcached_webhook.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | "errors" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | ctrl "sigs.k8s.io/controller-runtime" 23 | logf "sigs.k8s.io/controller-runtime/pkg/log" 24 | "sigs.k8s.io/controller-runtime/pkg/webhook" 25 | ) 26 | 27 | // log is for logging in this package. 28 | var memcachedlog = logf.Log.WithName("memcached-resource") 29 | 30 | func (r *Memcached) SetupWebhookWithManager(mgr ctrl.Manager) error { 31 | return ctrl.NewWebhookManagedBy(mgr). 32 | For(r). 33 | Complete() 34 | } 35 | 36 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 37 | 38 | // +kubebuilder:webhook:path=/mutate-cache-example-com-v1alpha1-memcached,mutating=true,failurePolicy=fail,groups=cache.example.com,resources=memcacheds,verbs=create;update,versions=v1alpha1,name=mmemcached.kb.io 39 | 40 | var _ webhook.Defaulter = &Memcached{} 41 | 42 | // Default implements webhook.Defaulter so a webhook will be registered for the type 43 | func (r *Memcached) Default() { 44 | memcachedlog.Info("default", "name", r.Name) 45 | 46 | if r.Spec.Size == 0 { 47 | r.Spec.Size = 3 48 | } 49 | } 50 | 51 | // TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. 52 | // +kubebuilder:webhook:verbs=create;update,path=/validate-cache-example-com-v1alpha1-memcached,mutating=false,failurePolicy=fail,groups=cache.example.com,resources=memcacheds,versions=v1alpha1,name=vmemcached.kb.io 53 | 54 | var _ webhook.Validator = &Memcached{} 55 | 56 | // ValidateCreate implements webhook.Validator so a webhook will be registered for the type 57 | func (r *Memcached) ValidateCreate() error { 58 | memcachedlog.Info("validate create", "name", r.Name) 59 | 60 | return validateOdd(r.Spec.Size) 61 | } 62 | 63 | // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type 64 | func (r *Memcached) ValidateUpdate(old runtime.Object) error { 65 | memcachedlog.Info("validate update", "name", r.Name) 66 | 67 | return validateOdd(r.Spec.Size) 68 | } 69 | 70 | // ValidateDelete implements webhook.Validator so a webhook will be registered for the type 71 | func (r *Memcached) ValidateDelete() error { 72 | memcachedlog.Info("validate delete", "name", r.Name) 73 | 74 | return nil 75 | } 76 | func validateOdd(n int32) error { 77 | if n%2 == 0 { 78 | return errors.New("Cluster size must be an odd number") 79 | } 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /go/memcached-operator/api/v1alpha1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // Code generated by controller-gen. DO NOT EDIT. 20 | 21 | package v1alpha1 22 | 23 | import ( 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 28 | func (in *Memcached) DeepCopyInto(out *Memcached) { 29 | *out = *in 30 | out.TypeMeta = in.TypeMeta 31 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 32 | out.Spec = in.Spec 33 | in.Status.DeepCopyInto(&out.Status) 34 | } 35 | 36 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Memcached. 37 | func (in *Memcached) DeepCopy() *Memcached { 38 | if in == nil { 39 | return nil 40 | } 41 | out := new(Memcached) 42 | in.DeepCopyInto(out) 43 | return out 44 | } 45 | 46 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 47 | func (in *Memcached) DeepCopyObject() runtime.Object { 48 | if c := in.DeepCopy(); c != nil { 49 | return c 50 | } 51 | return nil 52 | } 53 | 54 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 55 | func (in *MemcachedList) DeepCopyInto(out *MemcachedList) { 56 | *out = *in 57 | out.TypeMeta = in.TypeMeta 58 | in.ListMeta.DeepCopyInto(&out.ListMeta) 59 | if in.Items != nil { 60 | in, out := &in.Items, &out.Items 61 | *out = make([]Memcached, len(*in)) 62 | for i := range *in { 63 | (*in)[i].DeepCopyInto(&(*out)[i]) 64 | } 65 | } 66 | } 67 | 68 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedList. 69 | func (in *MemcachedList) DeepCopy() *MemcachedList { 70 | if in == nil { 71 | return nil 72 | } 73 | out := new(MemcachedList) 74 | in.DeepCopyInto(out) 75 | return out 76 | } 77 | 78 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 79 | func (in *MemcachedList) DeepCopyObject() runtime.Object { 80 | if c := in.DeepCopy(); c != nil { 81 | return c 82 | } 83 | return nil 84 | } 85 | 86 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 87 | func (in *MemcachedSpec) DeepCopyInto(out *MemcachedSpec) { 88 | *out = *in 89 | } 90 | 91 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedSpec. 92 | func (in *MemcachedSpec) DeepCopy() *MemcachedSpec { 93 | if in == nil { 94 | return nil 95 | } 96 | out := new(MemcachedSpec) 97 | in.DeepCopyInto(out) 98 | return out 99 | } 100 | 101 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 102 | func (in *MemcachedStatus) DeepCopyInto(out *MemcachedStatus) { 103 | *out = *in 104 | if in.Nodes != nil { 105 | in, out := &in.Nodes, &out.Nodes 106 | *out = make([]string, len(*in)) 107 | copy(*out, *in) 108 | } 109 | } 110 | 111 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MemcachedStatus. 112 | func (in *MemcachedStatus) DeepCopy() *MemcachedStatus { 113 | if in == nil { 114 | return nil 115 | } 116 | out := new(MemcachedStatus) 117 | in.DeepCopyInto(out) 118 | return out 119 | } 120 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | 3 | LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 4 | LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ 5 | LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ 6 | LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator 7 | LABEL operators.operatorframework.io.bundle.channels.v1=alpha 8 | LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0 9 | LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 10 | LABEL operators.operatorframework.io.metrics.project_layout=go.kubebuilder.io/v2 11 | LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ 12 | LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 13 | COPY bundle/manifests /manifests/ 14 | COPY bundle/metadata /metadata/ 15 | COPY bundle/tests/scorecard /tests/scorecard/ 16 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | annotations: 5 | controller-gen.kubebuilder.io/version: v0.3.0 6 | creationTimestamp: null 7 | name: memcacheds.cache.example.com 8 | spec: 9 | group: cache.example.com 10 | names: 11 | kind: Memcached 12 | listKind: MemcachedList 13 | plural: memcacheds 14 | singular: memcached 15 | scope: Namespaced 16 | subresources: 17 | status: {} 18 | validation: 19 | openAPIV3Schema: 20 | description: Memcached is the Schema for the memcacheds API 21 | properties: 22 | apiVersion: 23 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 27 | type: string 28 | metadata: 29 | type: object 30 | spec: 31 | description: MemcachedSpec defines the desired state of Memcached 32 | properties: 33 | size: 34 | format: int32 35 | type: integer 36 | required: 37 | - size 38 | type: object 39 | status: 40 | description: MemcachedStatus defines the observed state of Memcached 41 | properties: 42 | nodes: 43 | items: 44 | type: string 45 | type: array 46 | required: 47 | - nodes 48 | type: object 49 | type: object 50 | version: v1alpha1 51 | versions: 52 | - name: v1alpha1 53 | served: true 54 | storage: true 55 | status: 56 | acceptedNames: 57 | kind: "" 58 | plural: "" 59 | conditions: [] 60 | storedVersions: [] 61 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: memcached-operator-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - /metrics 9 | verbs: 10 | - get 11 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle/manifests/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: |- 6 | [ 7 | { 8 | "apiVersion": "cache.example.com/v1alpha1", 9 | "kind": "Memcached", 10 | "metadata": { 11 | "name": "memcached-sample" 12 | }, 13 | "spec": { 14 | "size": 3 15 | } 16 | } 17 | ] 18 | capabilities: Basic Install 19 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 20 | operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 21 | name: memcached-operator.v0.0.1 22 | namespace: placeholder 23 | spec: 24 | apiservicedefinitions: {} 25 | customresourcedefinitions: 26 | owned: 27 | - description: Memcached is the Schema for the memcacheds API 28 | displayName: Memcached 29 | kind: Memcached 30 | name: memcacheds.cache.example.com 31 | version: v1alpha1 32 | description: Memcached Operator description. TODO. 33 | displayName: Memcached Operator 34 | icon: 35 | - base64data: "" 36 | mediatype: "" 37 | install: 38 | spec: 39 | clusterPermissions: 40 | - rules: 41 | - apiGroups: 42 | - apps 43 | resources: 44 | - deployments 45 | verbs: 46 | - create 47 | - delete 48 | - get 49 | - list 50 | - patch 51 | - update 52 | - watch 53 | - apiGroups: 54 | - cache.example.com 55 | resources: 56 | - memcacheds 57 | verbs: 58 | - create 59 | - delete 60 | - get 61 | - list 62 | - patch 63 | - update 64 | - watch 65 | - apiGroups: 66 | - cache.example.com 67 | resources: 68 | - memcacheds/status 69 | verbs: 70 | - get 71 | - patch 72 | - update 73 | - apiGroups: 74 | - "" 75 | resources: 76 | - pods 77 | verbs: 78 | - get 79 | - list 80 | - apiGroups: 81 | - authentication.k8s.io 82 | resources: 83 | - tokenreviews 84 | verbs: 85 | - create 86 | - apiGroups: 87 | - authorization.k8s.io 88 | resources: 89 | - subjectaccessreviews 90 | verbs: 91 | - create 92 | serviceAccountName: default 93 | deployments: 94 | - name: memcached-operator-controller-manager 95 | spec: 96 | replicas: 1 97 | selector: 98 | matchLabels: 99 | control-plane: controller-manager 100 | strategy: {} 101 | template: 102 | metadata: 103 | labels: 104 | control-plane: controller-manager 105 | spec: 106 | containers: 107 | - args: 108 | - --secure-listen-address=0.0.0.0:8443 109 | - --upstream=http://127.0.0.1:8080/ 110 | - --logtostderr=true 111 | - --v=10 112 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 113 | name: kube-rbac-proxy 114 | ports: 115 | - containerPort: 8443 116 | name: https 117 | resources: {} 118 | - args: 119 | - --metrics-addr=127.0.0.1:8080 120 | - --enable-leader-election 121 | command: 122 | - /manager 123 | image: quay.io/example/memcached-operator:v0.0.1 124 | name: manager 125 | ports: 126 | - containerPort: 9443 127 | name: webhook-server 128 | protocol: TCP 129 | resources: 130 | limits: 131 | cpu: 100m 132 | memory: 30Mi 133 | requests: 134 | cpu: 100m 135 | memory: 20Mi 136 | volumeMounts: 137 | - mountPath: /tmp/k8s-webhook-server/serving-certs 138 | name: cert 139 | readOnly: true 140 | terminationGracePeriodSeconds: 10 141 | volumes: 142 | - name: cert 143 | secret: 144 | defaultMode: 420 145 | secretName: webhook-server-cert 146 | permissions: 147 | - rules: 148 | - apiGroups: 149 | - "" 150 | resources: 151 | - configmaps 152 | verbs: 153 | - get 154 | - list 155 | - watch 156 | - create 157 | - update 158 | - patch 159 | - delete 160 | - apiGroups: 161 | - "" 162 | resources: 163 | - configmaps/status 164 | verbs: 165 | - get 166 | - update 167 | - patch 168 | - apiGroups: 169 | - "" 170 | resources: 171 | - events 172 | verbs: 173 | - create 174 | - patch 175 | serviceAccountName: default 176 | strategy: deployment 177 | installModes: 178 | - supported: false 179 | type: OwnNamespace 180 | - supported: false 181 | type: SingleNamespace 182 | - supported: false 183 | type: MultiNamespace 184 | - supported: true 185 | type: AllNamespaces 186 | keywords: 187 | - memcached-operator 188 | links: 189 | - name: Memcached Operator 190 | url: https://memcached-operator.domain 191 | maintainers: 192 | - email: your@email.com 193 | name: Maintainer Name 194 | maturity: alpha 195 | provider: 196 | name: Provider Name 197 | url: https://your.domain 198 | version: 0.0.1 199 | webhookdefinitions: 200 | - admissionReviewVersions: 201 | - v1beta1 202 | deploymentName: memcached-operator-controller-manager 203 | failurePolicy: Fail 204 | generateName: vmemcached.kb.io 205 | rules: 206 | - apiGroups: 207 | - cache.example.com 208 | apiVersions: 209 | - v1alpha1 210 | operations: 211 | - CREATE 212 | - UPDATE 213 | resources: 214 | - memcacheds 215 | sideEffects: None 216 | type: ValidatingAdmissionWebhook 217 | webhookPath: /validate-cache-example-com-v1alpha1-memcached 218 | - admissionReviewVersions: 219 | - v1beta1 220 | deploymentName: memcached-operator-controller-manager 221 | failurePolicy: Fail 222 | generateName: mmemcached.kb.io 223 | rules: 224 | - apiGroups: 225 | - cache.example.com 226 | apiVersions: 227 | - v1alpha1 228 | operations: 229 | - CREATE 230 | - UPDATE 231 | resources: 232 | - memcacheds 233 | sideEffects: None 234 | type: MutatingAdmissionWebhook 235 | webhookPath: /mutate-cache-example-com-v1alpha1-memcached 236 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle/metadata/annotations.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | operators.operatorframework.io.bundle.channels.v1: alpha 3 | operators.operatorframework.io.bundle.manifests.v1: manifests/ 4 | operators.operatorframework.io.bundle.mediatype.v1: registry+v1 5 | operators.operatorframework.io.bundle.metadata.v1: metadata/ 6 | operators.operatorframework.io.bundle.package.v1: memcached-operator 7 | operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 9 | operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v2 10 | operators.operatorframework.io.test.config.v1: tests/scorecard/ 11 | operators.operatorframework.io.test.mediatype.v1: scorecard+v1 12 | -------------------------------------------------------------------------------- /go/memcached-operator/bundle/tests/scorecard/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: 8 | - entrypoint: 9 | - scorecard-test 10 | - basic-check-spec 11 | image: quay.io/operator-framework/scorecard-test:v1.1.0 12 | labels: 13 | suite: basic 14 | test: basic-check-spec-test 15 | - entrypoint: 16 | - scorecard-test 17 | - olm-bundle-validation 18 | image: quay.io/operator-framework/scorecard-test:v1.1.0 19 | labels: 20 | suite: olm 21 | test: olm-bundle-validation-test 22 | - entrypoint: 23 | - scorecard-test 24 | - olm-crds-have-validation 25 | image: quay.io/operator-framework/scorecard-test:v1.1.0 26 | labels: 27 | suite: olm 28 | test: olm-crds-have-validation-test 29 | - entrypoint: 30 | - scorecard-test 31 | - olm-crds-have-resources 32 | image: quay.io/operator-framework/scorecard-test:v1.1.0 33 | labels: 34 | suite: olm 35 | test: olm-crds-have-resources-test 36 | - entrypoint: 37 | - scorecard-test 38 | - olm-spec-descriptors 39 | image: quay.io/operator-framework/scorecard-test:v1.1.0 40 | labels: 41 | suite: olm 42 | test: olm-spec-descriptors-test 43 | - entrypoint: 44 | - scorecard-test 45 | - olm-status-descriptors 46 | image: quay.io/operator-framework/scorecard-test:v1.1.0 47 | labels: 48 | suite: olm 49 | test: olm-status-descriptors-test 50 | -------------------------------------------------------------------------------- /go/memcached-operator/config/certmanager/certificate.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager 0.11 check https://docs.cert-manager.io/en/latest/tasks/upgrading/index.html for 4 | # breaking changes 5 | apiVersion: cert-manager.io/v1alpha2 6 | kind: Issuer 7 | metadata: 8 | name: selfsigned-issuer 9 | namespace: system 10 | spec: 11 | selfSigned: {} 12 | --- 13 | apiVersion: cert-manager.io/v1alpha2 14 | kind: Certificate 15 | metadata: 16 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 17 | namespace: system 18 | spec: 19 | # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize 20 | dnsNames: 21 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc 22 | - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local 23 | issuerRef: 24 | kind: Issuer 25 | name: selfsigned-issuer 26 | secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize 27 | -------------------------------------------------------------------------------- /go/memcached-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /go/memcached-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /go/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.3.0 8 | creationTimestamp: null 9 | name: memcacheds.cache.example.com 10 | spec: 11 | group: cache.example.com 12 | names: 13 | kind: Memcached 14 | listKind: MemcachedList 15 | plural: memcacheds 16 | singular: memcached 17 | scope: Namespaced 18 | subresources: 19 | status: {} 20 | validation: 21 | openAPIV3Schema: 22 | description: Memcached is the Schema for the memcacheds API 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: MemcachedSpec defines the desired state of Memcached 38 | properties: 39 | size: 40 | format: int32 41 | type: integer 42 | required: 43 | - size 44 | type: object 45 | status: 46 | description: MemcachedStatus defines the observed state of Memcached 47 | properties: 48 | nodes: 49 | items: 50 | type: string 51 | type: array 52 | required: 53 | - nodes 54 | type: object 55 | type: object 56 | version: v1alpha1 57 | versions: 58 | - name: v1alpha1 59 | served: true 60 | storage: true 61 | status: 62 | acceptedNames: 63 | kind: "" 64 | plural: "" 65 | conditions: [] 66 | storedVersions: [] 67 | -------------------------------------------------------------------------------- /go/memcached-operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/cache.example.com_memcacheds.yaml 6 | # +kubebuilder:scaffold:crdkustomizeresource 7 | 8 | patchesStrategicMerge: 9 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 10 | # patches here are for enabling the conversion webhook for each CRD 11 | #- patches/webhook_in_memcacheds.yaml 12 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 13 | 14 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 15 | # patches here are for enabling the CA injection for each CRD 16 | #- patches/cainjection_in_memcacheds.yaml 17 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 18 | 19 | # the following config is for teaching kustomize how to do kustomization for CRDs. 20 | configurations: 21 | - kustomizeconfig.yaml 22 | -------------------------------------------------------------------------------- /go/memcached-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | group: apiextensions.k8s.io 8 | path: spec/conversion/webhookClientConfig/service/name 9 | 10 | namespace: 11 | - kind: CustomResourceDefinition 12 | group: apiextensions.k8s.io 13 | path: spec/conversion/webhookClientConfig/service/namespace 14 | create: false 15 | 16 | varReference: 17 | - path: metadata/annotations 18 | -------------------------------------------------------------------------------- /go/memcached-operator/config/crd/patches/cainjection_in_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 8 | name: memcacheds.cache.example.com 9 | -------------------------------------------------------------------------------- /go/memcached-operator/config/crd/patches/webhook_in_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables conversion webhook for CRD 2 | # CRD conversion requires k8s 1.13 or later. 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | name: memcacheds.cache.example.com 7 | spec: 8 | conversion: 9 | strategy: Webhook 10 | webhookClientConfig: 11 | # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, 12 | # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) 13 | caBundle: Cg== 14 | service: 15 | namespace: system 16 | name: webhook-service 17 | path: /convert 18 | -------------------------------------------------------------------------------- /go/memcached-operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: memcached-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: memcached-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 20 | # crd/kustomization.yaml 21 | - ../webhook 22 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 23 | - ../certmanager 24 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 25 | #- ../prometheus 26 | 27 | patchesStrategicMerge: 28 | # Protect the /metrics endpoint by putting it behind auth. 29 | # If you want your controller-manager to expose the /metrics 30 | # endpoint w/o any authn/z, please comment the following line. 31 | - manager_auth_proxy_patch.yaml 32 | 33 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 34 | # crd/kustomization.yaml 35 | - manager_webhook_patch.yaml 36 | 37 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 38 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 39 | # 'CERTMANAGER' needs to be enabled to use ca injection 40 | - webhookcainjection_patch.yaml 41 | 42 | # the following config is for teaching kustomize how to do var substitution 43 | vars: 44 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 45 | - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 46 | objref: 47 | kind: Certificate 48 | group: cert-manager.io 49 | version: v1alpha2 50 | name: serving-cert # this name should match the one in certificate.yaml 51 | fieldref: 52 | fieldpath: metadata.namespace 53 | - name: CERTIFICATE_NAME 54 | objref: 55 | kind: Certificate 56 | group: cert-manager.io 57 | version: v1alpha2 58 | name: serving-cert # this name should match the one in certificate.yaml 59 | - name: SERVICE_NAMESPACE # namespace of the service 60 | objref: 61 | kind: Service 62 | version: v1 63 | name: webhook-service 64 | fieldref: 65 | fieldpath: metadata.namespace 66 | - name: SERVICE_NAME 67 | objref: 68 | kind: Service 69 | version: v1 70 | name: webhook-service 71 | -------------------------------------------------------------------------------- /go/memcached-operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--metrics-addr=127.0.0.1:8080" 25 | - "--enable-leader-election" 26 | -------------------------------------------------------------------------------- /go/memcached-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /go/memcached-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1beta1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1beta1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /go/memcached-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: controller 8 | newTag: latest 9 | -------------------------------------------------------------------------------- /go/memcached-operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | containers: 26 | - command: 27 | - /manager 28 | args: 29 | - --enable-leader-election 30 | image: controller:latest 31 | name: manager 32 | resources: 33 | limits: 34 | cpu: 100m 35 | memory: 30Mi 36 | requests: 37 | cpu: 100m 38 | memory: 20Mi 39 | terminationGracePeriodSeconds: 10 40 | -------------------------------------------------------------------------------- /go/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: '[]' 6 | capabilities: Basic Install 7 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 9 | name: memcached-operator.vX.Y.Z 10 | namespace: placeholder 11 | spec: 12 | apiservicedefinitions: {} 13 | customresourcedefinitions: 14 | owned: 15 | - description: Memcached is the Schema for the memcacheds API 16 | displayName: Memcached 17 | kind: Memcached 18 | name: memcacheds.cache.example.com 19 | version: v1alpha1 20 | description: Memcached Operator description. TODO. 21 | displayName: Memcached Operator 22 | icon: 23 | - base64data: "" 24 | mediatype: "" 25 | install: 26 | spec: 27 | deployments: null 28 | strategy: "" 29 | installModes: 30 | - supported: false 31 | type: OwnNamespace 32 | - supported: false 33 | type: SingleNamespace 34 | - supported: false 35 | type: MultiNamespace 36 | - supported: true 37 | type: AllNamespaces 38 | keywords: 39 | - memcached-operator 40 | links: 41 | - name: Memcached Operator 42 | url: https://memcached-operator.domain 43 | maintainers: 44 | - email: your@email.com 45 | name: Maintainer Name 46 | maturity: alpha 47 | provider: 48 | name: Provider Name 49 | url: https://your.domain 50 | version: 0.0.0 51 | -------------------------------------------------------------------------------- /go/memcached-operator/config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | - ../samples 4 | - ../scorecard 5 | -------------------------------------------------------------------------------- /go/memcached-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /go/memcached-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | selector: 15 | matchLabels: 16 | control-plane: controller-manager 17 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - role_binding.yaml 4 | - leader_election_role.yaml 5 | - leader_election_role_binding.yaml 6 | # Comment the following 4 lines if you want to disable 7 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 8 | # which protects your /metrics endpoint. 9 | - auth_proxy_service.yaml 10 | - auth_proxy_role.yaml 11 | - auth_proxy_role_binding.yaml 12 | - auth_proxy_client_clusterrole.yaml 13 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - configmaps/status 23 | verbs: 24 | - get 25 | - update 26 | - patch 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - events 31 | verbs: 32 | - create 33 | - patch 34 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/memcached_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-editor-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - cache.example.com 21 | resources: 22 | - memcacheds/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/memcached_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-viewer-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - cache.example.com 17 | resources: 18 | - memcacheds/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - apps 11 | resources: 12 | - deployments 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - cache.example.com 23 | resources: 24 | - memcacheds 25 | verbs: 26 | - create 27 | - delete 28 | - get 29 | - list 30 | - patch 31 | - update 32 | - watch 33 | - apiGroups: 34 | - cache.example.com 35 | resources: 36 | - memcacheds/status 37 | verbs: 38 | - get 39 | - patch 40 | - update 41 | - apiGroups: 42 | - "" 43 | resources: 44 | - pods 45 | verbs: 46 | - get 47 | - list 48 | -------------------------------------------------------------------------------- /go/memcached-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /go/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cache.example.com/v1alpha1 2 | kind: Memcached 3 | metadata: 4 | name: memcached-sample 5 | spec: 6 | # Add fields here 7 | size: 3 8 | -------------------------------------------------------------------------------- /go/memcached-operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - cache_v1alpha1_memcached.yaml 4 | # +kubebuilder:scaffold:manifestskustomizesamples 5 | -------------------------------------------------------------------------------- /go/memcached-operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /go/memcached-operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | # +kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /go/memcached-operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /go/memcached-operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.1.0 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.1.0 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.1.0 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.1.0 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /go/memcached-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /go/memcached-operator/config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /go/memcached-operator/config/webhook/manifests.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: admissionregistration.k8s.io/v1beta1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | creationTimestamp: null 7 | name: mutating-webhook-configuration 8 | webhooks: 9 | - clientConfig: 10 | caBundle: Cg== 11 | service: 12 | name: webhook-service 13 | namespace: system 14 | path: /mutate-cache-example-com-v1alpha1-memcached 15 | failurePolicy: Fail 16 | name: mmemcached.kb.io 17 | rules: 18 | - apiGroups: 19 | - cache.example.com 20 | apiVersions: 21 | - v1alpha1 22 | operations: 23 | - CREATE 24 | - UPDATE 25 | resources: 26 | - memcacheds 27 | 28 | --- 29 | apiVersion: admissionregistration.k8s.io/v1beta1 30 | kind: ValidatingWebhookConfiguration 31 | metadata: 32 | creationTimestamp: null 33 | name: validating-webhook-configuration 34 | webhooks: 35 | - clientConfig: 36 | caBundle: Cg== 37 | service: 38 | name: webhook-service 39 | namespace: system 40 | path: /validate-cache-example-com-v1alpha1-memcached 41 | failurePolicy: Fail 42 | name: vmemcached.kb.io 43 | rules: 44 | - apiGroups: 45 | - cache.example.com 46 | apiVersions: 47 | - v1alpha1 48 | operations: 49 | - CREATE 50 | - UPDATE 51 | resources: 52 | - memcacheds 53 | -------------------------------------------------------------------------------- /go/memcached-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /go/memcached-operator/controllers/memcached_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "context" 21 | "reflect" 22 | 23 | "github.com/go-logr/logr" 24 | appsv1 "k8s.io/api/apps/v1" 25 | corev1 "k8s.io/api/core/v1" 26 | "k8s.io/apimachinery/pkg/api/errors" 27 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | "k8s.io/apimachinery/pkg/runtime" 29 | "k8s.io/apimachinery/pkg/types" 30 | ctrl "sigs.k8s.io/controller-runtime" 31 | "sigs.k8s.io/controller-runtime/pkg/client" 32 | 33 | cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" 34 | ) 35 | 36 | // MemcachedReconciler reconciles a Memcached object 37 | type MemcachedReconciler struct { 38 | client.Client 39 | Log logr.Logger 40 | Scheme *runtime.Scheme 41 | } 42 | 43 | // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds,verbs=get;list;watch;create;update;patch;delete 44 | // +kubebuilder:rbac:groups=cache.example.com,resources=memcacheds/status,verbs=get;update;patch 45 | // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete 46 | // +kubebuilder:rbac:groups=core,resources=pods,verbs=get;list; 47 | 48 | func (r *MemcachedReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { 49 | ctx := context.Background() 50 | log := r.Log.WithValues("memcached", req.NamespacedName) 51 | // Fetch the Memcached instance 52 | memcached := &cachev1alpha1.Memcached{} 53 | err := r.Get(ctx, req.NamespacedName, memcached) 54 | if err != nil { 55 | if errors.IsNotFound(err) { 56 | // Request object not found, could have been deleted after reconcile request. 57 | // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 58 | // Return and don't requeue 59 | log.Info("Memcached resource not found. Ignoring since object must be deleted") 60 | return ctrl.Result{}, nil 61 | } 62 | // Error reading the object - requeue the request. 63 | log.Error(err, "Failed to get Memcached") 64 | return ctrl.Result{}, err 65 | } 66 | 67 | // Check if the deployment already exists, if not create a new one 68 | found := &appsv1.Deployment{} 69 | err = r.Get(ctx, types.NamespacedName{Name: memcached.Name, Namespace: memcached.Namespace}, found) 70 | if err != nil && errors.IsNotFound(err) { 71 | // Define a new deployment 72 | dep := r.deploymentForMemcached(memcached) 73 | log.Info("Creating a new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) 74 | err = r.Create(ctx, dep) 75 | if err != nil { 76 | log.Error(err, "Failed to create new Deployment", "Deployment.Namespace", dep.Namespace, "Deployment.Name", dep.Name) 77 | return ctrl.Result{}, err 78 | } 79 | // Deployment created successfully - return and requeue 80 | return ctrl.Result{Requeue: true}, nil 81 | } else if err != nil { 82 | log.Error(err, "Failed to get Deployment") 83 | return ctrl.Result{}, err 84 | } 85 | 86 | // Ensure the deployment size is the same as the spec 87 | size := memcached.Spec.Size 88 | if *found.Spec.Replicas != size { 89 | found.Spec.Replicas = &size 90 | err = r.Update(ctx, found) 91 | if err != nil { 92 | log.Error(err, "Failed to update Deployment", "Deployment.Namespace", found.Namespace, "Deployment.Name", found.Name) 93 | return ctrl.Result{}, err 94 | } 95 | // Spec updated - return and requeue 96 | return ctrl.Result{Requeue: true}, nil 97 | } 98 | 99 | // Update the Memcached status with the pod names 100 | // List the pods for this memcached's deployment 101 | podList := &corev1.PodList{} 102 | listOpts := []client.ListOption{ 103 | client.InNamespace(memcached.Namespace), 104 | client.MatchingLabels(labelsForMemcached(memcached.Name)), 105 | } 106 | if err = r.List(ctx, podList, listOpts...); err != nil { 107 | log.Error(err, "Failed to list pods", "Memcached.Namespace", memcached.Namespace, "Memcached.Name", memcached.Name) 108 | return ctrl.Result{}, err 109 | } 110 | podNames := getPodNames(podList.Items) 111 | 112 | // Update status.Nodes if needed 113 | if !reflect.DeepEqual(podNames, memcached.Status.Nodes) { 114 | memcached.Status.Nodes = podNames 115 | err := r.Status().Update(ctx, memcached) 116 | if err != nil { 117 | log.Error(err, "Failed to update Memcached status") 118 | return ctrl.Result{}, err 119 | } 120 | } 121 | 122 | return ctrl.Result{}, nil 123 | } 124 | 125 | // deploymentForMemcached returns a memcached Deployment object 126 | func (r *MemcachedReconciler) deploymentForMemcached(m *cachev1alpha1.Memcached) *appsv1.Deployment { 127 | ls := labelsForMemcached(m.Name) 128 | replicas := m.Spec.Size 129 | 130 | dep := &appsv1.Deployment{ 131 | ObjectMeta: metav1.ObjectMeta{ 132 | Name: m.Name, 133 | Namespace: m.Namespace, 134 | }, 135 | Spec: appsv1.DeploymentSpec{ 136 | Replicas: &replicas, 137 | Selector: &metav1.LabelSelector{ 138 | MatchLabels: ls, 139 | }, 140 | Template: corev1.PodTemplateSpec{ 141 | ObjectMeta: metav1.ObjectMeta{ 142 | Labels: ls, 143 | }, 144 | Spec: corev1.PodSpec{ 145 | Containers: []corev1.Container{{ 146 | Image: "memcached:1.4.36-alpine", 147 | Name: "memcached", 148 | Command: []string{"memcached", "-m=64", "-o", "modern", "-v"}, 149 | Ports: []corev1.ContainerPort{{ 150 | ContainerPort: 11211, 151 | Name: "memcached", 152 | }}, 153 | }}, 154 | }, 155 | }, 156 | }, 157 | } 158 | // Set Memcached instance as the owner and controller 159 | ctrl.SetControllerReference(m, dep, r.Scheme) 160 | return dep 161 | } 162 | 163 | // labelsForMemcached returns the labels for selecting the resources 164 | // belonging to the given memcached CR name. 165 | func labelsForMemcached(name string) map[string]string { 166 | return map[string]string{"app": "memcached", "memcached_cr": name} 167 | } 168 | 169 | // getPodNames returns the pod names of the array of pods passed in 170 | func getPodNames(pods []corev1.Pod) []string { 171 | var podNames []string 172 | for _, pod := range pods { 173 | podNames = append(podNames, pod.Name) 174 | } 175 | return podNames 176 | } 177 | 178 | func (r *MemcachedReconciler) SetupWithManager(mgr ctrl.Manager) error { 179 | return ctrl.NewControllerManagedBy(mgr). 180 | For(&cachev1alpha1.Memcached{}). 181 | Owns(&appsv1.Deployment{}). 182 | Complete(r) 183 | } 184 | -------------------------------------------------------------------------------- /go/memcached-operator/controllers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "path/filepath" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo" 24 | . "github.com/onsi/gomega" 25 | "k8s.io/client-go/kubernetes/scheme" 26 | "k8s.io/client-go/rest" 27 | "sigs.k8s.io/controller-runtime/pkg/client" 28 | "sigs.k8s.io/controller-runtime/pkg/envtest" 29 | "sigs.k8s.io/controller-runtime/pkg/envtest/printer" 30 | logf "sigs.k8s.io/controller-runtime/pkg/log" 31 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 32 | 33 | cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" 34 | // +kubebuilder:scaffold:imports 35 | ) 36 | 37 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 38 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 39 | 40 | var cfg *rest.Config 41 | var k8sClient client.Client 42 | var testEnv *envtest.Environment 43 | 44 | func TestAPIs(t *testing.T) { 45 | RegisterFailHandler(Fail) 46 | 47 | RunSpecsWithDefaultAndCustomReporters(t, 48 | "Controller Suite", 49 | []Reporter{printer.NewlineReporter{}}) 50 | } 51 | 52 | var _ = BeforeSuite(func(done Done) { 53 | logf.SetLogger(zap.LoggerTo(GinkgoWriter, true)) 54 | 55 | By("bootstrapping test environment") 56 | testEnv = &envtest.Environment{ 57 | CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")}, 58 | } 59 | 60 | var err error 61 | cfg, err = testEnv.Start() 62 | Expect(err).ToNot(HaveOccurred()) 63 | Expect(cfg).ToNot(BeNil()) 64 | 65 | err = cachev1alpha1.AddToScheme(scheme.Scheme) 66 | Expect(err).NotTo(HaveOccurred()) 67 | 68 | // +kubebuilder:scaffold:scheme 69 | 70 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 71 | Expect(err).ToNot(HaveOccurred()) 72 | Expect(k8sClient).ToNot(BeNil()) 73 | 74 | close(done) 75 | }, 60) 76 | 77 | var _ = AfterSuite(func() { 78 | By("tearing down the test environment") 79 | err := testEnv.Stop() 80 | Expect(err).ToNot(HaveOccurred()) 81 | }) 82 | -------------------------------------------------------------------------------- /go/memcached-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/example/memcached-operator 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/go-logr/logr v0.1.0 7 | github.com/onsi/ginkgo v1.12.1 8 | github.com/onsi/gomega v1.10.1 9 | k8s.io/api v0.18.6 10 | k8s.io/apimachinery v0.18.6 11 | k8s.io/client-go v0.18.6 12 | sigs.k8s.io/controller-runtime v0.6.2 13 | ) 14 | -------------------------------------------------------------------------------- /go/memcached-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /go/memcached-operator/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "flag" 21 | "os" 22 | 23 | "k8s.io/apimachinery/pkg/runtime" 24 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 25 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 26 | _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 27 | ctrl "sigs.k8s.io/controller-runtime" 28 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 29 | 30 | cachev1alpha1 "github.com/example/memcached-operator/api/v1alpha1" 31 | "github.com/example/memcached-operator/controllers" 32 | // +kubebuilder:scaffold:imports 33 | ) 34 | 35 | var ( 36 | scheme = runtime.NewScheme() 37 | setupLog = ctrl.Log.WithName("setup") 38 | ) 39 | 40 | func init() { 41 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 42 | 43 | utilruntime.Must(cachev1alpha1.AddToScheme(scheme)) 44 | // +kubebuilder:scaffold:scheme 45 | } 46 | 47 | func main() { 48 | var metricsAddr string 49 | var enableLeaderElection bool 50 | flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") 51 | flag.BoolVar(&enableLeaderElection, "enable-leader-election", false, 52 | "Enable leader election for controller manager. "+ 53 | "Enabling this will ensure there is only one active controller manager.") 54 | flag.Parse() 55 | 56 | ctrl.SetLogger(zap.New(zap.UseDevMode(true))) 57 | 58 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 59 | Scheme: scheme, 60 | MetricsBindAddress: metricsAddr, 61 | Port: 9443, 62 | LeaderElection: enableLeaderElection, 63 | LeaderElectionID: "86f835c3.example.com", 64 | }) 65 | if err != nil { 66 | setupLog.Error(err, "unable to start manager") 67 | os.Exit(1) 68 | } 69 | 70 | if err = (&controllers.MemcachedReconciler{ 71 | Client: mgr.GetClient(), 72 | Log: ctrl.Log.WithName("controllers").WithName("Memcached"), 73 | Scheme: mgr.GetScheme(), 74 | }).SetupWithManager(mgr); err != nil { 75 | setupLog.Error(err, "unable to create controller", "controller", "Memcached") 76 | os.Exit(1) 77 | } 78 | if err = (&cachev1alpha1.Memcached{}).SetupWebhookWithManager(mgr); err != nil { 79 | setupLog.Error(err, "unable to create webhook", "webhook", "Memcached") 80 | os.Exit(1) 81 | } 82 | // +kubebuilder:scaffold:builder 83 | 84 | setupLog.Info("starting manager") 85 | if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 86 | setupLog.Error(err, "problem running manager") 87 | os.Exit(1) 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /go/memcached-operator/packagemanifests/0.0.1/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1beta1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | annotations: 5 | controller-gen.kubebuilder.io/version: v0.3.0 6 | creationTimestamp: null 7 | name: memcacheds.cache.example.com 8 | spec: 9 | group: cache.example.com 10 | names: 11 | kind: Memcached 12 | listKind: MemcachedList 13 | plural: memcacheds 14 | singular: memcached 15 | scope: Namespaced 16 | subresources: 17 | status: {} 18 | validation: 19 | openAPIV3Schema: 20 | description: Memcached is the Schema for the memcacheds API 21 | properties: 22 | apiVersion: 23 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 27 | type: string 28 | metadata: 29 | type: object 30 | spec: 31 | description: MemcachedSpec defines the desired state of Memcached 32 | properties: 33 | size: 34 | format: int32 35 | type: integer 36 | required: 37 | - size 38 | type: object 39 | status: 40 | description: MemcachedStatus defines the observed state of Memcached 41 | properties: 42 | nodes: 43 | items: 44 | type: string 45 | type: array 46 | required: 47 | - nodes 48 | type: object 49 | type: object 50 | version: v1alpha1 51 | versions: 52 | - name: v1alpha1 53 | served: true 54 | storage: true 55 | status: 56 | acceptedNames: 57 | kind: "" 58 | plural: "" 59 | conditions: [] 60 | storedVersions: [] 61 | -------------------------------------------------------------------------------- /go/memcached-operator/packagemanifests/0.0.1/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: memcached-operator-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - /metrics 9 | verbs: 10 | - get 11 | -------------------------------------------------------------------------------- /go/memcached-operator/packagemanifests/0.0.1/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: |- 6 | [ 7 | { 8 | "apiVersion": "cache.example.com/v1alpha1", 9 | "kind": "Memcached", 10 | "metadata": { 11 | "name": "memcached-sample" 12 | }, 13 | "spec": { 14 | "size": 3 15 | } 16 | } 17 | ] 18 | capabilities: Basic Install 19 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 20 | operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 21 | name: memcached-operator.v0.0.1 22 | namespace: placeholder 23 | spec: 24 | apiservicedefinitions: {} 25 | customresourcedefinitions: 26 | owned: 27 | - description: Memcached is the Schema for the memcacheds API 28 | displayName: Memcached 29 | kind: Memcached 30 | name: memcacheds.cache.example.com 31 | version: v1alpha1 32 | description: Memcached Operator description. TODO. 33 | displayName: Memcached Operator 34 | icon: 35 | - base64data: "" 36 | mediatype: "" 37 | install: 38 | spec: 39 | clusterPermissions: 40 | - rules: 41 | - apiGroups: 42 | - apps 43 | resources: 44 | - deployments 45 | verbs: 46 | - create 47 | - delete 48 | - get 49 | - list 50 | - patch 51 | - update 52 | - watch 53 | - apiGroups: 54 | - cache.example.com 55 | resources: 56 | - memcacheds 57 | verbs: 58 | - create 59 | - delete 60 | - get 61 | - list 62 | - patch 63 | - update 64 | - watch 65 | - apiGroups: 66 | - cache.example.com 67 | resources: 68 | - memcacheds/status 69 | verbs: 70 | - get 71 | - patch 72 | - update 73 | - apiGroups: 74 | - "" 75 | resources: 76 | - pods 77 | verbs: 78 | - get 79 | - list 80 | - apiGroups: 81 | - authentication.k8s.io 82 | resources: 83 | - tokenreviews 84 | verbs: 85 | - create 86 | - apiGroups: 87 | - authorization.k8s.io 88 | resources: 89 | - subjectaccessreviews 90 | verbs: 91 | - create 92 | serviceAccountName: default 93 | deployments: 94 | - name: memcached-operator-controller-manager 95 | spec: 96 | replicas: 1 97 | selector: 98 | matchLabels: 99 | control-plane: controller-manager 100 | strategy: {} 101 | template: 102 | metadata: 103 | labels: 104 | control-plane: controller-manager 105 | spec: 106 | containers: 107 | - args: 108 | - --secure-listen-address=0.0.0.0:8443 109 | - --upstream=http://127.0.0.1:8080/ 110 | - --logtostderr=true 111 | - --v=10 112 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 113 | name: kube-rbac-proxy 114 | ports: 115 | - containerPort: 8443 116 | name: https 117 | resources: {} 118 | - args: 119 | - --metrics-addr=127.0.0.1:8080 120 | - --enable-leader-election 121 | command: 122 | - /manager 123 | image: controller:latest 124 | name: manager 125 | ports: 126 | - containerPort: 9443 127 | name: webhook-server 128 | protocol: TCP 129 | resources: 130 | limits: 131 | cpu: 100m 132 | memory: 30Mi 133 | requests: 134 | cpu: 100m 135 | memory: 20Mi 136 | volumeMounts: 137 | - mountPath: /tmp/k8s-webhook-server/serving-certs 138 | name: cert 139 | readOnly: true 140 | terminationGracePeriodSeconds: 10 141 | volumes: 142 | - name: cert 143 | secret: 144 | defaultMode: 420 145 | secretName: webhook-server-cert 146 | permissions: 147 | - rules: 148 | - apiGroups: 149 | - "" 150 | resources: 151 | - configmaps 152 | verbs: 153 | - get 154 | - list 155 | - watch 156 | - create 157 | - update 158 | - patch 159 | - delete 160 | - apiGroups: 161 | - "" 162 | resources: 163 | - configmaps/status 164 | verbs: 165 | - get 166 | - update 167 | - patch 168 | - apiGroups: 169 | - "" 170 | resources: 171 | - events 172 | verbs: 173 | - create 174 | - patch 175 | serviceAccountName: default 176 | strategy: deployment 177 | installModes: 178 | - supported: false 179 | type: OwnNamespace 180 | - supported: false 181 | type: SingleNamespace 182 | - supported: false 183 | type: MultiNamespace 184 | - supported: true 185 | type: AllNamespaces 186 | keywords: 187 | - memcached-operator 188 | links: 189 | - name: Memcached Operator 190 | url: https://memcached-operator.domain 191 | maintainers: 192 | - email: your@email.com 193 | name: Maintainer Name 194 | maturity: alpha 195 | provider: 196 | name: Provider Name 197 | url: https://your.domain 198 | version: 0.0.1 199 | webhookdefinitions: 200 | - admissionReviewVersions: 201 | - v1beta1 202 | deploymentName: memcached-operator-controller-manager 203 | failurePolicy: Fail 204 | generateName: vmemcached.kb.io 205 | rules: 206 | - apiGroups: 207 | - cache.example.com 208 | apiVersions: 209 | - v1alpha1 210 | operations: 211 | - CREATE 212 | - UPDATE 213 | resources: 214 | - memcacheds 215 | sideEffects: None 216 | type: ValidatingAdmissionWebhook 217 | webhookPath: /validate-cache-example-com-v1alpha1-memcached 218 | - admissionReviewVersions: 219 | - v1beta1 220 | deploymentName: memcached-operator-controller-manager 221 | failurePolicy: Fail 222 | generateName: mmemcached.kb.io 223 | rules: 224 | - apiGroups: 225 | - cache.example.com 226 | apiVersions: 227 | - v1alpha1 228 | operations: 229 | - CREATE 230 | - UPDATE 231 | resources: 232 | - memcacheds 233 | sideEffects: None 234 | type: MutatingAdmissionWebhook 235 | webhookPath: /mutate-cache-example-com-v1alpha1-memcached 236 | -------------------------------------------------------------------------------- /go/memcached-operator/packagemanifests/memcached-operator.package.yaml: -------------------------------------------------------------------------------- 1 | channels: 2 | - currentCSV: memcached-operator.v0.0.1 3 | name: alpha 4 | defaultChannel: alpha 5 | packageName: memcached-operator 6 | -------------------------------------------------------------------------------- /helm/.generate/gen-helm-memcached.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2019 The Operator-SDK Authors 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Before run this script ensure that you have helm installed locally 18 | # with the stable repo as well. The helm sample will use the memcached chart 19 | # from helm repository. 20 | # To install: https://helm.sh/docs/intro/install/ 21 | # To add the repo run `helm repo add stable https://charts.helm.sh/stable` 22 | 23 | set -o errexit 24 | set -o pipefail 25 | 26 | # Turn colors in this script off by setting the NO_COLOR variable in your 27 | # environment to any value: 28 | # 29 | # $ NO_COLOR=1 test.sh 30 | NO_COLOR=${NO_COLOR:-""} 31 | if [ -z "$NO_COLOR" ]; then 32 | header=$'\e[1;33m' 33 | reset=$'\e[0m' 34 | else 35 | header='' 36 | reset='' 37 | fi 38 | 39 | operatorName="memcached-operator" 40 | function header_text { 41 | echo "$header$*$reset" 42 | } 43 | 44 | function gen_helm_sample { 45 | 46 | # When operator-sdk scaffolds Helm projects, it tries to use the discovery API of a Kubernetes 47 | # cluster to intelligently build the RBAC rules that the operator will require based on the 48 | # content of the helm chart. 49 | # 50 | # Here, we intentionally set KUBECONFIG to a broken value to ensure that operator-sdk will be 51 | # unable to reach a real cluster, and thus will generate a default RBAC rule set. This is 52 | # required to make Helm project generation idempotent because contributors and CI environments 53 | # can all have slightly different environments that can affect the content of the generated 54 | # role and cause sanity testing to fail. 55 | export KUBECONFIG="broken_so_we_generate_static_default_rules" 56 | 57 | local operIMG="quay.io/example-inc/memcached-operator:v0.0.1" 58 | local bundleIMG="quay.io/example-inc/memcached-operator-bundle:v0.0.1" 59 | 60 | header_text "starting to generate the sample ..." 61 | 62 | header_text "removing memcached-operator ..." 63 | cd .. 64 | rm -rf $operatorName 65 | 66 | header_text "creating $operatorName" 67 | 68 | 69 | header_text "creating memcached-operator ..." 70 | mkdir $operatorName 71 | cd $operatorName 72 | operator-sdk init --plugins=helm --domain=example.com 73 | operator-sdk create api --version=v1alpha1 --group=cache --kind=Memcached --helm-chart=stable/memcached 74 | 75 | header_text "customizing sample project ..." 76 | 77 | header_text "updating config/samples/cache_v1alpha1_memcached.yaml ..." 78 | sed -i".bak" -E -e 's/AntiAffinity: hard/AntiAffinity: soft/g' config/samples/cache_v1alpha1_memcached.yaml; rm -f config/samples/cache_v1alpha1_memcached.yaml.bak 79 | 80 | header_text "adding policy rbac roles ..." 81 | sed -i".bak" -E -e '/kubebuilder:scaffold:rules/d' config/rbac/role.yaml; rm -f config/rbac/role.yaml.bak 82 | cat ../.generate/policy-role.yaml >> config/rbac/role.yaml 83 | 84 | header_text "enabling prometheus metrics..." 85 | sed -i".bak" -E -e 's/(#- ..\/prometheus)/- ..\/prometheus/g' config/default/kustomization.yaml; rm -f config/default/kustomization.yaml.bak 86 | 87 | header_text "bulding the project ..." 88 | make docker-build IMG=$operIMG 89 | 90 | header_text "integrating with OLM ..." 91 | sed -i".bak" -E -e 's/operator-sdk generate kustomize manifests/operator-sdk generate kustomize manifests --interactive=false/g' Makefile; rm -f Makefile.bak 92 | 93 | header_text "generating bundle and building the image $bundleIMG ..." 94 | make bundle IMG=$operIMG 95 | make bundle-build BUNDLE_IMG=$bundleIMG 96 | } 97 | 98 | gen_helm_sample 99 | -------------------------------------------------------------------------------- /helm/.generate/policy-role.yaml: -------------------------------------------------------------------------------- 1 | ## 2 | ## Rules customized for cache.example.com/v1alpha1, Kind: Memcached 3 | ## 4 | - apiGroups: 5 | - policy 6 | resources: 7 | - events 8 | - poddisruptionbudgets 9 | verbs: 10 | - '*' 11 | - apiGroups: 12 | - "" 13 | resources: 14 | - serviceaccounts 15 | - services 16 | verbs: 17 | - '*' 18 | 19 | # +kubebuilder:scaffold:rules 20 | -------------------------------------------------------------------------------- /helm/README.md: -------------------------------------------------------------------------------- 1 | # Memcached Helm Operator 2 | 3 | ## Overview 4 | 5 | This Memcached operator is a simple example of the Operator SDK Helm-based operator. It is based on the [`stable/memcached` chart][stable/memcached] . 6 | 7 | ## Prerequisites 8 | 9 | - [docker][docker_tool] version 17.03+ 10 | - [kubectl][kubectl_tool] v1.14.1+ 11 | - [operator SDK][operator_install] 12 | - Access to a Kubernetes v1.16.0+ cluster. 13 | 14 | ## Getting Started 15 | 16 | ### Clone the repository 17 | 18 | Checkout this Memcached operator repository 19 | 20 | ```sh 21 | git clone https://github.com/operator-framework/operator-sdk-samples.git 22 | cd operator-sdk-samples/helm/memcached-operator 23 | ``` 24 | 25 | ### Build the operator image 26 | 27 | Build the Memcached operator image and push it to a public registry, such as quay.io: 28 | 29 | ```sh 30 | export IMAGE=quay.io/example-inc/memcached-operator:v0.0.1 31 | make docker-build docker-push IMG=$IMAGE 32 | ``` 33 | 34 | **NOTE** To allow the cluster pull the image the repository needs to be set as public or you must configure an image pull secret. 35 | 36 | 37 | ### Run the operator 38 | 39 | Deploy the project to the cluster. Set `IMG` with `make deploy` to use the image you just pushed: 40 | 41 | ```sh 42 | make deploy IMG=$IMAGE 43 | ``` 44 | 45 | ### Create a sample custom resource 46 | 47 | Create a sample CR: 48 | 49 | ```sh 50 | kubectl apply -f config/samples/cache_v1alpha1_memcached.yaml -n memcached-operator-system 51 | ``` 52 | 53 | Run the following command to verify that the installation was successful: 54 | 55 | ```console 56 | $ kubectl get all -n memcached-operator-system 57 | NAME READY STATUS RESTARTS AGE 58 | pod/memcached-operator-controller-manager-d54b5fb78-ltwqs 2/2 Running 0 2m16s 59 | pod/memcached-sample-0 1/1 Running 0 96s 60 | pod/memcached-sample-1 1/1 Running 0 82s 61 | pod/memcached-sample-2 1/1 Running 0 72s 62 | 63 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 64 | service/memcached-operator-controller-manager-metrics-service ClusterIP 10.107.115.48 8443/TCP 2m16s 65 | service/memcached-sample ClusterIP None 11211/TCP 96s 66 | 67 | NAME READY UP-TO-DATE AVAILABLE AGE 68 | deployment.apps/memcached-operator-controller-manager 1/1 1 1 2m16s 69 | 70 | NAME DESIRED CURRENT READY AGE 71 | replicaset.apps/memcached-operator-controller-manager-d54b5fb78 1 1 1 2m16s 72 | 73 | NAME READY AGE 74 | statefulset.apps/memcached-sample 3/3 96s 75 | ``` 76 | 77 | ### Clean up 78 | 79 | Delete the CR to uninstall the release: 80 | 81 | ```sh 82 | kubectl delete -f config/samples/cache_v1alpha1_memcached.yaml -n memcached-operator-system 83 | ``` 84 | 85 | Use `make uninstall` and `make undeploy` to uninstall the operator and its CRDs: 86 | 87 | ```sh 88 | make uninstall 89 | make undeploy 90 | ``` 91 | 92 | ### Troubleshooting 93 | 94 | Run the following command to check the operator logs. 95 | 96 | ```sh 97 | kubectl logs deployment.apps/memcached-operator-controller-manager -n memcached-operator-system -c manager 98 | ``` 99 | 100 | ### Extras 101 | 102 | This project was created by using the [gen-helm-memcached.sh][gen-helm-memcached.sh] script , which means that it is using the official [stable/memcached][stable/memcached] helm chart. 103 | 104 | Note that you must have Helm installed locally and add the stable helm charts repo to it to use the `stable/memcached` Helm charts. See the [Helm Quickstart guide][helm-quick] for installation instructions. Also, you can start with Helm-based Operators with SDK by checking its [quickstart][helm_guide]. 105 | 106 | [kubectl_tool]: https://kubernetes.io/docs/tasks/tools/install-kubectl/ 107 | [docker_tool]: https://docs.docker.com/install/ 108 | [operator_install]: https://sdk.operatorframework.io/docs/install-operator-sdk/ 109 | [helm_guide]: https://sdk.operatorframework.io/docs/helm/quickstart/ 110 | [stable/memcached]: https://github.com/helm/charts/tree/master/stable/memcached 111 | [helm-quick]: https://helm.sh/docs/intro/quickstart/ 112 | [gen-helm-memcached.sh]: .generate/gen-helm-memcached.sh 113 | -------------------------------------------------------------------------------- /helm/memcached-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # editor and IDE paraphernalia 11 | .idea 12 | *.swp 13 | *.swo 14 | *~ 15 | -------------------------------------------------------------------------------- /helm/memcached-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM quay.io/operator-framework/helm-operator:v1.1.0 3 | 4 | ENV HOME=/opt/helm 5 | COPY watches.yaml ${HOME}/watches.yaml 6 | COPY helm-charts ${HOME}/helm-charts 7 | WORKDIR ${HOME} 8 | -------------------------------------------------------------------------------- /helm/memcached-operator/Makefile: -------------------------------------------------------------------------------- 1 | # Current Operator version 2 | VERSION ?= 0.0.1 3 | # Default bundle image tag 4 | BUNDLE_IMG ?= controller-bundle:$(VERSION) 5 | # Options for 'bundle-build' 6 | ifneq ($(origin CHANNELS), undefined) 7 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 8 | endif 9 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 10 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 11 | endif 12 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 13 | 14 | # Image URL to use all building/pushing image targets 15 | IMG ?= controller:latest 16 | 17 | all: docker-build 18 | 19 | # Run against the configured Kubernetes cluster in ~/.kube/config 20 | run: helm-operator 21 | $(HELM_OPERATOR) run 22 | 23 | # Install CRDs into a cluster 24 | install: kustomize 25 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 26 | 27 | # Uninstall CRDs from a cluster 28 | uninstall: kustomize 29 | $(KUSTOMIZE) build config/crd | kubectl delete -f - 30 | 31 | # Deploy controller in the configured Kubernetes cluster in ~/.kube/config 32 | deploy: kustomize 33 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 34 | $(KUSTOMIZE) build config/default | kubectl apply -f - 35 | 36 | # Undeploy controller in the configured Kubernetes cluster in ~/.kube/config 37 | undeploy: kustomize 38 | $(KUSTOMIZE) build config/default | kubectl delete -f - 39 | 40 | # Build the docker image 41 | docker-build: 42 | docker build . -t ${IMG} 43 | 44 | # Push the docker image 45 | docker-push: 46 | docker push ${IMG} 47 | 48 | PATH := $(PATH):$(PWD)/bin 49 | SHELL := env PATH=$(PATH) /bin/sh 50 | OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') 51 | ARCH = $(shell uname -m | sed 's/x86_64/amd64/') 52 | OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') 53 | ARCHOPER = $(shell uname -m ) 54 | 55 | kustomize: 56 | ifeq (, $(shell which kustomize 2>/dev/null)) 57 | @{ \ 58 | set -e ;\ 59 | mkdir -p bin ;\ 60 | curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ 61 | } 62 | KUSTOMIZE=$(realpath ./bin/kustomize) 63 | else 64 | KUSTOMIZE=$(shell which kustomize) 65 | endif 66 | 67 | helm-operator: 68 | ifeq (, $(shell which helm-operator 2>/dev/null)) 69 | @{ \ 70 | set -e ;\ 71 | mkdir -p bin ;\ 72 | curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.1.0/helm-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ;\ 73 | mv helm-operator-v1.1.0-$(ARCHOPER)-$(OSOPER) ./bin/helm-operator ;\ 74 | chmod +x ./bin/helm-operator ;\ 75 | } 76 | HELM_OPERATOR=$(realpath ./bin/helm-operator) 77 | else 78 | HELM_OPERATOR=$(shell which helm-operator) 79 | endif 80 | 81 | # Generate bundle manifests and metadata, then validate generated files. 82 | .PHONY: bundle 83 | bundle: kustomize 84 | operator-sdk generate kustomize manifests --interactive=false -q 85 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 86 | $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 87 | operator-sdk bundle validate ./bundle 88 | 89 | # Build the bundle image. 90 | .PHONY: bundle-build 91 | bundle-build: 92 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 93 | -------------------------------------------------------------------------------- /helm/memcached-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: example.com 2 | layout: helm.sdk.operatorframework.io/v1 3 | projectName: memcached-operator 4 | resources: 5 | - group: cache 6 | kind: Memcached 7 | version: v1alpha1 8 | version: 3-alpha 9 | -------------------------------------------------------------------------------- /helm/memcached-operator/bundle.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | 3 | LABEL operators.operatorframework.io.bundle.mediatype.v1=registry+v1 4 | LABEL operators.operatorframework.io.bundle.manifests.v1=manifests/ 5 | LABEL operators.operatorframework.io.bundle.metadata.v1=metadata/ 6 | LABEL operators.operatorframework.io.bundle.package.v1=memcached-operator 7 | LABEL operators.operatorframework.io.bundle.channels.v1=alpha 8 | LABEL operators.operatorframework.io.metrics.builder=operator-sdk-v1.1.0 9 | LABEL operators.operatorframework.io.metrics.mediatype.v1=metrics+v1 10 | LABEL operators.operatorframework.io.metrics.project_layout=helm.sdk.operatorframework.io/v1 11 | LABEL operators.operatorframework.io.test.config.v1=tests/scorecard/ 12 | LABEL operators.operatorframework.io.test.mediatype.v1=scorecard+v1 13 | COPY bundle/manifests /manifests/ 14 | COPY bundle/metadata /metadata/ 15 | COPY bundle/tests/scorecard /tests/scorecard/ 16 | -------------------------------------------------------------------------------- /helm/memcached-operator/bundle/manifests/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | creationTimestamp: null 5 | name: memcacheds.cache.example.com 6 | spec: 7 | group: cache.example.com 8 | names: 9 | kind: Memcached 10 | listKind: MemcachedList 11 | plural: memcacheds 12 | singular: memcached 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: Memcached is the Schema for the memcacheds API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 22 | type: string 23 | kind: 24 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 25 | type: string 26 | metadata: 27 | type: object 28 | spec: 29 | description: Spec defines the desired state of Memcached 30 | type: object 31 | x-kubernetes-preserve-unknown-fields: true 32 | status: 33 | description: Status defines the observed state of Memcached 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | type: object 37 | served: true 38 | storage: true 39 | subresources: 40 | status: {} 41 | status: 42 | acceptedNames: 43 | kind: "" 44 | plural: "" 45 | conditions: null 46 | storedVersions: null 47 | -------------------------------------------------------------------------------- /helm/memcached-operator/bundle/manifests/memcached-operator-metrics-reader_rbac.authorization.k8s.io_v1beta1_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | creationTimestamp: null 5 | name: memcached-operator-metrics-reader 6 | rules: 7 | - nonResourceURLs: 8 | - /metrics 9 | verbs: 10 | - get 11 | -------------------------------------------------------------------------------- /helm/memcached-operator/bundle/metadata/annotations.yaml: -------------------------------------------------------------------------------- 1 | annotations: 2 | operators.operatorframework.io.bundle.channels.v1: alpha 3 | operators.operatorframework.io.bundle.manifests.v1: manifests/ 4 | operators.operatorframework.io.bundle.mediatype.v1: registry+v1 5 | operators.operatorframework.io.bundle.metadata.v1: metadata/ 6 | operators.operatorframework.io.bundle.package.v1: memcached-operator 7 | operators.operatorframework.io.metrics.builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io.metrics.mediatype.v1: metrics+v1 9 | operators.operatorframework.io.metrics.project_layout: helm.sdk.operatorframework.io/v1 10 | operators.operatorframework.io.test.config.v1: tests/scorecard/ 11 | operators.operatorframework.io.test.mediatype.v1: scorecard+v1 12 | -------------------------------------------------------------------------------- /helm/memcached-operator/bundle/tests/scorecard/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: 8 | - entrypoint: 9 | - scorecard-test 10 | - basic-check-spec 11 | image: quay.io/operator-framework/scorecard-test:v1.1.0 12 | labels: 13 | suite: basic 14 | test: basic-check-spec-test 15 | - entrypoint: 16 | - scorecard-test 17 | - olm-bundle-validation 18 | image: quay.io/operator-framework/scorecard-test:v1.1.0 19 | labels: 20 | suite: olm 21 | test: olm-bundle-validation-test 22 | - entrypoint: 23 | - scorecard-test 24 | - olm-crds-have-validation 25 | image: quay.io/operator-framework/scorecard-test:v1.1.0 26 | labels: 27 | suite: olm 28 | test: olm-crds-have-validation-test 29 | - entrypoint: 30 | - scorecard-test 31 | - olm-crds-have-resources 32 | image: quay.io/operator-framework/scorecard-test:v1.1.0 33 | labels: 34 | suite: olm 35 | test: olm-crds-have-resources-test 36 | - entrypoint: 37 | - scorecard-test 38 | - olm-spec-descriptors 39 | image: quay.io/operator-framework/scorecard-test:v1.1.0 40 | labels: 41 | suite: olm 42 | test: olm-spec-descriptors-test 43 | - entrypoint: 44 | - scorecard-test 45 | - olm-status-descriptors 46 | image: quay.io/operator-framework/scorecard-test:v1.1.0 47 | labels: 48 | suite: olm 49 | test: olm-status-descriptors-test 50 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/crd/bases/cache.example.com_memcacheds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: memcacheds.cache.example.com 6 | spec: 7 | group: cache.example.com 8 | names: 9 | kind: Memcached 10 | listKind: MemcachedList 11 | plural: memcacheds 12 | singular: memcached 13 | scope: Namespaced 14 | versions: 15 | - name: v1alpha1 16 | schema: 17 | openAPIV3Schema: 18 | description: Memcached is the Schema for the memcacheds API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of Memcached 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of Memcached 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/cache.example.com_memcacheds.yaml 6 | # +kubebuilder:scaffold:crdkustomizeresource 7 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: memcached-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: memcached-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 20 | - ../prometheus 21 | 22 | patchesStrategicMerge: 23 | # Protect the /metrics endpoint by putting it behind auth. 24 | # If you want your controller-manager to expose the /metrics 25 | # endpoint w/o any authn/z, please comment the following line. 26 | - manager_auth_proxy_patch.yaml 27 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--metrics-addr=127.0.0.1:8080" 25 | - "--enable-leader-election" 26 | - "--leader-election-id=memcached-operator" 27 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: quay.io/example-inc/memcached-operator 8 | newTag: v0.0.1 9 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | containers: 26 | - image: controller:latest 27 | args: 28 | - "--enable-leader-election" 29 | - "--leader-election-id=memcached-operator" 30 | name: manager 31 | resources: 32 | limits: 33 | cpu: 100m 34 | memory: 90Mi 35 | requests: 36 | cpu: 100m 37 | memory: 60Mi 38 | terminationGracePeriodSeconds: 10 39 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/manifests/bases/memcached-operator.clusterserviceversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: ClusterServiceVersion 3 | metadata: 4 | annotations: 5 | alm-examples: '[]' 6 | capabilities: Basic Install 7 | operators.operatorframework.io/builder: operator-sdk-v1.1.0 8 | operators.operatorframework.io/project_layout: helm.sdk.operatorframework.io/v1 9 | name: memcached-operator.vX.Y.Z 10 | namespace: placeholder 11 | spec: 12 | apiservicedefinitions: {} 13 | customresourcedefinitions: {} 14 | description: Memcached Operator description. TODO. 15 | displayName: Memcached Operator 16 | icon: 17 | - base64data: "" 18 | mediatype: "" 19 | install: 20 | spec: 21 | deployments: null 22 | strategy: "" 23 | installModes: 24 | - supported: false 25 | type: OwnNamespace 26 | - supported: false 27 | type: SingleNamespace 28 | - supported: false 29 | type: MultiNamespace 30 | - supported: true 31 | type: AllNamespaces 32 | keywords: 33 | - memcached-operator 34 | links: 35 | - name: Memcached Operator 36 | url: https://memcached-operator.domain 37 | maintainers: 38 | - email: your@email.com 39 | name: Maintainer Name 40 | maturity: alpha 41 | provider: 42 | name: Provider Name 43 | url: https://your.domain 44 | version: 0.0.0 45 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | - ../samples 4 | - ../scorecard 5 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | selector: 15 | matchLabels: 16 | control-plane: controller-manager 17 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - role.yaml 3 | - role_binding.yaml 4 | - leader_election_role.yaml 5 | - leader_election_role_binding.yaml 6 | # Comment the following 4 lines if you want to disable 7 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 8 | # which protects your /metrics endpoint. 9 | - auth_proxy_service.yaml 10 | - auth_proxy_role.yaml 11 | - auth_proxy_role_binding.yaml 12 | - auth_proxy_client_clusterrole.yaml 13 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - patch 26 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/memcached_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-editor-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - cache.example.com 21 | resources: 22 | - memcacheds/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/memcached_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view memcacheds. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: memcached-viewer-role 6 | rules: 7 | - apiGroups: 8 | - cache.example.com 9 | resources: 10 | - memcacheds 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - cache.example.com 17 | resources: 18 | - memcacheds/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: manager-role 5 | rules: 6 | ## 7 | ## Base operator rules 8 | ## 9 | # We need to get namespaces so the operator can read namespaces to ensure they exist 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - namespaces 14 | verbs: 15 | - get 16 | # We need to manage Helm release secrets 17 | - apiGroups: 18 | - "" 19 | resources: 20 | - secrets 21 | verbs: 22 | - "*" 23 | # We need to create events on CRs about things happening during reconciliation 24 | - apiGroups: 25 | - "" 26 | resources: 27 | - events 28 | verbs: 29 | - create 30 | 31 | ## 32 | ## Rules for cache.example.com/v1alpha1, Kind: Memcached 33 | ## 34 | - apiGroups: 35 | - cache.example.com 36 | resources: 37 | - memcacheds 38 | - memcacheds/status 39 | verbs: 40 | - create 41 | - delete 42 | - get 43 | - list 44 | - patch 45 | - update 46 | - watch 47 | - apiGroups: 48 | - "" 49 | resources: 50 | - pods 51 | - services 52 | - services/finalizers 53 | - endpoints 54 | - persistentvolumeclaims 55 | - events 56 | - configmaps 57 | - secrets 58 | verbs: 59 | - create 60 | - delete 61 | - get 62 | - list 63 | - patch 64 | - update 65 | - watch 66 | - apiGroups: 67 | - apps 68 | resources: 69 | - deployments 70 | - daemonsets 71 | - replicasets 72 | - statefulsets 73 | verbs: 74 | - create 75 | - delete 76 | - get 77 | - list 78 | - patch 79 | - update 80 | - watch 81 | 82 | ## 83 | ## Rules customized for cache.example.com/v1alpha1, Kind: Memcached 84 | ## 85 | - apiGroups: 86 | - policy 87 | resources: 88 | - events 89 | - poddisruptionbudgets 90 | verbs: 91 | - '*' 92 | - apiGroups: 93 | - "" 94 | resources: 95 | - serviceaccounts 96 | - services 97 | verbs: 98 | - '*' 99 | 100 | # +kubebuilder:scaffold:rules 101 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: default 12 | namespace: system 13 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/samples/cache_v1alpha1_memcached.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cache.example.com/v1alpha1 2 | kind: Memcached 3 | metadata: 4 | name: memcached-sample 5 | spec: 6 | # Default values copied from /helm-charts/memcached/values.yaml 7 | AntiAffinity: soft 8 | affinity: {} 9 | extraContainers: "" 10 | extraVolumes: "" 11 | image: memcached:1.5.20 12 | kind: StatefulSet 13 | memcached: 14 | extendedOptions: modern 15 | extraArgs: [] 16 | maxItemMemory: 64 17 | verbosity: v 18 | metrics: 19 | enabled: false 20 | image: quay.io/prometheus/memcached-exporter:v0.6.0 21 | resources: {} 22 | serviceMonitor: 23 | enabled: false 24 | interval: 15s 25 | nodeSelector: {} 26 | pdbMinAvailable: 2 27 | podAnnotations: {} 28 | replicaCount: 3 29 | resources: 30 | requests: 31 | cpu: 50m 32 | memory: 64Mi 33 | securityContext: 34 | enabled: true 35 | fsGroup: 1001 36 | runAsUser: 1001 37 | serviceAnnotations: {} 38 | tolerations: {} 39 | updateStrategy: 40 | type: RollingUpdate 41 | 42 | 43 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | resources: 3 | - cache_v1alpha1_memcached.yaml 4 | # +kubebuilder:scaffold:manifestskustomizesamples 5 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | patchesJson6902: 4 | - path: patches/basic.config.yaml 5 | target: 6 | group: scorecard.operatorframework.io 7 | version: v1alpha3 8 | kind: Configuration 9 | name: config 10 | - path: patches/olm.config.yaml 11 | target: 12 | group: scorecard.operatorframework.io 13 | version: v1alpha3 14 | kind: Configuration 15 | name: config 16 | # +kubebuilder:scaffold:patchesJson6902 17 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /helm/memcached-operator/config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.1.0 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.1.0 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.1.0 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.1.0 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.1.0 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/.helmignore: -------------------------------------------------------------------------------- 1 | .git 2 | OWNERS 3 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: 1.5.20 3 | description: Free & open source, high-performance, distributed memory object caching system. 4 | home: http://memcached.org/ 5 | icon: https://upload.wikimedia.org/wikipedia/en/thumb/2/27/Memcached.svg/1024px-Memcached.svg.png 6 | keywords: 7 | - memcached 8 | - cache 9 | maintainers: 10 | - email: gtaylor@gc-taylor.com 11 | name: gtaylor 12 | - email: o.with@sportradar.com 13 | name: olemarkus 14 | - email: k.aasan@sportradar.com 15 | name: kennethaasan 16 | name: memcached 17 | sources: 18 | - https://github.com/docker-library/memcached 19 | version: 3.2.3 20 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Memcached can be accessed via port 11211 on the following DNS name from within your cluster: 2 | {{ template "memcached.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local 3 | 4 | If you'd like to test your instance, forward the port locally: 5 | 6 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "memcached.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 7 | kubectl port-forward $POD_NAME 11211 8 | 9 | In another tab, attempt to set a key: 10 | 11 | $ echo -e 'set mykey 0 60 5\r\nhello\r' | nc localhost 11211 12 | 13 | You should see: 14 | 15 | STORED 16 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "memcached.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | */}} 13 | {{- define "memcached.fullname" -}} 14 | {{- if .Values.fullnameOverride -}} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 16 | {{- else -}} 17 | {{- $name := default .Chart.Name .Values.nameOverride -}} 18 | {{- if contains $name .Release.Name -}} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 20 | {{- else -}} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 22 | {{- end -}} 23 | {{- end -}} 24 | {{- end -}} 25 | 26 | {{/* 27 | Common labels 28 | */}} 29 | {{- define "memcached.labels" -}} 30 | app.kubernetes.io/name: {{ include "memcached.name" . }} 31 | helm.sh/chart: {{ include "memcached.chart" . }} 32 | app.kubernetes.io/instance: {{ .Release.Name }} 33 | {{- if .Chart.AppVersion }} 34 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 35 | {{- end }} 36 | app.kubernetes.io/managed-by: {{ .Release.Service }} 37 | {{- end -}} 38 | 39 | {{/* 40 | Create chart name and version as used by the chart label. 41 | */}} 42 | {{- define "memcached.chart" -}} 43 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 44 | {{- end -}} 45 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/pdb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: policy/v1beta1 2 | kind: PodDisruptionBudget 3 | metadata: 4 | name: {{ template "memcached.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | annotations: 7 | helm.sh/hook: "post-upgrade, post-install" 8 | helm.sh/hook-delete-policy: "before-hook-creation" 9 | labels: 10 | {{ include "memcached.labels" . | indent 4 }} 11 | spec: 12 | selector: 13 | matchLabels: 14 | app.kubernetes.io/name: {{ include "memcached.name" . }} 15 | app.kubernetes.io/instance: {{ .Release.Name }} 16 | minAvailable: {{ .Values.pdbMinAvailable }} 17 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ template "memcached.fullname" . }} 6 | namespace: {{ .Release.Namespace }} 7 | labels: 8 | {{ include "memcached.labels" . | indent 4 }} 9 | spec: 10 | selector: 11 | matchLabels: 12 | app.kubernetes.io/name: {{ include "memcached.name" . }} 13 | app.kubernetes.io/instance: {{ .Release.Name }} 14 | endpoints: 15 | - port: metrics 16 | interval: {{ .Values.metrics.serviceMonitor.interval }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: {{ .Values.kind }} 3 | metadata: 4 | name: {{ template "memcached.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{ include "memcached.labels" . | indent 4 }} 8 | spec: 9 | selector: 10 | matchLabels: 11 | app.kubernetes.io/name: {{ include "memcached.name" . }} 12 | app.kubernetes.io/instance: {{ .Release.Name }} 13 | {{- if eq .Values.kind "StatefulSet" }} 14 | serviceName: {{ template "memcached.fullname" . }} 15 | {{- end }} 16 | replicas: {{ .Values.replicaCount }} 17 | template: 18 | metadata: 19 | labels: 20 | app.kubernetes.io/name: {{ include "memcached.name" . }} 21 | app.kubernetes.io/instance: {{ .Release.Name }} 22 | {{- with .Values.podLabels }} 23 | {{ toYaml . | indent 8 }} 24 | {{- end}} 25 | {{- with .Values.podAnnotations }} 26 | annotations: 27 | {{ toYaml . | indent 8 }} 28 | {{- end }} 29 | spec: 30 | {{- if .Values.securityContext.enabled }} 31 | securityContext: 32 | fsGroup: {{ .Values.securityContext.fsGroup }} 33 | {{- end }} 34 | affinity: 35 | podAntiAffinity: 36 | {{- if eq .Values.AntiAffinity "hard" }} 37 | requiredDuringSchedulingIgnoredDuringExecution: 38 | - topologyKey: "kubernetes.io/hostname" 39 | labelSelector: 40 | matchLabels: 41 | app.kubernetes.io/name: {{ include "memcached.name" . }} 42 | app.kubernetes.io/instance: {{ .Release.Name }} 43 | {{- else if eq .Values.AntiAffinity "soft" }} 44 | preferredDuringSchedulingIgnoredDuringExecution: 45 | - weight: 5 46 | podAffinityTerm: 47 | topologyKey: "kubernetes.io/hostname" 48 | labelSelector: 49 | matchLabels: 50 | app.kubernetes.io/name: {{ include "memcached.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end }} 53 | {{- if .Values.priorityClassName }} 54 | priorityClassName: "{{ .Values.priorityClassName }}" 55 | {{- end }} 56 | containers: 57 | - name: {{ template "memcached.fullname" . }} 58 | image: {{ .Values.image }} 59 | imagePullPolicy: {{ default "" .Values.imagePullPolicy | quote }} 60 | {{- if .Values.securityContext.enabled }} 61 | securityContext: 62 | runAsUser: {{ .Values.securityContext.runAsUser }} 63 | {{- end }} 64 | command: 65 | - memcached 66 | - -m {{ .Values.memcached.maxItemMemory }} 67 | {{- if .Values.memcached.extendedOptions }} 68 | - -o 69 | - {{ .Values.memcached.extendedOptions }} 70 | {{- end }} 71 | {{- if .Values.memcached.verbosity }} 72 | - -{{ .Values.memcached.verbosity }} 73 | {{- end }} 74 | {{- with .Values.memcached.extraArgs }} 75 | {{ toYaml . | indent 8 }} 76 | {{- end }} 77 | ports: 78 | - name: memcache 79 | containerPort: 11211 80 | livenessProbe: 81 | tcpSocket: 82 | port: memcache 83 | initialDelaySeconds: 30 84 | timeoutSeconds: 5 85 | readinessProbe: 86 | tcpSocket: 87 | port: memcache 88 | initialDelaySeconds: 5 89 | timeoutSeconds: 1 90 | resources: 91 | {{ toYaml .Values.resources | indent 10 }} 92 | {{- if .Values.metrics.enabled }} 93 | - name: metrics 94 | image: {{ .Values.metrics.image }} 95 | imagePullPolicy: {{ default "" .Values.metrics.imagePullPolicy | quote }} 96 | {{- if .Values.securityContext.enabled }} 97 | securityContext: 98 | runAsUser: {{ .Values.securityContext.runAsUser }} 99 | {{- end }} 100 | ports: 101 | - name: metrics 102 | containerPort: 9150 103 | resources: 104 | {{ toYaml .Values.metrics.resources | indent 10 }} 105 | {{- end }} 106 | {{- with .Values.extraContainers }} 107 | {{ tpl . $ | indent 6 }} 108 | {{- end }} 109 | {{- with .Values.extraVolumes }} 110 | volumes: 111 | {{ tpl . $ | indent 6 }} 112 | {{- end }} 113 | {{- with .Values.nodeSelector }} 114 | nodeSelector: 115 | {{ toYaml . | trim | indent 8}} 116 | {{- end }} 117 | {{- with .Values.tolerations }} 118 | tolerations: 119 | {{ toYaml . | trim | indent 8}} 120 | {{- end }} 121 | {{- with .Values.affinity }} 122 | affinity: 123 | {{ toYaml . | trim | indent 8}} 124 | {{- end }} 125 | {{- if eq .Values.kind "StatefulSet" }} 126 | updateStrategy: 127 | {{- else }} 128 | strategy: 129 | {{- end }} 130 | type: {{ .Values.updateStrategy.type }} 131 | {{- if (eq "Recreate" .Values.updateStrategy.type) }} 132 | rollingUpdate: null 133 | {{- end }} 134 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/templates/svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ template "memcached.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{ include "memcached.labels" . | indent 4 }} 8 | annotations: 9 | {{ toYaml .Values.serviceAnnotations | indent 4 }} 10 | spec: 11 | clusterIP: None 12 | ports: 13 | - name: memcache 14 | port: 11211 15 | targetPort: memcache 16 | {{- if .Values.metrics.enabled }} 17 | - name: metrics 18 | port: 9150 19 | targetPort: metrics 20 | {{- end }} 21 | selector: 22 | app.kubernetes.io/name: {{ include "memcached.name" . }} 23 | app.kubernetes.io/instance: {{ .Release.Name }} 24 | -------------------------------------------------------------------------------- /helm/memcached-operator/helm-charts/memcached/values.yaml: -------------------------------------------------------------------------------- 1 | ## Memcached image and tag 2 | ## ref: https://hub.docker.com/r/library/memcached/tags/ 3 | ## 4 | image: memcached:1.5.20 5 | 6 | ## Specify a imagePullPolicy 7 | ## 'Always' if imageTag is 'latest', else set to 'IfNotPresent' 8 | ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images 9 | ## 10 | # imagePullPolicy: 11 | # 12 | 13 | ## Replica count 14 | replicaCount: 3 15 | 16 | ## Pod disruption budget minAvailable count 17 | ## Ensure this value is lower than replicaCount in order to allow a worker 18 | ## node to drain successfully 19 | pdbMinAvailable: 2 20 | 21 | ## Select AntiAffinity as either hard or soft, default is hard 22 | AntiAffinity: "hard" 23 | 24 | memcached: 25 | ## Various values that get set as command-line flags. 26 | ## ref: https://github.com/memcached/memcached/wiki/ConfiguringServer#commandline-arguments 27 | ## 28 | maxItemMemory: 64 29 | verbosity: v 30 | extendedOptions: modern 31 | 32 | ## Additional command line arguments to pass to memcached 33 | ## E.g. to specify a maximum value size 34 | ## extraArgs: 35 | ## - -I 2m 36 | extraArgs: [] 37 | 38 | ## Define various attributes of the service 39 | serviceAnnotations: {} 40 | # prometheus.io/scrape: "true" 41 | 42 | ## StatefulSet or Deployment 43 | kind: StatefulSet 44 | 45 | ## Update Strategy for the StatefulSet or Deployment 46 | ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#update-strategies 47 | ## ref: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#updating-a-deployment 48 | updateStrategy: 49 | type: RollingUpdate 50 | 51 | ## Configure resource requests and limits 52 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 53 | ## 54 | resources: 55 | requests: 56 | memory: 64Mi 57 | cpu: 50m 58 | 59 | ## Key:value pair for assigning pod to specific sets of nodes 60 | ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ 61 | nodeSelector: {} 62 | 63 | ## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ 64 | tolerations: {} 65 | 66 | ## Advanced scheduling controls 67 | ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ 68 | affinity: {} 69 | 70 | ## Memcached pod Security Context 71 | ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ 72 | securityContext: 73 | enabled: true 74 | fsGroup: 1001 75 | runAsUser: 1001 76 | 77 | metrics: 78 | ## Expose memcached metrics in Prometheus format 79 | enabled: false 80 | serviceMonitor: 81 | enabled: false 82 | interval: 15s 83 | 84 | ## Memcached exporter image and tag 85 | image: quay.io/prometheus/memcached-exporter:v0.6.0 86 | 87 | ## Specify a imagePullPolicy 88 | ## 'Always' if imageTag is 'latest', else set to 'IfNotPresent' 89 | ## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images 90 | ## 91 | # imagePullPolicy: IfNotPresent 92 | 93 | ## Configure resource requests and limits 94 | ## ref: http://kubernetes.io/docs/user-guide/compute-resources/ 95 | ## 96 | resources: {} 97 | 98 | extraContainers: | 99 | 100 | extraVolumes: | 101 | 102 | ## Custom metadata labels to be applied to statefulset and pods 103 | # podLabels: 104 | # foo: "bar" 105 | # bar: "foo" 106 | 107 | # To be added to the server pod(s) 108 | podAnnotations: {} 109 | 110 | ## Set pod priority class 111 | # priorityClassName: "" 112 | -------------------------------------------------------------------------------- /helm/memcached-operator/watches.yaml: -------------------------------------------------------------------------------- 1 | # Use the 'create api' subcommand to add watches to this file. 2 | - group: cache.example.com 3 | version: v1alpha1 4 | kind: Memcached 5 | chart: helm-charts/memcached 6 | # +kubebuilder:scaffold:watch 7 | --------------------------------------------------------------------------------