Example playbooks

To use the Micetro Ansible Integration you need to create Ansible playbooks that utilize the functionality of Micetro.

Following are a couple of example playbooks for inspiration. These playbooks have been tested extensively with different operating systems, versions of Ansible and Python.

play-user

---
#
# Add, delete and change users in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice users test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Get the free IP address and show info
      debug:
        msg:
          - "Ansible version    : {{ ansible_version.full }}"
          - "Python version     : {{ ansible_facts['python_version'] }}"
          - "Python executable  : {{ ansible_facts['python']['executable'] }}"

    - name: Add the user 'mauricem' as an admin
      mm_user:
        username: mauricem
        password: password
        full_name: Maurice Moss
        state: present
        authentication_type: internal
        roles:
          - Administrators (built-in)
          - DNS Administrators (built-in)
          - DHCP Administrators (built-in)
          - IPAM Administrators (built-in)
          - User Administrators (built-in)
          - Approvers (built-in)
          - Requesters (built-in)
        provider: "{{ provider }}"

    - name: Check idempotency
      mm_user:
        username: mauricem
        password: password
        full_name: Maurice Moss
        state: present
        authentication_type: internal
        roles:
          - Administrators (built-in)
          - DNS Administrators (built-in)
          - DHCP Administrators (built-in)
          - IPAM Administrators (built-in)
          - User Administrators (built-in)
          - Approvers (built-in)
          - Requesters (built-in)
        provider: "{{ provider }}"

    - name: Change the groups
      mm_user:
        username: mauricem
        password: password
        full_name: Maurice Moss
        state: present
        authentication_type: internal
        roles:
          - Administrators (built-in)
          - User Administrators (built-in)
          - Approvers (built-in)
          - Requesters (built-in)
        provider: "{{ provider }}"

    - name: Check idempotency again
      mm_user:
        username: mauricem
        password: password
        full_name: Maurice Moss
        state: present
        authentication_type: internal
        roles:
          - Administrators (built-in)
          - User Administrators (built-in)
          - Approvers (built-in)
          - Requesters (built-in)
        provider: "{{ provider }}"

    - name: Remove the user again
      mm_user:
        username: mauricem
        state: absent
        provider: "{{ provider }}"

play-group

---
#
# Add, delete and change groups in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice users test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Get the free IP address and show info
      debug:
        msg:
          - "Ansible version    : {{ ansible_version.full }}"
          - "Python version     : {{ ansible_facts['python_version'] }}"
          - "Python executable  : {{ ansible_facts['python']['executable'] }}"

    - name: Add the 'local' group
      mm_group:
        name: local
        desc: A local rgroup
        state: present
        users:
          - mauricemoss
          - jenbarber
        provider: "{{ provider }}"

    - name: Check idempotency
      mm_group:
        name: local
        desc: A local group
        state: present
        users:
          - mauricemoss
          - jenbarber
        provider: "{{ provider }}"

    - name: Add nonexisting user to group
      mm_group:
        name: local
        desc: A local group
        state: present
        users:
          - roy
        provider: "{{ provider }}"
      ignore_errors: true

    - name: Remove the 'local' group
      mm_group:
        name: local
        state: absent
        provider: "{{ provider }}"

play-role

---
#
# Add, delete and change roles in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice users test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Get the free IP address and show info
      debug:
        msg:
          - "Ansible version    : {{ ansible_version.full }}"
          - "Python version     : {{ ansible_facts['python_version'] }}"
          - "Python executable  : {{ ansible_facts['python']['executable'] }}"

    - name: Add the 'local' role
      mm_role:
        name: local
        desc: A local role
        state: present
        users:
          - mauricemoss
          - jenbarber
        provider: "{{ provider }}"

    - name: Check idempotency
      mm_role:
        name: local
        desc: A local role
        state: present
        users:
          - mauricemoss
          - jenbarber
        provider: "{{ provider }}"

    - name: Add nonexisting user to role
      mm_role:
        name: local
        desc: A local role
        state: present
        users:
          - roy
        provider: "{{ provider }}"
      ignore_errors: true

    - name: Remove the 'local' role
      mm_role:
        name: local
        state: absent
        provider: "{{ provider }}"

play-props

---
#
# Set, delete and change custom properties in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice Custom Properties test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    - name: Set text property
      mm_props:
        state: present
        name: MyProperty
        proptype: text
        dest: dnsserver
        listitems:
          - Paul
          - Daniel
          - April
          - Nolan
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Check idempotentie
      mm_props:
        state: present
        name: MyProperty
        proptype: text
        dest: dnsserver
        listitems:
          - Paul
          - Daniel
          - April
          - Nolan
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Change type - not allowed
      mm_props:
        state: present
        name: MyProperty
        proptype: yesno
        dest: dnsserver
        listitems:
          - Paul
          - Daniel
          - April
          - Nolan
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Change list around
      mm_props:
        state: present
        name: MyProperty
        proptype: text
        dest: dnsserver
        listitems:
          - Paul
          - Daniel
          - April
          - Nolan
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Remove property
      mm_props:
        state: absent
        name: MyProperty
        proptype: text
        dest: dnsserver
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Remove property - again
      mm_props:
        state: absent
        name: MyProperty
        proptype: yesno
        dest: dnsserver
        provider: "{{ provider }}"
      delegate_to: localhost

