Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

added role ocp_operator_deployment and playbook deploy-ocp-operators #52

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions playbooks/deploy-ocp-operators.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# This playbook is not officially supported and comes with no guarantees.
# Use it at your own risk. Ensure you test thoroughly in your environment
# before deploying to production.

## Overview:
# This Ansible playbook automates the deployment of multiple OpenShift operators using
# the **Operator Lifecycle Manager (OLM)**. It includes tasks to install necessary dependencies,
# configure variables, and deploy the specified operators into the designated namespaces.

## Prerequisites:
# - Ansible 2.9+ installed on the control node.
# - Ansible control node configured with necessary permissions.
# - SSH Access to bastion hosts.
# - ocp version of link to operator release version
# - pre-configured hosts_vars and grup_vars directories
# - installed openshift cluster
# - KUBECONFIG file

## Roles Requirements
# The playbook uses role:
# - redhatci.ocp.catalog_source
# - redhatci.ocp.catalog_source

## Usage:
# - Ensure all required variables are defined in the inventory or host_vars/group_vars.
# - Execute the playbook using Ansible's command-line tool:
#
# ansible-playbook ./playbooks/deploy-ocp-operators.yaml -i ./inventories/ocp-deployment/deploy-ocp-hybrid-multinode.yml \
# --extra-vars 'kubeconfig="/path/to/kubeconfig" \
# version="4.16" operators=[
# {"name":"sriov-network-operator","catalog":"redhat-operators","nsname":"openshift-sriov-network-operator","deploy_default_config":"true"},\
# {"name":"metallb-operator","catalog":"redhat-operators","nsname":"metallb-system","channel":"stable","og_spec":{},deploy_default_config: "true"}]
#
# Notes:
# - This playbook assumes the OCP cluster and bastion hosts are pre-installed and ready.
# - Test in a non-production environment before deploying.
---
- name: Deploy operator
hosts: bastion
gather_facts: false
# Refer to the variables below as an example.
# vars:
# version: "4.17"
# operators: # Refer as example
# - name: sriov-network-operator
# catalog: redhat-operators-stage
# nsname: openshift-sriov-network-operator
# deploy_default_config: true
# - name: ptp-operator
# catalog: redhat-operators-stage
# nsname: openshift-ptp
# ns_labels:
# workload.openshift.io/allowed: management
# name: openshift-ptp
# - name: kubernetes-nmstate-operator
# catalog: redhat-operators
# nsname: openshift-nmstate
# - name: sriov-fec
# catalog: certified-operators
# nsname: vran-acceleration-operators
# channel: stable
# - name: metallb-operator
# catalog: redhat-operators-stage
# nsname: metallb-system
# channel: stable
# deploy_default_config: true
# og_spec: {}
environment:
K8S_AUTH_KUBECONFIG: "{{ kubeconfig }}"
tasks:
- name: Install requirements
ansible.builtin.pip:
name:
- kubernetes
- openshift
state: present

- name: Install Operators
ansible.builtin.include_role:
name: ocp_operator_deployment
vars:
ocp_operator_deployment_version: "{{ version }}"
ocp_operator_deployment_operators: "{{ operators | from_json }}"
ocp_operator_deployment_stage_repo_image: "{{ stage_catalog_index_image | default(omit) }}"
ocp_operator_deployment_stage_cs_secret: "{{ registry_credentials | default(omit) }}"
111 changes: 111 additions & 0 deletions playbooks/roles/ocp_operator_deployment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# OCP Operator Deployment Ansible Role

## Disclaimer
This role is provided as-is, without any guarantees of support or maintenance.
The author or contributors are not responsible for any issues arising from the use of this role. Use it at your own discretion.

## Overview
The `ocp_operator_deployment` Ansible role automates the deployment of OpenShift operators using the **Operator Lifecycle Manager (OLM)**. It supports different catalog sources, including **stage, pre-ga, and brew** repositories.

## Features
- Ensures required variables are defined before execution.
- Deploys operators from different catalog sources (`stage`, `pre-ga`, `brew`).
- Creates **CatalogSource** and required **secrets** dynamically.
- Installs and configures operators using OLM.
- Supports custom **OperatorGroup** configurations.
- Applies default operator configurations if available.

