-
Notifications
You must be signed in to change notification settings - Fork 270
/
foreman_resource_rest_v3_spec.rb
197 lines (162 loc) · 9.36 KB
/
foreman_resource_rest_v3_spec.rb
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
require 'spec_helper'
require 'oauth'
provider_class = Puppet::Type.type(:foreman_resource).provider(:rest_v3)
describe provider_class do
let(:resource) do
double('resource')
end
let(:provider) do
provider = provider_class.new
provider.resource = resource
provider
end
describe '#generate_token' do
it 'returns an OAuth::AccessToken' do
expect(provider).to receive(:oauth_consumer).and_return(OAuth::Consumer.new('test', 'test'))
expect(provider.generate_token).to be_an(OAuth::AccessToken)
end
end
describe '#oauth_consumer' do
it 'returns an OAuth::Consumer' do
expect(provider).to receive(:oauth_consumer_key).and_return('oauth_key')
expect(provider).to receive(:oauth_consumer_secret).and_return('oauth_secret')
expect(provider).to receive(:foreman_url).and_return('https://foreman.example.com')
expect(resource).to receive(:[]).with(:ssl_ca).and_return('/etc/foreman/ssl/ca.pem')
expect(resource).to receive(:[]).with(:timeout).and_return(500)
consumer = provider.oauth_consumer
expect(consumer).to be_an(OAuth::Consumer)
expect(consumer.site).to eq('https://foreman.example.com')
expect(consumer.options[:ca_file]).to eq('/etc/foreman/ssl/ca.pem')
expect(consumer.options[:timeout]).to eq(500)
end
end
describe '#oauth_consumer_key' do
it 'uses resource consumer_key' do
expect(resource).to receive(:[]).twice.with(:consumer_key).and_return('oauth_key')
expect(provider.oauth_consumer_key).to eq('oauth_key')
end
it 'uses settings.yaml if resource has no consumer_key' do
expect(resource).to receive(:[]).with(:consumer_key).and_return(nil)
expect(YAML).to receive(:load_file).with('/etc/foreman/settings.yaml').and_return(:oauth_consumer_key => 'oauth_key')
expect(provider.oauth_consumer_key).to eq('oauth_key')
end
end
describe '#oauth_consumer_secret' do
it 'uses resource consumer_secret' do
expect(resource).to receive(:[]).twice.with(:consumer_secret).and_return('oauth_secret')
expect(provider.oauth_consumer_secret).to eq('oauth_secret')
end
it 'uses settings.yaml if resource has no consumer_secret' do
expect(resource).to receive(:[]).with(:consumer_secret).and_return(nil)
expect(YAML).to receive(:load_file).with('/etc/foreman/settings.yaml').and_return(:oauth_consumer_secret => 'oauth_secret')
expect(provider.oauth_consumer_secret).to eq('oauth_secret')
end
end
describe '#request' do
before do
expect(provider).to receive(:foreman_url).and_return(base_url)
expect(provider).to receive(:oauth_consumer).at_least(1).and_return(consumer)
expect(resource).to receive(:[]).with(:effective_user).and_return(effective_user)
end
let(:base_url) { 'https://foreman.example.com' }
let(:consumer) { double('oauth_consumer') }
let(:effective_user) { 'admin' }
it 'makes GET request via consumer and returns response' do
response = double(:code => '200')
expect(consumer).to receive(:request).with(:get, 'https://foreman.example.com/api/v2/example', kind_of(OAuth::AccessToken), {}, kind_of(Hash)).and_return(response)
expect(provider.request(:get, 'api/v2/example')).to eq(response)
end
it 'makes PUT request via consumer and returns response' do
response = double(:code => '200')
expect(consumer).to receive(:request).with(:put, 'https://foreman.example.com/api/v2/example', kind_of(OAuth::AccessToken), {}, nil, kind_of(Hash)).and_return(response)
expect(provider.request(:put, 'api/v2/example')).to eq(response)
end
it 'specifies foreman_user header' do
expect(consumer).to receive(:request).with(:get, anything, anything, anything, hash_including('foreman_user' => 'admin')).and_return(double(:code => '200'))
provider.request(:get, 'api/v2/example')
end
it 'passes parameters' do
expect(consumer).to receive(:request).with(:get, 'https://foreman.example.com/api/v2/example?test=value', anything, anything, anything).and_return(double(:code => '200'))
provider.request(:get, 'api/v2/example', :test => 'value')
end
it 'passes data' do
expect(consumer).to receive(:request).with(:post, anything, anything, anything, 'test', anything).and_return(double(:code => '200'))
provider.request(:post, 'api/v2/example', {}, 'test')
end
it 'merges headers' do
expect(consumer).to receive(:request).with(:get, anything, anything, anything, hash_including('test' => 'value', 'Accept' => 'application/json')).and_return(double(:code => '200'))
provider.request(:get, 'api/v2/example', {}, nil, {'test' => 'value'})
end
describe 'with non-root base URL' do
let(:base_url) { 'https://foreman.example.com/foreman' }
it 'concatenates the base and request URLs' do
expect(consumer).to receive(:request).with(:get, 'https://foreman.example.com/foreman/api/v2/example', anything, anything, anything).and_return(double(:code => '200'))
provider.request(:get, 'api/v2/example')
end
end
it 'retries on timeout' do
expect(consumer).to receive(:request).twice.and_raise(Timeout::Error)
expect(provider).to receive(:warning).with('Timeout calling API at https://foreman.example.com/api/v2/example. Retrying ..').twice
expect(consumer).to receive(:request).and_return(double(:code => '200'))
provider.request(:get, 'api/v2/example')
end
it 'fails resource after multiple timeouts' do
expect(consumer).to receive(:request).exactly(5).times.and_raise(Timeout::Error)
expect { provider.request(:get, 'api/v2/example') }.to raise_error(Puppet::Error, /Timeout/)
end
it 'fails resource with network errors' do
expect(consumer).to receive(:request).and_raise(Errno::ECONNRESET)
expect { provider.request(:get, 'api/v2/example') }.to raise_error(Puppet::Error, /Exception/)
end
end
describe '#success?(response)' do
it 'returns true for response code in 2xx' do
expect(provider.success?(double(:code => '256'))).to eq(true)
end
it 'returns false for non-2xx response code' do
expect(provider.success?(double(:code => '404'))).to eq(false)
end
end
describe '#error_message(response)' do
before { expect(provider).to receive(:foreman_url).and_return(base_url) }
let(:base_url) { 'https://foreman.example.com' }
it 'returns array of errors from JSON' do
expect(provider.error_message(double(:body => '{"error":{"full_messages":["error1","error2"]}}', :code => 'dummycode'))).to eq('error1 error2')
end
it 'returns message for unrecognized response code' do
expect(provider.error_message(double(:body => '{}', :code => '418', :message => "I'm a teapot"))).to eq("Response: 418 I'm a teapot")
end
it 'returns message for 400 response' do
expect(provider.error_message(double(:body => '{}', :code => '400', :message => 'Bad Request'))).to eq('Response: 400 Bad Request: Something is wrong with the data sent to Foreman at foreman.example.com')
end
it 'returns message for 401 response' do
expect(provider.error_message(double(:body => '{}', :code => '401', :message => 'Unauthorized Request'))).to eq('Response: 401 Unauthorized Request: Often this is caused by invalid Oauth credentials sent to Foreman at foreman.example.com')
end
it 'returns message for 404 response' do
expect(provider.error_message(double(:body => '{}', :code => '404', :message => 'Not Found'))).to eq('Response: 404 Not Found: The requested resource was not found in Foreman at foreman.example.com')
end
it 'returns message for 500 response' do
expect(provider.error_message(double(:body => '{}', :code => '500', :message => 'Internal Server Error'))).to eq('Response: 500 Internal Server Error: Check /var/log/foreman/production.log on foreman.example.com for detailed information')
end
it 'returns message for 502 response' do
expect(provider.error_message(double(:body => '{}', :code => '502', :message => 'Bad Gateway'))).to eq('Response: 502 Bad Gateway: The webserver received an invalid response from the backend service. Was Foreman at foreman.example.com unable to handle the request?')
end
it 'returns message for 503 response' do
expect(provider.error_message(double(:body => '{}', :code => '503', :message => 'Service Unavailable'))).to eq('Response: 503 Service Unavailable: The webserver was unable to reach the backend service. Is Foreman running at foreman.example.com?')
end
it 'returns message for 504 response' do
expect(provider.error_message(double(:body => '{}', :code => '504', :message => 'Gateway Timeout'))).to eq('Response: 504 Gateway Timeout: The webserver timed out waiting for a response from the backend service. Is Foreman at foreman.example.com under unusually heavy load?')
end
end
describe '#foreman_url' do
it 'uses resource base_url' do
expect(resource).to receive(:[]).twice.with(:base_url).and_return('https://foo.example.com')
expect(provider.foreman_url).to eq('https://foo.example.com')
end
it 'uses foreman-proxy/settings.yml if resource has no base_url' do
expect(resource).to receive(:[]).with(:base_url).and_return(nil)
expect(YAML).to receive(:load_file).with('/etc/foreman-proxy/settings.yml').and_return(:foreman_url => 'https://bar.example.com')
expect(provider.foreman_url).to eq('https://bar.example.com')
end
end
end