Overview

Migrate from Puppet to Ansible

1 Comment

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.

Kommentare

  • Thomas

    5. June 2015 von Thomas

    > The Puppet output does not look very nice, but it is better than having nothing at all.

    you could call puppet with “–color=none” to disable the clored output. So the output would be bit nicer.

Comment

Your email address will not be published. Required fields are marked *