Mike Klebolt
Mike Klebolt

Reputation: 23

Use Jinja2 dict as part of an Ansible modules options

I have the following dict:

endpoint:
    esxi_hostname: servername.domain.com

I'm trying to use it as an option via jinja2 for the vmware_guest but have been unsuccessful. The reason I'm trying to do it this way is because the dict is dynamic...it can either be cluster: clustername or esxi_hostname: hostname, both mutually exclusive in the vmware_guest module.

Here is how I'm presenting it to the module:

- name: Create VM pysphere
  vmware_guest:
   hostname: "{{ vcenter_hostname }}"
   username: "{{ username }}"
   password: "{{ password }}"
   validate_certs: no
   datacenter: "{{ ansible_host_datacenter }}"
   folder: "/DCC/{{ ansible_host_datacenter }}/vm"
   "{{ endpoint }}"
   name: "{{ guest }}"
   state: present
   guest_id: "{{ osid }}"
   disk: "{{ disks }}"
   networks: "{{ niclist }}"
   hardware:
    memory_mb: "{{ memory_gb|int * 1024 }}"
    num_cpus: "{{ num_cpus|int }}"
    scsi: "{{ scsi }}"
   customvalues: "{{ customvalues }}"
   cdrom:
    type: client
  delegate_to: localhost

And here is the error I'm getting when including the tasks file:

TASK [Preparation : Include VM tasks] *********************************************************************************************************************************************************************************   
fatal: [10.10.10.10]: FAILED! => {"reason": "Syntax Error while loading YAML.


The error appears to have been in '/data01/home/hit/tools/ansible/playbooks/roles/Preparation/tasks/prepareVM.yml': line 36, column 4, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

    "{{ endpoint }}"
   hostname: "{{ vcenter_hostname }}"
   ^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes.  Always quote template expression brackets when they
start a value. For instance:

    with_items:
      - {{ foo }}

Should be written as:

    with_items:
      - "{{ foo }}"

exception type: <class 'yaml.parser.ParserError'>
exception: while parsing a block mapping
  in "<unicode string>", line 33, column 3
did not find expected key
  in "<unicode string>", line 36, column 4"}

So in summary, I'm not sure how to format this or if it is even possible.

Upvotes: 2

Views: 358

Answers (2)

Guy
Guy

Reputation: 647

The post from techraf sums up your problem, but for a possible solution, in the docs, especially regarding Jinja filters, there is the following bit:

Omitting Parameters

As of Ansible 1.8, it is possible to use the default filter to omit module parameters using the special omit variable:

- name: touch files with an optional mode
  file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}}   >       with_items:
    - path: /tmp/foo
    - path: /tmp/bar
    - path: /tmp/baz
      mode: "0444"

For the first two files in the list, the default mode will be determined by the umask of the system as the mode= parameter will not be sent to the file module while the final file will receive the mode=0444 option.

So it looks like what should be tried is:

esxi_hostname: "{{ endpoint.esxi_hostname | default(omit) }}"
# however you want the alternative cluster settings done.
# I dont know this module.
cluster: "{{ cluster | default(omit) }}"

This is obviously reliant on the vars to only have one choice set.

Upvotes: 1

techraf
techraf

Reputation: 68509

There is no way you could ever use the syntax you tried in the question, because firstly and foremostly Ansible requires a valid YAML file.

The closest workaround would be to use a YAML anchor/alias although it would work only with literals:

# ...

  vars:
    endpoint: &endpoint
      esxi_hostname: servername.domain.com

  tasks:
     - name: Create VM pysphere
       vmware_guest:
         hostname: "{{ vcenter_hostname }}"
         username: "{{ username }}"
         password: "{{ password }}"
         validate_certs: no
         datacenter: "{{ ansible_host_datacenter }}"
         folder: "/DCC/{{ ansible_host_datacenter }}/vm"
         <<: *endpoint
         name: "{{ guest }}"
         state: present
         guest_id: "{{ osid }}"
         disk: "{{ disks }}"
         networks: "{{ niclist }}"
         hardware:
           memory_mb: "{{ memory_gb|int * 1024 }}"
           num_cpus: "{{ num_cpus|int }}"
           scsi: "{{ scsi }}"
         customvalues: "{{ customvalues }}"
         cdrom:
           type: client
       delegate_to: localhost

Upvotes: 1

Related Questions