In a previous post, I wrote about combining Ansible and Puppet, with Ansible as remote executor for arbitrary commands. In this post I take a look at how to migrate from Puppet to Ansible.
Combine the Execution of Ansible and Puppet
If you want to migrate from Puppet to Ansible, an all or nothing approach is hard to implement. It has all the disadvantages which apply to any Big Bang migration.
The other option is to migrate Puppet modules one by one to Ansible and remove them from Puppet. During the migration you would have to call both tools to provision a server. That is not very effective and error prone. So what can you do?
You can execute Puppet from within an Ansible playbook. This way you always execute both tools and will not miss any role or module.
But you cannot just call Puppet from Ansible, as Ansible expects a return code of 0 when everything works as expected. Puppet will return a code of 2 when it changed something, which is totally fine. However, Ansible interprets this as a failure and stops executing any other steps on this server. So you need to make Ansible accept 0 as well as 2 as successful return codes:
- name: Start puppet agent sudo: yes shell: /usr/bin/puppet agent --test --verbose register: puppet_agent_result changed_when: puppet_agent_result.rc == 2 failed_when: puppet_agent_result.rc != 2 and puppet_agent_result.rc != 0 |
This way Puppet fits into Ansibles way of handling things.
Finegrained Integration of Puppet into Ansible
If you would like to take a more fine grained approach, you could use Puppet tags to execute Ansible tasks between two different Puppet agent calls:
- name: Start puppet agent for system module sudo: yes shell: /usr/bin/puppet agent -t -v --tags=system register: puppet_agent_result changed_when: puppet_agent_result.rc == 2 failed_when: puppet_agent_result.rc != 2 and puppet_agent_result.rc != 0 - name: Do something with Ansible debug: msg=”something” - name: Start puppet agent for apache module sudo: yes shell: /usr/bin/puppet agent -t -v --tags=apache register: puppet_agent_result changed_when: puppet_agent_result.rc == 2 failed_when: puppet_agent_result.rc != 2 and puppet_agent_result.rc != 0 |
Execution output
An important detail to consider when calling Puppet from Ansible is Puppet’s execution output. Even though Ansible now knows how to interpret Puppet’s return codes, Ansible only tells you that something changed, but not what changes were made:
ansible-playbook -s -i /etc/ansible/puppet_hosts -l "server01*" puppet-ansible-test.yaml PLAY [Test Puppet agent execution via ansible] ******************************** GATHERING FACTS *************************************************************** ok: [server01.example.com] TASK: [Puppet run] ************************************************************ changed: [server01.example.com] PLAY RECAP ******************************************************************** server01.example.com : ok=2 changed=1 unreachable=0 failed=0 |
If you want to see Puppet’s output, when something changed or went wrong, you can use the debug task:
- debug: var=puppet_agent_result.stdout_lines when: puppet_agent_result.rc != 0 |
ansible-playbook -s -i /etc/ansible/puppet_hosts -l "server01*" puppet-ansible-test.yaml PLAY [Test Puppet agent execution via ansible] ******************************** GATHERING FACTS *************************************************************** ok: [server01.example.com] TASK: [Puppet run] ************************************************************ changed: [server01.example.com] TASK: [debug var=puppet_agent_result.stdout_lines] **************************** ok: [server01.example.com] => { "puppet_agent_result.stdout_lines": [ "\u001b[0;32mInfo: Retrieving plugin\u001b[0m", "\u001b[0;32mInfo: Caching catalog for server01.example.com\u001b[0m", "\u001b[0;32mInfo: Applying configuration version '1414749704'\u001b[0m", "\u001b[mNotice: /Stage[main]//Node[server01.example.com]/File[/tmp/ansible-test]/content: ", "--- /tmp/ansible-test\t2014-10-31 11:03:09.792572953 +0100", "+++ /tmp/puppet-file20141031-19593-alc2zo-0\t2014-10-31 11:11:44.243616162 +0100", "@@ -1 +1 @@", "-Jst a test", "+Just a test", "\\ No newline at end of file", "\u001b[0m", "\u001b[0;32mInfo: FileBucket adding {md5}280ef2f78e2399bbefb3b2a487b79281\u001b[0m", "\u001b[0;32mInfo: /Stage[main]//Node[server01.example.com]/File[/tmp/ansible-test]: Filebucketed /tmp/ansible-test to puppet with sum 280ef2f78e2399bbefb3b2a487b79281\u001b[0m", "\u001b[mNotice: /Stage[main]//Node[server01.example.com]/File[/tmp/ansible-test]/content: content changed '{md5}280ef2f78e2399bbefb3b2a487b79281' to '{md5}9543518919cb69d012934d9a78fb50b3'\u001b[0m", "\u001b[mNotice: Finished catalog run in 0.20 seconds\u001b[0m" ] } PLAY RECAP ******************************************************************** server01.example.com : ok=3 changed=1 unreachable=0 failed=0 |
The Puppet output does not look very nice, but it is better than having nothing at all. To make it a bit more readable, perhaps such an Ansible callback plugin might help. But this will be the topic of another post.
This post shows how to execute Puppet from inside Ansible Playbooks. I hope this post gives you a starting point on how to migrate your own Puppet installation to Ansible. As always, do not hesitate to contact me when you have any questions.
The post Migrate from Puppet to Ansible appeared first on codecentric Blog.