|
37 | 37 | state: directory |
38 | 38 | mode: "0755" |
39 | 39 |
|
40 | | - # Legacy OpenShift mirror CRD; empty or error is OK (parsed as no items). |
41 | 40 | - name: Get ICSP mirror rules |
42 | 41 | ansible.builtin.command: |
43 | 42 | cmd: oc get imagecontentsourcepolicy -o json |
44 | 43 | register: _pulled_report_icsp |
45 | 44 | failed_when: false |
46 | 45 |
|
47 | | - # Preferred / current mirror CRD alongside ICSP. |
48 | 46 | - name: Get IDMS mirror rules |
49 | 47 | ansible.builtin.command: |
50 | 48 | cmd: oc get imagedigestmirrorset -o json |
51 | 49 | register: _pulled_report_idms |
52 | 50 | failed_when: false |
53 | 51 |
|
54 | | - # One flat list of rules for templating: each mirror list entry becomes |
55 | | - # its own row so prefix matching can use the same loop for all mirrors. |
| 52 | + # Flatten ICSP repositoryDigestMirrors and IDMS imageDigestMirrors into |
| 53 | + # a single list of {source, mirror} pairs. A source with N mirrors |
| 54 | + # produces N entries so the Jinja template can prefix-match every |
| 55 | + # mirror in one loop. |
| 56 | + # Example output (_pulled_report_mirror_mappings): |
| 57 | + # - source: registry.redhat.io/openstack-k8s-operators |
| 58 | + # mirror: quay.example.com/rh-osbs/openstack-k8s-operators |
| 59 | + # - source: registry.redhat.io/openstack-k8s-operators |
| 60 | + # mirror: internal-registry.corp.net/openstack-k8s-operators |
56 | 61 | - name: Build source-to-mirror mapping from ICSP/IDMS |
57 | 62 | vars: |
58 | 63 | _icsp_items: >- |
|
85 | 90 | ansible.builtin.set_fact: |
86 | 91 | _pulled_report_mirror_mappings: "{{ _mappings | trim | from_yaml }}" |
87 | 92 |
|
88 | | - - name: Report ICSP/IDMS mirror rules found |
89 | | - when: _pulled_report_mirror_mappings | length > 0 |
90 | | - ansible.builtin.debug: |
91 | | - msg: >- |
92 | | - {{ item.source }} -> {{ item.mirror }} |
93 | | - loop: "{{ _pulled_report_mirror_mappings }}" |
94 | | - loop_control: |
95 | | - label: "{{ item.source }}" |
96 | | - |
97 | 93 | - name: Warn if no ICSP/IDMS mirror rules found |
98 | 94 | when: _pulled_report_mirror_mappings | length == 0 |
99 | 95 | ansible.builtin.debug: |
|
115 | 111 | label: "{{ item }}" |
116 | 112 | failed_when: false |
117 | 113 |
|
118 | | - # Flatten all loop results, then one report row per container + initContainer. |
119 | 114 | - name: Build per-pod pulled images report |
120 | | - vars: |
121 | | - _report: >- |
122 | | - {% set entries = [] %} |
123 | | - {% set all_pods = _pulled_report_pods.results | |
124 | | - map(attribute='resources', default=[]) | flatten %} |
125 | | - {% for pod in all_pods %} |
126 | | - {% set pod_labels = pod.metadata.labels | default({}) %} |
127 | | - {% set operator_name = pod_labels.get('openstack.org/operator-name', '') %} |
128 | | - {% set app_label = pod_labels.get('app', pod_labels.get('app.kubernetes.io/name', '')) %} |
129 | | - {# Build a single list so regular and init containers share one loop #} |
130 | | - {% set image_statuses = [] %} |
131 | | - {% for cs in pod.status.containerStatuses | default([]) %} |
132 | | - {% set _ = image_statuses.append({'cs': cs, 'type': 'container'}) %} |
133 | | - {% endfor %} |
134 | | - {% for cs in pod.status.initContainerStatuses | default([]) %} |
135 | | - {% set _ = image_statuses.append({'cs': cs, 'type': 'init_container'}) %} |
136 | | - {% endfor %} |
137 | | - {% for entry in image_statuses %} |
138 | | - {% set cs = entry.cs %} |
139 | | - {% set image = cs.image | default('unknown') %} |
140 | | - {% set image_id = cs.imageID | default('') %} |
141 | | - {% set image_repo = image.split('@')[0].split(':')[0] %} |
142 | | - {% set image_name = image_repo.split('/')[-1] %} |
143 | | - {# Default: host = first path segment of image ref; basis = source #} |
144 | | - {% set match = namespace(host=image.split('/')[0], expected_pull_basis='source') %} |
145 | | - {# First mapping where image startswith source: use mirror registry host #} |
146 | | - {% for m in _pulled_report_mirror_mappings if m.source is defined and m.source and image.startswith(m.source) %} |
147 | | - {% if loop.first %} |
148 | | - {% set match.host = m.mirror.split('/')[0] %} |
149 | | - {% set match.expected_pull_basis = 'mirror' %} |
150 | | - {% endif %} |
151 | | - {% endfor %} |
152 | | - {% set _ = entries.append({ |
153 | | - 'namespace': pod.metadata.namespace, |
154 | | - 'pod': pod.metadata.name, |
155 | | - 'node': pod.spec.get('nodeName', 'unknown'), |
156 | | - 'container': cs.name, |
157 | | - 'container_type': entry.type, |
158 | | - 'operator': operator_name if operator_name else 'N/A', |
159 | | - 'app': app_label if app_label else image_name, |
160 | | - 'image': image, |
161 | | - 'image_id': image_id, |
162 | | - 'expected_pull_location': match.host, |
163 | | - 'expected_pull_basis': match.expected_pull_basis |
164 | | - }) %} |
165 | | - {% endfor %} |
166 | | - {% endfor %} |
167 | | - {{ entries }} |
168 | 115 | ansible.builtin.set_fact: |
169 | | - _pulled_images_report: "{{ _report | trim | from_yaml }}" |
| 116 | + _pulled_images_report: >- |
| 117 | + {{ lookup('template', 'pulled_images_report.j2') | trim | from_yaml }} |
170 | 118 |
|
171 | 119 | # Counts for the YAML artifact summary section. |
172 | 120 | - name: Build report summary |
|
197 | 145 | content: "{{ _full_report | to_nice_yaml }}" |
198 | 146 | mode: "0644" |
199 | 147 |
|
200 | | - # Console visibility: split rows by how ICSP/IDMS classification turned out. |
201 | | - - name: Images with expected_pull_basis source |
| 148 | + - name: Pulled images report summary |
202 | 149 | ansible.builtin.debug: |
203 | 150 | msg: >- |
204 | | - [{{ item.app }}] {{ item.image }} -> |
205 | | - expected pull location {{ item.expected_pull_location }} |
206 | | - ({{ item.container_type }}: {{ item.container }} |
207 | | - | operator: {{ item.operator }} |
208 | | - | pod: {{ item.namespace }}/{{ item.pod }}) |
209 | | - loop: >- |
210 | | - {{ _pulled_images_report | |
211 | | - selectattr('expected_pull_basis', 'equalto', 'source') | list }} |
212 | | - loop_control: |
213 | | - label: "{{ item.app }}/{{ item.container }}" |
214 | | - |
215 | | - - name: Images with expected_pull_basis mirror |
216 | | - ansible.builtin.debug: |
217 | | - msg: >- |
218 | | - [{{ item.app }}] {{ item.image }} -> |
219 | | - expected pull location {{ item.expected_pull_location }} |
220 | | - ({{ item.container_type }}: {{ item.container }} |
221 | | - | operator: {{ item.operator }} |
222 | | - | pod: {{ item.namespace }}/{{ item.pod }}) |
223 | | - loop: >- |
224 | | - {{ _pulled_images_report | |
225 | | - selectattr('expected_pull_basis', 'equalto', 'mirror') | list }} |
226 | | - loop_control: |
227 | | - label: "{{ item.app }}/{{ item.container }}" |
| 151 | + Pulled images report: {{ _pulled_report_summary.total_containers }} containers |
| 152 | + ({{ _pulled_report_summary.containers_expected_basis_mirror }} mirror, |
| 153 | + {{ _pulled_report_summary.containers_expected_basis_source }} source), |
| 154 | + {{ _pulled_report_summary.mirror_rules_found }} mirror rules. |
| 155 | + Full report: {{ cifmw_env_op_images_pulled_report_path }} |
0 commit comments