forked from fxkr/ansible-etckeeper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
etckeeper
103 lines (83 loc) · 3.22 KB
/
etckeeper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python
# To test this, use:
#
# mkdir test
# export ETCKEEPER_DIR="$(realpath test)"
# etckeeper init
# ansible localhost -m "etckeeper" -a "action=begin"
# ansible localhost -m "etckeeper" -a "action=commit msg=..."
DOCUMENTATION = '''
---
module: etckeeper
short_description: Provides a concise way to invoke etckeeper before and after plays.
'''
EXAMPLES = '''
# Put this at the beginning of all plays.
# It ensures that the play starts with a clean /etc.
- etckeeper: action=begin
# Put this at the end of all normal plays.
# If there were changes in /etc, it'll commit them.
- etckeeper: action=commit msg="foo"
# Put this at the end of all plays only including other plays.
# It does the same thing "begin" does: ensuring /etc is clean.
- etckeeper: action=end
# If you want, you can add the git revision of the playbook
# to the commit messages:
- set_fact:
revision: "{{ lookup('pipe', 'cd \"%s\" ; git rev-parse HEAD' % playbook_dir) }}"
- etckeeper: "action=commit msg='foo' rev={{ revision }}"
# There are two notable exceptions:
#
# 1. A role responsible for installing etckeeper can't use "etckeeper action=begin"
# during the first run, because etckeeper won't be available yet. However,
# during subsequent runs, you actually do want action=begin to ensure /etc is clean.
# The solution is:
- etckeeper: action=begin ignore_missing_etckeeper=yes
# 2. etckeeper will create commits during package management actions automatically.
# Therefore, apt/yum/... tasks should be outside (ideally: before) an etckeeper begin/end.
'''
from os.path import exists
from ansible.module_utils.basic import *
import distutils.spawn
def main():
module = AnsibleModule(
supports_check_mode=True,
argument_spec={
'action': dict(required=True, choices=['begin', 'commit', 'end']),
'ignore_missing_etckeeper': dict(default='no', choices=['yes', 'no']),
'msg': dict(),
'rev': dict(),
}
)
if not distutils.spawn.find_executable('etckeeper'):
if module.params['ignore_missing_etckeeper']:
module.exit_json()
rc, out, err = module.run_command(['etckeeper', 'unclean'])
if err:
module.fail_json(msg=err)
is_clean = (rc != 0)
if module.params['action'] in ('begin', 'end'):
if is_clean:
module.exit_json()
else:
module.fail_json(msg='/etc is not clean')
elif module.params['action'] == 'commit':
if module.check_mode:
if is_clean:
module.exit_json(changed=False)
else:
module.fail_json(msg='/etc is supposed to remain clean in check mode')
if not is_clean:
msg = module.params['msg']
if not msg:
module.fail_json(msg='msg must not be empty')
if module.params['rev']:
msg += "\n\nRevision: " + module.params['rev']
rc, out, err = module.run_command(['etckeeper', 'commit', msg], check_rc=True)
if err:
module.fail_json(msg=err)
module.exit_json(changed=not is_clean)
else:
module.fail_json(msg='bad action: "%s"' % module.params['action'])
if __name__ == '__main__':
main()