Creating multiple times the same role, but with di

2019-05-05 17:52发布

问题:

I have a playbook that prepare 3 different Vagrants in my machine, so I have create a role that create this Vagrant. I don't find the correct syntax. It looks like roles is not a module, so I don't have all options, only tutorials.

playbook file :

- hosts: localhost
  connection: local

  roles :
    - role: vagrant
      with_items:
        - {index: 1, ip: 192.168.222.1, name: mongo1, user: nicorama }
        - {index: 2, ip: 192.168.222.2, name: mongo2, user: nicorama }
        - {index: 3, ip: 192.168.222.3, name: mongo3, user: nicorama }

And the tasks in the vagrant role

- file: path=/linux/{{item.name}} state=directory  owner={{item.user}} group={{item.user}} mode="u=rwx,g=rwx,o=rx"
- file: src=playbook.yml dest=/linux/{{item.name}}
- template: src=Vagrantfile dest=/linux/{{item.name}}/Vagrantfile

The error is 'item.name' undefined. It does work using with_items inside the role, but it would even hurt my grandmother eyes

- file: path=/linux/{{item.name}} state=directory  owner={{item.user}} group={{item.user}} mode="u=rwx,g=rwx,o=rx"
  with_items:
        - {index: 1, ip: 192.168.222.1, name: mongo1, user: nicorama }
        - {index: 2, ip: 192.168.222.2, name: mongo2, user: nicorama }
        - {index: 3, ip: 192.168.222.3, name: mongo3, user: nicorama }
- copy: src=playbook.yml dest=/linux/{{item.name}}/playbook.yml
  with_items:
        - {index: 1, ip: 192.168.222.1, name: mongo1, user: nicorama }
        - {index: 2, ip: 192.168.222.2, name: mongo2, user: nicorama }
        - {index: 3, ip: 192.168.222.3, name: mongo3, user: nicorama }
...

回答1:

Reading your question again, I noticed you did actually not mention it has to be some kind of loop. Maybe applying 3 times the same role with different parameters suits your needs:

- hosts: localhost
  connection: local

  roles :

    - role: vagrant
      index: 1
      ip: 192.168.222.1
      name: mongo1
      user: nicorama

    - role: vagrant
      index: 2,
      ip: 192.168.222.2
      name: mongo2
      user: nicorama

    - role: vagrant
      index: 3
      ip: 192.168.222.3
      name: mongo3
      user: nicorama

Then in your role you can use the vars index, ip etc.



回答2:

Indeed, you can not apply loops directly to roles. Loops are meant for tasks.

But roles can take any parameters which you can use in your role. This is not the same as applying the role 3 times with different parameters. But in your role you can handle all the looping. If that's an option, then let's re-model it a bit:

The playbook:

- hosts: localhost
  connection: local

  roles :
    - role: vagrant
      instances:
        - {index: 1, ip: 192.168.222.1, name: mongo1, user: nicorama }
        - {index: 2, ip: 192.168.222.2, name: mongo2, user: nicorama }
        - {index: 3, ip: 192.168.222.3, name: mongo3, user: nicorama }

The tasks of your role:

- file: path=/linux/{{item.name}} state=directory  owner={{item.user}} group={{item.user}} mode="u=rwx,g=rwx,o=rx"
  with_items: instances

- file: src=playbook.yml dest=/linux/{{item.name}}
  with_items: instances

- template: src=Vagrantfile dest=/linux/{{item.name}}/Vagrantfile
  with_items: instances

Of course, this is extremely uncomfortable if you have to loop on every single task. In Ansible 2 it is (again) possible to loop over includes and this might get handy here. You can move all your tasks into a separate file:

- file: path=/linux/{{instance.name}} state=directory  owner={{instance.user}} group={{instance.user}} mode="u=rwx,g=rwx,o=rx"
- file: src=playbook.yml dest=/linux/{{instance.name}}
- template: src=Vagrantfile dest=/linux/{{instance.name}}/Vagrantfile

Then in your main.yml you'd only have this task:

- include: other-file.yml
  with_items: instances
  instance: "{{ item }}"


回答3:

Define a variable and use it inside your role.

- hosts: localhost
  connection: local
  vars:
    my_list:
      - {index: 1, ip: 192.168.222.1, name: mongo1, user: nicorama }
      - {index: 2, ip: 192.168.222.2, name: mongo2, user: nicorama }
      - {index: 3, ip: 192.168.222.3, name: mongo3, user: nicorama }
  roles :
    - vagrant

Use the variable inside your playbook using with_items:

- file: path=/linux/{{item.name}} state=directory  owner={{item.user}} 
  group={{item.user}} mode="u=rwx,g=rwx,o=rx"
  with_items: my_list

- file: src=playbook.yml dest=/linux/{{item.name}}
  with_items: my_list

- template: src=Vagrantfile dest=/linux/{{item.name}}/Vagrantfil
  with_items: my_list