tdi 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/Gemfile.lock +6 -2
- data/README.md +257 -22
- data/bin/tdi +25 -13
- data/doc/json/acl.json +25 -0
- data/doc/json/file.json +31 -0
- data/doc/json/http.json +38 -0
- data/doc/json/ssh.json +16 -0
- data/helper/acl.rb +28 -17
- data/helper/file.rb +9 -8
- data/helper/http.rb +65 -65
- data/helper/ssh.rb +23 -12
- data/lib/planner.rb +9 -7
- data/lib/rblank.rb +1 -1
- data/lib/rmerge.rb +1 -1
- data/lib/runner.rb +36 -16
- data/lib/tdi.rb +20 -8
- data/lib/tdi/version.rb +2 -2
- data/lib/util.rb +110 -0
- data/tdi.gemspec +2 -0
- metadata +35 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47c8026be31f39925f4b22a48afdd0070a0c0d39
|
4
|
+
data.tar.gz: 0c1286f06d7550f8a39b370afffecfaeaaafb5bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dba228dc172403647f00af1b49777b0ed7282ddb6dd368a2c3ece1f99a9598350bf1af368db8e5fc35ae5eff57712aa189c13cada7b8cf1e082565afb773a167
|
7
|
+
data.tar.gz: 4166852fd8e3059b7848d0fcaf948caa879ec910b8eab6440c761e1fbd2624a727bef55258b2d39ee4f8aa15e66f5bcf3240bce5fbcaf9109c3487d8c83ebad8
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tdi (0.1.
|
4
|
+
tdi (0.1.7)
|
5
|
+
awesome_print
|
5
6
|
colorize
|
6
7
|
etc
|
8
|
+
ipaddress
|
7
9
|
net-ssh
|
8
10
|
os
|
9
11
|
slop (~> 3.6)
|
@@ -12,8 +14,10 @@ PATH
|
|
12
14
|
GEM
|
13
15
|
remote: https://rubygems.org/
|
14
16
|
specs:
|
15
|
-
|
17
|
+
awesome_print (1.6.1)
|
18
|
+
colorize (0.7.7)
|
16
19
|
etc (0.2.0)
|
20
|
+
ipaddress (0.8.0)
|
17
21
|
net-ssh (2.9.2)
|
18
22
|
os (0.9.6)
|
19
23
|
rake (10.4.2)
|
data/README.md
CHANGED
@@ -1,46 +1,281 @@
|
|
1
1
|
# TDI
|
2
2
|
|
3
|
-
Test Driven Infrastructure acceptance helpers
|
4
|
-
|
3
|
+
Test Driven Infrastructure acceptance helpers.
|
4
|
+
|
5
|
+
Validate your deployed infrastructure and external dependencies.
|
5
6
|
|
6
7
|
## Installation
|
7
8
|
|
8
|
-
Add this line to your
|
9
|
+
Add this line to your Gemfile:
|
9
10
|
|
10
|
-
|
11
|
+
```bash
|
12
|
+
gem 'tdi'
|
13
|
+
```
|
11
14
|
|
12
15
|
And then execute:
|
13
16
|
|
14
|
-
|
17
|
+
```bash
|
18
|
+
$ bundle
|
19
|
+
```
|
15
20
|
|
16
|
-
Or install
|
21
|
+
Or install with:
|
17
22
|
|
18
|
-
|
23
|
+
```bash
|
24
|
+
$ gem install tdi
|
25
|
+
```
|
19
26
|
|
20
27
|
## Usage
|
21
28
|
|
22
|
-
|
29
|
+
```bash
|
30
|
+
$ tdi [-h]
|
23
31
|
|
24
32
|
Usage:
|
25
33
|
|
26
|
-
tdi [options]
|
34
|
+
tdi test_plan_file [options]
|
27
35
|
|
28
36
|
Examples:
|
29
37
|
|
30
38
|
tdi tdi.json
|
31
|
-
|
32
|
-
tdi
|
33
|
-
tdi
|
34
|
-
|
35
|
-
tdi
|
36
|
-
tdi
|
37
|
-
tdi
|
38
|
-
tdi
|
39
|
+
|
40
|
+
tdi tdi.json -n
|
41
|
+
tdi tdi.json --nofail
|
42
|
+
|
43
|
+
tdi tdi.json -p app
|
44
|
+
tdi tdi.json --plan app
|
45
|
+
tdi tdi.json --plan app::acl
|
46
|
+
tdi tdi.json --plan app::acl,app::file
|
47
|
+
|
48
|
+
tdi tdi.json -r /tmp/tdi-report.json
|
49
|
+
tdi tdi.json --reportfile /tmp/tdi-report.json
|
50
|
+
|
51
|
+
tdi tdi.json -s
|
52
|
+
tdi tdi.json --shred
|
53
|
+
|
54
|
+
tdi tdi.json -v
|
55
|
+
tdi tdi.json -vv
|
56
|
+
tdi tdi.json -vvv
|
57
|
+
|
58
|
+
tdi --version
|
39
59
|
|
40
60
|
Options:
|
41
61
|
|
42
|
-
-n, --nofail
|
43
|
-
-p, --plan
|
44
|
-
-
|
45
|
-
-
|
46
|
-
-
|
62
|
+
-n, --nofail No fail mode.
|
63
|
+
-p, --plan Test plan list.
|
64
|
+
-r, --reportfile Report file to save test plan status.
|
65
|
+
-s, --shred Wipe out the test plan, leaving no trace behind.
|
66
|
+
-v, --verbose Verbose mode.
|
67
|
+
--version Version.
|
68
|
+
-h, --help Display this help message.
|
69
|
+
```
|
70
|
+
|
71
|
+
## Test plan samples
|
72
|
+
|
73
|
+
[Sample TDI JSONs](https://github.com/globocom/tdi/tree/master/doc/json)
|
74
|
+
|
75
|
+
### ACL
|
76
|
+
|
77
|
+
Test network access/filters for TCP services.
|
78
|
+
|
79
|
+
[acl.json](https://github.com/globocom/tdi/tree/master/doc/json/acl.json)
|
80
|
+
|
81
|
+
```json
|
82
|
+
{
|
83
|
+
"app": {
|
84
|
+
"desc": "Test role",
|
85
|
+
"acl": {
|
86
|
+
"port": 80,
|
87
|
+
|
88
|
+
"www.globo.com": {},
|
89
|
+
|
90
|
+
"globoesporte.globo.com": {},
|
91
|
+
|
92
|
+
"cartolafc.globo.com": {},
|
93
|
+
|
94
|
+
"doesnotexist.globo.com": {},
|
95
|
+
|
96
|
+
"www.example.com": {
|
97
|
+
"port": [80, 9999],
|
98
|
+
"timeout": 3
|
99
|
+
},
|
100
|
+
|
101
|
+
"localhost": {
|
102
|
+
"port": [22, 31337]
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
```
|
108
|
+
|
109
|
+
### FILE
|
110
|
+
|
111
|
+
Test files and diretories permissions.
|
112
|
+
|
113
|
+
[file.json](https://github.com/globocom/tdi/tree/master/doc/json/file.json)
|
114
|
+
|
115
|
+
```json
|
116
|
+
{
|
117
|
+
"app": {
|
118
|
+
"desc": "Test role",
|
119
|
+
"file": {
|
120
|
+
"user": "nobody",
|
121
|
+
"perm": "rw",
|
122
|
+
"type": "file",
|
123
|
+
"location": "local",
|
124
|
+
|
125
|
+
"/tmp/afile1.txt": {},
|
126
|
+
|
127
|
+
"/tmp/afile2.txt": {
|
128
|
+
"perm": "ro"
|
129
|
+
},
|
130
|
+
|
131
|
+
"/tmp/afile3.txt": {
|
132
|
+
"user": "root"
|
133
|
+
},
|
134
|
+
|
135
|
+
"/tmp/doesnotexist/afile.txt": {},
|
136
|
+
|
137
|
+
"/tmp/doesnotexist": {
|
138
|
+
"type": "directory"
|
139
|
+
},
|
140
|
+
|
141
|
+
"/tmp": {
|
142
|
+
"type": "directory"
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
```
|
148
|
+
|
149
|
+
### HTTP
|
150
|
+
|
151
|
+
Test URLs and match expected responses.
|
152
|
+
|
153
|
+
[http.json](https://github.com/globocom/tdi/tree/master/doc/json/http.json)
|
154
|
+
|
155
|
+
```json
|
156
|
+
{
|
157
|
+
"app": {
|
158
|
+
"desc": "Test role",
|
159
|
+
"http": {
|
160
|
+
"globoesporte.globo.com": {
|
161
|
+
"match": "<html"
|
162
|
+
},
|
163
|
+
|
164
|
+
"http://globoesporte.com": {
|
165
|
+
"code": 301,
|
166
|
+
"expect_header": "Location: http://globoesporte.globo.com/"
|
167
|
+
},
|
168
|
+
|
169
|
+
"http://api.sde.globo.com/docs": {
|
170
|
+
"code" : 301
|
171
|
+
},
|
172
|
+
|
173
|
+
"https://api.sde.globo.com/path/to/resource": {
|
174
|
+
"code" : 401
|
175
|
+
},
|
176
|
+
|
177
|
+
"doesnotexist.globo.com": {},
|
178
|
+
|
179
|
+
"https://api.cartola.globo.com/mercado/status.json": {},
|
180
|
+
|
181
|
+
"https://api.cartola.globo.com/wrong-url": {},
|
182
|
+
|
183
|
+
"http://g1.globo.com": {
|
184
|
+
"code": 301,
|
185
|
+
"match": "<html"
|
186
|
+
},
|
187
|
+
|
188
|
+
"http://g1.globo.com/index.html": {
|
189
|
+
"match": "<html"
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
}
|
194
|
+
```
|
195
|
+
|
196
|
+
### SSH
|
197
|
+
|
198
|
+
Test SSH access and login using public/private key pairs.
|
199
|
+
|
200
|
+
[ssh.json](https://github.com/globocom/tdi/tree/master/doc/json/ssh.json)
|
201
|
+
|
202
|
+
```json
|
203
|
+
{
|
204
|
+
"app": {
|
205
|
+
"desc": "Test role",
|
206
|
+
"ssh": {
|
207
|
+
"timeout": 7,
|
208
|
+
|
209
|
+
"u_remote@localhost": {
|
210
|
+
"local_user": "u_local"
|
211
|
+
},
|
212
|
+
|
213
|
+
"u_remote2@localhost": {
|
214
|
+
"local_user": ["u_local", "u_local2"]
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
}
|
219
|
+
```
|
220
|
+
|
221
|
+
## Generating test plans
|
222
|
+
|
223
|
+
You may write your test plans as JSON in the following ways:
|
224
|
+
|
225
|
+
* By hand, as pure JSON files
|
226
|
+
|
227
|
+
* Using some templating engine (ERB, Jinja, etc...)
|
228
|
+
|
229
|
+
* With your favorite programming language (Ruby, Python, etc...)
|
230
|
+
|
231
|
+
It does not matter how you generate your test plan, as long as it results in a
|
232
|
+
valid JSON file. Certainly it would be a good idea to write your test plans from
|
233
|
+
within Capistrano/Fabric/Chef/Puppet. Since the difference between environments
|
234
|
+
(development, staging, production) should be known by your deployment tool, it
|
235
|
+
would be clever to let that tool decide which paths, users, permissions and
|
236
|
+
addresses to write into the test plan file.
|
237
|
+
|
238
|
+
Bellow we give you some suggestions on how to generate your test plans more
|
239
|
+
efficiently (because writting JSON by hand is boring):
|
240
|
+
|
241
|
+
### Ruby
|
242
|
+
|
243
|
+
```ruby
|
244
|
+
require 'json'
|
245
|
+
|
246
|
+
tdi_plan = {
|
247
|
+
:app => {
|
248
|
+
:desc => 'Test role',
|
249
|
+
:acl => {'localhost' => {:port => [22, 80]}},
|
250
|
+
:http => {'globo.com' => {:code => 301}},
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
File.open('tdi.json', 'w').write(JSON.pretty_generate(tdi_plan))
|
255
|
+
```
|
256
|
+
|
257
|
+
### Python
|
258
|
+
|
259
|
+
```python
|
260
|
+
import json
|
261
|
+
|
262
|
+
tdi_plan = {
|
263
|
+
'app': {
|
264
|
+
'desc': 'Test role',
|
265
|
+
'acl': {'localhost': {'port': [22, 80]}},
|
266
|
+
'http': {'globo.com': {'code': 301}},
|
267
|
+
}
|
268
|
+
}
|
269
|
+
|
270
|
+
open('tdi.json', 'w').write(json.dumps(tdi_plan, indent=2))
|
271
|
+
```
|
272
|
+
|
273
|
+
### Validate
|
274
|
+
|
275
|
+
Use JSONLint site to validate your JSONs.
|
276
|
+
|
277
|
+
http://jsonlint.com/
|
278
|
+
|
279
|
+
## Contributors
|
280
|
+
|
281
|
+
[People](https://github.com/globocom/tdi/graphs/contributors)
|
data/bin/tdi
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
#
|
21
21
|
# === Copyright
|
22
22
|
#
|
23
|
-
# Copyright (C) 2013-
|
23
|
+
# Copyright (C) 2013-2015 Globo.com
|
24
24
|
#
|
25
25
|
|
26
26
|
# This file is part of TDI.
|
@@ -157,31 +157,43 @@ end
|
|
157
157
|
|
158
158
|
# Command line options.
|
159
159
|
begin
|
160
|
-
opts = Slop.parse(:
|
160
|
+
opts = Slop.parse(help: true, strict: true) do
|
161
161
|
banner <<-EOS
|
162
162
|
Usage:
|
163
163
|
|
164
|
-
tdi [options]
|
164
|
+
tdi test_plan_file [options]
|
165
165
|
|
166
166
|
Examples:
|
167
167
|
|
168
168
|
tdi tdi.json
|
169
|
-
|
170
|
-
tdi
|
171
|
-
tdi
|
172
|
-
|
173
|
-
tdi
|
174
|
-
tdi
|
175
|
-
tdi
|
176
|
-
tdi
|
169
|
+
|
170
|
+
tdi tdi.json -n
|
171
|
+
tdi tdi.json --nofail
|
172
|
+
|
173
|
+
tdi tdi.json -p app
|
174
|
+
tdi tdi.json --plan app
|
175
|
+
tdi tdi.json --plan app::acl
|
176
|
+
tdi tdi.json --plan app::acl,app::file
|
177
|
+
|
178
|
+
tdi tdi.json -r /tmp/tdi-report.json
|
179
|
+
tdi tdi.json --reportfile /tmp/tdi-report.json
|
180
|
+
|
181
|
+
tdi tdi.json -s
|
182
|
+
tdi tdi.json --shred
|
183
|
+
|
184
|
+
tdi tdi.json -v
|
185
|
+
tdi tdi.json -vv
|
186
|
+
tdi tdi.json -vvv
|
187
|
+
|
177
188
|
tdi --version
|
178
189
|
|
179
190
|
Options:
|
180
191
|
EOS
|
181
192
|
on :n, :nofail, 'No fail mode.'
|
182
|
-
on :p, :plan, 'Test plan list.', :
|
193
|
+
on :p, :plan, 'Test plan list.', as: Array, argument: :optional
|
194
|
+
on :r, :reportfile, 'Report file to save test plan status.', argument: :required
|
183
195
|
on :s, :shred, 'Wipe out the test plan, leaving no trace behind.'
|
184
|
-
on :v, :verbose, 'Verbose mode.', :
|
196
|
+
on :v, :verbose, 'Verbose mode.', as: :count
|
185
197
|
on :version, 'Version.'
|
186
198
|
end
|
187
199
|
rescue => e
|
data/doc/json/acl.json
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"app": {
|
3
|
+
"desc": "Test role",
|
4
|
+
"acl": {
|
5
|
+
"port": 80,
|
6
|
+
|
7
|
+
"www.globo.com": {},
|
8
|
+
|
9
|
+
"globoesporte.globo.com": {},
|
10
|
+
|
11
|
+
"cartolafc.globo.com": {},
|
12
|
+
|
13
|
+
"doesnotexist.globo.com": {},
|
14
|
+
|
15
|
+
"www.example.com": {
|
16
|
+
"port": [80, 9999],
|
17
|
+
"timeout": 3
|
18
|
+
},
|
19
|
+
|
20
|
+
"localhost": {
|
21
|
+
"port": [22, 31337]
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
data/doc/json/file.json
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
{
|
2
|
+
"app": {
|
3
|
+
"desc": "Test role",
|
4
|
+
"file": {
|
5
|
+
"user": "nobody",
|
6
|
+
"perm": "rw",
|
7
|
+
"type": "file",
|
8
|
+
"location": "local",
|
9
|
+
|
10
|
+
"/tmp/afile1.txt": {},
|
11
|
+
|
12
|
+
"/tmp/afile2.txt": {
|
13
|
+
"perm": "ro"
|
14
|
+
},
|
15
|
+
|
16
|
+
"/tmp/afile3.txt": {
|
17
|
+
"user": "root"
|
18
|
+
},
|
19
|
+
|
20
|
+
"/tmp/doesnotexist/afile.txt": {},
|
21
|
+
|
22
|
+
"/tmp/doesnotexist": {
|
23
|
+
"type": "directory"
|
24
|
+
},
|
25
|
+
|
26
|
+
"/tmp": {
|
27
|
+
"type": "directory"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|