Create a Post
cancel
Showing results for 
Search instead for 
Did you mean: 
ukohae
Contributor

Ansible - Add members to a group

Jump to solution

Is there a way to read all host objects  in a csv file and add them to a member of a group using  
cp_mgmt_group module?

my playbook only adds the last host ( gTest103, 10.1.2.5, FWP - Applying changes ) to a member,  gTest1A, in my playbook. Is there a reason why it adds only the last host gTest103? and then it removes the other hosts

Network.csv

 

 

Name,IP,Comments
gTest101,10.1.2.3,FWP - Testing this
gTest102,10.1.2.4,FWP - Applying this
gTest103,10.1.2.5,FWP - Applying changes
---
- name: Global Objects
  hosts: check_point
  connection: httpapi
  gather_facts: False
  vars_files:
    - 'credentials/my_var.yml'
    - 'credentials/login.yml'

  tasks:
  - name:  read-csv-file
    read_csv:
      path: file_reader/Networks.csv
      key: Name
    register: user

  - name: add-host-object
    check_point.mgmt.cp_mgmt_host:                    
      name: "{{ item.value.Name | quote }}"           
      ip_address: "{{ item.value.IP | quote }}"       
      comments: "{{ item.value.Comments }}"           
      state: present
      auto_publish_session: yes
    loop: "{{ user.dict | dict2items }}"               
    ignore_errors: yes
    delegate_to: Global

  - name: add-network-group
    check_point.mgmt.cp_mgmt_group:
      name: gTest1A
      comments: "anything"
      state: present
      members:
        - "{{ item.value.Name }}"
      auto_publish_session: yes
    loop: "{{ user.dict|dict2items }}"
    ignore_errors: yes
    delegate_to: Global     

 

 

 

0 Kudos
3 Solutions

Accepted Solutions
Jonas_Rosenboom
Employee
Employee

Hi,

you are using loop here, which causes multiple calls to the cp_mgmt_group module, each specifying the group to have ONE member (and no others). That's why you end up with the last host from your CSV, because the last call changes the group to contain exactly that host (and no other objects).

With the CSV parsed like in your example, the following would be a valid approach.
It creates a list from all the dictionary keys present (which in your example is the name for the object), and provides the full list as the member parameter to the group module.

  - set_fact:
      hosts_in_group: "{{ user.dict | dict2items | map(attribute='key') | list }}"

  - name: add-network-group
    check_point.mgmt.cp_mgmt_group:
      name: ExampleGroup
      state: present
      members: "{{ hosts_in_group }}"
      auto_publish_session: yes

 This requires the CSV to contain a complete list of all the objects you want to be present in the group.

View solution in original post

0 Kudos
Jonas_Rosenboom
Employee
Employee

If you ignore_warnings as discussed before it will create the additional host objects, and you can use the original list you've created from the CSV.

For the other options, you can register the result in a variable (e.g. result). Starting in Ansible 1.6.1, the results registered with multiple items are stored in result.results as an array. You then need to create a filter to weed out the bad ones and use the result. 

See: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

However, I advise against this approach for anything but a temporary solution, as it goes against the Ansible concept of Idempotency, and will make your future life much harder.

View solution in original post

0 Kudos
Jonas_Rosenboom
Employee
Employee

I assume you mean it changes the existing host object's comment here. 

That is what Ansible is designed for. It makes sure that after the playbook finishes, the actual state of your objects matches the values configured in Ansible. 

There should be one "correct" comment for an object at any given time. Either you would need to update the configuration in Ansible, or change the comment in the object (the latter being done for you by Ansible in this case). 

View solution in original post

0 Kudos
8 Replies
Jonas_Rosenboom
Employee
Employee

Hi,

you are using loop here, which causes multiple calls to the cp_mgmt_group module, each specifying the group to have ONE member (and no others). That's why you end up with the last host from your CSV, because the last call changes the group to contain exactly that host (and no other objects).

With the CSV parsed like in your example, the following would be a valid approach.
It creates a list from all the dictionary keys present (which in your example is the name for the object), and provides the full list as the member parameter to the group module.

  - set_fact:
      hosts_in_group: "{{ user.dict | dict2items | map(attribute='key') | list }}"

  - name: add-network-group
    check_point.mgmt.cp_mgmt_group:
      name: ExampleGroup
      state: present
      members: "{{ hosts_in_group }}"
      auto_publish_session: yes

 This requires the CSV to contain a complete list of all the objects you want to be present in the group.

View solution in original post

0 Kudos
ukohae
Contributor

hi, in the code below, if the host already exist in gTest1A or shows any error of multiple objects with the same IPs exist if a new host is added, I am trying to tell it to ignore existing host or objects with multiple IPs and create the new host with a unique IP into the group gTest2A (gTest105, 10.1.2.5, FWP -Ansible) , it doesn't create the new host gTest105, 10.1.2.5, FWP -Ansible

Note: gTest1A already exist, but gTest2A needs to be created

gTest1A.csv

Name,IP,Comments
gTest101,10.1.2.3,FWP - Test,
gTest102,10.1.2.4, FWP - Fix,

 

gTest2A.csv

