Can I slice an existing group within a play (without a unique attribute to group_by)?

162 views
Skip to first unread message

Mark Casey

unread,
Dec 11, 2014, 1:47:32 PM12/11/14
to ansible...@googlegroups.com
Hello,

I have a group of servers in EC2 that will be a cluster of Consul server nodes, but on some of them I also want to run LDAP.

I believe in a static inventory file this would be:

[consul]
server1
server2
server3

[ldap]
server1
server 2

I'm using the pattern from the EC2 guide of calling out to the ec2 module to create or persist/no-op the instances and then using add_host to group them (so it does ec2/add_host during every call to ansible-playbook). I'm passing 'type: consul' in to the ec2 role which ends up in some of the naming tags and being used for idempotence/exact_count.

My question is: Where do I create the second group ('ldap')?

I'm kind of hoping I could slice the existing 'consul' group into an ldap group or start a play (within the same run of ansible-playbook) on only some of the hosts in the consul group:

- name: Create instances
  hosts: localhost
  connection: local
  roles:
    - role: ec2
      type: consul
      count: 3

- name: Install Consul
  hosts: consul
  roles:
    - role: consul

- name: Install LDAP
  hosts: "A subset of 'consul', or a new 'ldap' subgroup created from a subset of 'consul'"
  roles:
    - role: ldap


And finally... the catch.

I'm using just enough tags to name the instances and get 'count_tags'+'exact_count' to work with the EC2 module. I'd rather not add more tags to get an 'ldap' group out of ec2.py because I want to be able to use this with other cloud providers (existing playbooks already work with EC2 and Rackspace). In the past I've found that some providers may only support one tag/group, may not allow changing groups via API, or don't do tags/groups at all and impotence is based on the instance name alone.

I'm hoping I'm overlooking an obvious fix but right now I'm planning to do:

- name: Create instances
  hosts: localhost
  connection: local
  roles:
    - role: ec2
      type: consul_ldap
      count: 2
    - role: ec2
      type: consul
      count: 1

- name: Install Consul
  hosts: consul_ldap:consul
  roles:
    - role: consul

- name: Install LDAP
  hosts: consul_ldap
  roles:
    - role: ldap


Thanks,
Mark

James Cammarata

unread,
Dec 11, 2014, 3:04:08 PM12/11/14
to ansible...@googlegroups.com
Hi Mark, the way you're planning is the correct way to do this, however you could use a conditional on the ldap role such that it would only run if the consul_ldap group was in the current host's groups:

- { role: consul_ldap, when: "'consul_ldap' is in group_names" }

I don't really recommend doing that, but it's there should you decide to use it.


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/24334d89-61fa-45ef-b1f1-8a71c67e7ff4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Mark Casey

unread,
May 26, 2015, 1:02:44 PM5/26/15
to ansible...@googlegroups.com
James (and list),

Thanks for the feedback on this back when... I just got a semi-permanent solution added that I wanted to share/see if I could get any thoughts on.

I added a couple tasks in my VM provisioning Ansible roles that process a new fact named "additional_roles" (with 'roles' in this context meaning "things this host does". I need to do some term-fixing... this is using 'role', 'service', and 'type' fairly interchangably... but anyway)


This is the call which would set the new fact, and 'provider' may be ec2, rax, vagrant, or etc.:

  roles:
    - role: '{{ provider }}/{{ provider }}_add'
      type: dbnode
      additional_roles: webnode
      count: 1

and then the tasks within the ec2_add role, for example (new tasks in bold):

---

- name: Set up a new host instance on EC2
  local_action:
    module: ec2
    region: "{{ region }}"

  ... ...

  register: ec2

- name: Add instance(s) to group representing type of host such as webnode or dbnode
  local_action: add_host hostname={{ item.private_ip }} ansible_ssh_host={{ item.private_ip }} groupname={{ type }}
  with_items: ec2.tagged_instances
  when: wait == "yes"

- name: Add instance(s) to combo service_type group, such as prod_dbnode, or staging_webnode
  local_action: add_host hostname={{ item.private_ip }} ansible_ssh_host={{ item.private_ip }} groupname="{{ service }}_{{ type }}"
  with_items: ec2.tagged_instances
  when: wait == "yes"

- name: Add instance(s) to group representing type of host such as webnode or dbnode
  local_action: add_host hostname={{ item[0].private_ip }} ansible_ssh_host={{ item[0].private_ip }} groupname={{ item[1] }}
  with_nested:
    - ec2.tagged_instances
    - additional_roles
  when: wait == "yes"

- name: Add instance(s) to combo service_type group, such as prod_dbnode, or staging_webnode
  local_action: add_host hostname={{ item[0].private_ip }} ansible_ssh_host={{ item[0].private_ip }} groupname="{{ service }}_{{ item[1] }}"
  with_nested:
    - ec2.tagged_instances
    - additional_roles
  when: wait == "yes"



So, the method for my original goal of 3 consul nodes and 2 ldap nodes would be:

  roles:
    - role: '{{ provider }}/{{ provider }}_add'
      type: consul
      additional_roles: ldap
      count: 2

  roles:
    - role: '{{ provider }}/{{ provider }}_add'
      type: consul
      count: 1


Thanks,
Mark

Mark Casey

unread,
May 26, 2015, 1:04:07 PM5/26/15
to ansible...@googlegroups.com
I forgot to bold the new tasks after I said they'd be bold... In case it isn't very obvious they are the only two shown that use 'with_nested:'
Reply all
Reply to author
Forward
0 new messages