SlideShare une entreprise Scribd logo
1  sur  26
Télécharger pour lire hors ligne
Ansible Roles done right
Ansible Berlin Meetup
Fetching and installing roles
• requirements.yml
• ansible-galaxy install -r requirements.yml
• depending on how you access the repo, you
might need a valid key in your ssh agent for
grabbing the role
• it's a good idea to specify the path of the roles in
your ansible.cfg file. that will also tell Galaxy
where to unpack the roles
Ansible Berlin Meetup
$ cat requirements.yml
---
- name: ec2
src: ‘git@bitbucket.org:dan_vaida/ansible-roles-ec2.git’
scm: git
- name: rds
src: ‘git@bitbucket.org:dan_vaida/ansible-roles-rds.git’
scm: git
- name: nginx
src: ‘git@bitbucket.org:dan_vaida/ansible-roles-nginx.git’
scm: git
- { name: ntp, src: ‘git@bitbucket.org:dan_vaida/ansible-roles-ntp.git’, scm: git }
- name: postfix
src: ‘https://github.com/danvaida/ansible-roles-postfix.git’
Ansible Berlin Meetup
$ cat ansible.cfg
[defaults]
roles_path = ./roles
retry_files_enabled = False
$ ansible-galaxy install -r requirements.yml
- extracting ec2 to /Users/dvaida/work/ansible_berlin/ansible-pim/roles/ec2
- ec2 was installed successfully
- extracting rds to /Users/dvaida/work/ansible_berlin/ansible-pim/roles/rds
- rds was installed successfully
- nginx is already installed, skipping.
$ cat .gitignore
roles/ec2
roles/rds
roles/nginx
Ansible Berlin Meetup
Docker containers
FROM debian:wheezy
RUN apt-get -y update
RUN apt-get -y install python-pip=1.1-3 
python-dev=2.7.3-4+deb7u1 
libffi-dev=3.0.10-3
RUN pip install ansible==2.1
ADD run-tests.sh run-tests.sh
CMD ["./run-tests.sh"]
Ansible Berlin Meetup
$ cd /path/to/the/role
$ docker build -t ansible-roles-test tests/support
$ docker run -v $PWD:/role ansible-roles-test
Ansible Berlin Meetup
Docker containers
Docker containers
• docker containers powered by images that describe immutable
packages and configs
• Dockerfile with specific versions because doing apt get update
&& apt-get install ansible -y defeats more than half of the
purpose of containers
• rarely needed to run containers with --privileged (i.e. when faking
a file system for formatting, mounting, etc.)
• --no-cache is generally a good idea but it's also a performance
killer, so an intermediary container that acts like an APT repo is
advisable (remember the vagrant plugin cachier?)
• install role prerequisites using the Dockerfile
Ansible Berlin Meetup
Wrapper bash script
$ cat ./ansible-roles-packages/tests/support/run-tests.sh
#!/bin/bash
set -e
cd /role/tests
ansible-playbook test_installation.yml
# running a second time to verify playbook's idempotence
set +e
ansible-playbook test_installation.yml > /tmp/
second_run.log
{
cat /tmp/second_run.log | tail -n 5 | grep 'changed=0'
&&
echo 'Playbook is idempotent'
} || {
cat /tmp/second_run.log
echo 'Playbook is **NOT** idempotent'
Ansible Berlin Meetup
exit 1
}
set -e
ansible-playbook test_removal.yml
# running a second time to verify playbook's idempotence
set +e
ansible-playbook test_removal.yml > /tmp/second_run.log
{
cat /tmp/second_run.log | tail -n 5 | grep 'changed=0'
&&
echo 'Playbook is idempotent'
} || {
cat /tmp/second_run.log
echo 'Playbook is **NOT** idempotent'
exit 1
}
Wrapper bash script
• very rudimentary
• it relies heavily on alternatively changing the exit
behaviour when a certain return code is seen
• we use it for invoking each playbook twice and
looking at the returned information to evaluate
idempotence
• it definitely needs refactoring, possibly ported to a
playbook; don't write ruby for this kind of stuff. please.
Ansible Berlin Meetup
changed=0 unreachable=0 failed=0
• Idempotence means f(x)=f(f(x))
• The tests that ship with the roles are like unit-
tests in the big picture
• You must write integration tests, too. They will
prove that your roles’ interconnection actually
works by testing your application's health.
Ansible Berlin Meetup
Custom modules, plugins
• sometimes a role uses an unpublished, custom
role you wrote
• simply place it in the library directory located in
the root of the role. the tests will be able to use it,
too
• same goes for some plugins like callbacks
• don't forget to include tests for your modules
Ansible Berlin Meetup
$ tree ansible-roles-elasticache/
├── README.md
├── defaults
│   └── main.yml
├── library
│   └── elasticache.py
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
└── tests
├── ansible.cfg
├── inventory
├── support
│   ├── Dockerfile
│   └── run-tests.sh
├── test_addition.yml
├── test_defaults.yml
└── test_removal.yml
6 directories, 12 files
Ansible Berlin Meetup
custom ElastiCache Ansible module
Standards
• Readability, easiness of editing, VCS-friendliness, deprecation warnings
• Example:
• only have True and False not yes, No, TRUE, etc.
• stick with your chosen way of writing tasks (foldable scalars (>), shorthand/
one-line (=) or structured map/list (:)
• use single-quotes for vars containing non-alphanumerical chars and
doube-quotes for dynamic vars
• prefix variables used within a role with the role’s name
• use tags with confidence
• …
Ansible Berlin Meetup
README.md
• Ansible is already runnable documentation, but
a clear explanation about what the role does,
what vars are exposed to the user (sort of like
API endpoints in other software) must be offered.
• Not all used vars need to be exposed.
• Dependencies, requirements, etc. It's basically
an enriched Galaxy meta/main.yml file.
Ansible Berlin Meetup
TDD
• tests driven development because first and foremost it is
Code as Infrastructure
• strict standards and rules must be defined and
respected, responsibly.
• tests for vars defaults and CRUD-like operations
• we're not in the business of testing Ansible itself (i.e.
modules) nor the user's input (i.e. config templates)
• mocks play a crucial role (APIs, fake block/object storage
devices, inventories, etc.)
Ansible Berlin Meetup
Example TDD cycle/steps to write a role
1. Write a test that is meant to run the role with the default vars (i.e.
test_defaults.yml)
2. Write your first task in the tasks/main.yml file. It can be something
like - debug: msg='This is here just to pass the imdepotence
test.’
3. Run test_defaults.yml and make sure it is idempotent.
4. Write your first assertion in a new file called test_addition.yml.
This would be for your first "real" task of your role (i.e. you’re create
a DNS record so make sure the zone is propagated)
5. Remove the dummy task from tasks/main.yml and add the first
"real" task of your role to make your test pass.
6. Run both test_defaults.yml & test_addition.yml and make sure
they are idempotent.
Ansible Berlin Meetup
Example TDD cycle/steps to write a role
7. Write your next assertion.
8. Add the task(s) for your respective assertion that will make the
test pass.
9. Repeat steps 5 and 6 until you got all your tasks responsible for
adding/updating things on the targets.
10. For the tasks responsible with removing things on the targets,
write another test file (i.e. test_removal.yml)
11. Principally repeat steps 5 and 6.
Tip: You might run into situations where instead of having the fairly
standard test files: test_defaults.yml, test_addition.yml and
test_removal.yml, you will see that you only need the
test_defaults.yml file.
Ansible Berlin Meetup
CI via Jenkins
• the complete flow includes automatic runs of the
docker containers which implicitly execute the role tests
• this is typically happening when a PR is made, a
branch is merged into the master branch.
• a working solution is to have two Jenkins jobs.
Example:
• ansible-roles-logrotate-dev-qa (runs against PRs)
• ansible-roles-logrotate-master (runs against master)
Ansible Berlin Meetup
CI via Jenkins
• Jenkins plugins used to integrate with BitBucket:
• Bitbucket Approve Plugin
• Bitbucket Plugin
• Bitbucket Pullrequest Builder Plugin
• embeddable-build-status
• ChuckNorris Plugin
Ansible Berlin Meetup
Ansible Berlin Meetup
"It works on my machine" always holds true for Chuck Norris.
Ansible Berlin Meetup
ansible-container
• Ansible’s new stab at Docker containers
• Builds and orchestrates containers in Docker
Compose style
• It’s well under heavy development
• Comes with init|build|run|push|shipit params
• Install and try it: pip install ansible-container
Ansible Berlin Meetup
$ tree ansible-roles-postfix/
├── README.md
├── ansible
│   ├── ansible.cfg
│   ├── container.yml
│   ├── inventory
│   ├── main.yml
│   ├── requirements.txt
│   ├── run-tests.sh
│   ├── templates
│   │   ├── dummy.cf.j2
│   │   └── virtual.j2
│   ├── test.yml
│   └── test_defaults.yml
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── mailname.j2
└── tests
└── ansible -> ../ansible
9 directories, 16 files
Ansible Berlin Meetup
$ tree ansible-roles-postfix/
├── README.md
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── mailname.j2
└── tests
├── ansible.cfg
├── inventory
├── support
│   ├── Dockerfile
│   └── run-tests.sh
├── templates
│   ├── dummy.cf.j2
│   └── virtual.j2
├── test.yml
└── test_defaults.yml
8 directories, 14 files
structure leveraging ansible-container
“simple” structure
ansible-container
$ git diff ansible-container master -- README.md
diff --git a/README.md b/README.md
index f8935b4..f104728 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,6 @@ None.
If you want to run the tests on the provided docker environment, run the
following commands:
- $ ansible-container build
- $ ansible-container run
+ $ docker build -t ansible-roles-test tests/support
+ $ docker run -it -v $PWD:/role ansible-roles-test
Ansible Berlin Meetup
Questions?
Ansible Berlin Meetup
Thanks.
@ansible_berlin
meetup.com/Ansible-Berlin
Ansible Berlin Meetup

