topological_inventory-providers-common 2.0.0 → 2.1.4

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.
@@ -1,7 +1,7 @@
1
1
  module TopologicalInventory
2
2
  module Providers
3
3
  module Common
4
- VERSION = "2.0.0".freeze
4
+ VERSION = "2.1.4".freeze
5
5
  end
6
6
  end
7
7
  end
@@ -7,8 +7,12 @@ RSpec.shared_examples "availability_check" do
7
7
  let(:sources_api_url) { "#{host_url}#{sources_api_path}" }
8
8
 
9
9
  let(:external_tenant) { '11001' }
10
+ let(:kafka_client) { TopologicalInventory::Providers::Common::MessagingClient.default.client }
10
11
  let(:identity) { {'x-rh-identity' => Base64.strict_encode64({'identity' => {'account_number' => external_tenant, 'user' => {'is_org_admin' => true}}}.to_json)} }
11
12
  let(:headers) { {'Content-Type' => 'application/json'}.merge(identity) }
13
+ let(:status_available) { described_class::STATUS_AVAILABLE }
14
+ let(:status_unavailable) { described_class::STATUS_UNAVAILABLE }
15
+ let(:error_message) { 'error_message' }
12
16
  let(:source_id) { '123' }
13
17
  let(:endpoint_id) { '234' }
14
18
  let(:application_id) { '345' }
@@ -32,101 +36,208 @@ RSpec.shared_examples "availability_check" do
32
36
 
33
37
  subject { described_class.new(payload["params"]) }
34
38
 
39
+ def kafka_message(resource_type, resource_id, status, error_message = nil)
40
+ res = {
41
+ :service => described_class::SERVICE_NAME,
42
+ :event => described_class::EVENT_AVAILABILITY_STATUS,
43
+ :payload => {
44
+ :resource_type => resource_type,
45
+ :resource_id => resource_id,
46
+ :status => status
47
+ }
48
+ }
49
+ res[:payload][:error] = error_message if error_message
50
+ res[:payload] = res[:payload].to_json
51
+ res
52
+ end
53
+
54
+ before do
55
+ allow(subject).to receive(:messaging_client).and_return(kafka_client)
56
+ end
57
+
35
58
  context "when not checked recently" do
36
59
  before do
37
60
  allow(subject).to receive(:checked_recently?).and_return(false)
38
61
  end
39
62
 
40
- it "updates Source and Endpoint when available" do
41
- # GET
42
- stub_get(:endpoint, list_endpoints_response)
43
- stub_get(:authentication, list_endpoint_authentications_response)
44
- stub_get(:password, internal_api_authentication_response)
45
- stub_not_found(:application)
63
+ context 'kafka' do
64
+ it 'updates Source and Endpoint when available' do
65
+ stub_get(:endpoint, list_endpoints_response)
66
+ stub_get(:application, list_applications_response)
46
67
 
47
- # PATCH
48
- source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
49
- endpoint_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'availability_status_error' => '', 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
68
+ expect(subject).to receive(:connection_status).and_return([status_available, ''])
50
69
 
51
- stub_patch(:source, source_patch_body)
52
- stub_patch(:endpoint, endpoint_patch_body)
70
+ expect(kafka_client).to receive(:publish_topic).with(
71
+ kafka_message("Source", source_id, status_available)
72
+ )
53
73
 
54
- # Check ---
55
- expect(subject).to receive(:connection_check).and_return([described_class::STATUS_AVAILABLE, nil])
74
+ expect(kafka_client).to receive(:publish_topic).with(
75
+ kafka_message("Endpoint", endpoint_id, status_available, '')
76
+ )
56
77
 
57
- subject.availability_check
78
+ expect(kafka_client).to receive(:publish_topic).with(
79
+ kafka_message("Application", application_id, status_available)
80
+ )
58
81
 
59
- assert_patch(:source, source_patch_body)
60
- assert_patch(:endpoint, endpoint_patch_body)
61
- end
82
+ subject.availability_check
83
+ end
62
84
 
63
- it "updates Source and Endpoint when unavailable" do
64
- # GET
65
- stub_get(:endpoint, list_endpoints_response)
66
- stub_get(:authentication, list_endpoint_authentications_response)
67
- stub_get(:password, internal_api_authentication_response)
68
- stub_not_found(:application)
69
85
 
70
- # PATCH
71
- connection_error_message = "Some connection error"
72
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
73
- endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => connection_error_message, 'last_checked_at' => subject.send(:check_time)}.to_json
86
+ it "updates Source and Endpoint when unavailable" do
87
+ stub_get(:endpoint, list_endpoints_response)
88
+ stub_get(:application, list_applications_response)
74
89
 
75
- stub_patch(:source, source_patch_body)
76
- stub_patch(:endpoint, endpoint_patch_body)
90
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
77
91
 
