SlideShare une entreprise Scribd logo
1  sur  55
Télécharger pour lire hors ligne
Writing Ansible Modules
Martin Schütte
Outline
Concepts
Writing Python Modules
Simple Example
Patterns
Module Execution – In-Depth
Low Level Module Execution
AnsiballZ
Debugging
Beyond Python
Conclusion
Martin Schütte | Ansible Modules | CLT’19 2/50
Concepts
Assumptions
You …
• configure servers or other IT systems
• have already used (or tried) Ansible
• can write shell or Python scripts
• have some “special” device or API
or a CLI that does not fit into a simple command
This talk …
• is no Ansible introduction
• has too many slides, I will skip some
Martin Schütte | Ansible Modules | CLT’19 3/50
Ansible – Concepts and Naming
Ansible is a radically simple IT automation platform.
• controller
• target host
• playbook
• role
• task
• module
Martin Schütte | Ansible Modules | CLT’19 4/50
Example: Simple Playbook
---
- hosts: webserver
vars:
apache_version: latest
tasks:
- name: ensure apache is at given version
yum:
name: httpd
state: ”{{ apache_version }}”
- hosts: dbserver
roles:
- ansible-role-postgresql
Martin Schütte | Ansible Modules | CLT’19 5/50
What is a Module?
some code snippet to run on the (remote) host
executable with input and output
Martin Schütte | Ansible Modules | CLT’19 6/50
Minimal Module
#!/bin/sh
echo ’{”foo”: ”bar”}’
exit 0
#!/usr/bin/python
if __name__ == ’__main__’:
print(’{”foo”: ”bar”}’)
exit(0)
Martin Schütte | Ansible Modules | CLT’19 7/50
File Locations: library and module_utils
my_role/
meta
defaults
tasks
library
my_module.py
module_utils
util.py
• role can use Ansible module my_module
• import * from util
finds Python module in module_utils
• for “larger” libraries use packages (pip/rpm/dpkg)
Martin Schütte | Ansible Modules | CLT’19 8/50
Action Plugins call Modules
• plugins run on the controller
• may prepare input for modules
• may handle “special” connections (non SSH or WinRM)
• may implement actions on the controller, e. g. debug
• defaults to normal to run module on target host
Martin Schütte | Ansible Modules | CLT’19 9/50
Writing Python Modules
Avoid Writing Own Code
• get_url – Downloads files
• uri – Interacts with webservices
• wait_for – Waits for a condition before continuing
• set_fact – Set host facts from a task
- name: Wait for port 8000 to become open on the host
wait_for:
port: 8000
delay: 10
- name: wait for service to become available
uri:
url: ’https://{{ inventory_hostname }}:{{ svc_port }}/service’
return_content: yes
register: content
until: content.status == 200
retries: 60
delay: 10
when: not ansible_check_mode
Martin Schütte | Ansible Modules | CLT’19 10/50
Documentation
ANSIBLE_METADATA = {’metadata_version’: ’1.1’,
’status’: [’stableinterface’],
’supported_by’: ’core’}
DOCUMENTATION = ’’’
---
module: ping
version_added: historical
short_description: Try to connect to host, verify a usable
python and return C(pong) on success
...
’’’
EXAMPLES = ’’’
# Induce an exception to see what happens
- ping:
data: crash
’’’
RETURN = ’’’
ping:
description: value provided with the data parameter
returned: success
type: string
sample: pong
’’’
Martin Schütte | Ansible Modules | CLT’19 11/50
ansible-doc
[mschuett@work:/home/mschuett] $ ansible-doc --snippet ping
- name: Try to connect to host, verify a usable python and return ‘pong’ on success
ping:
data: # Data to return for the ‘ping’ return value. If this
parameter is set to ‘crash’, the module will cause an
exception.
[mschuett@work:/home/mschuett] $ ansible-doc ping
> PING (.../site-packages/ansible/modules/system/ping.py)
A trivial test module, this module always returns ‘pong’ on
successful contact. It does not make sense in playbooks, but
it is useful from ‘/usr/bin/ansible’ to verify the ability to
login and that a usable Python is configured. This is NOT ICMP
ping, this is just a trivial test module that requires Python
on the remote-node. For Windows targets, use the [win_ping]
module instead. For Network targets, use the [net_ping] module
instead.
OPTIONS (= is mandatory):
- data
Data to return for the ‘ping’ return value.
...
Martin Schütte | Ansible Modules | CLT’19 12/50
ping.py
from ansible.module_utils.basic import AnsibleModule
def main():
module = AnsibleModule(
argument_spec=dict(
data=dict(type=’str’, default=’pong’),
),
supports_check_mode=True
)
if module.params[’data’] == ’crash’:
raise Exception(”boom”)
result = dict(
ping=module.params[’data’],
)
module.exit_json(**result)
if __name__ == ’__main__’:
main()
Martin Schütte | Ansible Modules | CLT’19 13/50
AnsibleModule
useful common methods:
• argument_spec for parameters
• supports_check_mode
• exit_json(), fail_json()
• atomic_move(), run_command()
• bytes_to_human(), human_to_bytes()
Other module_utils:
• api: function/decorator @rate_limit()
• timeout: function/decorator @timeout(secs)
• _text: new and unstable to_text()
Martin Schütte | Ansible Modules | CLT’19 14/50
Pattern: Idempotency
• Playbooks can run many times
• As few changes as possible
• Only perform required actions
1. Get spec parameters
2. Check actual state of system
if =: done, do nothing
if ̸=: action to change state
Martin Schütte | Ansible Modules | CLT’19 15/50
Pattern: Check Dependencies
try:
import psycopg2
import psycopg2.extras
except ImportError:
HAS_PSYCOPG2 = False
else:
HAS_PSYCOPG2 = True
def main():
module = AnsibleModule()
# ...
if not HAS_PSYCOPG2:
module.fail_json(
msg=”the python psycopg2 module is required”)
Martin Schütte | Ansible Modules | CLT’19 16/50
Check Mode/“Dry Run”
• Return information but never apply changes
• Optional but recommended for modules
• Interface provided by AnsibleModule
Example without support:
m = AnsibleModule(
argument_spec=...,
supports_check_mode=False
)
$ ansible-playbook -v --check playbook.yml
...
TASK [role-pymod : role_pymod | get_release_py] **************
skipping: [server] => {”changed”: false, ”msg”: ”remote module
(get_release_py) does not support check mode”}
Martin Schütte | Ansible Modules | CLT’19 17/50
Check Mode/“Dry Run”
def update_permanent_hostname(self):
name = self.module.params[’name’]
permanent_name = self.get_permanent_hostname()
if permanent_name != name:
if not self.module.check_mode:
self.set_permanent_hostname(name)
self.changed = True
Important: Modules without AnsibleModule (or non-Python)
have to handle this on their own!
⇒ test the _ansible_check_mode parameter
Martin Schütte | Ansible Modules | CLT’19 18/50
Common Return Values/Result Attributes
Common
• changed
• failed
• rc
• msg
• results
• invocation
• skipped
• stderr, stderr_lines
• stdout, stdout_lines
• backup_file
Internal use
• ansible_facts
• exception
• warnings
• deprecations
Martin Schütte | Ansible Modules | CLT’19 19/50
Other Common Return Value: Diff
Example from hostname:
if changed:
kw[’diff’] = {’after’: ’hostname = ’ + name + ’n’,
’before’: ’hostname = ’ + name_before + ’n’}
Example output, sample module:
TASK [role-minimal : role_minimal | py_sample_08] ************
task path: /vagrant/roles/role-minimal/tasks/main.yml:23
--- before
+++ after
@@ -1,3 +1,3 @@
common line
-old value
+new vale
common line
changed: [server] => {”changed”: ”true”, ”foo”: ”bar”}
Martin Schütte | Ansible Modules | CLT’19 20/50
Example: Set Facts
In a playbook:
- do_something:
# ...
register: result_var
- set_fact:
foo: ”{{ result_var.results | list }}”
In a module (from hostname):
kw = dict(changed=changed, name=name,
ansible_facts=dict(ansible_hostname=name.split(’.’)[0],
ansible_nodename=name,
ansible_fqdn=socket.getfqdn(),
ansible_domain=’.’.join(
socket.getfqdn().split(’.’)[1:])))
module.exit_json(**kw)
Martin Schütte | Ansible Modules | CLT’19 21/50
Example: String Formatting
When Jinja2 is not enough for variables and formatting …
Random example:
- name: calculate cluster config lines
calc_some_cluster_config:
hostname: ”{{ ansible_fqdn }}”
port: ”{{ application_port }}”
group: ”{{ groups[’appserver’] }}”
register: cluster_config
- name: cluster config
lineinfile:
path: ”{{ basedir }}/cluster/config”
line: ”{{ item }}”
with_items:
- ”hosts={{ cluster_config.tcp_hostlist | join(’,’) }}”
- ”exclude={{ cluster_config.exclude_roles | join(’,’) }}”
notify: appserver restart
Martin Schütte | Ansible Modules | CLT’19 22/50
Pattern: Provider Dict
- name: apply IOS config
ios_config:
provider: ”{{ ios_creds }}”
src: my_config2b.txt
- name: Import Zabbix json template configuration
local_action:
module: zabbix_template
server_url: http://127.0.0.1
login_user: username
login_password: password
template_name: Apache2
template_json: ”{{ lookup(’file’, ’apache2.json’) }}”
template_groups:
- Webservers
Martin Schütte | Ansible Modules | CLT’19 23/50
Common Module Pattern
class Controller(object):
def __init__(module)
def do_something()
def main():
module = AnsibleModule(...)
ctl = Controller(module)
result = ctl.do_something()
module.exit_json(**result)
if __name__ == ’__main__’:
main()
• simple access to input parameters
• access to util functions (e. g. module.run_command())
• difficult to unit test
Martin Schütte | Ansible Modules | CLT’19 24/50
Common Module Pattern II
class Controller(object):
def __init__(many_variables, ...)
def do_something()
def main():
module = AnsibleModule(...)
ctl = Controller(many_variables, ...)
result = ctl.do_something()
module.exit_json(**result)
if __name__ == ’__main__’:
main()
• good isolation
• re-use and testability
• often more complex
Martin Schütte | Ansible Modules | CLT’19 25/50
Module Execution – In-Depth
Minimal Module – Verbose Output
TASK [role-minimal : role_minimal | bash_sample_01] ****************************
task path: /vagrant/roles/role-minimal/tasks/main.yml:5
<192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant
<192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC
<192.168.56.202> (0, ’/home/vagrantn’, ’’)
<192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant
<192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC
<192.168.56.202> (0, ’ansible-tmp-1548772995.78-225807547469627=/home/vagrant/.ansible/tmp/ansi
Using module file /vagrant/roles/role-minimal/library/bash_sample_01
<192.168.56.202> PUT /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpnrj9rd TO /home/va
<192.168.56.202> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHo
<192.168.56.202> (0, ’sftp> put /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpnrj9rd
<192.168.56.202> PUT /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpgN3ZKr TO /home/va
<192.168.56.202> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHo
<192.168.56.202> (0, ’sftp> put /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpgN3ZKr
<192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant
<192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC
<192.168.56.202> (0, ’’, ’’)
<192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant
<192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC
Escalation succeeded
<192.168.56.202> (0, ’{”foo”:”bar”}rn’, ’Shared connection to 192.168.56.202 closed.rn’)
ok: [server] => {
”changed”: false,
”foo”: ”bar”
}
TASK [role-minimal : role_minimal | bash_sample_01] ****************************
task path: /vagrant/roles/role-minimal/tasks/main.yml:5
Martin Schütte | Ansible Modules | CLT’19 26/50
Argument File Format
Old-style default: key=value
[vagrant@server ~]$ cat $TMPDIR/args
_ansible_version=2.7.5
_ansible_selinux_special_fs=’[’”’”’fuse’”’”’,
’”’”’nfs’”’”’, ’”’”’vboxsf’”’”’, ’”’”’ramfs’”’”’,
’”’”’9p’”’”’]’ _ansible_no_log=False
_ansible_module_name=py_sample_01
_ansible_tmpdir=/home/vagrant/.ansible/tmp/ansible-tmp-
1548756932.8-240778677026680/ _ansible_verbosity=3
_ansible_keep_remote_files=True
_ansible_syslog_facility=LOG_USER _ansible_socket=None
_ansible_remote_tmp=’~/.ansible/tmp’ _ansible_diff=False
_ansible_debug=False _ansible_shell_executable=/bin/sh
_ansible_check_mode=False foo=baz
→
→
→
→
→
→
→
→
→
→
→
Martin Schütte | Ansible Modules | CLT’19 27/50
Want JSON Option
#!/bin/sh
# WANT_JSON
echo ’{”foo”:”bar”}’
exit 0
#!/usr/bin/python
# WANT_JSON
if __name__ == ’__main__’:
print(’{”foo”:”bar”}’)
exit(0)
Martin Schütte | Ansible Modules | CLT’19 28/50
Argument File Format
With WANT_JSON flag:
[vagrant@server ~]$ cat $TMPDIR/args
{”_ansible_version”: ”2.7.5”, ”_ansible_selinux_special_fs”:
[”fuse”, ”nfs”, ”vboxsf”, ”ramfs”, ”9p”],
”_ansible_no_log”: false, ”_ansible_module_name”:
”bash_sample_02”, ”_ansible_tmpdir”:
”/home/vagrant/.ansible/tmp/ansible-tmp-1548756933.19-
248002152304605/”, ”_ansible_verbosity”: 3,
”_ansible_keep_remote_files”: true,
”_ansible_syslog_facility”: ”LOG_USER”, ”_ansible_socket”:
null, ”_ansible_remote_tmp”: ”~/.ansible/tmp”,
”_ansible_diff”: false, ”_ansible_debug”: false,
”_ansible_shell_executable”: ”/bin/sh”,
”_ansible_check_mode”: false, ”foo”: ”baz”}
→
→
→
→
→
→
→
→
→
→
→
Martin Schütte | Ansible Modules | CLT’19 29/50
Remove Argument File: JSONARGS
#!/bin/sh
ARGS=’<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>’
echo ”arguments: $ARGS” | logger --tag $(basename ”$0”)
echo ’{”foo”:”bar”}’
exit 0
#!/usr/bin/python
import syslog
args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>”””
if __name__ == ’__main__’:
syslog.openlog()
syslog.syslog(args)
print(’{”foo”:”bar”}’)
exit(0)
Martin Schütte | Ansible Modules | CLT’19 30/50
JSONARGS – Verbose Output
<192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant
<192.168.56.202> SSH: EXEC ssh $SSH_OPTS -tt 192.168.56.202 +
’/bin/sh -c ’”’”’/bin/sh $TMPDIR/AnsiballZ_bash_sample_03 +
&& sleep 0’”’”’’
<192.168.56.202> (0, ’{”foo”:”bar”}rn’, +
’Shared connection to 192.168.56.202 closed.rn’)
ok: [server] => {
”changed”: false,
”foo”: ”bar”
}
Martin Schütte | Ansible Modules | CLT’19 31/50
JSONARGS – Argument in Script File
[vagrant@server ~]$ cat $TMPDIR/AnsiballZ_bash_sample_03
#!/bin/sh
ARGS=’{”_ansible_version”: ”2.7.5”,
”_ansible_selinux_special_fs”: [”fuse”, ”nfs”, ”vboxsf”,
”ramfs”, ”9p”], ”_ansible_no_log”: false,
”_ansible_module_name”: ”bash_sample_03”,
”_ansible_tmpdir”: ”/home/vagrant/.ansible/tmp/ansible-tmp-
1548797622.11-222413844288764/”, ”_ansible_verbosity”: 3,
”_ansible_keep_remote_files”: true,
”_ansible_syslog_facility”: ”LOG_USER”, ”_ansible_socket”:
null, ”_ansible_remote_tmp”: ”~/.ansible/tmp”,
”_ansible_diff”: false, ”_ansible_debug”: false,
”_ansible_shell_executable”: ”/bin/sh”,
”_ansible_check_mode”: false, ”foo”: ”baz”}’
→
→
→
→
→
→
→
→
→
→
→
echo ”arguments: $ARGS” | logger --tag $(basename ”$0”)
echo ’{”foo”:”bar”}’
exit 0
Martin Schütte | Ansible Modules | CLT’19 32/50
Import AnsibleModule
#!/usr/bin/python
args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>”””
from ansible.module_utils.basic import AnsibleModule
if __name__ == ’__main__’:
print(’{”foo”:”bar”}’)
exit(0)
Martin Schütte | Ansible Modules | CLT’19 33/50
Import AnsibleModule – Verbose Output
[vagrant@server ~]$ ls -hl $TMPDIR
-rwx------. 1 vagrant vagrant 75K Jan 29 14:53 AnsiballZ_py_sample_04.py
[vagrant@server ~]$ head $TMPDIR/AnsiballZ_py_sample_04.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
_ANSIBALLZ_WRAPPER = True # For test-module script to tell this is a ANSIBALLZ_WRAPPER
# This code is part of Ansible, but is an independent component.
# The code in this particular templatable string, and this templatable string
# only, is BSD licensed. Modules which end up using this snippet, which is
# dynamically combined together by Ansible still belong to the author of the
# module, and they may assign their own license to the complete work.
#
# Copyright (c), James Cammarata, 2016
[vagrant@server ~]$
Martin Schütte | Ansible Modules | CLT’19 34/50
AnsiballZ Wrapper
Python template script for
• helper functions (execute, explode)
• zipped data of
• module text
• JSON arguments
• all module_utils imports
Martin Schütte | Ansible Modules | CLT’19 35/50
Debugging Tools and Tips
Dev environment:
• Vagrant
• keep_remote_files = True
• ansible -vvv
• AnsiballZ code expand
• “print to output”
• AnsibleModule.log()
• q
Martin Schütte | Ansible Modules | CLT’19 36/50
Debugging – AnsiballZ Explode
[vagrant@server ~]$ ls -hl $TMPDIR
-rwx------. 1 vagrant vagrant 75K Jan 29 14:53 AnsiballZ_py_sample_04.py
[vagrant@server ~]$ $TMPDIR/AnsiballZ_py_sample_04.py explode
Module expanded into:
$TMPDIR/debug_dir
[vagrant@server ~]$ cd $TMPDIR/debug_dir; find .
.
./ansible
./ansible/__init__.py
./ansible/module_utils
./ansible/module_utils/__init__.py
./ansible/module_utils/basic.py
./ansible/module_utils/parsing
./ansible/module_utils/parsing/convert_bool.py
./ansible/module_utils/parsing/__init__.py
./ansible/module_utils/common
./ansible/module_utils/common/_collections_compat.py
./ansible/module_utils/common/process.py
./ansible/module_utils/common/__init__.py
./ansible/module_utils/common/file.py
./ansible/module_utils/six
./ansible/module_utils/six/__init__.py
./ansible/module_utils/_text.py
./ansible/module_utils/pycompat24.py
./__main__.py
./args
Martin Schütte | Ansible Modules | CLT’19 37/50
Debugging – AnsiballZ Explode
[vagrant@server debug_dir]$ cat __main__.py
#!/usr/bin/python
args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>”””
from ansible.module_utils.basic import AnsibleModule
if __name__ == ’__main__’:
print(’{”foo”:”bar”}’)
exit(0)
[vagrant@server debug_dir]$ $TMPDIR/AnsiballZ_py_sample_04.py execute
{”foo”:”bar”}
Martin Schütte | Ansible Modules | CLT’19 38/50
Debugging – printf
• Ansible reads stdin and stdout, expects JSON
⇒ cannot use print() to debug
• Use output values instead
# ...
debug_msg = ”some_func({}) returned {}”.format(bar, foo)
# ...
module.exit_json(result=foo, debug_msg=debug_msg)
ok: [server] => {
”changed”: false,
”debug_msg”: ”some_func(bar) returned foo”,
...
}
Martin Schütte | Ansible Modules | CLT’19 39/50
Debugging – AnsibleModule log()
• AnsibleModule includes method log()
with variants debug() and warn()
• Writes to journald or Syslog
module.log(”Hello World”)
# tail /var/log/messages
Feb 9 15:02:59 server ansible-my_module: Invoked with param=...
Feb 9 15:02:59 server ansible-my_module: Hello World
Martin Schütte | Ansible Modules | CLT’19 40/50
Debugging – q
• PyPI q or zestyping/q 
• Always writes to /tmp/q
• function decorators
try:
import q
except ImportError:
def q(x):
return x
@q
def my_func(params):
q(special_var)
# ...
$ tail /tmp/q
0.0s my_func(’VERSION’)
0.0s my_func: ’special_value’
0.0s -> {’failed’: False, ’msg’: ’...’}
Martin Schütte | Ansible Modules | CLT’19 41/50
Beyond Python
Ansible Modules in Other Languages
• Python: the default choice, best tools and support
• PowerShell: officially supported, but not covered here
• Scripting Languages: can use JSON_ARGS
• Binary Executables: can use WANT_JSON
Martin Schütte | Ansible Modules | CLT’19 42/50
Binary Executables, e. g. Go Tools
possible, but not recommended:
• binary in Ansible git repository
• should have own build chain and versions
• architecture dependent (all the world’s a x86_64?)
better:
• separate packaging and deployment (.deb and .rpm)
• thin wrapper module to execute installed file or library
• same for binary Python libraries (e. g. DB connectors)
Martin Schütte | Ansible Modules | CLT’19 43/50
Java
• “executable” JAR file
• not architecture dependent
• otherwise the same as binaries
Martin Schütte | Ansible Modules | CLT’19 44/50
Groovy
• JVM scripting language
• compromise between Ansible scripts and Java apps
• maybe best way to access/use Java libraries with Ansible
• may need workarounds to use custom classpath
Martin Schütte | Ansible Modules | CLT’19 45/50
Groovy – Small Example
#!/usr/bin/env groovy
import groovy.json.*
def jsonArgs=’’’<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>’’’
def args_object = new JsonSlurper().parseText(jsonArgs)
def checkMode = (boolean) args_object[’_ansible_check_mode’]
// do something useful
def result = [
foo: ’bar’,
code: 42,
did_check_mode: checkMode
]
print JsonOutput.toJson(result)
Martin Schütte | Ansible Modules | CLT’19 46/50
Scripting Languages
• Perl, Ruby, etc.
• need JSON library
• works
• question: why?
Martin Schütte | Ansible Modules | CLT’19 47/50
Conclusion
Useful Software Design Principles
Not only for Ansible modules …
• KISS
• YAGNI
• readability!
Martin Schütte | Ansible Modules | CLT’19 48/50
Links
• Ansible Docs on Modules:
Conventions, tips, and pitfalls
• ansible/ansible 
• Ansible: Up & Running, 2nd ed
by Lorin Hochstein & René Moser
Martin Schütte | Ansible Modules | CLT’19 49/50
The End
Thank You! — Questions?
Martin Schütte
@m_schuett 
info@martin-schuette.de 
slideshare.net/mschuett/ 
noti.st/mschuett/
Martin Schütte | Ansible Modules | CLT’19 50/50

Contenu connexe

Tendances

Terraform Modules and Continuous Deployment
Terraform Modules and Continuous DeploymentTerraform Modules and Continuous Deployment
Terraform Modules and Continuous DeploymentZane Williamson
 
Terraform introduction
Terraform introductionTerraform introduction
Terraform introductionJason Vance
 
Declarative & workflow based infrastructure with Terraform
Declarative & workflow based infrastructure with TerraformDeclarative & workflow based infrastructure with Terraform
Declarative & workflow based infrastructure with TerraformRadek Simko
 
Comprehensive Terraform Training
Comprehensive Terraform TrainingComprehensive Terraform Training
Comprehensive Terraform TrainingYevgeniy Brikman
 
Terraform at Scale - All Day DevOps 2017
Terraform at Scale - All Day DevOps 2017Terraform at Scale - All Day DevOps 2017
Terraform at Scale - All Day DevOps 2017Jonathon Brouse
 
Terraforming the Kubernetes Land
Terraforming the Kubernetes LandTerraforming the Kubernetes Land
Terraforming the Kubernetes LandRadek Simko
 
Effizientere WordPress-Plugin-Entwicklung mit Softwaretests
Effizientere WordPress-Plugin-Entwicklung mit SoftwaretestsEffizientere WordPress-Plugin-Entwicklung mit Softwaretests
Effizientere WordPress-Plugin-Entwicklung mit SoftwaretestsDECK36
 
Infrastructure as Code in Google Cloud
Infrastructure as Code in Google CloudInfrastructure as Code in Google Cloud
Infrastructure as Code in Google CloudRadek Simko
 
Case Study: Using Terraform and Packer to deploy go applications to AWS
Case Study: Using Terraform and Packer to deploy go applications to AWSCase Study: Using Terraform and Packer to deploy go applications to AWS
Case Study: Using Terraform and Packer to deploy go applications to AWSPatrick Bolduan
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015Fernando Hamasaki de Amorim
 
Puppet Node Classifiers Talk - Patrick Buckley
Puppet Node Classifiers Talk - Patrick BuckleyPuppet Node Classifiers Talk - Patrick Buckley
Puppet Node Classifiers Talk - Patrick BuckleyChristian Mague
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service ManagerChris Tankersley
 
Terraform modules and some of best-practices - March 2019
Terraform modules and some of best-practices - March 2019Terraform modules and some of best-practices - March 2019
Terraform modules and some of best-practices - March 2019Anton Babenko
 
Ansible fest Presentation slides
Ansible fest Presentation slidesAnsible fest Presentation slides
Ansible fest Presentation slidesAaron Carey
 
Agiles Peru 2019 - Infrastructure As Code
Agiles Peru 2019 - Infrastructure As CodeAgiles Peru 2019 - Infrastructure As Code
Agiles Peru 2019 - Infrastructure As CodeMario IC
 
Scaling terraform
Scaling terraformScaling terraform
Scaling terraformPaolo Tonin
 

Tendances (20)

Intro to Terraform
Intro to TerraformIntro to Terraform
Intro to Terraform
 
Terraform Modules and Continuous Deployment
Terraform Modules and Continuous DeploymentTerraform Modules and Continuous Deployment
Terraform Modules and Continuous Deployment
 
Terraform introduction
Terraform introductionTerraform introduction
Terraform introduction
 
Declarative & workflow based infrastructure with Terraform
Declarative & workflow based infrastructure with TerraformDeclarative & workflow based infrastructure with Terraform
Declarative & workflow based infrastructure with Terraform
 
Comprehensive Terraform Training
Comprehensive Terraform TrainingComprehensive Terraform Training
Comprehensive Terraform Training
 
Terraform at Scale
Terraform at ScaleTerraform at Scale
Terraform at Scale
 
Terraform at Scale - All Day DevOps 2017
Terraform at Scale - All Day DevOps 2017Terraform at Scale - All Day DevOps 2017
Terraform at Scale - All Day DevOps 2017
 
Terraforming the Kubernetes Land
Terraforming the Kubernetes LandTerraforming the Kubernetes Land
Terraforming the Kubernetes Land
 
Effizientere WordPress-Plugin-Entwicklung mit Softwaretests
Effizientere WordPress-Plugin-Entwicklung mit SoftwaretestsEffizientere WordPress-Plugin-Entwicklung mit Softwaretests
Effizientere WordPress-Plugin-Entwicklung mit Softwaretests
 
Infrastructure as Code in Google Cloud
Infrastructure as Code in Google CloudInfrastructure as Code in Google Cloud
Infrastructure as Code in Google Cloud
 
Case Study: Using Terraform and Packer to deploy go applications to AWS
Case Study: Using Terraform and Packer to deploy go applications to AWSCase Study: Using Terraform and Packer to deploy go applications to AWS
Case Study: Using Terraform and Packer to deploy go applications to AWS
 
Final terraform
Final terraformFinal terraform
Final terraform
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
 
Puppet Node Classifiers Talk - Patrick Buckley
Puppet Node Classifiers Talk - Patrick BuckleyPuppet Node Classifiers Talk - Patrick Buckley
Puppet Node Classifiers Talk - Patrick Buckley
 
Into the ZF2 Service Manager
Into the ZF2 Service ManagerInto the ZF2 Service Manager
Into the ZF2 Service Manager
 
Terraform modules and some of best-practices - March 2019
Terraform modules and some of best-practices - March 2019Terraform modules and some of best-practices - March 2019
Terraform modules and some of best-practices - March 2019
 
Ansible fest Presentation slides
Ansible fest Presentation slidesAnsible fest Presentation slides
Ansible fest Presentation slides
 
Agiles Peru 2019 - Infrastructure As Code
Agiles Peru 2019 - Infrastructure As CodeAgiles Peru 2019 - Infrastructure As Code
Agiles Peru 2019 - Infrastructure As Code
 
Scaling terraform
Scaling terraformScaling terraform
Scaling terraform
 
DevOps with Fabric
DevOps with FabricDevOps with Fabric
DevOps with Fabric
 

Similaire à Writing Ansible Modules (CLT'19)

TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07garrett honeycutt
 
Automation with Ansible and Containers
Automation with Ansible and ContainersAutomation with Ansible and Containers
Automation with Ansible and ContainersRodolfo Carvalho
 
Mock cli with Python unittest
Mock cli with Python unittestMock cli with Python unittest
Mock cli with Python unittestSong Jin
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshuSidd Singh
 
Portland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPortland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPuppet
 
June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules Puppet
 
Deploying systemd at scale
Deploying systemd at scaleDeploying systemd at scale
Deploying systemd at scaleDavide Cavalca
 
External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLAntony T Curtis
 
Zabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensZabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensNETWAYS
 
Troubleshooting the Puppet Enterprise Stack
Troubleshooting the Puppet Enterprise StackTroubleshooting the Puppet Enterprise Stack
Troubleshooting the Puppet Enterprise StackPuppet
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2PVS-Studio
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The LandingHaci Murat Yaman
 
Preparse Query Rewrite Plugins
Preparse Query Rewrite PluginsPreparse Query Rewrite Plugins
Preparse Query Rewrite PluginsSveta Smirnova
 
PowerShell Fundamentals
PowerShell FundamentalsPowerShell Fundamentals
PowerShell Fundamentalsmozdzen
 
Symfony2 Introduction Presentation
Symfony2 Introduction PresentationSymfony2 Introduction Presentation
Symfony2 Introduction PresentationNerd Tzanetopoulos
 
Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016Yuta Iwama
 
C# 7 development
C# 7 developmentC# 7 development
C# 7 developmentFisnik Doko
 

Similaire à Writing Ansible Modules (CLT'19) (20)

TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
 
Automation with Ansible and Containers
Automation with Ansible and ContainersAutomation with Ansible and Containers
Automation with Ansible and Containers
 
Mock cli with Python unittest
Mock cli with Python unittestMock cli with Python unittest
Mock cli with Python unittest
 
friends functionToshu
friends functionToshufriends functionToshu
friends functionToshu
 
Scala to assembly
Scala to assemblyScala to assembly
Scala to assembly
 
Portland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modulesPortland Puppet User Group June 2014: Writing and publishing puppet modules
Portland Puppet User Group June 2014: Writing and publishing puppet modules
 
June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules June 2014 PDX PUG: Writing and Publishing Puppet Modules
June 2014 PDX PUG: Writing and Publishing Puppet Modules
 
C++ Functions.ppt
C++ Functions.pptC++ Functions.ppt
C++ Functions.ppt
 
Deploying systemd at scale
Deploying systemd at scaleDeploying systemd at scale
Deploying systemd at scale
 
External Language Stored Procedures for MySQL
External Language Stored Procedures for MySQLExternal Language Stored Procedures for MySQL
External Language Stored Procedures for MySQL
 
Zabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet MensZabbix LLD from a C Module by Jan-Piet Mens
Zabbix LLD from a C Module by Jan-Piet Mens
 
Operator overload rr
Operator overload  rrOperator overload  rr
Operator overload rr
 
Troubleshooting the Puppet Enterprise Stack
Troubleshooting the Puppet Enterprise StackTroubleshooting the Puppet Enterprise Stack
Troubleshooting the Puppet Enterprise Stack
 
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
Analysis of Haiku Operating System (BeOS Family) by PVS-Studio. Part 2
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 
Preparse Query Rewrite Plugins
Preparse Query Rewrite PluginsPreparse Query Rewrite Plugins
Preparse Query Rewrite Plugins
 
PowerShell Fundamentals
PowerShell FundamentalsPowerShell Fundamentals
PowerShell Fundamentals
 
Symfony2 Introduction Presentation
Symfony2 Introduction PresentationSymfony2 Introduction Presentation
Symfony2 Introduction Presentation
 
Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016Treasure Data Summer Internship 2016
Treasure Data Summer Internship 2016
 
C# 7 development
C# 7 developmentC# 7 development
C# 7 development
 

Plus de Martin Schütte

Terraform: Cloud Configuration Management (WTC/IPC'16)
Terraform: Cloud Configuration Management (WTC/IPC'16)Terraform: Cloud Configuration Management (WTC/IPC'16)
Terraform: Cloud Configuration Management (WTC/IPC'16)Martin Schütte
 
Terraform: Configuration Management for Cloud Services
Terraform: Configuration Management for Cloud ServicesTerraform: Configuration Management for Cloud Services
Terraform: Configuration Management for Cloud ServicesMartin Schütte
 
The IPv6 Snort Plugin (at DeepSec 2014)
The IPv6 Snort Plugin (at DeepSec 2014)The IPv6 Snort Plugin (at DeepSec 2014)
The IPv6 Snort Plugin (at DeepSec 2014)Martin Schütte
 
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)Martin Schütte
 
Short Introduction to IPv6
Short Introduction to IPv6Short Introduction to IPv6
Short Introduction to IPv6Martin Schütte
 
Software Testing on the Web
Software Testing on the WebSoftware Testing on the Web
Software Testing on the WebMartin Schütte
 
NetBSD syslogd with IETF Syslog Protocols
NetBSD syslogd with IETF Syslog ProtocolsNetBSD syslogd with IETF Syslog Protocols
NetBSD syslogd with IETF Syslog ProtocolsMartin Schütte
 
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...Martin Schütte
 

Plus de Martin Schütte (10)

Terraform: Cloud Configuration Management (WTC/IPC'16)
Terraform: Cloud Configuration Management (WTC/IPC'16)Terraform: Cloud Configuration Management (WTC/IPC'16)
Terraform: Cloud Configuration Management (WTC/IPC'16)
 
Terraform: Configuration Management for Cloud Services
Terraform: Configuration Management for Cloud ServicesTerraform: Configuration Management for Cloud Services
Terraform: Configuration Management for Cloud Services
 
The IPv6 Snort Plugin (at DeepSec 2014)
The IPv6 Snort Plugin (at DeepSec 2014)The IPv6 Snort Plugin (at DeepSec 2014)
The IPv6 Snort Plugin (at DeepSec 2014)
 
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)
The IPv6 Snort Plugin (at Troopers 14 IPv6 Security Summit)
 
Short Introduction to IPv6
Short Introduction to IPv6Short Introduction to IPv6
Short Introduction to IPv6
 
Software Testing on the Web
Software Testing on the WebSoftware Testing on the Web
Software Testing on the Web
 
NetBSD syslogd with IETF Syslog Protocols
NetBSD syslogd with IETF Syslog ProtocolsNetBSD syslogd with IETF Syslog Protocols
NetBSD syslogd with IETF Syslog Protocols
 
PGP/GPG Einführung
PGP/GPG EinführungPGP/GPG Einführung
PGP/GPG Einführung
 
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...
Design and Implementation of an IPv6 Plugin for the Snort Intrusion Detection...
 
Syslog Protocols
Syslog ProtocolsSyslog Protocols
Syslog Protocols
 

Dernier

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 

Dernier (20)

Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 

Writing Ansible Modules (CLT'19)

  • 2. Outline Concepts Writing Python Modules Simple Example Patterns Module Execution – In-Depth Low Level Module Execution AnsiballZ Debugging Beyond Python Conclusion Martin Schütte | Ansible Modules | CLT’19 2/50
  • 4. Assumptions You … • configure servers or other IT systems • have already used (or tried) Ansible • can write shell or Python scripts • have some “special” device or API or a CLI that does not fit into a simple command This talk … • is no Ansible introduction • has too many slides, I will skip some Martin Schütte | Ansible Modules | CLT’19 3/50
  • 5. Ansible – Concepts and Naming Ansible is a radically simple IT automation platform. • controller • target host • playbook • role • task • module Martin Schütte | Ansible Modules | CLT’19 4/50
  • 6. Example: Simple Playbook --- - hosts: webserver vars: apache_version: latest tasks: - name: ensure apache is at given version yum: name: httpd state: ”{{ apache_version }}” - hosts: dbserver roles: - ansible-role-postgresql Martin Schütte | Ansible Modules | CLT’19 5/50
  • 7. What is a Module? some code snippet to run on the (remote) host executable with input and output Martin Schütte | Ansible Modules | CLT’19 6/50
  • 8. Minimal Module #!/bin/sh echo ’{”foo”: ”bar”}’ exit 0 #!/usr/bin/python if __name__ == ’__main__’: print(’{”foo”: ”bar”}’) exit(0) Martin Schütte | Ansible Modules | CLT’19 7/50
  • 9. File Locations: library and module_utils my_role/ meta defaults tasks library my_module.py module_utils util.py • role can use Ansible module my_module • import * from util finds Python module in module_utils • for “larger” libraries use packages (pip/rpm/dpkg) Martin Schütte | Ansible Modules | CLT’19 8/50
  • 10. Action Plugins call Modules • plugins run on the controller • may prepare input for modules • may handle “special” connections (non SSH or WinRM) • may implement actions on the controller, e. g. debug • defaults to normal to run module on target host Martin Schütte | Ansible Modules | CLT’19 9/50
  • 12. Avoid Writing Own Code • get_url – Downloads files • uri – Interacts with webservices • wait_for – Waits for a condition before continuing • set_fact – Set host facts from a task - name: Wait for port 8000 to become open on the host wait_for: port: 8000 delay: 10 - name: wait for service to become available uri: url: ’https://{{ inventory_hostname }}:{{ svc_port }}/service’ return_content: yes register: content until: content.status == 200 retries: 60 delay: 10 when: not ansible_check_mode Martin Schütte | Ansible Modules | CLT’19 10/50
  • 13. Documentation ANSIBLE_METADATA = {’metadata_version’: ’1.1’, ’status’: [’stableinterface’], ’supported_by’: ’core’} DOCUMENTATION = ’’’ --- module: ping version_added: historical short_description: Try to connect to host, verify a usable python and return C(pong) on success ... ’’’ EXAMPLES = ’’’ # Induce an exception to see what happens - ping: data: crash ’’’ RETURN = ’’’ ping: description: value provided with the data parameter returned: success type: string sample: pong ’’’ Martin Schütte | Ansible Modules | CLT’19 11/50
  • 14. ansible-doc [mschuett@work:/home/mschuett] $ ansible-doc --snippet ping - name: Try to connect to host, verify a usable python and return ‘pong’ on success ping: data: # Data to return for the ‘ping’ return value. If this parameter is set to ‘crash’, the module will cause an exception. [mschuett@work:/home/mschuett] $ ansible-doc ping > PING (.../site-packages/ansible/modules/system/ping.py) A trivial test module, this module always returns ‘pong’ on successful contact. It does not make sense in playbooks, but it is useful from ‘/usr/bin/ansible’ to verify the ability to login and that a usable Python is configured. This is NOT ICMP ping, this is just a trivial test module that requires Python on the remote-node. For Windows targets, use the [win_ping] module instead. For Network targets, use the [net_ping] module instead. OPTIONS (= is mandatory): - data Data to return for the ‘ping’ return value. ... Martin Schütte | Ansible Modules | CLT’19 12/50
  • 15. ping.py from ansible.module_utils.basic import AnsibleModule def main(): module = AnsibleModule( argument_spec=dict( data=dict(type=’str’, default=’pong’), ), supports_check_mode=True ) if module.params[’data’] == ’crash’: raise Exception(”boom”) result = dict( ping=module.params[’data’], ) module.exit_json(**result) if __name__ == ’__main__’: main() Martin Schütte | Ansible Modules | CLT’19 13/50
  • 16. AnsibleModule useful common methods: • argument_spec for parameters • supports_check_mode • exit_json(), fail_json() • atomic_move(), run_command() • bytes_to_human(), human_to_bytes() Other module_utils: • api: function/decorator @rate_limit() • timeout: function/decorator @timeout(secs) • _text: new and unstable to_text() Martin Schütte | Ansible Modules | CLT’19 14/50
  • 17. Pattern: Idempotency • Playbooks can run many times • As few changes as possible • Only perform required actions 1. Get spec parameters 2. Check actual state of system if =: done, do nothing if ̸=: action to change state Martin Schütte | Ansible Modules | CLT’19 15/50
  • 18. Pattern: Check Dependencies try: import psycopg2 import psycopg2.extras except ImportError: HAS_PSYCOPG2 = False else: HAS_PSYCOPG2 = True def main(): module = AnsibleModule() # ... if not HAS_PSYCOPG2: module.fail_json( msg=”the python psycopg2 module is required”) Martin Schütte | Ansible Modules | CLT’19 16/50
  • 19. Check Mode/“Dry Run” • Return information but never apply changes • Optional but recommended for modules • Interface provided by AnsibleModule Example without support: m = AnsibleModule( argument_spec=..., supports_check_mode=False ) $ ansible-playbook -v --check playbook.yml ... TASK [role-pymod : role_pymod | get_release_py] ************** skipping: [server] => {”changed”: false, ”msg”: ”remote module (get_release_py) does not support check mode”} Martin Schütte | Ansible Modules | CLT’19 17/50
  • 20. Check Mode/“Dry Run” def update_permanent_hostname(self): name = self.module.params[’name’] permanent_name = self.get_permanent_hostname() if permanent_name != name: if not self.module.check_mode: self.set_permanent_hostname(name) self.changed = True Important: Modules without AnsibleModule (or non-Python) have to handle this on their own! ⇒ test the _ansible_check_mode parameter Martin Schütte | Ansible Modules | CLT’19 18/50
  • 21. Common Return Values/Result Attributes Common • changed • failed • rc • msg • results • invocation • skipped • stderr, stderr_lines • stdout, stdout_lines • backup_file Internal use • ansible_facts • exception • warnings • deprecations Martin Schütte | Ansible Modules | CLT’19 19/50
  • 22. Other Common Return Value: Diff Example from hostname: if changed: kw[’diff’] = {’after’: ’hostname = ’ + name + ’n’, ’before’: ’hostname = ’ + name_before + ’n’} Example output, sample module: TASK [role-minimal : role_minimal | py_sample_08] ************ task path: /vagrant/roles/role-minimal/tasks/main.yml:23 --- before +++ after @@ -1,3 +1,3 @@ common line -old value +new vale common line changed: [server] => {”changed”: ”true”, ”foo”: ”bar”} Martin Schütte | Ansible Modules | CLT’19 20/50
  • 23. Example: Set Facts In a playbook: - do_something: # ... register: result_var - set_fact: foo: ”{{ result_var.results | list }}” In a module (from hostname): kw = dict(changed=changed, name=name, ansible_facts=dict(ansible_hostname=name.split(’.’)[0], ansible_nodename=name, ansible_fqdn=socket.getfqdn(), ansible_domain=’.’.join( socket.getfqdn().split(’.’)[1:]))) module.exit_json(**kw) Martin Schütte | Ansible Modules | CLT’19 21/50
  • 24. Example: String Formatting When Jinja2 is not enough for variables and formatting … Random example: - name: calculate cluster config lines calc_some_cluster_config: hostname: ”{{ ansible_fqdn }}” port: ”{{ application_port }}” group: ”{{ groups[’appserver’] }}” register: cluster_config - name: cluster config lineinfile: path: ”{{ basedir }}/cluster/config” line: ”{{ item }}” with_items: - ”hosts={{ cluster_config.tcp_hostlist | join(’,’) }}” - ”exclude={{ cluster_config.exclude_roles | join(’,’) }}” notify: appserver restart Martin Schütte | Ansible Modules | CLT’19 22/50
  • 25. Pattern: Provider Dict - name: apply IOS config ios_config: provider: ”{{ ios_creds }}” src: my_config2b.txt - name: Import Zabbix json template configuration local_action: module: zabbix_template server_url: http://127.0.0.1 login_user: username login_password: password template_name: Apache2 template_json: ”{{ lookup(’file’, ’apache2.json’) }}” template_groups: - Webservers Martin Schütte | Ansible Modules | CLT’19 23/50
  • 26. Common Module Pattern class Controller(object): def __init__(module) def do_something() def main(): module = AnsibleModule(...) ctl = Controller(module) result = ctl.do_something() module.exit_json(**result) if __name__ == ’__main__’: main() • simple access to input parameters • access to util functions (e. g. module.run_command()) • difficult to unit test Martin Schütte | Ansible Modules | CLT’19 24/50
  • 27. Common Module Pattern II class Controller(object): def __init__(many_variables, ...) def do_something() def main(): module = AnsibleModule(...) ctl = Controller(many_variables, ...) result = ctl.do_something() module.exit_json(**result) if __name__ == ’__main__’: main() • good isolation • re-use and testability • often more complex Martin Schütte | Ansible Modules | CLT’19 25/50
  • 29. Minimal Module – Verbose Output TASK [role-minimal : role_minimal | bash_sample_01] **************************** task path: /vagrant/roles/role-minimal/tasks/main.yml:5 <192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant <192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC <192.168.56.202> (0, ’/home/vagrantn’, ’’) <192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant <192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC <192.168.56.202> (0, ’ansible-tmp-1548772995.78-225807547469627=/home/vagrant/.ansible/tmp/ansi Using module file /vagrant/roles/role-minimal/library/bash_sample_01 <192.168.56.202> PUT /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpnrj9rd TO /home/va <192.168.56.202> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHo <192.168.56.202> (0, ’sftp> put /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpnrj9rd <192.168.56.202> PUT /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpgN3ZKr TO /home/va <192.168.56.202> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHo <192.168.56.202> (0, ’sftp> put /home/vagrant/.ansible/tmp/ansible-local-32044a_dXdg/tmpgN3ZKr <192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant <192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC <192.168.56.202> (0, ’’, ’’) <192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant <192.168.56.202> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyC Escalation succeeded <192.168.56.202> (0, ’{”foo”:”bar”}rn’, ’Shared connection to 192.168.56.202 closed.rn’) ok: [server] => { ”changed”: false, ”foo”: ”bar” } TASK [role-minimal : role_minimal | bash_sample_01] **************************** task path: /vagrant/roles/role-minimal/tasks/main.yml:5 Martin Schütte | Ansible Modules | CLT’19 26/50
  • 30. Argument File Format Old-style default: key=value [vagrant@server ~]$ cat $TMPDIR/args _ansible_version=2.7.5 _ansible_selinux_special_fs=’[’”’”’fuse’”’”’, ’”’”’nfs’”’”’, ’”’”’vboxsf’”’”’, ’”’”’ramfs’”’”’, ’”’”’9p’”’”’]’ _ansible_no_log=False _ansible_module_name=py_sample_01 _ansible_tmpdir=/home/vagrant/.ansible/tmp/ansible-tmp- 1548756932.8-240778677026680/ _ansible_verbosity=3 _ansible_keep_remote_files=True _ansible_syslog_facility=LOG_USER _ansible_socket=None _ansible_remote_tmp=’~/.ansible/tmp’ _ansible_diff=False _ansible_debug=False _ansible_shell_executable=/bin/sh _ansible_check_mode=False foo=baz → → → → → → → → → → → Martin Schütte | Ansible Modules | CLT’19 27/50
  • 31. Want JSON Option #!/bin/sh # WANT_JSON echo ’{”foo”:”bar”}’ exit 0 #!/usr/bin/python # WANT_JSON if __name__ == ’__main__’: print(’{”foo”:”bar”}’) exit(0) Martin Schütte | Ansible Modules | CLT’19 28/50
  • 32. Argument File Format With WANT_JSON flag: [vagrant@server ~]$ cat $TMPDIR/args {”_ansible_version”: ”2.7.5”, ”_ansible_selinux_special_fs”: [”fuse”, ”nfs”, ”vboxsf”, ”ramfs”, ”9p”], ”_ansible_no_log”: false, ”_ansible_module_name”: ”bash_sample_02”, ”_ansible_tmpdir”: ”/home/vagrant/.ansible/tmp/ansible-tmp-1548756933.19- 248002152304605/”, ”_ansible_verbosity”: 3, ”_ansible_keep_remote_files”: true, ”_ansible_syslog_facility”: ”LOG_USER”, ”_ansible_socket”: null, ”_ansible_remote_tmp”: ”~/.ansible/tmp”, ”_ansible_diff”: false, ”_ansible_debug”: false, ”_ansible_shell_executable”: ”/bin/sh”, ”_ansible_check_mode”: false, ”foo”: ”baz”} → → → → → → → → → → → Martin Schütte | Ansible Modules | CLT’19 29/50
  • 33. Remove Argument File: JSONARGS #!/bin/sh ARGS=’<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>’ echo ”arguments: $ARGS” | logger --tag $(basename ”$0”) echo ’{”foo”:”bar”}’ exit 0 #!/usr/bin/python import syslog args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>””” if __name__ == ’__main__’: syslog.openlog() syslog.syslog(args) print(’{”foo”:”bar”}’) exit(0) Martin Schütte | Ansible Modules | CLT’19 30/50
  • 34. JSONARGS – Verbose Output <192.168.56.202> ESTABLISH SSH CONNECTION FOR USER: vagrant <192.168.56.202> SSH: EXEC ssh $SSH_OPTS -tt 192.168.56.202 + ’/bin/sh -c ’”’”’/bin/sh $TMPDIR/AnsiballZ_bash_sample_03 + && sleep 0’”’”’’ <192.168.56.202> (0, ’{”foo”:”bar”}rn’, + ’Shared connection to 192.168.56.202 closed.rn’) ok: [server] => { ”changed”: false, ”foo”: ”bar” } Martin Schütte | Ansible Modules | CLT’19 31/50
  • 35. JSONARGS – Argument in Script File [vagrant@server ~]$ cat $TMPDIR/AnsiballZ_bash_sample_03 #!/bin/sh ARGS=’{”_ansible_version”: ”2.7.5”, ”_ansible_selinux_special_fs”: [”fuse”, ”nfs”, ”vboxsf”, ”ramfs”, ”9p”], ”_ansible_no_log”: false, ”_ansible_module_name”: ”bash_sample_03”, ”_ansible_tmpdir”: ”/home/vagrant/.ansible/tmp/ansible-tmp- 1548797622.11-222413844288764/”, ”_ansible_verbosity”: 3, ”_ansible_keep_remote_files”: true, ”_ansible_syslog_facility”: ”LOG_USER”, ”_ansible_socket”: null, ”_ansible_remote_tmp”: ”~/.ansible/tmp”, ”_ansible_diff”: false, ”_ansible_debug”: false, ”_ansible_shell_executable”: ”/bin/sh”, ”_ansible_check_mode”: false, ”foo”: ”baz”}’ → → → → → → → → → → → echo ”arguments: $ARGS” | logger --tag $(basename ”$0”) echo ’{”foo”:”bar”}’ exit 0 Martin Schütte | Ansible Modules | CLT’19 32/50
  • 36. Import AnsibleModule #!/usr/bin/python args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>””” from ansible.module_utils.basic import AnsibleModule if __name__ == ’__main__’: print(’{”foo”:”bar”}’) exit(0) Martin Schütte | Ansible Modules | CLT’19 33/50
  • 37. Import AnsibleModule – Verbose Output [vagrant@server ~]$ ls -hl $TMPDIR -rwx------. 1 vagrant vagrant 75K Jan 29 14:53 AnsiballZ_py_sample_04.py [vagrant@server ~]$ head $TMPDIR/AnsiballZ_py_sample_04.py #!/usr/bin/python # -*- coding: utf-8 -*- _ANSIBALLZ_WRAPPER = True # For test-module script to tell this is a ANSIBALLZ_WRAPPER # This code is part of Ansible, but is an independent component. # The code in this particular templatable string, and this templatable string # only, is BSD licensed. Modules which end up using this snippet, which is # dynamically combined together by Ansible still belong to the author of the # module, and they may assign their own license to the complete work. # # Copyright (c), James Cammarata, 2016 [vagrant@server ~]$ Martin Schütte | Ansible Modules | CLT’19 34/50
  • 38. AnsiballZ Wrapper Python template script for • helper functions (execute, explode) • zipped data of • module text • JSON arguments • all module_utils imports Martin Schütte | Ansible Modules | CLT’19 35/50
  • 39. Debugging Tools and Tips Dev environment: • Vagrant • keep_remote_files = True • ansible -vvv • AnsiballZ code expand • “print to output” • AnsibleModule.log() • q Martin Schütte | Ansible Modules | CLT’19 36/50
  • 40. Debugging – AnsiballZ Explode [vagrant@server ~]$ ls -hl $TMPDIR -rwx------. 1 vagrant vagrant 75K Jan 29 14:53 AnsiballZ_py_sample_04.py [vagrant@server ~]$ $TMPDIR/AnsiballZ_py_sample_04.py explode Module expanded into: $TMPDIR/debug_dir [vagrant@server ~]$ cd $TMPDIR/debug_dir; find . . ./ansible ./ansible/__init__.py ./ansible/module_utils ./ansible/module_utils/__init__.py ./ansible/module_utils/basic.py ./ansible/module_utils/parsing ./ansible/module_utils/parsing/convert_bool.py ./ansible/module_utils/parsing/__init__.py ./ansible/module_utils/common ./ansible/module_utils/common/_collections_compat.py ./ansible/module_utils/common/process.py ./ansible/module_utils/common/__init__.py ./ansible/module_utils/common/file.py ./ansible/module_utils/six ./ansible/module_utils/six/__init__.py ./ansible/module_utils/_text.py ./ansible/module_utils/pycompat24.py ./__main__.py ./args Martin Schütte | Ansible Modules | CLT’19 37/50
  • 41. Debugging – AnsiballZ Explode [vagrant@server debug_dir]$ cat __main__.py #!/usr/bin/python args=”””<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>””” from ansible.module_utils.basic import AnsibleModule if __name__ == ’__main__’: print(’{”foo”:”bar”}’) exit(0) [vagrant@server debug_dir]$ $TMPDIR/AnsiballZ_py_sample_04.py execute {”foo”:”bar”} Martin Schütte | Ansible Modules | CLT’19 38/50
  • 42. Debugging – printf • Ansible reads stdin and stdout, expects JSON ⇒ cannot use print() to debug • Use output values instead # ... debug_msg = ”some_func({}) returned {}”.format(bar, foo) # ... module.exit_json(result=foo, debug_msg=debug_msg) ok: [server] => { ”changed”: false, ”debug_msg”: ”some_func(bar) returned foo”, ... } Martin Schütte | Ansible Modules | CLT’19 39/50
  • 43. Debugging – AnsibleModule log() • AnsibleModule includes method log() with variants debug() and warn() • Writes to journald or Syslog module.log(”Hello World”) # tail /var/log/messages Feb 9 15:02:59 server ansible-my_module: Invoked with param=... Feb 9 15:02:59 server ansible-my_module: Hello World Martin Schütte | Ansible Modules | CLT’19 40/50
  • 44. Debugging – q • PyPI q or zestyping/q  • Always writes to /tmp/q • function decorators try: import q except ImportError: def q(x): return x @q def my_func(params): q(special_var) # ... $ tail /tmp/q 0.0s my_func(’VERSION’) 0.0s my_func: ’special_value’ 0.0s -> {’failed’: False, ’msg’: ’...’} Martin Schütte | Ansible Modules | CLT’19 41/50
  • 46. Ansible Modules in Other Languages • Python: the default choice, best tools and support • PowerShell: officially supported, but not covered here • Scripting Languages: can use JSON_ARGS • Binary Executables: can use WANT_JSON Martin Schütte | Ansible Modules | CLT’19 42/50
  • 47. Binary Executables, e. g. Go Tools possible, but not recommended: • binary in Ansible git repository • should have own build chain and versions • architecture dependent (all the world’s a x86_64?) better: • separate packaging and deployment (.deb and .rpm) • thin wrapper module to execute installed file or library • same for binary Python libraries (e. g. DB connectors) Martin Schütte | Ansible Modules | CLT’19 43/50
  • 48. Java • “executable” JAR file • not architecture dependent • otherwise the same as binaries Martin Schütte | Ansible Modules | CLT’19 44/50
  • 49. Groovy • JVM scripting language • compromise between Ansible scripts and Java apps • maybe best way to access/use Java libraries with Ansible • may need workarounds to use custom classpath Martin Schütte | Ansible Modules | CLT’19 45/50
  • 50. Groovy – Small Example #!/usr/bin/env groovy import groovy.json.* def jsonArgs=’’’<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>’’’ def args_object = new JsonSlurper().parseText(jsonArgs) def checkMode = (boolean) args_object[’_ansible_check_mode’] // do something useful def result = [ foo: ’bar’, code: 42, did_check_mode: checkMode ] print JsonOutput.toJson(result) Martin Schütte | Ansible Modules | CLT’19 46/50
  • 51. Scripting Languages • Perl, Ruby, etc. • need JSON library • works • question: why? Martin Schütte | Ansible Modules | CLT’19 47/50
  • 53. Useful Software Design Principles Not only for Ansible modules … • KISS • YAGNI • readability! Martin Schütte | Ansible Modules | CLT’19 48/50
  • 54. Links • Ansible Docs on Modules: Conventions, tips, and pitfalls • ansible/ansible  • Ansible: Up & Running, 2nd ed by Lorin Hochstein & René Moser Martin Schütte | Ansible Modules | CLT’19 49/50
  • 55. The End Thank You! — Questions? Martin Schütte @m_schuett  info@martin-schuette.de  slideshare.net/mschuett/  noti.st/mschuett/ Martin Schütte | Ansible Modules | CLT’19 50/50