rundeck 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.hound.yml +4 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +35 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/Guardfile +16 -0
- data/LICENSE.txt +10 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/lib/rundeck.rb +29 -0
- data/lib/rundeck/api.rb +17 -0
- data/lib/rundeck/client.rb +21 -0
- data/lib/rundeck/client/jobs.rb +119 -0
- data/lib/rundeck/client/keys.rb +177 -0
- data/lib/rundeck/configuration.rb +42 -0
- data/lib/rundeck/error.rb +45 -0
- data/lib/rundeck/objectified_hash.rb +24 -0
- data/lib/rundeck/request.rb +93 -0
- data/lib/rundeck/version.rb +3 -0
- data/rundeck.gemspec +33 -0
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/job.xml +17 -0
- data/spec/fixtures/job_executions.xml +31 -0
- data/spec/fixtures/job_run.xml +16 -0
- data/spec/fixtures/jobs_import.xml +23 -0
- data/spec/fixtures/jobs_my_project.xml +14 -0
- data/spec/fixtures/jobs_xml.xml +32 -0
- data/spec/fixtures/jobs_yaml.xml +22 -0
- data/spec/fixtures/key_contents_public.xml +1 -0
- data/spec/fixtures/key_private.xml +8 -0
- data/spec/fixtures/key_public.xml +7 -0
- data/spec/fixtures/keys.xml +27 -0
- data/spec/rundeck/client/jobs_spec.rb +181 -0
- data/spec/rundeck/client/keys_spec.rb +216 -0
- data/spec/rundeck/client_spec.rb +36 -0
- data/spec/rundeck/objectified_hash_spec.rb +46 -0
- data/spec/rundeck/request_spec.rb +40 -0
- data/spec/rundeck_spec.rb +55 -0
- data/spec/spec_helper.rb +77 -0
- metadata +258 -0
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rundeck::Client do
|
4
|
+
describe '.jobs' do
|
5
|
+
before do
|
6
|
+
stub_get('/project/My_Project/jobs', 'jobs_my_project')
|
7
|
+
@jobs = Rundeck.jobs('My_Project')
|
8
|
+
end
|
9
|
+
subject { @jobs }
|
10
|
+
|
11
|
+
it { is_expected.to be_an Array }
|
12
|
+
its('first.name') { is_expected.to eq('Job 1') }
|
13
|
+
|
14
|
+
it 'expects a get to have been made' do
|
15
|
+
expect(a_get('/project/My_Project/jobs')).to have_been_made
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '.job' do
|
20
|
+
before do
|
21
|
+
stub_get('/job/c07518ef-b697-4792-9a59-5b4f08855b67', 'job')
|
22
|
+
@job = Rundeck.job('c07518ef-b697-4792-9a59-5b4f08855b67')
|
23
|
+
end
|
24
|
+
subject { @job }
|
25
|
+
|
26
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
27
|
+
its(:name) { is_expected.to eq('Hello World') }
|
28
|
+
|
29
|
+
it 'expects a get to have been made' do
|
30
|
+
expect(
|
31
|
+
a_get('/job/c07518ef-b697-4792-9a59-5b4f08855b67')
|
32
|
+
).to have_been_made
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.delete_job' do
|
37
|
+
before do
|
38
|
+
stub_delete('/job/c07518ef-b697-4792-9a59-5b4f08855b67', 'empty')
|
39
|
+
@job = Rundeck.delete_job('c07518ef-b697-4792-9a59-5b4f08855b67')
|
40
|
+
end
|
41
|
+
subject { @job }
|
42
|
+
|
43
|
+
it { is_expected.to be_nil }
|
44
|
+
|
45
|
+
it 'expects a delete to have been made' do
|
46
|
+
expect(
|
47
|
+
a_delete('/job/c07518ef-b697-4792-9a59-5b4f08855b67')
|
48
|
+
).to have_been_made
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '.job_executions' do
|
53
|
+
before do
|
54
|
+
stub_get('/job/c07518ef-b697-4792-9a59-5b4f08855b67/executions',
|
55
|
+
'job_executions')
|
56
|
+
@job_executions =
|
57
|
+
Rundeck.job_executions('c07518ef-b697-4792-9a59-5b4f08855b67')
|
58
|
+
end
|
59
|
+
subject { @job_executions }
|
60
|
+
|
61
|
+
it { is_expected.to be_an Array }
|
62
|
+
its('first.job.name') { is_expected.to eq('Job 1') }
|
63
|
+
|
64
|
+
it 'expects a get to have been made' do
|
65
|
+
expect(
|
66
|
+
a_get('/job/c07518ef-b697-4792-9a59-5b4f08855b67/executions')
|
67
|
+
).to have_been_made
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '.run_job' do
|
72
|
+
before do
|
73
|
+
stub_post('/job/c07518ef-b697-4792-9a59-5b4f08855b67/executions',
|
74
|
+
'job_run')
|
75
|
+
@run_job =
|
76
|
+
Rundeck.run_job('c07518ef-b697-4792-9a59-5b4f08855b67')
|
77
|
+
end
|
78
|
+
subject { @run_job }
|
79
|
+
|
80
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
81
|
+
its('job.name') { is_expected.to eq('My_Job') }
|
82
|
+
|
83
|
+
it 'expects a post to have been made' do
|
84
|
+
expect(
|
85
|
+
a_post('/job/c07518ef-b697-4792-9a59-5b4f08855b67/executions')
|
86
|
+
).to have_been_made
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '.import_job' do
|
91
|
+
context 'with valid format' do
|
92
|
+
before do
|
93
|
+
stub_post("/jobs/import?format=#{format}", 'jobs_import')
|
94
|
+
@import = Rundeck.import_jobs(content, format)
|
95
|
+
end
|
96
|
+
subject { @import }
|
97
|
+
|
98
|
+
context 'yaml' do
|
99
|
+
let(:format) { 'yaml' }
|
100
|
+
let(:content) { '- id: 123456' }
|
101
|
+
|
102
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
103
|
+
its('succeeded.count') { is_expected.to eq('1') }
|
104
|
+
its('failed.count') { is_expected.to eq('0') }
|
105
|
+
|
106
|
+
it 'expects a post to have been made' do
|
107
|
+
expect(a_post('/jobs/import?format=yaml')).to have_been_made
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'xml' do
|
112
|
+
let(:format) { 'xml' }
|
113
|
+
let(:content) { '<id>12345</id>' }
|
114
|
+
|
115
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
116
|
+
its('succeeded.count') { is_expected.to eq('1') }
|
117
|
+
its('failed.count') { is_expected.to eq('0') }
|
118
|
+
|
119
|
+
it 'expects a post to have been made' do
|
120
|
+
expect(a_post('/jobs/import?format=xml')).to have_been_made
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'with invalid format' do
|
126
|
+
specify do
|
127
|
+
expect do
|
128
|
+
Rundeck.import_jobs('content', 'invalid_format')
|
129
|
+
end.to raise_error(Rundeck::Error::InvalidAttributes,
|
130
|
+
'format must be yaml or xml')
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe '.export_job' do
|
136
|
+
context 'with valid format' do
|
137
|
+
before do
|
138
|
+
stub_get("/jobs/export?project=my_project&format=#{format}", fixture)
|
139
|
+
@jobs = Rundeck.export_jobs('my_project', format)
|
140
|
+
end
|
141
|
+
subject { @jobs }
|
142
|
+
|
143
|
+
context 'yaml' do
|
144
|
+
let(:format) { 'yaml' }
|
145
|
+
let(:fixture) { 'jobs_yaml' }
|
146
|
+
|
147
|
+
it { is_expected.to be_a String }
|
148
|
+
it { is_expected.to include 'id: c07518ef-b697-4792-9a59-5b4f08855b67' }
|
149
|
+
|
150
|
+
it 'expects a get to have been made' do
|
151
|
+
expect(
|
152
|
+
a_get('/jobs/export?project=my_project&format=yaml')
|
153
|
+
).to have_been_made
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'xml' do
|
158
|
+
let(:format) { 'xml' }
|
159
|
+
let(:fixture) { 'jobs_xml' }
|
160
|
+
|
161
|
+
it { is_expected.to be_a String }
|
162
|
+
it { is_expected.to include '<id>c07518ef-b697-4792-9a59-5b4f08855b67</id>' }
|
163
|
+
|
164
|
+
it 'expects a get to have been made' do
|
165
|
+
expect(
|
166
|
+
a_get('/jobs/export?project=my_project&format=xml')
|
167
|
+
).to have_been_made
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with invalid format' do
|
173
|
+
specify do
|
174
|
+
expect do
|
175
|
+
Rundeck.export_jobs('my_project', 'invalid_format')
|
176
|
+
end.to raise_error(Rundeck::Error::InvalidAttributes,
|
177
|
+
'format must be yaml or xml')
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rundeck::Client do
|
4
|
+
describe '.keys' do
|
5
|
+
context 'with a path containing multiple keys' do
|
6
|
+
before do
|
7
|
+
stub_get('/storage/keys/', 'keys')
|
8
|
+
@keys = Rundeck.keys
|
9
|
+
end
|
10
|
+
subject { @keys }
|
11
|
+
|
12
|
+
it { is_expected.to be_an Array }
|
13
|
+
its('first.resource_meta.rundeck_key_type') { is_expected.to eq('public') }
|
14
|
+
|
15
|
+
it 'expects a get to have been made' do
|
16
|
+
expect(a_get('/storage/keys/')).to have_been_made
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'with a direct path to a key' do
|
21
|
+
before do
|
22
|
+
stub_get('/storage/keys/path/to/key1', 'key_public')
|
23
|
+
end
|
24
|
+
|
25
|
+
specify do
|
26
|
+
expect do
|
27
|
+
Rundeck.keys('path/to/key1')
|
28
|
+
end.to raise_error(Rundeck::Error::InvalidAttributes,
|
29
|
+
'Please provide a key storage path that ' \
|
30
|
+
'isn\'t a direct path to a key')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.key_metadata' do
|
36
|
+
context 'with a direct path to a key' do
|
37
|
+
before do
|
38
|
+
stub_get('/storage/keys/path/to/key1', 'key_public')
|
39
|
+
@key = Rundeck.key_metadata('path/to/key1')
|
40
|
+
end
|
41
|
+
subject { @key }
|
42
|
+
|
43
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
44
|
+
its(:rundeck_content_type) { is_expected.to eq('application/pgp-keys') }
|
45
|
+
|
46
|
+
it 'expects a get to have been made' do
|
47
|
+
expect(a_get('/storage/keys/path/to/key1')).to have_been_made
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with a path containing multiple keys' do
|
52
|
+
before do
|
53
|
+
stub_get('/storage/keys/path/to/keys', 'keys')
|
54
|
+
end
|
55
|
+
|
56
|
+
it do
|
57
|
+
expect do
|
58
|
+
Rundeck.key_metadata('path/to/keys')
|
59
|
+
end.to raise_error(Rundeck::Error::InvalidAttributes,
|
60
|
+
'Please provide a key storage path that ' \
|
61
|
+
'is a direct path to a key')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '.key_contents' do
|
67
|
+
context 'with a direct path to a key' do
|
68
|
+
before do
|
69
|
+
stub_get('/storage/keys/path/to/key1', 'key_public')
|
70
|
+
stub_get('/storage/keys/path/to/key1', 'key_contents_public', 'pgp-keys')
|
71
|
+
@key = Rundeck.key_contents('path/to/key1')
|
72
|
+
end
|
73
|
+
subject { @key }
|
74
|
+
|
75
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
76
|
+
its(:public_key) { is_expected.to include('ssh-rsa') }
|
77
|
+
|
78
|
+
it 'expects a get to have been made' do
|
79
|
+
expect(a_get('/storage/keys/path/to/key1')).to have_been_made
|
80
|
+
end
|
81
|
+
it 'expects a get to have been made' do
|
82
|
+
expect(a_get('/storage/keys/path/to/key1', 'pgp-keys')).to have_been_made
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'with a path containing multiple keys' do
|
87
|
+
before do
|
88
|
+
stub_get('/storage/keys/path/to/keys', 'keys')
|
89
|
+
end
|
90
|
+
|
91
|
+
it do
|
92
|
+
expect do
|
93
|
+
Rundeck.key_contents('path/to/keys')
|
94
|
+
end.to raise_error(Rundeck::Error::InvalidAttributes,
|
95
|
+
'Please provide a key storage path that ' \
|
96
|
+
'is a direct path to a key')
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when trying to get a private key' do
|
101
|
+
before do
|
102
|
+
stub_get('/storage/keys/path/to/key2', 'key_private')
|
103
|
+
end
|
104
|
+
|
105
|
+
it do
|
106
|
+
expect do
|
107
|
+
Rundeck.key_contents('path/to/key2')
|
108
|
+
end.to raise_error(Rundeck::Error::Unauthorized,
|
109
|
+
'You are not allowed to retrieve the contents ' \
|
110
|
+
'of a private key')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '.create_private_key' do
|
116
|
+
before do
|
117
|
+
keystring = <<-EOD
|
118
|
+
-----BEGIN RSA PRIVATE KEY-----
|
119
|
+
Proc-Type: 4,ENCRYPTED
|
120
|
+
DEK-Info: AES-128-CBC,E283774838299...
|
121
|
+
-----END RSA PRIVATE KEY-----
|
122
|
+
EOD
|
123
|
+
stub_post('/storage/keys/path/to/my_key', 'key_private')
|
124
|
+
@key = Rundeck.create_private_key('path/to/my_key', keystring)
|
125
|
+
end
|
126
|
+
subject { @key }
|
127
|
+
|
128
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
129
|
+
its(:rundeck_key_type) { is_expected.to eq('private') }
|
130
|
+
|
131
|
+
it 'expects a post to have been made' do
|
132
|
+
expect(
|
133
|
+
a_post('/storage/keys/path/to/my_key')
|
134
|
+
).to have_been_made
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '.update_private_key' do
|
139
|
+
before do
|
140
|
+
keystring = <<-EOD
|
141
|
+
-----BEGIN RSA PRIVATE KEY-----
|
142
|
+
Proc-Type: 4,ENCRYPTED
|
143
|
+
DEK-Info: AES-128-CBC,E283774838299...
|
144
|
+
-----END RSA PRIVATE KEY-----
|
145
|
+
EOD
|
146
|
+
stub_get('/storage/keys/path/to/key1', 'key_private')
|
147
|
+
stub_put('/storage/keys/path/to/key1', 'key_private')
|
148
|
+
@key = Rundeck.update_private_key('path/to/key1', keystring)
|
149
|
+
end
|
150
|
+
subject { @key }
|
151
|
+
|
152
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
153
|
+
its(:rundeck_key_type) { is_expected.to eq('private') }
|
154
|
+
|
155
|
+
it 'expects a get to have been made' do
|
156
|
+
expect(a_get('/storage/keys/path/to/key1')).to have_been_made
|
157
|
+
end
|
158
|
+
it 'expects a put to have been made' do
|
159
|
+
expect(a_put('/storage/keys/path/to/key1')).to have_been_made
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '.create_public_key' do
|
164
|
+
before do
|
165
|
+
keystring = 'ssh-rsa AAAA....3MOj user@example.com'
|
166
|
+
stub_post('/storage/keys/path/to/my_public_key', 'key_public')
|
167
|
+
@key = Rundeck.create_public_key('path/to/my_public_key', keystring)
|
168
|
+
end
|
169
|
+
subject { @key }
|
170
|
+
|
171
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
172
|
+
its(:rundeck_content_type) { is_expected.to eq('application/pgp-keys') }
|
173
|
+
|
174
|
+
it 'expects a post to have been made' do
|
175
|
+
expect(
|
176
|
+
a_post('/storage/keys/path/to/my_public_key')
|
177
|
+
).to have_been_made
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '.update_public_key' do
|
182
|
+
before do
|
183
|
+
keystring = <<-EOD
|
184
|
+
ssh-rsa AAAA....ZlxUH user@example.com
|
185
|
+
EOD
|
186
|
+
stub_get('/storage/keys/path/to/key1', 'key_public')
|
187
|
+
stub_put('/storage/keys/path/to/key1', 'key_public')
|
188
|
+
@key = Rundeck.update_public_key('path/to/key1', keystring)
|
189
|
+
end
|
190
|
+
subject { @key }
|
191
|
+
|
192
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
193
|
+
its(:rundeck_content_type) { is_expected.to eq('application/pgp-keys') }
|
194
|
+
|
195
|
+
it 'expects a get to have been made' do
|
196
|
+
expect(a_get('/storage/keys/path/to/key1')).to have_been_made
|
197
|
+
end
|
198
|
+
it 'expects a put to have been made' do
|
199
|
+
expect(a_put('/storage/keys/path/to/key1')).to have_been_made
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe '.delete_key' do
|
204
|
+
before do
|
205
|
+
stub_delete('/storage/keys/path/to/my_key', 'empty')
|
206
|
+
@key = Rundeck.delete_key('path/to/my_key')
|
207
|
+
end
|
208
|
+
subject { @key }
|
209
|
+
|
210
|
+
it { is_expected.to be_nil }
|
211
|
+
|
212
|
+
it 'expects a delete to have been made' do
|
213
|
+
expect(a_delete('/storage/keys/path/to/my_key')).to have_been_made
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rundeck::Client do
|
4
|
+
describe '#objectify' do
|
5
|
+
subject { Rundeck::Client.new.objectify(result) }
|
6
|
+
|
7
|
+
context 'when result' do
|
8
|
+
context 'is a hash' do
|
9
|
+
let(:result) { { a: 1, b: 2 } }
|
10
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'is an array' do
|
14
|
+
let(:result) { [{ a: 1, b: 2 }, { c: 3, d: 4 }] }
|
15
|
+
|
16
|
+
it { is_expected.to be_a Array }
|
17
|
+
its([0]) { is_expected.to be_a Rundeck::ObjectifiedHash }
|
18
|
+
its([1]) { is_expected.to be_a Rundeck::ObjectifiedHash }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'is a string' do
|
22
|
+
it do
|
23
|
+
expect do
|
24
|
+
Rundeck::Client.new.objectify('string')
|
25
|
+
end.to raise_error Rundeck::Error::Parsing,
|
26
|
+
"Couldn't parse a response body"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'is nil' do
|
31
|
+
let(:result) { nil }
|
32
|
+
it { is_expected.to be_nil }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rundeck::ObjectifiedHash do
|
4
|
+
before do
|
5
|
+
@hash = { a: 1, b: 2 }
|
6
|
+
@obj_hash = Rundeck::ObjectifiedHash.new(@hash)
|
7
|
+
end
|
8
|
+
subject { @obj_hash }
|
9
|
+
|
10
|
+
its(:a) { is_expected.to eq(@hash[:a]) }
|
11
|
+
its(:b) { is_expected.to eq(@hash[:b]) }
|
12
|
+
|
13
|
+
describe '#to_hash' do
|
14
|
+
subject { @obj_hash.to_hash }
|
15
|
+
|
16
|
+
it { is_expected.to eq(@hash) }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#to_h' do
|
20
|
+
subject { @obj_hash.to_hash }
|
21
|
+
|
22
|
+
it { is_expected.to eq(@hash) }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with nested hashes' do
|
26
|
+
before do
|
27
|
+
@hash = { a: 1, b: { c: 2, d: { e: 3 } } }
|
28
|
+
@obj_hash = Rundeck::ObjectifiedHash.new(@hash)
|
29
|
+
end
|
30
|
+
subject { @obj_hash }
|
31
|
+
|
32
|
+
describe 'b' do
|
33
|
+
subject { @obj_hash.b }
|
34
|
+
|
35
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
36
|
+
its(:c) { is_expected.to eq(@hash[:b][:c]) }
|
37
|
+
|
38
|
+
describe 'd' do
|
39
|
+
subject { @obj_hash.b.d }
|
40
|
+
|
41
|
+
it { is_expected.to be_a Rundeck::ObjectifiedHash }
|
42
|
+
its(:e) { is_expected.to eq(@hash[:b][:d][:e]) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|