78
- # Check ---
79
- expect(subject).to receive(:connection_check).and_return([described_class::STATUS_UNAVAILABLE, connection_error_message])
92
+ expect(kafka_client).to receive(:publish_topic).with(
93
+ kafka_message("Source", source_id, status_unavailable)
94
+ )
80
95
 
81
- subject.availability_check
96
+ expect(kafka_client).to receive(:publish_topic).with(
97
+ kafka_message("Endpoint", endpoint_id, status_unavailable, error_message)
98
+ )
82
99
 
83
- assert_patch(:source, source_patch_body)
84
- assert_patch(:endpoint, endpoint_patch_body)
85
- end
100
+ expect(kafka_client).to receive(:publish_topic).with(
101
+ kafka_message("Application", application_id, status_unavailable)
102
+ )
86
103
 
87
- it "updates only Source to 'unavailable' status if Endpoint not found" do
88
- # GET
89
- stub_not_found(:endpoint)
90
- stub_not_found(:application)
104
+ subject.availability_check
105
+ end
91
106
 
92
- # PATCH
93
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
94
- stub_patch(:source, source_patch_body)
107
+ it "updates only Source to 'unavailable' status if Endpoint not found" do
108
+ stub_not_found(:endpoint)
109
+ stub_not_found(:application)
95
110
 
96
- # Check
97
- api_client = subject.send(:sources_api)
98
- expect(api_client).not_to receive(:update_endpoint)
111
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
99
112
 
100
- subject.availability_check
113
+ expect(kafka_client).to receive(:publish_topic).with(
114
+ kafka_message("Source", source_id, status_unavailable)
115
+ )
116
+
117
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_unavailable}] message [#{error_message}]")
118
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_unavailable}")
119
+
120
+ subject.availability_check
121
+ end
122
+
123
+ it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
124
+ stub_get(:endpoint, list_endpoints_response)
125
+ stub_not_found(:application)
126
+
127
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
128
+
129
+ expect(kafka_client).to receive(:publish_topic).with(
130
+ kafka_message("Source", source_id, status_unavailable)
131
+ )
132
+
133
+ expect(kafka_client).to receive(:publish_topic).with(
134
+ kafka_message("Endpoint", endpoint_id, status_unavailable, error_message)
135
+ )
101
136
 
102
- assert_patch(:source, source_patch_body)
137
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_unavailable}] message [#{error_message}]")
138
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_unavailable}")
139
+
140
+ subject.availability_check
141
+ end
103
142
  end
104
143
 
105
- it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
106
- # GET
107
- stub_get(:endpoint, list_endpoints_response)
108
- stub_get(:authentication, list_endpoint_authentications_response_empty)
109
- stub_not_found(:application)
144
+ context 'sources_api' do
145
+ before do
146
+ subject.send(:updates_via_kafka=, false)
147
+ end
110
148
 
111
- # PATCH
112
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
113
- endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => described_class::ERROR_MESSAGES[:authentication_not_found], 'last_checked_at' => subject.send(:check_time)}.to_json
149
+ it "updates Source and Endpoint when available" do
150
+ # GET
151
+ stub_get(:endpoint, list_endpoints_response)
152
+ stub_get(:authentication, list_endpoint_authentications_response)
153
+ stub_get(:password, internal_api_authentication_response)
154
+ stub_not_found(:application)
114
155
 
115
- stub_patch(:source, source_patch_body)
116
- stub_patch(:endpoint, endpoint_patch_body)
156
+ # PATCH
157
+ source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
158
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'availability_status_error' => '', 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
117
159
 
