Skip to content

Commit 9c1985f

Browse files
committed
Allow to prune operators from different catalogs
1 parent 668bf3e commit 9c1985f

File tree

8 files changed

+194
-31
lines changed

8 files changed

+194
-31
lines changed

roles/imageset_mirroring/README.md

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ This role provides three different approaches to mirror operators from a source
3232

3333
#### mirror-latest & mirror-all
3434

35-
| Variable | Type | Required | Description |
36-
|-------------------|------------|----------|-------------------------------------------------------------------------------------------|
37-
| `im_source_index` | string | yes | Source catalog index (e.g., `registry.redhat.io/redhat/redhat-operator-index:v4.20`) |
38-
| `im_operators` | dictionary | yes | Dictionary of operators to mirror (keys are operator names) |
35+
| Variable | Type | Required | Description |
36+
|-------------------|------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
37+
| `im_source_index` | string | yes | Default source catalog index (e.g., `registry.redhat.io/redhat/redhat-operator-index:v4.20`). Can be overridden per-operator. |
38+
| `im_operators` | dictionary | yes | Dictionary of operators to mirror (keys are operator names). Each operator value can be an empty dict or contain a `catalog` key to override the default catalog. |
3939

4040
#### mirror-custom
4141

@@ -63,6 +63,29 @@ This role provides three different approaches to mirror operators from a source
6363
im_auths_file: /path/to/pull-secret.json
6464
```
6565
66+
### Example 1c: Mirror Latest Version from Multiple Catalogs
67+
68+
```yaml
69+
- name: "Mirror operators from different catalogs"
70+
ansible.builtin.include_role:
71+
name: redhatci.ocp.imageset_mirroring
72+
vars:
73+
im_task: latest
74+
im_source_index: registry.redhat.io/redhat/redhat-operator-index:v4.20
75+
im_target: registry.lab:4443
76+
im_operators:
77+
# These operators use the default im_source_index
78+
mcg-operator:
79+
ocs-client-operator:
80+
# This operator overrides the catalog
81+
custom-operator:
82+
catalog: quay.io/prega/prega-operator-index:v4.21-latest
83+
another-custom-operator:
84+
catalog: quay.io/prega/prega-operator-index:v4.21-latest
85+
im_allow_insecure_registries: true
86+
im_auths_file: /path/to/pull-secret.json
87+
```
88+
6689
### Example 1b: Mirror Latest Version (using tasks_from - legacy)
6790
6891
```yaml
@@ -96,6 +119,23 @@ This role provides three different approaches to mirror operators from a source
96119
rhacm-operator:
97120
```
98121
122+
### Example 2b: Mirror All Versions from Multiple Catalogs
123+
124+
```yaml
125+
- name: "Mirror all operators from multiple catalogs"
126+
ansible.builtin.include_role:
127+
name: redhatci.ocp.imageset_mirroring
128+
vars:
129+
im_task: all
130+
im_source_index: registry.redhat.io/redhat/redhat-operator-index:v4.20
131+
im_target: registry.lab:4443
132+
im_operators:
133+
openshift-gitops-operator:
134+
rhacm-operator:
135+
prega-operator:
136+
catalog: quay.io/prega/prega-operator-index:v4.21-20251111T044345
137+
```
138+
99139
### Example 3: Mirror Using Custom ImageSetConfiguration
100140
101141
```yaml
@@ -167,16 +207,18 @@ This role provides three different approaches to mirror operators from a source
167207
### mirror-latest
168208
169209
1. Downloads the latest `oc-mirror` binary
170-
2. Queries the source catalog for each operator's default channel
171-
3. Identifies the latest CSV version for the default channel
172-
4. Generates an ImageSetConfiguration with specific version constraints
173-
5. Executes `oc-mirror` to perform the mirroring
210+
2. Groups operators by their catalog source (using `im_source_index` as default)
211+
3. Queries each catalog for each operator's default channel
212+
4. Identifies the latest CSV version for the default channel
213+
5. Generates an ImageSetConfiguration with multiple catalog entries (if operators use different catalogs)
214+
6. Executes `oc-mirror` to perform the mirroring
174215

175216
### mirror-all
176217

177218
1. Downloads the latest `oc-mirror` binary
178-
2. Generates an ImageSetConfiguration with `full: true` for all operators
179-
3. Executes `oc-mirror` to mirror all channels and versions
219+
2. Groups operators by their catalog source (using `im_source_index` as default)
220+
3. Generates an ImageSetConfiguration with `full: true` for all operators, organized by catalog
221+
4. Executes `oc-mirror` to mirror all channels and versions
180222

181223
### mirror-custom
182224

