-
Notifications
You must be signed in to change notification settings - Fork 15
/
goss.py
147 lines (121 loc) · 4.56 KB
/
goss.py
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python3
# FROM: https://github.com/indusbox/goss-ansible
''' Launch goss (https://github.com/aelsabbahy/goss) tests '''
import os
from ansible.module_utils.basic import AnsibleModule
DOCUMENTATION = '''
---
module: goss
author: Mathieu Corbin
short_description: Launch goss (https://github.com/aelsabbahy/goss) tests
description:
- Launch goss tests.
This module always returns `changed = false` for idempotence.
options:
path:
required: true
description:
- Test file to validate.
The test file must be on the remote machine.
goss_path:
required: false
description:
- Path location for the goss executable.
Default is "goss" (ie.`no absolute path, goss executable must be available in $PATH).
vars_path:
required: false
description:
- Path location for a variables YAML/JSON file to use as templating inputs.
format:
required: false
description:
- Output goss format.
Goss format list : goss v --format => [documentation json junit nagios nagios_verbose rspecish tap silent].
Default is "rspecish".
output_file:
required: false
description:
- Save the result of the goss command in a file whose path is output_file
examples:
- name: run goss against the gossfile /path/to/file.yml
goss:
path: "/path/to/file.yml"
- name: run goss against the gossfile /path/to/file.yml with nagios output
goss:
path: "/path/to/file.yml"
format: "nagios"
- name: run /usr/local/bin/goss against the gossfile /path/to/file.yml
goss:
path: "/path/to/file.yml"
goss_path: "/usr/local/bin/goss"
- name: run /usr/local/bin/goss with a variables file
goss:
vars_path: "/path/to/file.yml"
- name: run goss against multiple gossfiles and write the result in JSON format to /my/output/ for each file
goss:
path: "{{ item }}"
format: json
output_file : /my/output/{{ item }}
with_items: "{{ goss_files }}"
'''
def check(module, test_file_path, output_format, goss_path, vars_path):
"""
Launch goss validate command on the file
"""
cmd = f'{ goss_path } --gossfile { test_file_path }'
# goss parent command flags
if vars_path is not None:
cmd += f' --vars { vars_path }'
# validate sub-command flags
cmd += ' validate'
if output_format is not None:
cmd += f' --format { output_format }'
return module.run_command(cmd)
def write_result(output_file_path, out):
"""
Write goss result to output_file_path
"""
if output_file_path is not None:
with open(output_file_path, 'w', encoding="utf-8") as output_file:
output_file.write(out)
def run_module():
"""
Launch goss tests
"""
module = AnsibleModule(
argument_spec=dict(
path=dict(required=True, type='str'),
format=dict(required=False, type='str'),
output_file=dict(required=False, type='str'),
vars_path=dict(required=False, type='str'),
goss_path=dict(required=False, default='goss', type='str'),
),
supports_check_mode=False
)
test_file_path = module.params['path']
output_format = module.params['format'] # goss output format
output_file_path = module.params['output_file']
goss_path = module.params['goss_path']
vars_path = module.params['vars_path']
test_file_path = os.path.expanduser(test_file_path)
if not os.access(test_file_path, os.R_OK):
module.fail_json(msg=f'Test file { test_file_path } not readable')
if os.path.isdir(test_file_path):
module.fail_json(msg=f'Test file { test_file_path } must be a file but is a path')
rc, out, err = check(module, test_file_path, output_format, goss_path, vars_path)
if output_file_path is not None:
output_file_path = os.path.expanduser(output_file_path)
if output_file_path.endswith(os.sep):
module.fail_json(msg=f'output_file { output_file_path } must be a file')
output_dirname = os.path.dirname(output_file_path)
if not os.path.exists(output_dirname):
module.fail_json(msg=f'directory { output_dirname } does not exists')
if not os.access(os.path.dirname(output_file_path), os.W_OK):
module.fail_json(msg=f'Destination { output_dirname } not writable')
write_result(output_file_path, out)
if rc is not None and rc != 0:
error_msg = f'err : { err } ; out : { out }'
module.fail_json(msg=error_msg)
module.exit_json(stdout=out, changed=False)
if __name__ == '__main__':
run_module()