play-claimip

---
#
# Claim and release an IP address in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
#
- name: Men&Mice ClaimIP test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    - name: Claim IP address
      mm_claimip:
        state: present
        ipaddress: 172.16.12.14
        provider: "{{ provider }}"

    - name: Check idempotentie
      mm_claimip:
        state: present
        ipaddress: 172.16.12.14
        provider: "{{ provider }}"

    - name: Unclaim IP address
      mm_claimip:
        state: present
        ipaddress: 172.16.12.14
        provider: "{{ provider }}"

    # This task claims an IP address that cannot exit
    # and returns a warning because of that
    - name: Claim erroneous IP address
      mm_claimip:
        state: present
        ipaddress: 456.978.12.14
        provider: "{{ provider }}"

play-dhcp

---
#
# Make a DHCP reservation and release it in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice DHCP test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    - name: Add a reservation for an IP address
      mm_dhcp:
        state: present
        name: myreservation
        ipaddress: 172.16.17.8
        macaddress: 44:55:66:77:88:00
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: check idempotentie
      mm_dhcp:
        state: present
        name: myreservation
        ipaddress: 172.16.17.8
        macaddress: 44:55:66:77:88:00
        provider: "{{ provider }}"
      delegate_to: localhost

    # Changing the MAC address of a reservation is not allowed, as this
    # would alter the reservation. To achieve this, release the reservation
    # and reclaim it.
    - name: change mac
      mm_dhcp:
        state: present
        name: myreservation
        ipaddress: 172.16.17.8
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: change ip
      mm_dhcp:
        state: present
        name: myreservation
        ipaddress: 172.16.17.9
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: change name
      mm_dhcp:
        state: present
        name: movemyreservation
        ipaddress: 172.16.17.9
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: delete reservation (wrong one)
      mm_dhcp:
        state: absent
        name: movemyreservation
        ipaddress: 172.16.17.9
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: delete reservation (correct one)
      mm_dhcp:
        state: absent
        name: myreservation
        ipaddress: 172.16.17.8
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: create reservation in invalid range
      mm_dhcp:
        state: present
        name: reservationnonet
        ipaddress: 172.16.17.58
        macaddress: 44:55:66:77:88:99
        provider: "{{ provider }}"
      delegate_to: localhost

play-zone

---
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice DHCP test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    - name: Ensure the zone
      mm_zone:
        state: present
        name: example.com
        nameserver: mandm.example.com
        authority: mandm.example.net
        masters: mandm.example.net
        servtype: master
        customproperties:
          owner: Reynholm Industries
          place: London
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Remove the zone
      mm_zone:
        state: absent
        name: example.com
        provider: "{{ provider }}"
      delegate_to: localhost

play-dnsrecord

---
#
# Set and change a DNS record in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice DNSRecord test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    - name: Set DNS record
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: A
        dnszone: testzone
        data: 192.168.10.12
        comment: From The API side
        ttl: 86400
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Check idempotentie
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: A
        dnszone: testzone
        data: 192.168.10.12
        comment: From The API side
        ttl: 86400
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Set DNS record with erroneous values
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: AAAA
        dnszone: testzone
        data: 192.168.10.127
        comment: From The API side
        ttl: apple
        provider: "{{ provider }}"
      delegate_to: localhost
      ignore_errors: true

    - name: Change record
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: A
        dnszone: testzone
        data: 192.168.10.14
        comment: From The API side
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Do something stupid
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: A
        dnszone: notthetestzone
        data: 192.168.90.14
        comment: Welcome to the error
        provider: "{{ provider }}"
      delegate_to: localhost
      ignore_errors: true

    - name: Do more something stupid things
      mm_dnsrecord:
        state: present
        name: reynholm
        rrtype: A
        dnszone: testzone
        data: 192.168.390.14
        comment: Welcome to the error
        provider: "{{ provider }}"
      delegate_to: localhost
      ignore_errors: true

    - name: Remove record
      mm_dnsrecord:
        state: absent
        name: reynholm
        dnszone: notthetestzone
        data: 192.168.90.14
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Remove record - again
      mm_dnsrecord:
        state: absent
        name: reynholm
        dnszone: notthetestzone
        data: 192.168.90.14
        provider: "{{ provider }}"
      delegate_to: localhost