118
- # Check
119
- expect(subject).not_to receive(:connection_check)
120
- subject.availability_check
160
+ stub_patch(:source, source_patch_body)
161
+ stub_patch(:endpoint, endpoint_patch_body)
162
+
163
+ # Check ---
164
+ expect(subject).to receive(:connection_check).and_return([described_class::STATUS_AVAILABLE, nil])
165
+
166
+ subject.availability_check
167
+
168
+ assert_patch(:source, source_patch_body)
169
+ assert_patch(:endpoint, endpoint_patch_body)
170
+ end
171
+
172
+ it "updates Source and Endpoint when unavailable" do
173
+ # GET
174
+ stub_get(:endpoint, list_endpoints_response)
175
+ stub_get(:authentication, list_endpoint_authentications_response)
176
+ stub_get(:password, internal_api_authentication_response)
177
+ stub_not_found(:application)
178
+
179
+ # PATCH
180
+ connection_error_message = "Some connection error"
181
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
182
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => connection_error_message, 'last_checked_at' => subject.send(:check_time)}.to_json
183
+
184
+ stub_patch(:source, source_patch_body)
185
+ stub_patch(:endpoint, endpoint_patch_body)
186
+
187
+ # Check ---
188
+ expect(subject).to receive(:connection_check).and_return([described_class::STATUS_UNAVAILABLE, connection_error_message])
189
+
190
+ subject.availability_check
191
+
192
+ assert_patch(:source, source_patch_body)
193
+ assert_patch(:endpoint, endpoint_patch_body)
194
+ end
195
+
196
+ it "updates only Source to 'unavailable' status if Endpoint not found" do
197
+ # GET
198
+ stub_not_found(:endpoint)
199
+ stub_not_found(:application)
200
+
201
+ # PATCH
202
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
203
+ stub_patch(:source, source_patch_body)
204
+
205
+ # Check
206
+ api_client = subject.send(:sources_api)
207
+ expect(api_client).not_to receive(:update_endpoint)
208
+
209
+ subject.availability_check
210
+
211
+ assert_patch(:source, source_patch_body)
212
+ end
213
+
214
+ it "updates Source and Endpoint to 'unavailable' if Authentication not found" do
215
+ # GET
216
+ stub_get(:endpoint, list_endpoints_response)
217
+ stub_get(:authentication, list_endpoint_authentications_response_empty)
218
+ stub_not_found(:application)
121
219
 
122
- assert_patch(:source, source_patch_body)
123
- assert_patch(:endpoint, endpoint_patch_body)
220
+ # PATCH
221
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
222
+ endpoint_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'availability_status_error' => described_class::ERROR_MESSAGES[:authentication_not_found], 'last_checked_at' => subject.send(:check_time)}.to_json
223
+
224
+ stub_patch(:source, source_patch_body)
225
+ stub_patch(:endpoint, endpoint_patch_body)
226
+
227
+ # Check
228
+ expect(subject).not_to receive(:connection_check)
229
+ subject.availability_check
230
+
231
+ assert_patch(:source, source_patch_body)
232
+ assert_patch(:endpoint, endpoint_patch_body)
233
+ end
124
234
  end
125
235
  end
126
236
 
127
237
  context "when checked recently" do
128
238
  before do
129
239
  allow(subject).to receive(:checked_recently?).and_return(true)
240
+ subject.send(:updates_via_kafka=, false)
130
241
  end
131
242
 
132
243
  it "doesn't do connection check" do
@@ -140,44 +251,97 @@ RSpec.shared_examples "availability_check" do
140
251
 
141
252
  context "when there is an application" do
142
253
  context "when it is available" do
