Roles in Ansible build on the idea of include files and combine them to form clean, reusable abstractions
From Ansible doc:Roles in Ansible build on the idea of include files and combine them to form clean, reusable abstractions
I really want to love roles and use them extensively in our system, but so far I'm getting a heap of frustration instead. I am trying to position Ansible at work as the preferred automation platform to manage a complex system with several internally developed apps, plus db, web server, and more. (together this is one product/system) Multiple environments too, as usual.
I'd think it makes sense to have roles like:
- appX (for X in 1 through N)
- web
- db
- etc (more.. skipped)
One seemingly basic thing I need to do is to restart this entire system occasionally. I would like to use Ansible to do that. Here's a simplified pseudo-code recipe of a playbook:
- web.startMaintenance()
- app1.stop()
- app2.stop()
- app2.start()
- app1.start()
- web.endMaintenance()
I want to run a single playbook command to do this. That seems clearly possible with include files but not possible with roles. The following doesn't work:
ansible-playbook --tags "app1.stop,app1.start,app2.start,app2.stop,web.startMaintenance,web.endMaintenance" playbooks/testRoleDeps.yml
That doesn't work because all plays in the playbook are filtered by the tags provided, and each play needs to have a particular tag applied (first stop then start later), not all of them.
My conclusion? As of 1.8.4, roles are inadequate for complex playbooks and include files need to be used instead.
That's unfortunate for code reuse reasons, etc. I would love to hear that this is not the case and I have overlooked something. Maybe a feature to resolve this is in the release plan?
I can't figure out how to do this even after reading the documentation repeatedly, reading the ansible O'Reilly book (pre-release copy), the code in ansible-examples, and various other resources.
Some replies inline!
On Mon, Feb 23, 2015 at 1:41 PM, <jack.ma...@gmail.com> wrote:From Ansible doc:Roles in Ansible build on the idea of include files and combine them to form clean, reusable abstractions
I really want to love roles and use them extensively in our system, but so far I'm getting a heap of frustration instead. I am trying to position Ansible at work as the preferred automation platform to manage a complex system with several internally developed apps, plus db, web server, and more. (together this is one product/system) Multiple environments too, as usual.
I'd think it makes sense to have roles like:
- appX (for X in 1 through N)
- web
- db
- etc (more.. skipped)That's usually the case for simple stuff, but for each app or component of the system, I usually end up with multiple roles. Maybe a role, a role to configure, a role to restart. When you start wanting to call individual parts of a single role separately, that's a good sign that you need to break that role up into multiple parts. For organizational purposes, you can definitely do:roles/web/setup/*roles/web/install/*roles/web/config/*roles/web/restart/*
One seemingly basic thing I need to do is to restart this entire system occasionally. I would like to use Ansible to do that. Here's a simplified pseudo-code recipe of a playbook:
- web.startMaintenance()
- app1.stop()
- app2.stop()
- app2.start()
- app1.start()
- web.endMaintenance()
I want to run a single playbook command to do this. That seems clearly possible with include files but not possible with roles. The following doesn't work:ansible-playbook --tags "app1.stop,app1.start,app2.start,app2.stop,web.startMaintenance,web.endMaintenance" playbooks/testRoleDeps.ymlIt seems like a single playbook for all of these different configurations might not be realistic. Why not have multiple playbooks, one per general operation, and call the roles as needed?
That doesn't work because all plays in the playbook are filtered by the tags provided, and each play needs to have a particular tag applied (first stop then start later), not all of them.
My conclusion? As of 1.8.4, roles are inadequate for complex playbooks and include files need to be used instead.Roles are pretty simple--for more complex purposes, you may want to mix in playbook includes too. That's fine! I wouldn't get too hung up on getting all of the behavior for a certain part of your app in a single role. That's going to be confusing and complicated to use.That's unfortunate for code reuse reasons, etc. I would love to hear that this is not the case and I have overlooked something. Maybe a feature to resolve this is in the release plan?
I can't figure out how to do this even after reading the documentation repeatedly, reading the ansible O'Reilly book (pre-release copy), the code in ansible-examples, and various other resources.I'm not sure if I understand any specific requests for improvement here--besides being able to use a single playbook to drive multiple operations, which is not really Ansible-style. If I've misunderstood, feel free to let me know! :)
---Tim
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/CAH4wdVWc73Hc9x19AmiZ2CbZNJZPW2FyKv%3D7g-w88qnQtQNeQQ%40mail.gmail.com.
ansible$ find roles/{web,app1,app2} -type f | sort
roles/app1/startServer/tasks/main.yml
roles/app1/stopServer/tasks/main.yml
roles/app2/startServer/tasks/main.yml
roles/app2/stopServer/tasks/main.yml
roles/web/startMaintenance/tasks/main.yml
roles/web/startServer/tasks/main.yml
roles/web/stopMaintenance/tasks/main.yml
roles/web/stopServer/tasks/main.yml
ansible$ cat roles/web/startMaintenance/tasks/main.yml
---
- name: Run first task for startMaintenance
debug: msg="Doing first task"
- name: Run second task for startMaintenance
debug: msg="Doing second task"
ansible$ find playbooks/test/ -type f | grep -v restart | sort
playbooks/test/app1_startServer.yml
playbooks/test/app1_stopServer.yml
playbooks/test/app2_startServer.yml
playbooks/test/app2_stopServer.yml
playbooks/test/web_startMaintenance.yml
playbooks/test/web_stopMaintenance.yml
ansible$ cat playbooks/test/web_startMaintenance.yml
---
- hosts: 127.0.0.1 # Imagine 'web'
connection: local
roles:
- web/startMaintenance
ansible$ find playbooks/test/ -type f | grep restart
playbooks/test/restart_system.yml
ansible$ cat playbooks/test/restart_system.yml
---
- include: web_startMaintenance.yml
- include: app1_stopServer.yml
- include: app2_stopServer.yml
- include: app2_startServer.yml
- include: app1_startServer.yml
- include: web_stopMaintenance.yml
The entire mission of Ansible is "simple IT automation", right? :) Wherever possible, my preference would be for a single Ansible playbook to handle the execution of a single high-level "goal"/"user request". If that isn't the case, then one needs to somehow bundle those externally, typically in a script. That requires the local "Ansible team" to decide on and maintain knowledge in such a scripting language, and requires implementing error checking and possibly error recovery in the scripting language. Sure.. it isn't strictly necessary, but I would rather just call a script "restart_system.bash" that makes a call to a single ansible playbook instead of seeing the bash script make a call to 6 ansible playbooks. What happens if the playbooks need to pass state or other data between each other? Much cleaner if it occurs in a single call, no?
--
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/CAH4wdVX2Dfh3he3u%3Dza1heytT9Hy6shsDGawDQ6GS7RTTbnT5Q%40mail.gmail.com.
Now you can invoke it with:ansible-playbook restart_system.yml --tags app1
...to only restart app1, or without tags to restart everything. (Maybe the web start/stop should be untagged, so it runs every time--not sure. Depends on your app.)This way you lose the intermediary playbooks, and end up with a single playbook to do all of your restart tasks.
If app1 and app2 roles are really close together, maybe you could parameterize them, too:- { role: genericApp/stopServer, appName: "app1", tags: ["app1"] }
-Tim