roles/imageset_mirroring/meta/argument_specs.yml

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,16 @@ argument_specs:
3535
im_source_index:
3636
type: str
3737
required: true
38-
description: Source catalog index (e.g., registry.redhat.io/redhat/redhat-operator-index:v4.20).
38+
description: |
39+
Default source catalog index (e.g., registry.redhat.io/redhat/redhat-operator-index:v4.20).
40+
Can be overridden per-operator in im_operators dictionary.
3941
im_operators:
4042
type: dict
4143
required: true
42-
description: Dictionary of operators to mirror (keys are operator names).
44+
description: |
45+
Dictionary of operators to mirror (keys are operator names).
46+
Each operator can optionally specify a 'catalog' key to override im_source_index.
47+
Example: {'operator1': {}, 'operator2': {'catalog': 'custom.io/index:v1.0'}}
4348
im_allow_insecure_registries:
4449
type: bool
4550
required: false
@@ -62,11 +67,16 @@ argument_specs:
6267
im_source_index:
6368
type: str
6469
required: true
65-
description: Source catalog index (e.g., registry.redhat.io/redhat/redhat-operator-index:v4.20).
70+
description: |
71+
Default source catalog index (e.g., registry.redhat.io/redhat/redhat-operator-index:v4.20).
72+
Can be overridden per-operator in im_operators dictionary.
6673
im_operators:
6774
type: dict
6875
required: true
69-
description: Dictionary of operators to mirror (keys are operator names).
76+
description: |
77+
Dictionary of operators to mirror (keys are operator names).
78+
Each operator can optionally specify a 'catalog' key to override im_source_index.
79+
Example: {'operator1': {}, 'operator2': {'catalog': 'custom.io/index:v1.0'}}
7080
im_allow_insecure_registries:
7181
type: bool
7282
required: false

roles/imageset_mirroring/tasks/mirror-all.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@
66
- im_operators | dict2items | length > 0
77
fail_msg: "im_operators must contain at least one operator"
88

9+
- name: Build operators with catalog mapping
10+
ansible.builtin.set_fact:
11+
_im_operators_with_catalog: >-
12+
{{
13+
_im_operators_with_catalog | default([]) +
14+
[{
15+
'catalog': item.value.catalog | default(im_source_index),
16+
'operator': item.key
17+
}]
18+
}}
19+
loop: "{{ im_operators | dict2items }}"
20+
loop_control:
21+
label: "{{ item.key }}"
22+
23+
- name: Group operators by catalog for template
24+
ansible.builtin.set_fact:
25+
_im_catalogs_with_operators: >-
26+
{{ _im_operators_with_catalog | groupby('catalog') }}
27+
928
- name: Render ImageSetConfiguration for all versions of listed operators
1029
ansible.builtin.template:
1130
src: imagesetconfig-full.yaml.j2

roles/imageset_mirroring/tasks/mirror-latest.yml

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
cmd: |
1212
set -o pipefail
1313
{{ _im_tmp_dir.path }}/oc-mirror list operators \
14-
--catalog {{ im_source_index }} \
14+
--catalog {{ item.value.catalog | default(im_source_index) }} \
1515
--package {{ item.key }} \
1616
2>/dev/null | \
1717
awk 'NR==2 {operator=$1; def_channel=$NF}
@@ -24,20 +24,31 @@
2424
retries: 3
2525
delay: 10
2626
loop: "{{ im_operators | dict2items }}"
27+
loop_control:
28+
label: "{{ item.key }} from {{ item.value.catalog | default(im_source_index) }}"
2729
changed_when: false
2830

31+
- name: Build operators with catalog mapping
32+
ansible.builtin.set_fact:
33+
_im_operators_with_catalog: >-
34+
{{
35+
_im_operators_with_catalog | default([]) +
36+
[{
37+
'catalog': item.item.value.catalog | default(im_source_index),
38+
'stdout': item.stdout,
39+
'operator': item.item.key
40+
}]
41+
}}
42+
loop: "{{ _im_operator_info.results }}"
43+
loop_control:
44+
label: "{{ item.item.key }}"
45+
46+
- name: Group operators by catalog for template
47+
ansible.builtin.set_fact:
48+
_im_catalogs_with_operators: >-
49+
{{ _im_operators_with_catalog | groupby('catalog') }}
50+
2951
- name: Render ImageSetConfiguration for latest version of listed operators
30-
vars:
31-
im_packages_var: |
32-
{% for result in _im_operator_info.results %}
33-
{%- set parts = result.stdout.split() %}
34-
{%- set version = parts[2].split('.v')[-1] if '.v' in parts[2] else parts[2].split('-')[-1] %}
35-
- name: '{{ parts[0] }}'
36-
channels:
37-
- name: '{{ parts[1] }}'
38-
minVersion: '{{ version }}'
39-
maxVersion: '{{ version }}'
40-
{% endfor %}
4152
ansible.builtin.template:
4253
src: imagesetconfig-latest.yaml.j2
4354
dest: "{{ _im_tmp_dir.path }}/imagesetconfig.yaml"

