Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 days ago.
Improve this question
We don't see any issues when we pass Individual dictionary items like follows
service:
-
name: "POP3"
-
name: "NFS"
-
name: "HTTP"
-
name: "HTTPS"
However, we are getting the below error when we pass this as list of dictionaries (after reading from sytem facts)
"dictionary requested, could not parse JSON or key=value",
Following is the dictionary we wanted to pass.
"msg": " [{'name': 'ALL_UDP', 'q_origin_key': 'ALL_UDP'}, {'name': 'NFS', 'q_origin_key': 'NFS'}]"
Complete Code:
- name: When existing policy exists with the provided constraints
block:
- name: add new service to existing services if it already does not exist
ansible.builtin.set_fact:
updated_fw_services: " {{ existing_fw_services + [ {'name': firewall_policy_service, 'q_origin_key': firewall_policy_service} ] }}"
when: "'{{ firewall_policy_service }}' not in existing_fw_services | map(attribute='name') | list"
- name: "Update Existing Firewall Policy: {{ existing_fw_name }}"
fortios_firewall_policy:
vdom: "{{ vdom }}"
state: "present"
access_token: "{{ fortigate_access_token }}"
firewall_policy: "{{ existing_fw_object | combine({'service': updated_fw_services }) }}"
when:
- updated_fw_services is defined
when: existing_fw_object is defined
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 10 months ago.
Improve this question
I am trying to list VMs from the vcenter, filtering VM names which starts with linTest and winTest. How can I pass linTest|winTest as a variable in the code below?
- name: Gather all registered virtual machines
vmware_vm_info:
hostname: '{{ vc_host }}'
username: '{{ vc_user }}'
password: '{{ vc_pass }}'
validate_certs: False
delegate_to: localhost
register: vminfo
- set_fact:
vm_hostname: "{{ vminfo.virtual_machines | map(attribute='guest_name')|select('match', '^(linTest|winTest)')| list }} "
- debug:
var: vm_hostname
I understand that you like to pass a variable regluar expression to the filter. To do so you could use an approach like
...
vars:
REGEX: '^(linTest|winTest)'
tasks:
- set_fact:
vm_hostname: "{{ vminfo.virtual_machines | map(attribute='guest_name') | select('match', REGEX) | list }}"
...
in short select('match', REGEX).
Further Q&A
How to use a variable inside a variable definition that uses filters
Ansible ... select filter ...
Can variables be use as Ansible filter parameters?
How to list all the services of a system with state=='running' without providing a list like the first code?
- name: Populate service facts
service_facts:
no_log: true
register: inspect_services2
when: "ansible_facts.services[] is defined and ansible_facts.services[].state == 'running' "
I have manage to list them only if I use a list:
- name: Running Services
debug:
msg: "{{ ansible_facts.services[item].state == 'running' }}"
when: "ansible_facts.services[item] is defined and ansible_facts.services[item].state == 'running' "
loop: "{{ inspect_services2 }}"
ignore_errors: yes
In a nutshell:
---
- name: work with service facts
hosts: localhost
tasks:
- name: gather service facts
service_facts:
- name: show running services
debug:
msg: "{{ ansible_facts.services | dict2items
| selectattr('value.state', '==', 'running') | items2dict }}"
This gives you a dict with all info for all running services. If e.g. you only want to display the names of those services, your could change the message in debug task to:
msg: "{{ ansible_facts.services | dict2items
| selectattr('value.state', '==', 'running') | map(attribute='key') }}"
You are of course absolutely free to use that result and put it in a variable somewhere as an alias to reuse it. Below a useless yet functional example creating a file with the service name on the target server just to illustrate:
---
- name: Work with service facts II
hosts: localhost
vars:
# Note1: this will be undefined until service facts are gathered
# Note2: this time this var will be a list of all dicts
# dropping the initial key wich is identical to `name`
running_services: "{{ ansible_facts.services | dict2items
| selectattr('value.state', '==', 'running') | map(attribute='value') }}"
tasks:
- name: gather service facts
service_facts:
- name: useless task creating a file with service name in tmp
copy:
content: "ho yeah. {{ item.name }} is running"
dest: "/tmp/{{ item.name }}.txt"
loop: "{{ running_services }}"
To list the running services only, just
- name: Loop over all services and print name
debug:
msg: "{{ item }}"
when:
- ansible_facts.services[item].state == 'running'
with_items: "{{ ansible_facts.services }}"
Thanks to
Ansible: How to get ... running services?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I'm trying to loop over two lists being a combinations of hosts from the inventory and ports from a variable in the task.
Given the inventory:
all:
children:
kafka_broker:
hosts:
server1.company.com:
server2.company.com:
And the list of ports:
[9091, 9092]
I am want to produce four items being the combination of those two list:
server1.company.com:9091
server1.company.com:9092
server2.company.com:9091
server2.company.com:9091
I have tried:
using nested loops
- debug: msg=" debug msg {{ item[0] }}:{{ item[1] }}"
with_nested:
- groups['kafka_broker']
- [9091, 9092]
This gives the output:
ok: [server1.company.com] => (item=[u"groups['kafka_broker']", 9091]) => {
"msg": " debug msg groups['kafka_broker']:9091"
}
ok: [server1.company.com] => (item=[u"groups['kafka_broker']", 9092]) => {
"msg": " debug msg groups['kafka_broker']:9092"
}
ok: [server2.company.com] => (item=[u"groups['kafka_broker']", 9091]) => {
"msg": " debug msg groups['kafka_broker']:9091"
}
ok: [server2.company.com] => (item=[u"groups['kafka_broker']", 9092]) => {
"msg": " debug msg groups['kafka_broker']:9092"
}
using with_inventory_hostnames
- debug:
msg: "{{ item[0] }}:{{ item[1] }}" -tls1
with_nested:
- with_inventory_hostnames['kafka_broker']
- [9091, 9092]
I'm looking for an explanation why those attempts do not work as expected or a simpler solution to my problem.
You need to do a Cartesian Product of the list of hosts with the list of ports (if you have more than one host or port).
This is how you do it:
- debug:
msg: " debug msg {{ item[0] }}:{{ item[1] }}"
loop: "{{ lookup('community.general.cartesian', groups['kafka_broker'], [9091, 9092]) }}"
You can also use this, which is a bit longer, but does the same
- debug:
msg: " debug msg {{ item[0] }}:{{ item[1] }}"
with_community.general.cartesian:
- "{{ groups['kafka_broker'] }}"
- [9091, 9092]
If you are using ansible version 2.9 or older, you need to replace community.general.cartesian with cartesian.
Documentation of community.general.cartesian.
Hi I would like to known how I can select a list nested in an attibut of a list. I've done a research on my F5 BIG IP and it give me a list of the attibutes of the virtuals servers like that:
"/Common/vs_portailopal_wi_https_virtual_server": {
"last_hop_pool": "",
"name": "vs_portailopal_wi_https_virtual_server",
"nat64_state": "STATE_DISABLED",
"object_status": {
"availability_status": "AVAILABILITY_STATUS_RED",
"enabled_status": "ENABLED_STATUS_DISABLED",
"status_description": "The children pool member(s) are down"
},
"profile": [
{
"profile_context": "PROFILE_CONTEXT_TYPE_CLIENT",
"profile_name": "/Common/vs_portailopal_wi_clientssl_profile",
"profile_type": "PROFILE_TYPE_CLIENT_SSL"
},
{
"profile_context": "PROFILE_CONTEXT_TYPE_ALL",
"profile_name": "/Common/vs_portailopal_wi_http_profile",
"profile_type": "PROFILE_TYPE_HTTP"
},
{
"profile_context": "PROFILE_CONTEXT_TYPE_ALL",
"profile_name": "/Common/vs_portailopal_wi_http_profile-cache",
"profile_type": "PROFILE_TYPE_WEBACCELERATION"
},]
},
},
So I would like to compare the name of the virtual serveur and the name of each profile. I can select the name of the vitual server but I can't enter in the list of profile to select the name because it's a nested list in an attribute
This is I doing:
---
- name: Search
hosts: F5
gather_facts: no
connection: local
vars:
username: '{{ cpt_username }}'
password: '{{ cpt_password }}'
tasks:
- name: Get virtual-servers
bigip_facts:
include:
- virtual_server
server: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: no
- name: filter on VIP_nommage when VIP_partition is OK
lineinfile:
line:
- "{{ inventory_hostname }} Virtual Server : {{ item.key }} => POOL: {{ item.value.profile.name }}"
dest: "xxxxx/file.csv"
state: present
with_dict: "{{ virtual_server }}"
I want to store in file all profiles name per virtual serveur and in other task filter on their names.
I am not familiar with the bigip Ansible modules, and I definitely don't have any F5 kit to test against :) Before saying anything else, a big note is that the docs say that 'bigip_facts' is now deprecated, and you should be using 'bigip_device_facts'. But if you want to use this module, can you do a couple of things:
1) Edit your original question to add the detail you posted in your reply. It is better to keep editing your original question with additional information, rather than add answers, as it makes it easier to understand your entire situation.
2) Create a new playbook that contains:
---
- hosts: F5
gather_facts: no
connection: local
vars:
username: '{{ cpt_username }}'
password: '{{ cpt_password }}'
tasks:
- name: Get virtual-servers
bigip_facts:
include:
- virtual_server
server: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: no
register: bigip_facts_data
- name: Display collected data
debug:
var: bigip_facts_data
This will show us the data that Ansible is actually working with. Paste the output into your original reply, in place the of the JSON that you originally pasted. It may look like this:
"/Common/vs_portailopal_wi_https_virtual_server":
last_hop_pool: ''
name: vs_portailopal_wi_https_virtual_server
nat64_state: STATE_DISABLED
object_status:
availability_status: AVAILABILITY_STATUS_RED
enabled_status: ENABLED_STATUS_DISABLED
status_description: The children pool member(s) are down
profile:
- profile_context: PROFILE_CONTEXT_TYPE_CLIENT
profile_name: "/Common/vs_portailopal_wi_clientssl_profile"
profile_type: PROFILE_TYPE_CLIENT_SSL
- profile_context: PROFILE_CONTEXT_TYPE_ALL
profile_name: "/Common/vs_portailopal_wi_http_profile"
profile_type: PROFILE_TYPE_HTTP
- profile_context: PROFILE_CONTEXT_TYPE_ALL
profile_name: "/Common/vs_portailopal_wi_http_profile-cache"
profile_type: PROFILE_TYPE_WEBACCELERATION
If it does, then this may produce the output you need (tho I am still not clear I fully understand what you require - hopefully we are closer):
- name: filter on VIP_nommage when VIP_partition is OK
lineinfile:
line:
- "{{ inventory_hostname }} Virtual Server : {{ item.0.name }} => POOL: {{ item.1.profile_name }}"
dest: "xxxxx/file.csv"
state: present
with_subelements:
- "{{ bigip_fact_data }}"
- profile
Really, 'with_subelements' is deprecated now along with the other 'with_' constructs, but if you are using 'bigip_facts' I guess you are using an older version of Ansible.
This question already has answers here:
How to get the first element of a list from the output of setup module in Ansible?
(3 answers)
Closed 4 years ago.
I have the following values in a data structure:
kafka_topic:
topic:
- "DATA.APP_TOPIC"
partitions:
- "1"
replication-factor:
- "1"
I am retrieving the topic value and passing it to the command module:
- name: Topic Name
set_fact:
topic_name: "{{ kafka_topic.topic }}"
- name: Create Topic with Specific Configuration
command: "{{ kafka_bin_dir }}/{{ kafka_config_script }}
--zookeeper {{ prefix }}-kafka-{{ Kafka_node }}.{{ DNSDomain}}:{{ zookeeper_port }}
--entity-type topics
--alter
--entity-name {{ topic_name }}
--add-config
{{ item.topic_property }}={{ item.value }}"
with_items: "{{ app_kafka_topic_properties_dicts }}"
However, the actual value passed to the command module is [uDATA.APP_TOPIC].
How do I make sure just the value DATA.APP_TOPIC is passed to the command module?
The solution was easy. I just returned the first element of the kafka_topic.topic list.
- name: Topic Name
set_fact:
topic_name: "{{ kafka_topic.topic[0] }}"
This returns the element as oppose to the entire list.