play-freeip

---
#
# Find a set of free IP addresses in a range in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice FreeIP test play
  hosts: localhost
  connection: local
  become: false

  vars:
    network:
      - examplenet

  tasks:
    - name: Set free IP addresses as a fact
      set_fact:
        freeips: "{{ query('mm_freeip',
                         provider,
                         network,
                         multi=25,
                         claim=60,
                         excludedhcp=True,
                         ping=True)
               }}"

    - name: Get the free IP address and show info
      debug:
        msg:
          - "Free IPs           : {{ freeips }}"
          - "Queried network(s) : {{ network }}"
          - "Ansible version    : {{ ansible_version.full }}"
          - "Python version     : {{ ansible_facts['python_version'] }}"
          - "Python executable  : {{ ansible_facts['python']['executable'] }}"

    - name: Loop over IP addresses
      debug:
        msg:
          - "Next free IP       : {{ item }}"
      loop: "{{ freeips }}"

play-ipinfo

---
#
# Get all info for an IP address in Micetro example
#
# The file <ansible_topdir>/group_vars/all contains:
#
#    ---
#    provider:
#      mmurl: http://micetro.example.net
#      user: apiuser
#      password: apipasswd
#
- name: Men&Mice IP Info test play
  hosts: localhost
  connection: local
  become: false

  tasks:
    - name: Get get IP info
      set_fact:
        ipinfo: "{{ query('mm_ipinfo', provider, '172.16.17.2') | to_nice_json }}"

    - name: Show Ansible and Python information
      debug:
        msg:
          - "Ansible version    : {{ ansible_version.full }}"
          - "Python version     : {{ ansible_facts['python_version'] }}"
          - "Python executable  : {{ ansible_facts['python']['executable'] }}"

    - name: Show all infor for this IP address
      debug:
        var: ipinfo

    # This task tries to get the information for a non-existing IP address
    # which results in a fatal `Object not found for reference` error
    - name: Get get IP info for a non existing IP address
      set_fact:
        ipinfo: "{{ query('mm_ipinfo', provider, '390.916.17.2') | to_nice_json }}"
      ignore_errors: true

play_it_all

Example of a playbook that combines functionality