Contenu connexe

Tendances

Tendances (20)

Introduction to Ansible
Introduction to AnsibleIntroduction to Ansible
Introduction to Ansible
 
Best practices for ansible
Best practices for ansibleBest practices for ansible
Best practices for ansible
 
Introduction to Ansible
Introduction to AnsibleIntroduction to Ansible
Introduction to Ansible
 
ansible why ?
ansible why ?ansible why ?
ansible why ?
 
Getting started with Ansible
Getting started with AnsibleGetting started with Ansible
Getting started with Ansible
 
IT Automation with Ansible
IT Automation with AnsibleIT Automation with Ansible
IT Automation with Ansible
 
Ansible
AnsibleAnsible
Ansible
 
Ansible 101
Ansible 101Ansible 101
Ansible 101
 
Automating with Ansible
Automating with AnsibleAutomating with Ansible
Automating with Ansible
 
Ansible intro
Ansible introAnsible intro
Ansible intro
 
Ansible, best practices
Ansible, best practicesAnsible, best practices
Ansible, best practices
 
Automation with ansible
Automation with ansibleAutomation with ansible
Automation with ansible
 
Ansible - Hands on Training
Ansible - Hands on TrainingAnsible - Hands on Training
Ansible - Hands on Training
 
Ansible
AnsibleAnsible
Ansible
 
