Creating the ability to select vmware template from multiple

I will try to explain this as clearly as I can, so I don’t have to transcribe a bunch Ansible syntax from our internal system to here. We have been a single-OS shop for years, but a new manager wants us to offer other OS’s to users, such as Ubuntu and Debian (possibly more to come). Our build playbook looked complex but was pretty straightforward, since it was just calling for different configurations of the same Rocky OS (cli, GUI, pre-configured for GPU). Here is the snippet that calls the specific vmware template type:

vmware_linux_golden_template: '{% if gpu_profile is defined %}{{ vgpu | selectattr("profile", "match", gpu_profile) | map(attribute="template") | join }}{% elif has_gnome %}{{vmware selectattr("cluster", "match", vmware_cluster) | map(attribute="gui_template") | join }}{%else %}{{vmware | selectattr("cluster", "match", vmware_cluster) | map(attribute="cli_template") | join }}{% endif %}'

The variables there are either pulled from …/all/vars.yml or are specified further down the line in the group_vars for each specific project. The above template selection can get a little cumbersome and messy when additional OS’s are added, so I wanted to ask what are some ways to easily present multiple OS’s to select from for our admins and engineers when creating new VM’s?

I’ve tried creating a numbered list of VMware templates to choose from and was able to get a list to present, but could not figure out why only a single template was being used regardless of the number chosen. I’m fine removing the above line and using something completely different, so long as the alternative can easily be modified when a new OS is approved for use.

I think its difficult to answer this without knowing the current data structure your using to hold the template type, but it seems like you’ve overloaded that task/structure.

You could have a dictionary like this:

supported_templates:
  rocky:
    gpu_profiles:
      foo: template-1
      bar: template-2
    gnome:
      cluster1: template-3
      cluster2: template-4
    other:
      cluster1: template-5
  fedora:
      .......
  ubuntu:
      .......

Then you present that to the user, and they can tell you what template they want to use. Or if you want to look it up based on their inputs variables like os_type, gpu_profile, has_gnome
You get your template name with some set of tasks like

- name: Get Template
  block:
    - name: Get GPU Template
      ansible.builtin.set_fact:
        selected_template: "{{ supported_templates[os_type]['gpu_profiles'][gpu_profile] }}"
      when: gpu_profile
    - name: Get GNOME Template
      ansible.builtin.set_fact:
        selected_template: "{{ supported_templates[os_type]['gnome'][_cluster_name] }}"
      vars:
        _cluster_name: '{{ vmware | selectattr("cluster", "match", vmware_cluster) }}'
      when: has_gnome
    - name: Get Basic Template
      ansible.builtin.set_fact:
        selected_template: "{{ supported_templates[os_type]['other'][_cluster_name] }}"
      vars:
        _cluster_name: '{{ vmware | selectattr("cluster", "match", vmware_cluster) }}'
      when: not has_gnome and not gpu_profile
  rescue:
    - name: Unable To Find Template
      ansible.builtin.fail:
        msg: Unable to find template for user inputs <write inputs here>

set_fact is a very cheap module. You can use it a lot without significantly impacting the speed of the playbook. And if you use when your even further reducing the cpu/memory demand. All while making the playbook easier to read