## Requirements
- Ansible **2.9+**
- OpenShift Cluster **4.x**
- redhatci.ocp.catalog_source
- redhatci.ocp.catalog_source
- [`kubernetes.core` collection](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/index.html) installed:
```sh
ansible-galaxy collection install kubernetes.core

## Role Variables

### Required Variables

- **`ocp_operator_deployment_operators`** – List of operators to deploy.
- **`ocp_operator_deployment_version`** – Version of the deployment.

### Optional Variables

- **`ocp_operator_deployment_catalog_source_ns`** (default: `"openshift-marketplace"`)
Namespace for the CatalogSource.

- **`ocp_operator_deployment_stage_repo_image`**
Image for the stage CatalogSource (**required if using `stage` catalog**).

- **`ocp_operator_deployment_stage_cs_secret`**
Secret for accessing the stage registry (**required if using `stage` catalog**).

- **`ocp_operator_deployment_default_label`** (default: `{}`)
Default labels for operator namespaces.

## Operator List Example

Each operator should be defined with the required parameters:

```yaml
ocp_operator_deployment_operators:
- name: "example-operator"
namespace: "example-namespace"
catalog: "stage"
channel: "stable" # optional
og_spec: # optional
targetNamespaces:
- "example-namespace"
starting_csv: "example-operator.v1.2.3" # optional

## Usage

### Basic Playbook Example - deploy from prod

```yaml
- name: Deploy OpenShift Operators
hosts: localhost
roles:
- role: ocp_operator_deployment
vars:
ocp_operator_deployment_version: "4.16"
ocp_operator_deployment_operators:
- name: "example-operator"
namespace: "example-namespace"
catalog: "stage"
channel: "stable"
```

## Tasks Breakdown

1. **Verify Required Variables**
- Ensures all required inputs are provided before execution.

2. **Deploy CatalogSources**
- Creates the necessary **CatalogSource** in OpenShift.
- Generates required **secrets** for the registry.

3. **Deploy Operators**
- Uses **OLM** to deploy specified operators.
- Supports different installation **channels**.

4. **Apply Configurations**
- Automatically applies **default operator configurations** (if available).

## Dependencies

