topological_inventory-providers-common 1.0.9 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +31 -0
  3. data/.rubocop.yml +1 -1
  4. data/.yamllint +8 -0
  5. data/CHANGELOG.md +25 -2
  6. data/lib/topological_inventory/providers/common.rb +2 -2
  7. data/lib/topological_inventory/providers/common/collectors_pool.rb +2 -1
  8. data/lib/topological_inventory/providers/common/logging.rb +10 -4
  9. data/lib/topological_inventory/providers/common/messaging_client.rb +40 -0
  10. data/lib/topological_inventory/providers/common/metrics.rb +84 -0
  11. data/lib/topological_inventory/providers/common/mixins/sources_api.rb +61 -0
  12. data/lib/topological_inventory/providers/common/mixins/statuses.rb +19 -0
  13. data/lib/topological_inventory/providers/common/mixins/topology_api.rb +26 -0
  14. data/lib/topological_inventory/providers/common/mixins/x_rh_headers.rb +24 -0
  15. data/lib/topological_inventory/providers/common/operations/async_worker.rb +56 -0
  16. data/lib/topological_inventory/providers/common/operations/health_check.rb +15 -0
  17. data/lib/topological_inventory/providers/common/operations/processor.rb +46 -104
  18. data/lib/topological_inventory/providers/common/operations/source.rb +183 -144
  19. data/lib/topological_inventory/providers/common/sources_api_client.rb +92 -0
  20. data/lib/topological_inventory/providers/common/topology_api_client.rb +43 -0
  21. data/lib/topological_inventory/providers/common/version.rb +1 -1
  22. data/spec/support/shared/availability_check.rb +254 -90
  23. data/spec/topological_inventory/providers/common/operations/async_worker_spec.rb +36 -0
  24. data/spec/topological_inventory/providers/common/operations/processor_spec.rb +52 -83
  25. data/topological_inventory-providers-common.gemspec +14 -10
  26. metadata +75 -9
  27. data/lib/topological_inventory/providers/common/operations/endpoint_client.rb +0 -65
  28. data/lib/topological_inventory/providers/common/operations/sources_api_client.rb +0 -94
  29. data/lib/topological_inventory/providers/common/operations/topology_api_client.rb +0 -28