[1A7]Ansible의이해와활용
[1A7]Ansible의이해와활용[1A7]Ansible의이해와활용
[1A7]Ansible의이해와활용
 
Network Automation with Ansible
Network Automation with AnsibleNetwork Automation with Ansible
Network Automation with Ansible
 
Ansible
AnsibleAnsible
Ansible
 
DevOps with Ansible
DevOps with AnsibleDevOps with Ansible
DevOps with Ansible
 
Network Automation (NetDevOps) with Ansible
Network Automation (NetDevOps) with AnsibleNetwork Automation (NetDevOps) with Ansible
Network Automation (NetDevOps) with Ansible
 
Hands On Introduction To Ansible Configuration Management With Ansible Comple...
Hands On Introduction To Ansible Configuration Management With Ansible Comple...Hands On Introduction To Ansible Configuration Management With Ansible Comple...
Hands On Introduction To Ansible Configuration Management With Ansible Comple...
 

En vedette

En vedette (6)

V2 and beyond
V2 and beyondV2 and beyond
V2 and beyond
 
AnsibleBuilding a Docker-ized Microservice In Node, Using Ansible - AnsibleF...
AnsibleBuilding a Docker-ized Microservice  In Node, Using Ansible - AnsibleF...AnsibleBuilding a Docker-ized Microservice  In Node, Using Ansible - AnsibleF...
AnsibleBuilding a Docker-ized Microservice In Node, Using Ansible - AnsibleF...
 
docker build with Ansible
docker build with Ansibledocker build with Ansible
docker build with Ansible
 
Cyansible
CyansibleCyansible
Cyansible
 
