-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Chris Evich <cevich@redhat.com>
- Loading branch information
0 parents
commit d035e51
Showing
12 changed files
with
1,068 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
# Ansible bits | ||
*.retry | ||
|
||
# Test bits | ||
tests/path/ | ||
|
||
# Created by travis | ||
ansible.cfg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
--- | ||
language: python | ||
branch: | ||
only: | ||
- master | ||
python: | ||
- 2.7 | ||
|
||
matrix: | ||
fast_finish: true | ||
|
||
git: | ||
submodules: false | ||
|
||
env: | ||
global: | ||
- TYPOS="'ecoh' 'roel' 'fixup!' 'squash!' 'FIXME' '<<<<<<<' '=======' '>>>>>>>'" | ||
# fix vim syntax highlighting: " | ||
|
||
before_install: | ||
- sudo apt-get update -qq | ||
- pip install ansible==2.3 | ||
|
||
install: | ||
# Add ansible.cfg to pick up roles path. | ||
- echo -e '[defaults]\nroles_path = ../' > ansible.cfg | ||
# Galaxy would normally install this with a cevich prefix | ||
- export ROLEBASE="$(basename $PWD)" && ln -sfv "$ROLEBASE" "../cevich.$ROLEBASE" | ||
|
||
script: | ||
- > | ||
echo "$(git log -1 --format=%H origin/master)" > /tmp/start; | ||
echo "$(git log -1 --format=%H HEAD)" > /tmp/end; | ||
git log -p $(cat /tmp/start)..$(cat /tmp/end) -- . ':!.travis.yml' &> /tmp/commits; | ||
echo "Typos found:"; | ||
egrep -a -i -2 "$TYPOS" /tmp/commits | tee /tmp/typos; | ||
test "$(cat /tmp/typos | wc -l)" -eq "0" || exit 1; | ||
- stat /tmp/foobar || true | ||
- ansible-playbook -i tests/inventory tests/test.yml --verbose --syntax-check | ||
- stat /tmp/foobar || true | ||
- ansible-playbook -i tests/inventory tests/test.yml --verbose | ||
- > | ||
ansible-playbook -i tests/inventory tests/again.yml --verbose | tee /tmp/idempotence; | ||
grep -q 'changed=0.*failed=0' /tmp/idempotence \ | ||
&& (echo 'Idempotence test: pass' && exit 0) \ | ||
|| (echo 'Idempotence test: fail' && exit 1); | ||
- stat /tmp/foobar || true | ||
|
||
notifications: | ||
webhooks: https://galaxy.ansible.com/api/v1/notifications/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
Touchstone | ||
=========== | ||
|
||
Ansible role to easily make sets of plays, roles or tasks idempotent. | ||
This is critical for some sequence declarations. For example | ||
if one role does partitioning, and another does formatting. Re-applying | ||
that sequence in the future stands a good chance of wrecking your data. | ||
|
||
Requirements | ||
------------ | ||
|
||
Same as stock Ansible 2.3+ | ||
|
||
Role Variables | ||
-------------- | ||
|
||
``touch_touchstone``: | ||
When true, mark the end-state or completion identified by ``stone_name``. | ||
|
||
``stone_name``: | ||
Optional, identification string to use when multiple end-states must be | ||
tracked. For example multiple playbooks. Defaults to the base, directory | ||
name of the current playbook. | ||
|
||
``touchstone_filepath``: | ||
Directory path where the touchstone ``stone_name`` will exist. Must | ||
be a permanent and writable directory for ``ansible_user``, i.e. not | ||
a ``tmpdir`` based ``/tmp``. | ||
|
||
``stone_touched``: | ||
A boolean value, set during the role to reflect the current touchstone | ||
state. When ``True``, it indicates the stone was touched at least once | ||
in the past. | ||
|
||
Dependencies | ||
------------ | ||
|
||
A systemd-based machine with a unique /etc/machine-id. | ||
|
||
Example Playbook | ||
---------------- | ||
|
||
:: | ||
|
||
- hosts: all | ||
roles: | ||
- cevich.parallel_git_repos | ||
|
||
License | ||
------- | ||
|
||
Easily make sets of plays, roles or tasks idempotent. | ||
Copyright (C) 2017 Christopher C. Evich | ||
|
||
This program is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
|
||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
|
||
Author Information | ||
------------------ | ||
|
||
Causing trouble and inciting mayhem with Linux since Windows 98 | ||
|
||
|
||
Continuous Integration | ||
----------------------- | ||
|
||
Travis CI: |ci_status| | ||
|
||
.. |ci_status| image:: https://travis-ci.org/cevich/touchstone.svg?branch=master | ||
:target: https://travis-ci.org/cevich/touchstone |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
|
||
# When true, touch touchstone identified by touchstone_name. | ||
touch_touchstone: False | ||
|
||
# The name of the touchstone, in case there's more than one. | ||
stone_name: "{{ playbook_dir | basename }}" | ||
|
||
# Full/absolute path where touchstone lives, must be permanent and readable/writable. | ||
touchstone_filepath: '{{ ansible_user_dir | default("/var/tmp") }}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import errno | ||
import sys | ||
import os | ||
import argparse | ||
import fcntl | ||
from contextlib import contextmanager | ||
|
||
@contextmanager | ||
def flock(filepath): | ||
if os.path.basename(filepath).startswith('.'): | ||
pfx_fmt = '{0}.lock' | ||
else: | ||
pfx_fmt = '.{0}.lock' | ||
filepath = os.path.join(os.path.dirname(filepath), | ||
pfx_fmt.format(os.path.basename(filepath))) | ||
with open(filepath, 'a') as lockfile: | ||
try: | ||
fcntl.flock(lockfile, fcntl.LOCK_EX) | ||
yield lockfile | ||
finally: | ||
fcntl.flock(lockfile, fcntl.LOCK_UN) | ||
|
||
|
||
def touch_touchstone(filepath, lines): | ||
already_touched = False | ||
contents = '\n'.join(lines) | ||
with flock(filepath): | ||
try: | ||
with open(filepath, 'rU') as touchstone: | ||
contents = touchstone.read() | ||
already_touched = True | ||
except IOError as xcept: | ||
if xcept.errno != errno.ENOENT: | ||
raise | ||
with open(filepath, 'w') as touchstone: | ||
touchstone.write(contents) | ||
if not contents.endswith('\n'): | ||
touchstone.write('\n') | ||
return already_touched | ||
|
||
|
||
def is_touched(filepath): | ||
with flock(filepath): | ||
try: | ||
with open(filepath, 'rU') as touchstone: | ||
return (True, touchstone.read()) | ||
except IOError: | ||
return (False, None) | ||
|
||
|
||
def parse_arguments(argv): | ||
adhf = argparse.ArgumentDefaultsHelpFormatter | ||
parser = argparse.ArgumentParser(formatter_class=adhf, | ||
epilog='Prints "True"/"False" to stdout,' | ||
' indicating touchstone status') | ||
parser.add_argument("filepath", default=None, | ||
help="Path to the touchstone file to examine or update.") | ||
parser.add_argument('-t', '--touch', default=False, action='store_true', | ||
help="Ensure the touchstone <filepath> exists, on creation" | ||
" populate it with all [line]") | ||
parser.add_argument('line', default=None, nargs="*", | ||
help="Lines to store in <filepath> on creation.") | ||
try: | ||
return parser.parse_args(argv[1:]) | ||
except IndexError: | ||
return parser.parse_args(argv) | ||
|
||
|
||
def main(argv): | ||
args = parse_arguments(argv) | ||
already_touched = False | ||
if args.touch: | ||
already_touched = touch_touchstone(args.filepath, args.line) | ||
state, contents = is_touched(args.filepath) | ||
sys.stdout.write('{0}\n'.format(state)) | ||
# Do not print contents upon first touch as "changed" signal to ansible | ||
if state and already_touched: | ||
sys.stderr.write('{0}'.format(contents)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main(sys.argv) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
galaxy_info: | ||
author: Chris Evich | ||
description: Easily make sets of plays, roles or tasks idempotent. | ||
company: Red Hat | ||
license: GPLv3 | ||
min_ansible_version: 2.3 | ||
platforms: | ||
- name: all | ||
versions: | ||
- all | ||
galaxy_tags: | ||
- sequence | ||
- ending | ||
- unidirectional | ||
- complete | ||
- stop | ||
- play | ||
- task | ||
- role | ||
- idempotent | ||
|
||
dependencies: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
|
||
- name: stone_touched fact is initially false | ||
set_fact: | ||
stone_touched: False | ||
|
||
- name: Input expectations are verified | ||
assert: | ||
that: | ||
- 'hostvars.localhost.ansible_machine_id | default("", True) | trim | length' | ||
- 'stone_touched == False' # make sure it's not read-only | ||
- 'touchstone_filepath | default("", True) | trim | length' | ||
- 'touch_touchstone | default(False) in [True, False]' | ||
- '"{{ role_path }}/files/touchstone.py" | is_file' | ||
|
||
- name: Touchstone script command-line arguments are initialized | ||
set_fact: | ||
result: 'touchstone.py' | ||
|
||
- name: Touchstone script command-line has --touch appended | ||
set_fact: | ||
result: '{{ result }} --touch' | ||
when: touch_touchstone | default(False) | ||
|
||
- name: Touchstone script command-line has complete touchstone_filepath appended | ||
set_fact: | ||
result: '{{ result }} {{ touchstone_filepath }}/.{{ stone_name }}.touchstone' | ||
|
||
- name: Touchstone script command-line has content lines appended | ||
set_fact: | ||
result: '{{ result }} {{ item | quote }}' | ||
when: touch_touchstone | default(False) | ||
with_items: | ||
- 'Touched by {{ hostvars.localhost.ansible_nodename }}' | ||
- 'Machine_id {{ hostvars.localhost.ansible_machine_id }}' | ||
- 'On {{ hostvars.localhost.ansible_date_time.iso8601 }}' | ||
|
||
- name: Touchstone script is executed to modify and/or retrieve stone status | ||
script: '{{ result }}' | ||
changed_when: touch_touchstone and | ||
result.stdout | trim | lower == "true" and | ||
result.stderr | trim == '' | ||
register: result | ||
|
||
- name: Script output expectations are verified | ||
assert: | ||
that: 'result.stdout | trim | lower in ["true","false"]' | ||
|
||
- name: Touchstone result is converted into boolean | ||
set_fact: | ||
stone_touched: '{{ result.stdout | trim | lower == "true" }}' | ||
|
||
- name: Touchstone variables are debugged | ||
debug: | ||
var: '{{ item }}' | ||
with_items: | ||
- stone_name | ||
- stone_touched | ||
- result.stderr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- | ||
|
||
- hosts: all | ||
gather_subset: network | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched is defined' | ||
roles: | ||
- cevich.touchstone | ||
post_tasks: | ||
- assert: that='stone_touched == True' | ||
|
||
- hosts: all | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched == True' | ||
roles: | ||
- role: cevich.touchstone | ||
touch_touchstone: True | ||
post_tasks: | ||
- assert: that='stone_touched == True' | ||
|
||
- hosts: all | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched == True' | ||
roles: | ||
- role: cevich.touchstone | ||
touch_touchstone: True | ||
post_tasks: | ||
- assert: that='stone_touched == True' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
localhost ansible_connection=local |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- | ||
|
||
- hosts: all | ||
gather_subset: network | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched is defined' | ||
roles: | ||
- cevich.touchstone | ||
post_tasks: | ||
- assert: that='stone_touched == False' | ||
|
||
- hosts: all | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched == False' | ||
roles: | ||
- role: cevich.touchstone | ||
touch_touchstone: True | ||
post_tasks: | ||
- assert: that='stone_touched == True' | ||
|
||
- hosts: all | ||
vars: | ||
stone_name: foobar | ||
touchstone_filepath: /tmp | ||
pre_tasks: | ||
- assert: that='stone_touched == True' | ||
roles: | ||
- role: cevich.touchstone | ||
touch_touchstone: True | ||
post_tasks: | ||
- assert: that='stone_touched == True' |
Oops, something went wrong.