This role does not have any hard dependencies but requires the [`kubernetes.core`](https://docs.ansible.com/ansible/latest/collections/kubernetes/core/index.html) collection.

## License

Apache

## Authors

- **Nikita Kononov**

## Contributions

Feel free to **open issues** or **submit PRs** to enhance functionality!
5 changes: 5 additions & 0 deletions playbooks/roles/ocp_operator_deployment/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
# defaults file for ocp_operator_deployment
ocp_operator_deployment_default_label:
workload.openshift.io/allowed: management
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we always need this label or just in specific cases?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As far as I see yes it's like an default label.

ocp_operator_deployment_catalog_source_ns: openshift-marketplace
13 changes: 13 additions & 0 deletions playbooks/roles/ocp_operator_deployment/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
galaxy_info:
author: Nikita Kononov
description: Ansible role for deploying OpenShift operators using OLM from different catalog sources.
company: Red Hat
license: Apache-2.0
min_ansible_version: "2.9"
galaxy_tags:
- openshift
- kubernetes
- operator
- olm
- deployment
dependencies: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- name: Todo - Brew
Copy link
Contributor

Choose a reason for hiding this comment

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

I believe we should merge this once its set up.

ansible.builtin.fail:
msg: TODO - implement task list
34 changes: 34 additions & 0 deletions playbooks/roles/ocp_operator_deployment/tasks/deploy_operator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
- name: Set OperatorGroup spec configuration
ansible.builtin.set_fact:
operator_group_spec_config: >-
{{
item.og_spec | default({'targetNamespaces': [item.nsname]})
}}

- name: Deploy operator via olm
tags:
- skip_ansible_lint
ansible.builtin.include_role:
name: redhatci.ocp.olm_operator
vars:
operator: "{{ item.name }}"
source: "{{ item.catalog }}"
namespace: "{{ item.nsname }}"
operator_group_name: "{{ item.og_name | default(item.name) }}"
channel: "{{ item.channel | default(omit) }}"
ns_labels:
"{{ item.ns_labels | default(ocp_operator_deployment_default_label) }}"
operator_group_spec: "{{ operator_group_spec_config }}"
starting_csv: "{{ item.starting_csv | default(omit) }}"
install_approval: "{{ item.install_approval | default('Automatic') }}"

- name: Apply default operator configuration if exist
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this task installing operators that have templates, regardless of whether they are needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well this task starts operator on cluster Without operator's configuration we have only operator's pod running. Refer for more info:
https://docs.openshift.com/container-platform/4.17/networking/networking_operators/sr-iov-operator/installing-sriov-operator.html#install-operator-cli_installing-sriov-operator Step 4
https://docs.openshift.com/container-platform/4.10/networking/metallb/metallb-operator-install.html#nw-metallb-operator-initial-config_metallb-operator-install

This actually deploy some 'hardcoded' resource that are required in order to lauch operators on cluster.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that if we want to make this role generic, we should make this step optional

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added deploy_default_config parameter.

kubernetes.core.k8s:
template: "{{ role_path }}/templates/{{ item.name }}-config.j2"
state: present
force: true
register: result
when:
- item.deploy_default_config is defined
- item.deploy_default_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- name: Todo - Pre-Ga
ansible.builtin.fail:
msg: TODO - implement task list
46 changes: 46 additions & 0 deletions playbooks/roles/ocp_operator_deployment/tasks/deploy_stage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
- name: Verify if stage catalog already deployed
kubernetes.core.k8s_info:
api: operators.coreos.com/v1alpha1
namespace: "{{ ocp_operator_deployment_catalog_source_ns }}"
kind: CatalogSource
name: "{{ item.catalog }}"
register: catalog_source

- name: Check if secret exists
kubernetes.core.k8s_info:
api_version: v1
kind: Secret
namespace: "{{ ocp_operator_deployment_catalog_source_ns }}"
name: "{{ item.catalog }}"
register: secret_check

- name: Create catalog source secret if missing
when: secret_check.resources | length == 0
vars:
_secret_definition: |-
apiVersion: v1
kind: Secret
type: kubernetes.io/dockerconfigjson
metadata:
name: "{{ item.catalog }}"
namespace: "{{ ocp_operator_deployment_catalog_source_ns }}"
data:
.dockerconfigjson: "{{ ocp_operator_deployment_stage_cs_secret | to_json | b64encode }}"
kubernetes.core.k8s:
definition: "{{ _secret_definition }}"
state: present

- name: Deploy catalog source if not present
when: catalog_source.resources | length == 0
ansible.builtin.include_role:
name: redhatci.ocp.catalog_source
vars:
cs_name: "{{ item.catalog }}"
cs_namespace: "{{ ocp_operator_deployment_catalog_source_ns }}"
cs_image: "{{ ocp_operator_deployment_stage_repo_image }}:v{{ ocp_operator_deployment_version }}"
cs_publisher: "Red Hat"
cs_secrets:
- "{{ item.catalog }}"
cs_update_strategy:
registryPoll:
interval: 15m
37 changes: 37 additions & 0 deletions playbooks/roles/ocp_operator_deployment/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
# tasks file for ocp_operator_deployment
- name: Verify that required variables are present
ansible.builtin.assert:
that:
- ocp_operator_deployment_operators is defined
- ocp_operator_deployment_operators | length > 0
- ocp_operator_deployment_version is defined
fail_msg: Required variables are not set or empty

- name: Verify that stage repo required variables are present
loop: "{{ ocp_operator_deployment_operators }}"
ansible.builtin.assert:
that:
- ocp_operator_deployment_stage_repo_image is defined
- ocp_operator_deployment_stage_cs_secret is defined
fail_msg: Required stage variables are not set
when: item.catalog == stage

- name: Deploy stage CatalogSource
ansible.builtin.include_tasks: deploy_stage.yaml
loop: "{{ ocp_operator_deployment_operators }}"
when: item.catalog == stage

- name: Deploy pre-ga CatalogSource
ansible.builtin.include_tasks: deploy_pre_ga.yaml
loop: "{{ ocp_operator_deployment_operators }}"
when: item.catalog == pre_ga

- name: Deploy brew CatalogSource
ansible.builtin.include_tasks: deploy_brew.yaml
loop: "{{ ocp_operator_deployment_operators }}"
when: item.catalog == brew

- name: "Deploy operator"
ansible.builtin.include_tasks: deploy_operator.yaml
loop: "{{ ocp_operator_deployment_operators }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: nmstate.io/v1
kind: NMState
metadata:
name: nmstate
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: metallb.io/v1beta1
kind: MetalLB
metadata:
name: metallb
namespace: "{{ item.nsname }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovOperatorConfig
metadata:
name: default
namespace: "{{ item.nsname }}"
spec:
enableInjector: true
enableOperatorWebhook: true
logLevel: 2
disableDrain: false
6 changes: 6 additions & 0 deletions playbooks/roles/ocp_operator_deployment/vars/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# vars file for ocp_operator_deployment
stage: redhat-operators-stage
prod: redhat-operators
pre_ga: redhat-operators-pre-ga
brew: redhat-operators-brew
2 changes: 2 additions & 0 deletions requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ collections:
version: "1.3.0"
- name: redhatci.ocp
version: "2.0.1740507199"
- name: kubernetes.core
version: "2.4.2"