143
- it "updates the availability status to available" do
144
- # GET
145
- stub_not_found(:endpoint)
146
- stub_get(:application, list_applications_response)
147
- # PATCH
148
- application_patch_body = {'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
149
- source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
254
+ context 'kafka' do
255
+ it "updates the availability status to available" do
256
+ stub_not_found(:endpoint)
257
+ stub_get(:application, list_applications_response)
150
258
 
151
- stub_patch(:source, source_patch_body)
152
- stub_patch(:application, application_patch_body)
259
+ expect(subject).to receive(:connection_status).and_return([status_available, ''])
153
260
 
154
- # Check
155
- expect(subject).not_to receive(:connection_check)
156
- subject.availability_check
261
+ expect(kafka_client).to receive(:publish_topic).with(
262
+ kafka_message("Source", source_id, status_available)
263
+ )
157
264
 
158
- assert_patch(:source, source_patch_body)
159
- assert_patch(:application, application_patch_body)
265
+ expect(kafka_client).to receive(:publish_topic).with(
266
+ kafka_message("Application", application_id, status_available)
267
+ )
268
+
269
+ expect(subject.logger).to receive(:availability_check).with("Updating source [#{source_id}] status [#{status_available}] message []")
270
+ expect(subject.logger).to receive(:availability_check).with("Completed: Source #{source_id} is #{status_available}")
271
+
272
+ subject.availability_check
273
+ end
274
+ end
275
+
276
+ context 'sources_api' do
277
+ before do
278
+ subject.send(:updates_via_kafka=, false)
279
+ end
280
+
281
+ it "updates the availability status to available" do
282
+ # GET
283
+ stub_not_found(:endpoint)
284
+ stub_get(:application, list_applications_response)
285
+ # PATCH
286
+ application_patch_body = {'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
287
+ source_patch_body = {'availability_status' => described_class::STATUS_AVAILABLE, 'last_available_at' => subject.send(:check_time), 'last_checked_at' => subject.send(:check_time)}.to_json
288
+
289
+ stub_patch(:source, source_patch_body)
290
+ stub_patch(:application, application_patch_body)
291
+
292
+ # Check
293
+ expect(subject).not_to receive(:connection_check)
294
+ subject.availability_check
295
+
296
+ assert_patch(:source, source_patch_body)
297
+ assert_patch(:application, application_patch_body)
298
+ end
160
299
  end
161
300
  end
162
301
 
163
302
  context "when it is unavailable" do
164
- it "updates the availability status to unavailable" do
165
- # GET
166
- stub_not_found(:endpoint)
167
- stub_get(:application, list_applications_unavailable_response)
168
- # PATCH
169
- application_patch_body = {'last_checked_at' => subject.send(:check_time)}.to_json
170
- source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
303
+ context 'kafka' do
304
+ it "updates the availability status to unavailable" do
305
+ stub_not_found(:endpoint)
306
+ stub_get(:application, list_applications_unavailable_response)
171
307
 
172
- stub_patch(:source, source_patch_body)
173
- stub_patch(:application, application_patch_body)
308
+ expect(subject).to receive(:connection_status).and_return([status_unavailable, error_message])
174
309
 
175
- # Check
176
- expect(subject).not_to receive(:connection_check)
177
- subject.availability_check
310
+ expect(kafka_client).to receive(:publish_topic).with(
311
+ kafka_message("Source", source_id, status_unavailable)
312
+ )
178
313
 
179
- assert_patch(:source, source_patch_body)
180
- assert_patch(:application, application_patch_body)
314
+ expect(kafka_client).to receive(:publish_topic).with(
315
+ kafka_message("Application", application_id, status_unavailable)
316
+ )
317
+
318
+ subject.availability_check
319
+ end
320
+ end
321
+
322
+ context 'sources_api' do
323
+ before do
324
+ subject.send(:updates_via_kafka=, false)
325
+ end
326
+
327
+ it "updates the availability status to unavailable" do
328
+ # GET
329
+ stub_not_found(:endpoint)
330
+ stub_get(:application, list_applications_unavailable_response)
331
+ # PATCH
332
+ application_patch_body = {'last_checked_at' => subject.send(:check_time)}.to_json
333
+ source_patch_body = {'availability_status' => described_class::STATUS_UNAVAILABLE, 'last_checked_at' => subject.send(:check_time)}.to_json
334
+
335
+ stub_patch(:source, source_patch_body)
336
+ stub_patch(:application, application_patch_body)
337
+
338
+ # Check
339
+ expect(subject).not_to receive(:connection_check)
340
+ subject.availability_check
341
+
342
+ assert_patch(:source, source_patch_body)
343
+ assert_patch(:application, application_patch_body)
344
+ end
181
345
  end
182
346
  end
183
347
  end
@@ -3,33 +3,42 @@ require "topological_inventory/providers/common/operations/async_worker"
3
3
  describe TopologicalInventory::Providers::Common::Operations::AsyncWorker do
4
4
  let(:queue) { double }
5
5
  let(:impl) { double }
6
+ let(:metrics) { double('metrics') }
6
7
  let(:msg) { double }
7
- subject { described_class.new(impl, queue) }
8
+ let(:operation) { "Source.availability_check" }
9
+
10
+ subject { described_class.new(impl, :queue => queue, :metrics => metrics) }
8
11
 
9
12
  before do
10
13
  allow(queue).to receive(:length).and_return(0)
11
- allow(msg).to receive(:message).and_return("Source.availability_check")
14
+ allow(msg).to receive(:message).and_return(operation)
12
15
  end
13
16
 
14
17
  context "when the message is able to be processed" do
18
+ let(:result) { subject.operation_status[:success] }
15
19
  before do
16
- allow(impl).to receive(:process!).with(msg)
20
+ allow(impl).to receive(:process!).with(msg, metrics).and_return(result)
17
21
  allow(msg).to receive(:ack)
18
22
  end
19
23
 
20
24
  it "drains messages that are added to the queue" do
21
- expect(impl).to receive(:process!).with(msg).once
25
+ expect(impl).to receive(:process!).with(msg, metrics).once
26
+ expect(metrics).to receive(:record_operation).with(operation, :status => result)
22
27
  subject.send(:process_message, msg)
23
28
  end
24
29
  end
25
30
 
26
31
  context "when the message results in an error" do
32
+ let(:result) { subject.operation_status[:error] }
27
33
  before do
28
- allow(impl).to receive(:process!).with(msg).and_raise(StandardError.new("boom!"))
34
+ allow(impl).to receive(:process!).with(msg, metrics).and_raise(StandardError.new("boom!"))
29
35
  end
30
36
 
31
37
  it "ack's the message on failure" do
38
+ allow(subject).to receive(:logger).and_return(double.as_null_object)
39
+
32
40
  expect(msg).to receive(:ack).once
41
+ expect(metrics).to receive(:record_operation).with(operation, :status => result)
33
42
  subject.send(:process_message, msg)
34
43
  end
35
44
  end