diff --git a/installplan-approver/README.md b/installplan-approver/README.md index de01b51d..3898188e 100644 --- a/installplan-approver/README.md +++ b/installplan-approver/README.md @@ -1,27 +1,135 @@ -# Install Plan Approver +# Operator GitOps Deployment Template -In OCP 4 when you set an operator for manual upgrades you need to manually approve the initial deployment which is challenging in a gitops world. The installplan-approver-job created by Andrew Pitt can be used to approve all pending installplans in the namespace in which it is deployed. +## How to use this template -## Usage +This template can be used to setup an automated Operator deployment and upgrade capability that leverages GitOps using ArgoCD. This template is built using Kustomize to allow for customization of the deployment as well as specific configurations for each environment category to be deployed to. This includes specific configuration for Staging, Development, and Production. + +To use this template: + +Clone to new repo +1) Create a new repository to host the new operator within Git +2) Copy the contents from this repo into your new repo as the starting point or on repo creation just to copy this existing repo +3) All following code changes should be made to your copy of this content in the new repo and not to the original template content + +Gather Information +1) Identify the Operator you wish to configure deployment using this GitOps Template +2) Identify the Channel you wish the operator to use + a) this can be done by installing the operator and reviewing the channel choice in the subscription object +3) Identify the install version, and desired update version if different from install version + a) this can be done by installing the operator in the test environment and viewing the ClusterSubscriptionVersion (CSV) file associated with the deployment +4) Identify the target namespace for the operator. The template is built around using operatorname-operator as its basis so this is the easiest format to use. i.e. amqstreams-operator +5) Identify any customizations you need to apply to the operator deployment. This are not usually required, but sometimes are in special cases. i.e. FIPS configuration for AMQ-Streams + +Update Template +1) Update the filename of all included yaml files to be named appropriately for the desired operator. i.e. operatorname-operator-subscription.yaml -> amqstreams-operator-subscription.yaml + +Here is a rename command that you may be able to use depending on your setup: +`rename 's/operatorname/rhsso/' *yaml` + +2) Find all instances of "operatorname-operator" within the included yaml files and replace with the appropriate name. The following is a list of each instance of this item +base/kustomization.yaml: - operatorname-operator-subscription.yaml +base/kustomization.yaml: - operatorname-operator-operatorgroup.yaml +base/kustomization.yaml: - operatorname-operator-install-approvaljob.yaml +base/kustomization.yaml: - operatorname-operator-upgrade-approvaljob.yaml +base/kustomization.yaml: - operatorname-operator-rbac.yaml +base/operatorname-operator-install-approvaljob.yaml: namespace: operatorname-operator +base/operatorname-operator-install-approvaljob.yaml: value: "operatorname-operator" +base/operatorname-operator-rbac.yaml: namespace: operatorname-operator +base/operatorname-operator-rbac.yaml: namespace: operatorname-operator +base/operatorname-operator-sa.yaml: namespace: operatorname-operator +base/operatorname-operator-subscription.yaml: namespace: operatorname-operator +base/operatorname-operator-upgrade-approvaljob.yaml: namespace: operatorname-operator +base/operatorname-operator-upgrade-approvaljob.yaml: value: "operatorname-operator" +base/operatorname-operator-operatorgroup.yaml: namespace: operatorname-operator +base/operatorname-operator-operatorgroup.yaml: - operatorname-operator +overlays/Development/kustomization.yaml:namespace: operatorname-operator +overlays/Production/kustomization.yaml:namespace: operatorname-operator +overlays/Staging/kustomization.yaml:namespace: operatorname-operator + +Here is a sed command that can help you quickly rename these. Please verify correctness after running the command: +`find . -type f -name "*.yaml" -exec sed -i 's/operatorname-operator/newname-operator/g' {} +` +where newname is the name you would be inserting such as amqstreams + +Next replace all instances of the term "operatorname" with the appropriate name for the operator. Here is a list of all of these instances that need replacement: +operatorname-operator-install-approvaljob.yaml: name: operatorname-versions +operatorname-operator-subscription.yaml: name: operatorname +operatorname-operator-subscription.yaml: name: operatorname +operatorname-operator-upgrade-approvaljob.yaml: name: operatorname-versions +operatorname-operator-operatorgroup.yaml: name: operatorname-og + +Here is a sed command that can help you quickly rename these. Please verify correctness after running the command: +`find . -type f -name "*.yaml" -exec sed -i 's/operatorname/newname/g' {} +` +where newname is the name you would be inserting such as amqstreams + +3) Update the subscription.yaml + a) Identify the appropriate name for the subscription from the "Gather Information" stage. It is important to get this correct or the install will not complete successfully. The subscription object spec/name field must match the name part of the version string + b) Identify the appropriate channel from the "Gather Information" stage. Often is "stable" which is the default in the template + c) Identify the version for the "Gather Information" stage and add it to the startingCSV section replacing "operator-install-version". + +4) Update BOTH approvaljob yaml files + a) Ensure the name field was updated correctly by the automatic rename commands + b) Next, update the configuration fields list here: + ` env: + - name: APPROVAL_NAMESPACE + value: "operatorname-operator" + - name: APPROVAL_SUB + value: "subscriptionobjectname" + envFrom: + - configMapRef: + name: operatorname-versions` + c) The APPROVAL_NAMESPACES value should be updated by the automatic renaming command + d) The APPROVAL_SUB field needs to be manually update with the name of the subscription object. If using the standard conventions this should be operatorname-operator. + e) The configmapRef/name field should be updated to match the name identified in the overlay kustomization files in the next field. Usually this just means replacing operatorname with the appropriate name + + +5) Update the version files + a) In each overlay directory there is a kustomizations.yaml file. Edit that file by ensuring the namespace field and configMapGenerator/name: operatorname-versions were updated properly from the automatic replacement commands + b) Open each operator.versions file and add the appropriate version information found in the "Gather Information" section + *Note* You do NOT need to change the name of the operator.versions file. This keeps it's same name and only the contents inside change + c) If your initial install and upgrade version are the same, just enter the same version information in each field -If you have cloned the `gitops-catalog` repository, you can install the installplan-approver job based on the overlay of your choice by running from the root `gitops-catalog` directory +6) Add any additional customizations using Kustomize Patches + a) Examples of kustomize patches can be found in a txt file in the root of this repository + b) These can be added to the kustomize.yaml in each of the overlay sections, or the base kustomize.yaml + c) These allow you to edit/change/configure sections of each yaml and handle that differently for each overlay -``` -oc apply -k installplan-approver/base -``` +7) Update the README here with the templates default content below to match information related to the specifics of the operator you have configured with this template + +8) Push code changes to Git and configure your ArgoCD Application to use the newly created and configured content + +# Operator GitOps Deployment Capability + +## Description + +This code base provides a template, that when completed, can be ingested by ArgoCD/Red Hat Git Ops to deploy and manage the configured Operator into an OpenShift cluster using GitOps. + +The code is structured using kustomize to template the included yaml and allow customized deployment to multiple environments including Staging, Development, and Production + +This code can also be used to manage the version or upgrade of the operator installed and ensure consistency across all clusters in a particular environment category. + +## Installation + +To utilize this project first ensure you have created a credential robot account for the repository and can provide those credentials in a ArgoCD Credentials object. Next, setup a new "Application" within your ArgoCD Instance that has access to the repository you cloned this template into. Target the appropriate overlay by providing the path. This should match the environment you are deploying the operator too. Use overlay/Staging for Staging overlay/Development for Development and overlay/Production for production. + +You can verify what versions will be targeted for initial installation and the final upgraded version by checking the operator.versions file within each of the overlay folders + +Once the application is created within ArgoCD use the Sync actions to advance the configuration. + +Sync 1 - Installs the Operator Subscription into the target Namespace and generates an InstallPlan to do the actual operator installation +Sync 2- Approves the initial InstallPlan and allows the cluster to finish the initial installation of the Operator into the target namespace +Sync 3- Approves any generated InstallPlans for upgrading the Operator to the version that is found the operator.version file and allows that upgrade to complete + +Your Operator is now installed, upgraded, and ready for use. + +## Usage -Or, without cloning: +This code is leveraged in a GitOps fashion by ArgoCD so any changes to configuration or capability are done directly within the Git Repository. Here are some potential configuration changes and how to action them: + +Changing Install Version: in the appropriate overlay (staging, development, production) update the operator.version file to have the new initial version you wish to install. Also, update the subscription objects desiredCSV field to have the new initial version. -``` -oc apply -k https://github.com/redhat-cop/gitops-catalog/installplan-approver/base -``` +Changing the Upgrade Version: in the appropriate overlay (staging, development, production) update the operator.version file to have the new upgrade version you wish to install. Run the "sync" operation and any install plans available for that version will be approved and the upgrade will roll out. -As part of a different overlay in your own GitOps repo: -``` -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization +## Features -resources: - - github.com/redhat-cop/gitops-catalog/installplan-approver/base?ref=main -``` +This code works by leveraging 2 OpenShift Jobs to approve InstallPlans for when Operators are set to "Manual" Approval mode. These Jobs leverage a serviceaccount within the cluster to check for install plans that match the versions in the operator.version file and approve them as needed. Once approved OpenShift handles migrating the Operator to the version approved in the InstallPlan diff --git a/installplan-approver/base/installplan-approver-job.yaml b/installplan-approver/base/installplan-approver-job.yaml deleted file mode 100644 index e2b97776..00000000 --- a/installplan-approver/base/installplan-approver-job.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: installplan-approver -spec: - template: - spec: - containers: - - image: registry.redhat.io/openshift4/ose-cli:v4.4 - command: - - /bin/bash - - -c - - | - export HOME=/tmp/approver - - echo "Approving operator install. Waiting a few seconds to make sure the InstallPlan gets created first." - sleep $SLEEP - for subscription in `oc get subscriptions.operators.coreos.com -o jsonpath='{.items[*].metadata.name}'` - do - echo "Processing subscription '$subscription'" - - installplan=$(oc get subscriptions.operators.coreos.com --field-selector metadata.name=${subscription} -o jsonpath='{.items[0].status.installPlanRef.name}') - - echo "Check installplan approved status" - oc get installplan $installplan -o jsonpath="{.spec.approved}" - - if [ "`oc get installplan $installplan -o jsonpath="{.spec.approved}"`" == "false" ]; then - - echo "Approving Subscription $subscription with install plan $installplan" - - oc patch installplan $installplan --type=json -p='[{"op":"replace","path": "/spec/approved", "value": true}]' - - else - echo "Install Plan '$installplan' already approved" - fi - done - imagePullPolicy: Always - name: installplan-approver - env: - - name: SLEEP - value: "20" - dnsPolicy: ClusterFirst - restartPolicy: OnFailure - serviceAccount: installplan-approver-job - serviceAccountName: installplan-approver-job - terminationGracePeriodSeconds: 30 diff --git a/installplan-approver/base/kustomization.yaml b/installplan-approver/base/kustomization.yaml index ab9e3c6f..0592128c 100644 --- a/installplan-approver/base/kustomization.yaml +++ b/installplan-approver/base/kustomization.yaml @@ -1,8 +1,12 @@ ---- apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization +namespace: openshift-operators + resources: - - serviceaccount.yaml - - rbac.yaml - - installplan-approver-job.yaml + - operatorname-operator-subscription.yaml + - operatorname-operator-operatorgroup.yaml + - operatorname-operator-install-approvaljob.yaml + - operatorname-operator-upgrade-approvaljob.yaml + - operatorname-operator-rbac.yaml + - operatorname-operator-sa.yaml diff --git a/installplan-approver/base/operatorname-operator-install-approvaljob.yaml b/installplan-approver/base/operatorname-operator-install-approvaljob.yaml new file mode 100644 index 00000000..6f307055 --- /dev/null +++ b/installplan-approver/base/operatorname-operator-install-approvaljob.yaml @@ -0,0 +1,52 @@ +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/sync-wave: "1" + argocd.argoproj.io/hook-delete-policy: BeforeHookCreation + name: installplan-approver-install + namespace: operatorname-operator +spec: + template: + spec: + containers: + - image: registry.redhat.io/openshift4/ose-cli:v4.4 + env: + - name: APPROVAL_NAMESPACE + value: "operatorname-operator" + - name: APPROVAL_SUB + value: "operatorname-operator" + envFrom: + - configMapRef: + name: operatorname-versions + command: + - /bin/bash + - -c + - | + export HOME=/tmp/approver + echo "Starting Approval Script" + namespace="$APPROVAL_NAMESPACE" + subscription="$APPROVAL_SUB" + desiredcsv="$INSTALL_VERSION" + echo "Install version to be approved: $desiredcsv" + for installplan in $(oc get installplan -n $namespace -o jsonpath="{.items[?(@.spec.clusterServiceVersionNames[*] == \"$desiredcsv\")].metadata.name}") + do + echo "Found installplan $installplan" + if [ "`oc get installplan $installplan -n $namespace -o jsonpath="{.spec.approved}"`" == "false" ]; then + + echo "Approving Subscription $subscription with install plan $installplan" + + oc patch -n $namespace installplan $installplan --type=json -p='[{"op":"replace","path": "/spec/approved", "value": true}]' + + else + echo "Install Plan $installplan already approved" + fi + done + imagePullPolicy: IfNotPresent + name: installplan-approver-install + dnsPolicy: ClusterFirst + restartPolicy: OnFailure + serviceAccount: installplan-approver + serviceAccountName: installplan-approver + terminationGracePeriodSeconds: 30 diff --git a/installplan-approver/base/operatorname-operator-operatorgroup.yaml b/installplan-approver/base/operatorname-operator-operatorgroup.yaml new file mode 100644 index 00000000..4e043b88 --- /dev/null +++ b/installplan-approver/base/operatorname-operator-operatorgroup.yaml @@ -0,0 +1,10 @@ +apiVersion: operators.coreos.com/v1 +kind: OperatorGroup +metadata: + name: operatorname-og + namespace: operatorname-operator + annotations: + argocd.argoproj.io/sync-wave: "2" +spec: + targetNamespaces: + - operatorname-operator diff --git a/installplan-approver/base/rbac.yaml b/installplan-approver/base/operatorname-operator-rbac.yaml similarity index 71% rename from installplan-approver/base/rbac.yaml rename to installplan-approver/base/operatorname-operator-rbac.yaml index 1e71a80f..2e8fd4ad 100644 --- a/installplan-approver/base/rbac.yaml +++ b/installplan-approver/base/operatorname-operator-rbac.yaml @@ -2,9 +2,13 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: installplan-approver + namespace: operatorname-operator + annotations: + argocd.argoproj.io/sync-wave: "0" rules: - apiGroups: - operators.coreos.com + - apps.open-cluster-management.io resources: - installplans - subscriptions @@ -17,10 +21,11 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: installplan-approvers + namespace: operatorname-operator roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: installplan-approver subjects: - kind: ServiceAccount - name: installplan-approver-job + name: installplan-approver diff --git a/installplan-approver/base/operatorname-operator-sa.yaml b/installplan-approver/base/operatorname-operator-sa.yaml new file mode 100644 index 00000000..c7d5f930 --- /dev/null +++ b/installplan-approver/base/operatorname-operator-sa.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: installplan-approver + namespace: operatorname-operator + annotations: + argocd.argoproj.io/sync-wave: "0" diff --git a/installplan-approver/base/operatorname-operator-subscription.yaml b/installplan-approver/base/operatorname-operator-subscription.yaml new file mode 100644 index 00000000..6baaec8b --- /dev/null +++ b/installplan-approver/base/operatorname-operator-subscription.yaml @@ -0,0 +1,16 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + labels: + operators.coreos.com/amq-streams.openshift-operators: "" + name: operatorname + namespace: operatorname-operator + annotations: + argocd.argoproj.io/sync-wave: "2" +spec: + channel: stable + installPlanApproval: Manual + name: operatorname + source: redhat-operators + sourceNamespace: openshift-marketplace + startingCSV: operator-install-version diff --git a/installplan-approver/base/operatorname-operator-upgrade-approvaljob.yaml b/installplan-approver/base/operatorname-operator-upgrade-approvaljob.yaml new file mode 100644 index 00000000..fb804f89 --- /dev/null +++ b/installplan-approver/base/operatorname-operator-upgrade-approvaljob.yaml @@ -0,0 +1,51 @@ +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/sync-wave: "1" + argocd.argoproj.io/hook-delete-policy: BeforeHookCreation + name: installplan-approver-upgrade + namespace: operatorname-operator +spec: + template: + spec: + containers: + - image: registry.redhat.io/openshift4/ose-cli:v4.4 + env: + - name: APPROVAL_NAMESPACE + value: "operatorname-operator" + - name: APPROVAL_SUB + value: "operatorname-operator" + envFrom: + - configMapRef: + name: operatorname-versions + command: + - /bin/bash + - -c + - | + export HOME=/tmp/approver + echo "Starting Approval Script" + namespace="$APPROVAL_NAMESPACE" + subscription="$APPROVAL_SUB" + desiredcsv="$UPGRADE_VERSION" + for installplan in $(oc get installplan -n $namespace -o jsonpath="{.items[?(@.spec.clusterServiceVersionNames[*] == \"$desiredcsv\")].metadata.name}") + do + echo "Found installplan $installplan" + if [ "`oc get installplan $installplan -n $namespace -o jsonpath="{.spec.approved}"`" == "false" ]; then + + echo "Approving Subscription $subscription with install plan $installplan" + + oc patch -n $namespace installplan $installplan --type=json -p='[{"op":"replace","path": "/spec/approved", "value": true}]' + + else + echo "Install Plan $installplan already approved" + fi + done + imagePullPolicy: IfNotPresent + name: installplan-approver-upgrade + dnsPolicy: ClusterFirst + restartPolicy: OnFailure + serviceAccount: installplan-approver + serviceAccountName: installplan-approver + terminationGracePeriodSeconds: 30 diff --git a/installplan-approver/base/serviceaccount.yaml b/installplan-approver/base/serviceaccount.yaml deleted file mode 100644 index 806e6820..00000000 --- a/installplan-approver/base/serviceaccount.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: installplan-approver-job diff --git a/installplan-approver/overlays/Development/kustomization.yaml b/installplan-approver/overlays/Development/kustomization.yaml new file mode 100644 index 00000000..cdf2318b --- /dev/null +++ b/installplan-approver/overlays/Development/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: operatorname-operator + +resources: + - ../../base + +configMapGenerator: + - name: operatorname-versions + envs: + - operator.versions diff --git a/installplan-approver/overlays/Development/operator.versions b/installplan-approver/overlays/Development/operator.versions new file mode 100644 index 00000000..4dde501b --- /dev/null +++ b/installplan-approver/overlays/Development/operator.versions @@ -0,0 +1,2 @@ +INSTALL_VERSION=operator-install-version +UPGRADE_VERSION=operator-upgrade-version diff --git a/installplan-approver/overlays/Production/kustomization.yaml b/installplan-approver/overlays/Production/kustomization.yaml new file mode 100644 index 00000000..cdf2318b --- /dev/null +++ b/installplan-approver/overlays/Production/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: operatorname-operator + +resources: + - ../../base + +configMapGenerator: + - name: operatorname-versions + envs: + - operator.versions diff --git a/installplan-approver/overlays/Production/operator.versions b/installplan-approver/overlays/Production/operator.versions new file mode 100644 index 00000000..4dde501b --- /dev/null +++ b/installplan-approver/overlays/Production/operator.versions @@ -0,0 +1,2 @@ +INSTALL_VERSION=operator-install-version +UPGRADE_VERSION=operator-upgrade-version diff --git a/installplan-approver/overlays/Staging/kustomization.yaml b/installplan-approver/overlays/Staging/kustomization.yaml new file mode 100644 index 00000000..cdf2318b --- /dev/null +++ b/installplan-approver/overlays/Staging/kustomization.yaml @@ -0,0 +1,12 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: operatorname-operator + +resources: + - ../../base + +configMapGenerator: + - name: operatorname-versions + envs: + - operator.versions diff --git a/installplan-approver/overlays/Staging/operator.versions b/installplan-approver/overlays/Staging/operator.versions new file mode 100644 index 00000000..4dde501b --- /dev/null +++ b/installplan-approver/overlays/Staging/operator.versions @@ -0,0 +1,2 @@ +INSTALL_VERSION=operator-install-version +UPGRADE_VERSION=operator-upgrade-version