@@ -0,0 +1,92 @@
1
+ require "sources-api-client"
2
+
3
+ module TopologicalInventory
4
+ module Providers
5
+ module Common
6
+ class SourcesApiClient < ::SourcesApiClient::ApiClient
7
+ delegate :update_source, :update_endpoint, :update_application, :to => :api
8
+
9
+ INTERNAL_API_PATH = '//internal/v1.0'.freeze
10
+
11
+ def initialize(identity = nil)
12
+ super(::SourcesApiClient::Configuration.default)
13
+ self.identity = identity
14
+ self.api = init_default_api
15
+ end
16
+
17
+ def init_default_api
18
+ default_headers.merge!(identity) if identity.present?
19
+ ::SourcesApiClient::DefaultApi.new(self)
20
+ end
21
+
22
+ def fetch_default_endpoint(source_id)
23
+ endpoints = api.list_source_endpoints(source_id)&.data || []
24
+ endpoints.find(&:default)
25
+ end
26
+
27
+ def fetch_application(source_id)
28
+ applications = api.list_source_applications(source_id)&.data || []
29
+ applications.first
30
+ end
31
+
32
+ def fetch_authentication(source_id, default_endpoint = nil, authtype = nil)
33
+ endpoint = default_endpoint || fetch_default_endpoint(source_id)
34
+ return if endpoint.nil?
35
+
36
+ endpoint_authentications = api.list_endpoint_authentications(endpoint.id.to_s).data || []
37
+ return if endpoint_authentications.empty?
38
+
39
+ auth_id = if authtype.nil?
40
+ endpoint_authentications.first&.id
41
+ else
42
+ endpoint_authentications.detect { |a| a.authtype = authtype }&.id
43
+ end
44
+ return if auth_id.nil?
45
+
46
+ fetch_authentication_with_password(auth_id)
47
+ end
48
+
49
+ private
50
+
51
+ attr_accessor :identity, :api, :custom_base_path
52
+
53
+ def fetch_authentication_with_password(auth_id)
54
+ on_internal_api do
55
+ local_var_path = "/authentications/#{auth_id}"
56
+
57
+ query_params = "expose_encrypted_attribute[]=password"
58
+
59
+ header_params = {'Accept' => select_header_accept(['application/json'])}
60
+ return_type = 'Authentication'
61
+ data, _, _ = call_api(:GET, local_var_path,
62
+ :header_params => header_params,
63
+ :query_params => query_params,
64
+ :auth_names => ['UserSecurity'],
65
+ :return_type => return_type)
66
+ data
67
+ end
68
+ end
69
+
70
+ def build_request_url(path)
71
+ # Add leading and trailing slashes to path
72
+ path = "/#{path}".gsub(/\/+/, '/')
73
+ URI.encode((custom_base_url || @config.base_url) + path)
74
+ end
75
+
76
+ def custom_base_url
77
+ return nil if custom_base_path.nil?
78
+
79
+ url = "#{@config.scheme}://#{[@config.host, custom_base_path].join('/').gsub(/\/+/, '/')}".sub(/\/+\z/, '')
80
+ URI.encode(url)
81
+ end
82
+
83
+ def on_internal_api
84
+ self.custom_base_path = INTERNAL_API_PATH
85
+ yield
86
+ ensure
87
+ self.custom_base_path = nil
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,43 @@
1
+ require "topological_inventory-api-client"
2
+
3
+ module TopologicalInventory
4
+ module Providers
5
+ module Common
6
+ class TopologyApiClient < ::TopologicalInventoryApiClient::ApiClient
7
+ attr_accessor :api
8
+
9
+ def initialize(identity = nil)
10
+ super(::TopologicalInventoryApiClient::Configuration.default)
11
+
12
+ self.identity = identity
13
+ self.api = init_default_api
14
+ end
15
+
16
+ def init_default_api
17
+ default_headers.merge!(identity) if identity.present?
18
+ ::TopologicalInventoryApiClient::DefaultApi.new(self)
19
+ end
20
+
21
+ def update_task(task_id, source_id: nil, state:, status:, target_type: nil, target_source_ref: nil, context: nil)
22
+ params = {'state' => state,
23
+ 'status' => status}
24
+ params['context'] = context if context
25
+ params['source_id'] = source_id if source_id
26
+ params['target_type'] = target_type if target_type
27
+ params['target_source_ref'] = target_source_ref if target_source_ref
28
+ task = TopologicalInventoryApiClient::Task.new(params)
29
+ api.update_task(task_id, task)
30
+ end
31
+
32
+ def svc_instance_url(service_instance)
33
+ rest_api_path = '/service_instances/{id}'.sub('{' + 'id' + '}', service_instance&.id.to_s)
34
+ build_request(:GET, rest_api_path).url
35
+ end
36
+
37
+ private
38
+
39
+ attr_accessor :identity
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,7 +1,7 @@
1
1
  module TopologicalInventory
2
2
  module Providers
3
3
  module Common
4
- VERSION = "1.0.9"
4
+ VERSION = "2.1.0".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
+ :message => 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_message).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_message).with(
75
+ kafka_message("Endpoint", endpoint_id, status_available, '')
76
+ )
56
77
 
57
- subject.availability_check
78
+ expect(kafka_client).to receive(:publish_message).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_message).with(
93
+ kafka_message("Source", source_id, status_unavailable)
94
+ )
80
95
 
81
- subject.availability_check
96
+ expect(kafka_client).to receive(:publish_message).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_message).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(:api_client)
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_message).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_message).with(
130
+ kafka_message("Source", source_id, status_unavailable)
131
+ )
132
+
133
+ expect(kafka_client).to receive(:publish_message).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_message).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_message).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_message).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_message).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