Adding conditionals in Packer provisioners? - packer

Is there a sane way to add a conditional inside of a packer provisioner? Something to the effect of:
$ packer build -var "debug=true" build.json
"provisioners": [{
"type": "puppet-masterless",
"execute_command": "{{ if eq `debug` "true" }} strace {{ end }} {{ .FacterVars }} puppet apply --verbose --detailed-exitcodes --modulepath='/tmp/manifests/modules' {{ .ManifestFile }}",
"facter": {},
"manifest_dir": "../manifests",
"manifest_file": "../manifests/vagrant/nocm.pp",
"module_paths": [
"../manifests/modules/external"
]
}],
"variables": {
"debug": "false",
}
Where execute command contains
{{ if eq `debug` "true" }} strace {{ end }}

did you try to add your variable in the provisioner part :
NOTE : I did not test it myself but use that for normal shell provisioner
"provisioners": [{
"environment_vars": [
"DEBUG={{user `debug`}}",
]
"type": "puppet-masterless",
"execute_command": "{{ if eq .DEBUG "true" }} strace {{ end }} {{ .FacterVars }} puppet apply --verbose --detailed-exitcodes --modulepath='/tmp/manifests/modules' {{ .ManifestFile }}",
"facter": {},
"manifest_dir": "../manifests",
"manifest_file": "../manifests/vagrant/nocm.pp",
"module_paths": [
"../manifests/modules/external"
]
}],
"variables": {
"debug": "false",
}

Related

ansible match variable pattern to json output