---
- name: Men&Mice test play
  hosts: localhost
  connection: local
  become: false

  vars:
    network: examplenet

  tasks:
    # Some extra information about Ansible and the used
    # Python version
    - name: Ansible information
      debug:
        msg:
          - "Ansible version   : {{ ansible_version.full }}"
          - "Python version    : {{ ansible_facts['python_version'] }}"
          - "Python executable : {{ ansible_facts['python']['executable'] }}"

    # The `ipaddr` filter needs the Python `netaddr` module, so make sure
    # this is installed
    # The `ipaddr` is used to determine the reverse IP address
    #
    # For example:
    #   vars:
    #     ipa4: "172.16.17.2"
    #     ipa6: "2001:785:beef:1:f2c4:8f9d:b554:e614"
    #
    #   - "Forward IPv4 address : {{ ipa4 }}"
    #   - "Forward IPv4 address : {{ ipa4 }}"
    #   - "Reverse IPv4 address : {{ ipa4 | ipaddr('revdns') }}"
    #   - "Reverse IPv6 address : {{ ipa6 | ipaddr('revdns') }}"
    #   - "Reverse IPv4 zone    : {{ (ipa4 | ipaddr('revdns')).split('.')[1:]  | join('.') }}"
    #   - "Reverse IPv6 zone    : {{ (ipa6 | ipaddr('revdns')).split('.')[16:] | join('.') }}"
    #
    # The reverse zones are split on '.' and only the last part is
    # used (in this example). The reverse for IPv4 assumes a '/24' network
    # and the '16' in the IPv6 zone conversion is for a '/64' network. Adapt these to your
    # own needs (e.g. '2' for a '/16' network on IPv4 or '20' for an IPv6 '/48' net.

    - name: Ensure the netaddr module is installed for Python 2
      pip:
        name: netaddr
        state: present
      when: ansible_facts['python_version'] is version('3', '<')
      become: true

    - name: Ensure the netaddr module is installed for Python 3
      pip:
        name: netaddr
        state: present
        executable: pip3
      when: ansible_facts['python_version'] is version('3', '>=')
      become: true

    - name: define custom properties for IP addresses
      mm_props:
        name: location
        state: present
        proptype: text
        dest: ipaddress
        provider: "{{ provider }}"

    # The above example defines just a single property.
    # Defining multiple properties can be achieved by using
    # the Ansible loop functionality.
    #
    # - name: Example of multiple properties
    #   mm_props:
    #      name: "{{ item.name }}"
    #      state: "{{ item.state }}"
    #      proptype: "{{ item.proptype }}"
    #      dest: "{{ item.dest }}"
    #  loop:
    #    - name: location
    #      state: present
    #      proptype: text
    #      dest: ipaddress
    #    - name: owner
    #      state: present
    #      proptype: text
    #      dest: ipaddress

    # When running an Ansible lookup plugin, this lookup action takes
    # place every time the variable is referenced. So it will not be
    # possible to claim an IP address for further reference, this way.
    # This has to do with the way Ansible works.  A solution for this
    # is to assign all collected free IP addresses to an Ansible fact,
    # but here you need to make sure the factname is not used over
    # multiple hosts.
    - name: get free IP addresses and set it as a fact
      set_fact:
        freeips: "{{ query('mm_freeip', provider, network, claim=60, excludedhcp=True) }}"

    - name: Get the free IP address and show info
      debug:
        msg:
          - "Free IPs           : {{ freeips }}"
          - "Queried network(s) : {{ network }}"

    # Make a DHCP reservation for this address
    # So claim it after DNS setting.
    - name: Reservation on IP address
      mm_dhcp:
        state: present
        name: testhost
        ipaddress: "{{ freeips }}"
        macaddress: "de:ad:be:ef:16:10"
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Set properties on IP
      mm_ipprops:
        state: present
        ipaddress: "{{ freeips }}"
        properties:
          claimed: false
          location: London
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Ensure the zone
      mm_zone:
        state: present
        name: thetestzone.com
        nameserver: mandm.example.com
        authority: mandm.example.net
        masters: mandm.example.net
        servtype: master
        provider: "{{ provider }}"
      delegate_to: localhost

    # The `mm_freeip` plugin always returns a list, but the request was for just 1
    # IP address. The `mm_dnsrecord` only needs a single IP address. That's why the
    # list-slice `[0]` is used.
    - name: Set a DNS record for the claimed IP
      mm_dnsrecord:
        dnszone: testzone
        name: testhost
        data: "{{ freeips[0] }}"
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Set a PTR DNS record for the claimed IP
      mm_dnsrecord:
        dnszone: "{{ (freeips[0] | ipaddr('revdns')).split('.')[1:]  | join('.') }}"
        name: "{{ freeips[0] | ipaddr('revdns') }}"
        data: "testhost.testzone."
        rrtype: PTR
        provider: "{{ provider }}"
      delegate_to: localhost

    # The `mm_ipinfo` returns all known information of an IP
    # address. This can be used to query certain properties, or
    # for debugging.
    - name: Get all info for this IP address
      debug:
        var: freeipinfo
      vars:
        freeipinfo: "{{ query('mm_ipinfo', provider, freeips[0]) | to_nice_json }}"

    - name: Renew properties on IP
      mm_ipprops:
        state: present
        ipaddress: "{{ freeips }}"
        properties:
          claimed: false
          location: Madrid
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Get all info for this IP address
      debug:
        var: freeipinfo
      vars:
        freeipinfo: "{{ query('mm_ipinfo', provider, freeips[0]) | to_nice_json }}"

    - name: Remove properties of IP
      mm_ipprops:
        state: present
        ipaddress: "{{ freeips }}"
        deleteunspecified: true
        properties:
          claimed: false
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Get all info for this IP address
      debug:
        var: freeipinfo
      vars:
        freeipinfo: "{{ query('mm_ipinfo', provider, freeips[0]) | to_nice_json }}"

    - name: Remove reservation on IP address
      mm_dhcp:
        state: absent
        name: testhost
        ipaddress: "{{ freeips }}"
        macaddress: "de:ad:be:ef:16:10"
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Get all info for this IP address
      debug:
        var: freeipinfo
      vars:
        freeipinfo: "{{ query('mm_ipinfo', provider, freeips[0]) | to_nice_json }}"

    - name: Remove DNS record for the claimed IP
      mm_dnsrecord:
        state: absent
        dnszone: testzone
        name: testhost
        data: "{{ freeips[0] }}"
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Remove the PTR DNS record for the claimed IP
      mm_dnsrecord:
        state: absent
        dnszone: "{{ (freeips[0] | ipaddr('revdns')).split('.')[1:]  | join('.') }}"
        name: "{{ freeips[0] | ipaddr('revdns') }}"
        data: "testhost.testzone."
        rrtype: PTR
        provider: "{{ provider }}"
      delegate_to: localhost

    - name: Get all info for this IP address
      debug:
        var: freeipinfo
      vars:
        freeipinfo: "{{ query('mm_ipinfo', provider, freeips[0]) | to_nice_json }}"

    - name: Ensure the zone absent
      mm_zone:
        state: absent
        name: thetestzone.com
        nameserver: mandm.example.com
        authority: mandm.example.net
        masters: mandm.example.net
        servtype: master
        provider: "{{ provider }}"
      delegate_to: localhost