Ansible presentation
Ansible presentationAnsible presentation
Ansible presentation
 
Ansible tips & tricks
Ansible tips & tricksAnsible tips & tricks
Ansible tips & tricks
 

Similaire à Ansible roles done right

Similaire à Ansible roles done right (20)

Ansible 101 - Presentation at Ansible STL Meetup
Ansible 101 - Presentation at Ansible STL MeetupAnsible 101 - Presentation at Ansible STL Meetup
Ansible 101 - Presentation at Ansible STL Meetup
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Docker perl build
Docker perl buildDocker perl build
Docker perl build
 
Ansible container
Ansible containerAnsible container
Ansible container
 
Ansible not only for Dummies
Ansible not only for DummiesAnsible not only for Dummies
Ansible not only for Dummies
 
OSCamp 2019 | #3 Ansible: Automated Tests of Ansible code with GitLab, Vagran...
OSCamp 2019 | #3 Ansible: Automated Tests of Ansible code with GitLab, Vagran...OSCamp 2019 | #3 Ansible: Automated Tests of Ansible code with GitLab, Vagran...
OSCamp 2019 | #3 Ansible: Automated Tests of Ansible code with GitLab, Vagran...
 
DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!DevOps for Humans - Ansible for Drupal Deployment Victory!
DevOps for Humans - Ansible for Drupal Deployment Victory!
 
Learn basic ansible using docker
Learn basic ansible using dockerLearn basic ansible using docker
Learn basic ansible using docker
 
Ansible at work
Ansible at workAnsible at work
Ansible at work
 
Introduction to Ansible - Peter Halligan
Introduction to Ansible - Peter HalliganIntroduction to Ansible - Peter Halligan
Introduction to Ansible - Peter Halligan
 
Testing Ansible
Testing AnsibleTesting Ansible
Testing Ansible
 
Introducing Ansible
Introducing AnsibleIntroducing Ansible
Introducing Ansible
 
Jenkins Job Builder: our experience
Jenkins Job Builder: our experienceJenkins Job Builder: our experience
Jenkins Job Builder: our experience
 
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
 
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
 
Ansible & Salt - Vincent Boon
Ansible & Salt - Vincent BoonAnsible & Salt - Vincent Boon
Ansible & Salt - Vincent Boon
 
Ansible 202 - sysarmy
Ansible 202 - sysarmyAnsible 202 - sysarmy
Ansible 202 - sysarmy
 
A tour of Ansible
A tour of AnsibleA tour of Ansible
A tour of Ansible
 
Automation with Ansible and Containers
Automation with Ansible and ContainersAutomation with Ansible and Containers
Automation with Ansible and Containers
 
[HKOSCon x COSCUP 2020][20200801][Ansible: From VM to Kubernetes]
[HKOSCon x COSCUP 2020][20200801][Ansible: From VM to Kubernetes][HKOSCon x COSCUP 2020][20200801][Ansible: From VM to Kubernetes]
[HKOSCon x COSCUP 2020][20200801][Ansible: From VM to Kubernetes]
 

Dernier