Name,IP,Comments
gTest103,10.1.2.3,FWP - New Comments,
gTest104,10.1.2.4, FWP - New Comments by user,
gTest105,10.1.2.5,FWp - Ansible,

 

playbook.yml

---
- name: Global Objects
  hosts: check_point
  connection: httpapi
  gather_facts: False
  vars_files:
    - 'credentials/my_var.yml'
    - 'credentials/login.yml'

  tasks:
  - name:  read-csv-file
    read_csv:
      path: file_reader/gTest2A.csv
      key: Name
    register: user


  - name: add-host-object
    check_point.mgmt.cp_mgmt_host:                  
      name: "{{ item.value.Name | quote }}"           
      ip_address: "{{ item.value.IP | quote }}"       
      comments: "{{ item.value.Comments }}"           
      state: present
      auto_publish_session: yes
    loop: "{{ user.dict | dict2items }}"               
    ignore_errors: yes
    delegate_to: Global

  - name: wait for session to be refreshed
    wait_for:
      timeout: 30

  - set_fact:
      hosts_in_group: "{{ user.dict | dict2items | map(attribute='key') | list }}"


  - name: add-network-group
    check_point.mgmt.cp_mgmt_group:
      name: gTest2A
      comments: "something different"
      state: present
      members: "{{ hosts_in_group }}"
      auto_publish_session: yes
    ignore_errors: yes
    delegate_to: Global 


 

0 Kudos
Jonas_Rosenboom
Employee
Employee

Based on your playbook, gTest105 should always be created, while gTest103 and gTest104 will fail validation due to another object with the same IP being present.

This will however cause the cp_mgmt_group module to fail, because it expects gTest103 and gTest104 to be present.
If you want to create gTest103 and gTest104 even if other objects with the same IP address exist, you can add "ignore_warnings: true" to the module parameters. Be aware that this may suppress other validation warnings too.

  - name: add-host-object
    check_point.mgmt.cp_mgmt_host:
      name: "{{ item.value.Name | quote }}"
      ip_address: "{{ item.value.IP | quote }}"
      comments: "{{ item.value.Comments }}"
      state: present
      ignore_warnings: yes
    loop: "{{ user.dict | dict2items }}"
    ignore_errors: yes

Note that ignore_warnings and ignore_errors apply at different levels. At the module level we ignore the validation warning, and at the task level we ignore any errors during module execution. It might be a good idea to remove the ignore_errors to fail EARLY in case we are facing an actual problem (instead of failing later on when creating the group).

If you wanted to skip creating any hosts that already exist with the same IP and a different name, you would have to append the output of each successful call of cp_host_mgmt to a separate list and set the group members based on that.

If you are certain that creation of gTest105 fails from your playbook (instead of it just missing from the group), please check the error message for clues and/or share it here.

0 Kudos
ukohae
Contributor

Thanks very much,  I am still a notice at this. Referring to this statement "If you wanted to skip creating any hosts that already exist with the same IP and a different name, you would have to append the output of each successful call of cp_host_mgmt to a separate list and set the group members based on that." 

How do I append each successful output to a list and pass it to a new group?

0 Kudos
ukohae
Contributor

How can I append the output of my result such that on successful call to cp_host_mgmt, it still applies only the  newly added host (excluding existing host and duplicate IPs)  to the new group gTest2A

0 Kudos
Jonas_Rosenboom
Employee
Employee

If you ignore_warnings as discussed before it will create the additional host objects, and you can use the original list you've created from the CSV.

For the other options, you can register the result in a variable (e.g. result). Starting in Ansible 1.6.1, the results registered with multiple items are stored in result.results as an array. You then need to create a filter to weed out the bad ones and use the result. 

See: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

However, I advise against this approach for anything but a temporary solution, as it goes against the Ansible concept of Idempotency, and will make your future life much harder.

View solution in original post

0 Kudos
ukohae
Contributor

Thanks.

Group: gTest1A

Host: gTest101
IP: 10.1.2.3
Comment: FWP - Firewall


New Group to be published

Group: gTest2A

Host: gTest101
IP: 10.1.2.3
Comment: FWP - Ansible Test



Another thing I was wondering about. What Happens if  Group: gTest1A already and it contains a Host [ gTest101, 10.1.2.3, FWP - Firewall]

if I publish a task to a new Group called gTest2A and the Host has the same Name and IP, but different Comment [gTest101, 10.1.2.3, FWP - Ansible Test]

Why does it edit the existing group's Comment in gTest1A ( from "FWP - Firewall"  to "FWP - Ansible Test"]

Ansible automatically updates the existing group's Comment. 

Before it gets changed automatically, ansible doesn't throw any error message that this object already exists. It just shows "changed" in my command line.

is there a way to create the new group gTest2A without editing existing Comments in gTest1A automatically?

0 Kudos
Jonas_Rosenboom
Employee
Employee

I assume you mean it changes the existing host object's comment here. 

That is what Ansible is designed for. It makes sure that after the playbook finishes, the actual state of your objects matches the values configured in Ansible. 

There should be one "correct" comment for an object at any given time. Either you would need to update the configuration in Ansible, or change the comment in the object (the latter being done for you by Ansible in this case). 

View solution in original post

0 Kudos