--- # Logic to identify image with given os_distro, os_version, os_purpose # Simply find the image for new SCS clouds that have os_purpose set. # Fall back to name matching otherwise. # (c) Kurt Garloff , 11/2025 # SPDX-License-Identifier: MIT # Created with help from Claude AI - name: Select Image with purpose and fall back to name matching hosts: localhost gather_facts: false vars: # Primary selection criteria os_version: '24.04' os_distro: 'ubuntu' os_purpose: 'generic' cloud_name: "{{ lookup('env', 'OS_CLOUD') | default('openstack') }}" tasks: - name: Get available images matching os_distro and os_version openstack.cloud.image_info: cloud: '{{ cloud_name }}' properties: os_distro: '{{ os_distro }}' os_version: '{{ os_version }}' register: _distro_images - name: 'Show images that match {{os_distro}} {{os_version}}' debug: msg: '{{ _distro_images.images | to_nice_json }}' - name: 'First choice: Match os_purpose' set_fact: _primary_images: >- {{ _distro_images.images | selectattr('properties.os_purpose', 'defined') | selectattr('properties.os_purpose', 'equalto', os_purpose) | list }} - name: 'Select primary image if found' set_fact: selected_image: >- {{ _primary_images | sort(attribute='created_at', reverse=true) | sort(attribute='name', reverse=true) | first }} match_type: 'primary' when: _primary_images | length > 0 # Fallback logic - only executed if no primary match - block: - name: 'Fallback 1 pattern' set_fact: _pattern1: "(?i){{ os_distro | regex_escape }}\\s+{{ os_version | regex_escape }}\\s+{{ os_purpose | regex_escape }}.*" - name: "Fallback 1: Filter images without os_purpose, matching name pattern '{{ os_distro }} {{ os_version }} {{ os_purpose }}'" set_fact: _fallback1_images: >- {{ _distro_images.images | rejectattr('properties.os_purpose', 'defined') | selectattr('name', 'search', _pattern1) | list }} - name: Select fallback 1 match if found set_fact: selected_image: >- {{ _fallback1_images | sort(attribute='created_at', reverse=true) | sort(attribute='name', reverse=true) | first }} match_type: 'fallback_pattern1' when: _fallback1_images | length > 0 when: _primary_images | length == 0 - block: - name: 'Fallback 2 pattern' set_fact: _pattern2: "(?i){{ os_distro | regex_escape }}\\s+{{ os_purpose | regex_escape }}\\s+{{ os_version | regex_escape }}.*" - name: "Fallback 2: Filter images without os_purpose, matching name pattern '{{ os_distro }} {{ os_purpose }} {{ os_version }}'" set_fact: _fallback2_images: >- {{ _distro_images.images | rejectattr('properties.os_purpose', 'defined') | selectattr('name', 'search', _pattern2) | list }} - name: Select fallback 2 match if found set_fact: selected_image: >- {{ _fallback2_images | sort(attribute='created_at', reverse=true) | sort(attribute='name', reverse=true) | first }} match_type: 'fallback_pattern2' when: _fallback2_images | length > 0 when: - _primary_images | length == 0 - _fallback1_images | default([]) | length == 0 - block: - name: 'Fallback 3 pattern' set_fact: _pattern3: "(?i){{ os_distro | regex_escape }}\\s+{{ os_version | regex_escape }}.*" - name: "Fallback 3: Filter images without os_purpose, matching name pattern '{{ os_distro }} {{ os_version }}'" set_fact: _fallback3_images: >- {{ _distro_images.images | rejectattr('properties.os_purpose', 'defined') | selectattr('name', 'search', _pattern3) | list }} - name: Select fallback 3 match if found set_fact: selected_image: >- {{ _fallback3_images | sort(attribute='created_at', reverse=true) | sort(attribute='name', reverse=true) | first }} match_type: 'fallback_pattern3' when: _fallback3_images | length > 0 when: - _primary_images | length == 0 - _fallback1_images | default([]) | length == 0 - _fallback2_images | default([]) | length == 0 - name: Display selected image debug: msg: - 'Match Type: {{ match_type }}' - 'Image Name: {{ selected_image.name }}' - 'Image ID: {{ selected_image.id }}' - 'Created: {{ selected_image.created_at }}' - 'Properties: {{ selected_image.properties }}' when: selected_image is defined - name: Fail if no suitable image found fail: msg: | No suitable image found matching criteria: - os_distro: {{ os_distro }} - os_version: {{ os_version }} - os_purpose: {{ os_purpose }} Tried: 1. Images with os_purpose property = '{{ os_purpose }}' 2. Images matching name pattern '{{ os_distro }} {{ os_version }} {{ os_purpose }}' 3. Images matching name pattern '{{ os_distro }} {{ os_purpose }} {{ os_version }}' 4. Images matching name pattern '{{ os_distro }} {{ os_version }}' when: selected_image is not defined