I am using the Ansible vmware_vm_info module to generate json like this:
{
"virtual_machines": [
{
"guest_name": "serverx",
"datacenter": "datacenter",
"guest_fullname": "Red Hat Enterprise Linux 7 (64-bit)",
"esxi_hostname": "host1",
"tags": [
],
"cluster": "cluster1",
"vm_network": {
},
"mac_address": [
],
"attributes": {
},
"folder": "",
"power_state": "poweredOff",
"ip_address": "",
"uuid": "33234323oijdlk"
},
{
"guest_name": "server2_01112022",
"datacenter": "datacenter",
"guest_fullname": "Microsoft Windows Server 2012 (64-bit)",
"esxi_hostname": "host1",
"tags": [
],
"cluster": "cluster1",
"vm_network": {
},
"mac_address": [
],
"attributes": {
},
"folder": "",
"power_state": "poweredOff",
"ip_address": "",
"uuid": "287292lkqjjjjd"
},
I have a variable that reads a csv and sets the vmname like this:
vmname
server1
server2
I need set a new fact that will look for the vmname string existing in the vminfo json output. In the example above, server2 would match server2_01112022.
I have tried the following but I don't get a match:
- set_fact:
renamedvm: "{{ item.guest_name }}"
with_items:
- "{{ vminfo.virtual_machines }}"
when:
- item.guest_name |regex_search('^result_item.vmname.$')
For example, given the list
vmname: [server1, server2]
the task
- set_fact:
renamedvm: "{{ renamedvm|d({})|combine({item: _value}) }}"
loop: "{{ vmname|unique|sort }}"
vars:
_selection: "{{ virtual_machines|selectattr('guest_name', 'search', item) }}"
_value: "{{ _selection|map(attribute='guest_fullname')|list }}"
gives
renamedvm:
server1: []
server2:
- Microsoft Windows Server 2012 (64-bit)

Packer prepare error while building an image using VMware player as host

I am new to packer.
I am trying to build a vmware VM using packer. I am using VMware player as host.
I set the variables and select the builders as following:
"builders": [
{
"boot_command": [" text net.ifnames=0 biosdevname=0 ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/ks.cfg"],
"disk_size": "{{ user disk_size }}",
"cpus": "{{ user cpus }}",
"memory": "{{ user memory }}",
"guest_os_type": "{{ user guest_os_type }}",
"headless": "{{ user headless }}",
"iso_checksum": "{{ user iso_checksum }}",
"iso_checksum_type": "{{ user iso_checksum_type }}",
"iso_url": "{{ user iso_url }}",
"output_directory": "output-{{ user vm_name }}-cloud",
"shutdown_command": "{{ user shutdown_command }}",
"shutdown_timeout": "5m",
"ssh_password": "{{ user ssh_password }}",
"ssh_username": "{{ user ssh_username }}",
"ssh_wait_timeout": "{{ user ssh_wait_timeout }}",
"type": "vmware-iso",
"vm_name": "{{ user vm_name }}"
}
],
"variables": {
"cpus": "2",
"disk_size": "",
"headless": "false",
"iso_checksum": "",
"iso_checksum_type": "sha256",
"iso_url": "file://",
"kickstart": "ks.cfg",
"memory": "512",
"shutdown_command": "shutdown -P now",
"ssh_password": "packer",
"ssh_username": "root",
"ssh_wait_timeout" : "10000s",
"guest_os_type": "rhel7-64",
"vm_name": ""
}
The error I am receiving is "Build 'vmware-iso' prepare failure: 1 error occurred:
* unknown configuration key:" then it list all the parameters
After that I am receiving this --> and ctx data is map[interface {}]interface {}(nil)
Anyone can help?
Thanks in advance!!
After a I run the following commands:
"packer fix myfile.json > myfile-fixed.json"
"packer validate myfile-fixed.json"
issue resolved

Variable in a variable Ansible

I'm trying to use a variable in a variable.
I have one JSON variable :
os: {
"centos_7_5": {
offer: "CentOS",
publisher: "OpenLogic",
sku: "7.5",
version: "latest"
},
"debian_9": {
offer: "Debian",
publisher: "credativ",
sku: "9",
version: "latest"
}
}
If I use
- debug:
msg: " {{ os.debian_9.offer }}"
The output is as desired :
"msg": " Debian"
Now, I'm trying to put the OS name in a variable (so that the variable can be in a config file) as follows :
desired_os: debian_9
I would like to do something like this :
- debug:
msg: " {{ os.desired_os.offer }}"
But I can't find a way to make it work.
I tried some concatenation in a set_fact using '{{ "os."~desired_os~".offer" }}' but the output is not as desired :
"msg": "stuff.os.debian_9.offer"
Thanks.
Hi try use this snippet:
json
{
"os": {
"centos_7_5": {
"offer": "CentOS",
"publisher": "OpenLogic",
"sku": "7.5",
"version": "latest"
},
"debian_9": {
"offer": "Debian",
"publisher": "credativ",
"sku": "9",
"version": "latest"
}
}
}
playbook:
---
- hosts: all
gather_facts: False
vars:
jsonVar: "{{ lookup('file', 'j.json') | from_json }}"
dist: "debian_9"
tasks:
- name: test loop
debug: msg="{{ jsonVar['os'][dist] }}"
You can use the varname[var] notation.
- hosts: localhost
gather_facts: no
vars:
os: {
"centos_7_5": {
offer: "CentOS",
publisher: "OpenLogic",
sku: "7.5",
version: "latest"
},
"debian_9": {
offer: "Debian",
publisher: "credativ",
sku: "9",
version: "latest"
}
}
desired_os: debian_9
tasks:
- debug:
msg: " {{ os['debian_9'].offer }}"
- debug:
msg: " {{ os[desired_os].offer }}"
Simply add the variable within double brackets.
- debug:
msg: " {{ os.{{ desired_os }}.offer }}"
Please try as below
debug: msg= "{{os.vars[desired_os].offer}}"

How to acces dictionary variable from ansible jinja2 templates?

i want to access the size_available variable from Dict list
"ansible_mounts": [
{
"device": "/dev/sda1",
"fstype": "ext4",
"mount": "/",
"options": "rw,errors=remount-ro",
"size_available": 15032406016,
"size_total": 20079898624
}
]
- action: debug msg="mem= {{ ansible_mounts.size_available }}"
TASK [debug] *******************************************************************
fatal: [127.0.0.1]: FAILED! => {"failed": true, "msg": "'list' object has no attribute 'size_available'"}
Can you please check this, didn't test it:
- action: debug msg="mem= {{ ansible_mounts[0].size_available }}"

Check if variable is in a list within a dictionary in Ansible

I have the following tasks:
- name: Retrieve records from Route53
route53:
command: get
zone: "{{ stag_zone }}"
record: "{{ stag_record }}"
type: A
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
register: rec
- name: Print records
debug: var=rec
- name: Record contains IP
debug: msg="{{rec}} contains {{stag_ip}}"
when: "'{{stag_ip}}' in {{rec.set.values}}"
The Print records task outputs something like this:
ok: [XXX.XXX.XXX.XXX] => {
"var": {
"rec": {
"changed": false,
"invocation": {
"module_args": "",
"module_name": "route53"
},
"set": {
"alias": false,
"record": "YYY.XXX.ZZZ.",
"ttl": "300",
"type": "A",
"value": "AAA.AAA.AAA.AAA,BBB.BBB.BBB.BBB",
"values": [
"AAA.AAA.AAA.AAA",
"BBB.BBB.BBB.BBB"
],
"zone": "XXX.ZZZ."
}
}
}
}
And I want to execute "Record contains IP" task only when {{stag_ip}} is in {{rec.set.values}}. But my when clause is definitely broken. It outputs this:
fatal: [XXX.XXX.XXX.XXX] => Failed to template {% if 'QQQ.QQQ.QQQ.QQQ' in <built-in method values of dict object at 0x7fb66f54e6e0> %} True {% else %} False {% endif %}: template error while templating string: unexpected '<'
How can I "cast" rec.set.values to a list?
The problem here is because values is a dict method. So it has "precedence" over accessing keys. To fix this, one has to explicitly call get:
when: stag_ip in rec.set.get('values')