Dernier (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 

Ansible roles done right

  • 1. Ansible Roles done right Ansible Berlin Meetup
  • 2. Fetching and installing roles • requirements.yml • ansible-galaxy install -r requirements.yml • depending on how you access the repo, you might need a valid key in your ssh agent for grabbing the role • it's a good idea to specify the path of the roles in your ansible.cfg file. that will also tell Galaxy where to unpack the roles Ansible Berlin Meetup
  • 3. $ cat requirements.yml --- - name: ec2 src: ‘git@bitbucket.org:dan_vaida/ansible-roles-ec2.git’ scm: git - name: rds src: ‘git@bitbucket.org:dan_vaida/ansible-roles-rds.git’ scm: git - name: nginx src: ‘git@bitbucket.org:dan_vaida/ansible-roles-nginx.git’ scm: git - { name: ntp, src: ‘git@bitbucket.org:dan_vaida/ansible-roles-ntp.git’, scm: git } - name: postfix src: ‘https://github.com/danvaida/ansible-roles-postfix.git’ Ansible Berlin Meetup
  • 4. $ cat ansible.cfg [defaults] roles_path = ./roles retry_files_enabled = False $ ansible-galaxy install -r requirements.yml - extracting ec2 to /Users/dvaida/work/ansible_berlin/ansible-pim/roles/ec2 - ec2 was installed successfully - extracting rds to /Users/dvaida/work/ansible_berlin/ansible-pim/roles/rds - rds was installed successfully - nginx is already installed, skipping. $ cat .gitignore roles/ec2 roles/rds roles/nginx Ansible Berlin Meetup
  • 5. Docker containers FROM debian:wheezy RUN apt-get -y update RUN apt-get -y install python-pip=1.1-3 python-dev=2.7.3-4+deb7u1 libffi-dev=3.0.10-3 RUN pip install ansible==2.1 ADD run-tests.sh run-tests.sh CMD ["./run-tests.sh"] Ansible Berlin Meetup
  • 6. $ cd /path/to/the/role $ docker build -t ansible-roles-test tests/support $ docker run -v $PWD:/role ansible-roles-test Ansible Berlin Meetup Docker containers
  • 7. Docker containers • docker containers powered by images that describe immutable packages and configs • Dockerfile with specific versions because doing apt get update && apt-get install ansible -y defeats more than half of the purpose of containers • rarely needed to run containers with --privileged (i.e. when faking a file system for formatting, mounting, etc.) • --no-cache is generally a good idea but it's also a performance killer, so an intermediary container that acts like an APT repo is advisable (remember the vagrant plugin cachier?) • install role prerequisites using the Dockerfile Ansible Berlin Meetup
  • 8. Wrapper bash script $ cat ./ansible-roles-packages/tests/support/run-tests.sh #!/bin/bash set -e cd /role/tests ansible-playbook test_installation.yml # running a second time to verify playbook's idempotence set +e ansible-playbook test_installation.yml > /tmp/ second_run.log { cat /tmp/second_run.log | tail -n 5 | grep 'changed=0' && echo 'Playbook is idempotent' } || { cat /tmp/second_run.log echo 'Playbook is **NOT** idempotent' Ansible Berlin Meetup exit 1 } set -e ansible-playbook test_removal.yml # running a second time to verify playbook's idempotence set +e ansible-playbook test_removal.yml > /tmp/second_run.log { cat /tmp/second_run.log | tail -n 5 | grep 'changed=0' && echo 'Playbook is idempotent' } || { cat /tmp/second_run.log echo 'Playbook is **NOT** idempotent' exit 1 }
  • 9. Wrapper bash script • very rudimentary • it relies heavily on alternatively changing the exit behaviour when a certain return code is seen • we use it for invoking each playbook twice and looking at the returned information to evaluate idempotence • it definitely needs refactoring, possibly ported to a playbook; don't write ruby for this kind of stuff. please. Ansible Berlin Meetup
  • 10. changed=0 unreachable=0 failed=0 • Idempotence means f(x)=f(f(x)) • The tests that ship with the roles are like unit- tests in the big picture • You must write integration tests, too. They will prove that your roles’ interconnection actually works by testing your application's health. Ansible Berlin Meetup
  • 11. Custom modules, plugins • sometimes a role uses an unpublished, custom role you wrote • simply place it in the library directory located in the root of the role. the tests will be able to use it, too • same goes for some plugins like callbacks • don't forget to include tests for your modules Ansible Berlin Meetup
  • 12. $ tree ansible-roles-elasticache/ ├── README.md ├── defaults │   └── main.yml ├── library │   └── elasticache.py ├── meta │   └── main.yml ├── tasks │   └── main.yml └── tests ├── ansible.cfg ├── inventory ├── support │   ├── Dockerfile │   └── run-tests.sh ├── test_addition.yml ├── test_defaults.yml └── test_removal.yml 6 directories, 12 files Ansible Berlin Meetup custom ElastiCache Ansible module
  • 13. Standards • Readability, easiness of editing, VCS-friendliness, deprecation warnings • Example: • only have True and False not yes, No, TRUE, etc. • stick with your chosen way of writing tasks (foldable scalars (>), shorthand/ one-line (=) or structured map/list (:) • use single-quotes for vars containing non-alphanumerical chars and doube-quotes for dynamic vars • prefix variables used within a role with the role’s name • use tags with confidence • … Ansible Berlin Meetup
  • 14. README.md • Ansible is already runnable documentation, but a clear explanation about what the role does, what vars are exposed to the user (sort of like API endpoints in other software) must be offered. • Not all used vars need to be exposed. • Dependencies, requirements, etc. It's basically an enriched Galaxy meta/main.yml file. Ansible Berlin Meetup
  • 15. TDD • tests driven development because first and foremost it is Code as Infrastructure • strict standards and rules must be defined and respected, responsibly. • tests for vars defaults and CRUD-like operations • we're not in the business of testing Ansible itself (i.e. modules) nor the user's input (i.e. config templates) • mocks play a crucial role (APIs, fake block/object storage devices, inventories, etc.) Ansible Berlin Meetup
  • 16. Example TDD cycle/steps to write a role 1. Write a test that is meant to run the role with the default vars (i.e. test_defaults.yml) 2. Write your first task in the tasks/main.yml file. It can be something like - debug: msg='This is here just to pass the imdepotence test.’ 3. Run test_defaults.yml and make sure it is idempotent. 4. Write your first assertion in a new file called test_addition.yml. This would be for your first "real" task of your role (i.e. you’re create a DNS record so make sure the zone is propagated) 5. Remove the dummy task from tasks/main.yml and add the first "real" task of your role to make your test pass. 6. Run both test_defaults.yml & test_addition.yml and make sure they are idempotent. Ansible Berlin Meetup
  • 17. Example TDD cycle/steps to write a role 7. Write your next assertion. 8. Add the task(s) for your respective assertion that will make the test pass. 9. Repeat steps 5 and 6 until you got all your tasks responsible for adding/updating things on the targets. 10. For the tasks responsible with removing things on the targets, write another test file (i.e. test_removal.yml) 11. Principally repeat steps 5 and 6. Tip: You might run into situations where instead of having the fairly standard test files: test_defaults.yml, test_addition.yml and test_removal.yml, you will see that you only need the test_defaults.yml file. Ansible Berlin Meetup
  • 18. CI via Jenkins • the complete flow includes automatic runs of the docker containers which implicitly execute the role tests • this is typically happening when a PR is made, a branch is merged into the master branch. • a working solution is to have two Jenkins jobs. Example: • ansible-roles-logrotate-dev-qa (runs against PRs) • ansible-roles-logrotate-master (runs against master) Ansible Berlin Meetup
  • 19. CI via Jenkins • Jenkins plugins used to integrate with BitBucket: • Bitbucket Approve Plugin • Bitbucket Plugin • Bitbucket Pullrequest Builder Plugin • embeddable-build-status • ChuckNorris Plugin Ansible Berlin Meetup
  • 21. "It works on my machine" always holds true for Chuck Norris. Ansible Berlin Meetup
  • 22. ansible-container • Ansible’s new stab at Docker containers • Builds and orchestrates containers in Docker Compose style • It’s well under heavy development • Comes with init|build|run|push|shipit params • Install and try it: pip install ansible-container Ansible Berlin Meetup
  • 23. $ tree ansible-roles-postfix/ ├── README.md ├── ansible │   ├── ansible.cfg │   ├── container.yml │   ├── inventory │   ├── main.yml │   ├── requirements.txt │   ├── run-tests.sh │   ├── templates │   │   ├── dummy.cf.j2 │   │   └── virtual.j2 │   ├── test.yml │   └── test_defaults.yml ├── defaults │   └── main.yml ├── handlers │   └── main.yml ├── meta │   └── main.yml ├── tasks │   └── main.yml ├── templates │   └── mailname.j2 └── tests └── ansible -> ../ansible 9 directories, 16 files Ansible Berlin Meetup $ tree ansible-roles-postfix/ ├── README.md ├── defaults │   └── main.yml ├── handlers │   └── main.yml ├── meta │   └── main.yml ├── tasks │   └── main.yml ├── templates │   └── mailname.j2 └── tests ├── ansible.cfg ├── inventory ├── support │   ├── Dockerfile │   └── run-tests.sh ├── templates │   ├── dummy.cf.j2 │   └── virtual.j2 ├── test.yml └── test_defaults.yml 8 directories, 14 files structure leveraging ansible-container “simple” structure
  • 24. ansible-container $ git diff ansible-container master -- README.md diff --git a/README.md b/README.md index f8935b4..f104728 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,6 @@ None. If you want to run the tests on the provided docker environment, run the following commands: - $ ansible-container build - $ ansible-container run + $ docker build -t ansible-roles-test tests/support + $ docker run -it -v $PWD:/role ansible-roles-test Ansible Berlin Meetup