roles/imageset_mirroring/templates/imagesetconfig-full.yaml.j2

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ apiVersion: mirror.openshift.io/v2alpha1
22
kind: ImageSetConfiguration
33
mirror:
44
operators:
5-
- catalog: {{ im_source_index }}
5+
{% for catalog, operators in _im_catalogs_with_operators %}
6+
- catalog: {{ catalog }}
67
full: true
78
packages:
8-
{% for package in im_operators.keys() %}
9-
- name: {{ package }}
9+
{% for op in operators %}
10+
- name: {{ op.operator }}
11+
{% endfor %}
1012
{% endfor %}

roles/imageset_mirroring/templates/imagesetconfig-latest.yaml.j2

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,26 @@ apiVersion: mirror.openshift.io/v2alpha1
22
kind: ImageSetConfiguration
33
mirror:
44
operators:
5-
- catalog: {{ im_source_index }}
5+
{% for catalog, results in _im_catalogs_with_operators %}
6+
- catalog: {{ catalog }}
67
full: false
78
packages:
8-
{{ im_packages_var | indent( width=8, first=false)}}
9+
{% for result in results %}
10+
{%- set parts = result.stdout.split() %}
11+
{%- set csv_full = parts[2] %}
12+
{%- if '.v' in csv_full %}
13+
{%- set version = csv_full.split('.v')[-1] %}
14+
{%- elif csv_full.startswith(parts[0] + '.') %}
15+
{%- set version = csv_full[parts[0]|length + 1:] %}
16+
{%- elif csv_full.startswith(parts[0] + '-') %}
17+
{%- set version = csv_full[parts[0]|length + 1:] %}
18+
{%- else %}
19+
{%- set version = csv_full.split('-')[-1] %}
20+
{%- endif %}
21+
- name: '{{ parts[0] }}'
22+
channels:
23+
- name: '{{ parts[1] }}'
24+
minVersion: '{{ version }}'
25+
maxVersion: '{{ version }}'
26+
{% endfor %}
27+
{% endfor %}

roles/prune_catalog/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,35 @@ Another example of a pruned catalog with specific channels
106106
```
107107
108108
In this example, the resulting catalog contains all the channels of the `compliance-operator`, channel `stable-5.8` for cluster-logging and only the `stable` channel for `file-integrity-operator`.
109+
110+
### Prune operators from multiple source catalogs
111+
112+
The role supports pruning operators from multiple source catalogs into a single destination catalog. This is useful when you need operators from different catalog sources (e.g., Red Hat operators, certified operators, community operators).
113+
114+
```yaml
115+
- name: "Create a pruned catalog with operators from multiple catalogs"
116+
include_role:
117+
name: redhatci.ocp.prune_catalog
118+
vars:
119+
pc_source_catalog: "registry.redhat.io/redhat/redhat-operator-index:v4.19"
120+
pc_destination_catalog: "<my-local-registry>:4443/pruned-catalog:latest"
121+
pc_operators:
122+
compliance-operator:
123+
channel: stable
124+
file-integrity-operator:
125+
channel: stable
126+
catalog: "registry.redhat.io/redhat/certified-operator-index:v4.19"
127+
ocs-operator:
128+
channel: stable-4.13
129+
catalog: "registry.redhat.io/redhat/redhat-operator-index:v4.19"
130+
prometheus:
131+
channel: beta
132+
catalog: "registry.redhat.io/redhat/community-operator-index:v4.19"
133+
pc_opm_args: "--skip-tls-verify=true"
134+
```
135+
136+
- Operators without a `catalog` field use the `pc_source_catalog`
137+
109138
```ShellSession
110139
$ DOCKER_CONFIG=/home/<user>/.docker oc-mirror list operators --catalog <my-local-registry>:4443/pruned-catalog:latest
111140
NAME DISPLAY NAME DEFAULT CHANNEL

roles/prune_catalog/tasks/main.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,37 @@
8181
retries: 3
8282
delay: 10
8383

84+
- name: "Render additional catalogs"
85+
vars:
86+
extra_catalogs: >-
87+
{{
88+
(pc_operators | type_debug == "dict") |
89+
ternary(
90+
pc_operators | dict2items |
91+
selectattr('value.catalog', 'defined') |
92+
map(attribute='value.catalog') |
93+
list | unique |
94+
difference([pc_source_catalog]),
95+
[]
96+
)
97+
}}
98+
ansible.builtin.shell:
99+
chdir: "{{ pc_tmp_dir }}"
100+
cmd: >
101+
set -x;
102+
{{ pc_opm_cmd }} render {{ catalog }} >>
103+
index-packages
104+
loop: "{{ extra_catalogs }}"
105+
loop_control:
106+
loop_var: catalog
107+
register: _pc_render_additional
108+
changed_when: _pc_render_additional.rc == 0
109+
until: _pc_render_additional.rc == 0
110+
retries: 3
111+
delay: 10
112+
when:
113+
- extra_catalogs | length > 0
114+
84115
- name: "Extract the listed channels for each operator"
85116
when: pc_operators | type_debug == "dict"
86117
block:

0 commit comments

Comments
 (0)