zuora_connect 2.1.1 → 3.0.0k
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/Rakefile +1 -1
- data/app/controllers/zuora_connect/static_controller.rb +84 -17
- data/app/models/zuora_connect/app_instance_base.rb +177 -107
- data/app/models/zuora_connect/zuora_user.rb +1 -1
- data/config/initializers/postgresql_adapter.rb +71 -1
- data/config/initializers/prometheus.rb +80 -23
- data/config/initializers/redis.rb +4 -4
- data/config/initializers/resque.rb +14 -12
- data/config/initializers/unicorn.rb +30 -2
- data/config/routes.rb +5 -1
- data/lib/metrics/net.rb +7 -7
- data/lib/middleware/json_parse_errors.rb +13 -2
- data/lib/middleware/metrics_middleware.rb +50 -71
- data/lib/resque/dynamic_queues.rb +1 -1
- data/lib/resque/plugins/app_instance_job.rb +1 -1
- data/lib/resque/plugins/custom_logger.rb +1 -1
- data/lib/zuora_connect.rb +6 -63
- data/lib/zuora_connect/controllers/helpers.rb +230 -90
- data/lib/zuora_connect/engine.rb +2 -1
- data/lib/zuora_connect/railtie.rb +6 -64
- data/lib/zuora_connect/version.rb +1 -1
- data/lib/zuora_connect/zuora_audit.rb +31 -0
- metadata +70 -16
- data/app/models/zuora_connect/telegraf.rb +0 -97
- data/lib/logging/connect_formatter.rb +0 -44
- data/lib/metrics/influx/point_value.rb +0 -79
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bad84d0fc35d26f517f83b2cc38e5d1569dafc4253c6c12a474f69aa9d9fee5e
|
|
4
|
+
data.tar.gz: 0ad1de0856425104abb6288662ca1481b097dfb3af696c40d1e8d5a1d018a0af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c00dcd65d70b84242e2c298f1d663d98259083c53e4232cf00c477b32fb32d480a49a39bf982a5682807ee0ae828905cd6dfeb1f548bf6e1a501dd4aca58c63e
|
|
7
|
+
data.tar.gz: 91fe7a9815f2340879cc0a30ef405b48960d44b54f1a020f193c5f029448b19ddb513944ce424fde25764cc0b5bf9a25ae25f3b70d124d715f69e4304ebf36d3
|
data/Rakefile
CHANGED
|
@@ -15,7 +15,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
|
|
|
15
15
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
APP_RAKEFILE = File.expand_path("../
|
|
18
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
|
19
19
|
load 'rails/tasks/engine.rake'
|
|
20
20
|
|
|
21
21
|
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
module ZuoraConnect
|
|
2
2
|
class StaticController < ApplicationController
|
|
3
|
-
before_action :authenticate_connect_app_request, :except => [:
|
|
4
|
-
before_action :clear_connect_app_session, :only => [:
|
|
5
|
-
after_action :persist_connect_app_session, :except => [:
|
|
6
|
-
|
|
7
|
-
skip_before_action :verify_authenticity_token, :only => [:initialize_app]
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type = params[:type].present? ? params[:type] : "versions"
|
|
11
|
-
render json: ZuoraConnect::AppInstance.get_metrics(type).to_json, status: 200
|
|
12
|
-
end
|
|
3
|
+
before_action :authenticate_connect_app_request, :except => [:health, :initialize_app, :provision, :instance_user]
|
|
4
|
+
before_action :clear_connect_app_session, :only => [:health, :initialize_app, :provision, :instance_user]
|
|
5
|
+
after_action :persist_connect_app_session, :except => [:health, :initialize_app, :provision, :instance_user]
|
|
6
|
+
|
|
7
|
+
skip_before_action :verify_authenticity_token, :only => [:initialize_app, :provision]
|
|
8
|
+
http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user]
|
|
9
|
+
|
|
13
10
|
|
|
14
11
|
def health
|
|
15
12
|
if params[:error].present?
|
|
16
|
-
begin
|
|
13
|
+
begin
|
|
17
14
|
raise ZuoraConnect::Exceptions::Error.new('This is an error')
|
|
18
15
|
rescue => ex
|
|
19
16
|
case params[:error]
|
|
20
|
-
when 'Log'
|
|
17
|
+
when 'Log'
|
|
21
18
|
Rails.logger.error("Error in Health", ex)
|
|
22
19
|
when 'Exception'
|
|
23
20
|
raise
|
|
@@ -34,11 +31,13 @@ module ZuoraConnect
|
|
|
34
31
|
def initialize_app
|
|
35
32
|
begin
|
|
36
33
|
authenticate_connect_app_request
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
unless performed?
|
|
35
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
|
36
|
+
render json: {
|
|
37
|
+
message: 'Success',
|
|
38
|
+
status: 200
|
|
39
|
+
}, status: 200
|
|
40
|
+
end
|
|
42
41
|
rescue => ex
|
|
43
42
|
Rails.logger.error("Failed to Initialize application", ex)
|
|
44
43
|
if performed?
|
|
@@ -52,6 +51,74 @@ module ZuoraConnect
|
|
|
52
51
|
end
|
|
53
52
|
end
|
|
54
53
|
|
|
54
|
+
def provision
|
|
55
|
+
create_new_instance
|
|
56
|
+
unless performed?
|
|
57
|
+
render json: {
|
|
58
|
+
status: 200,
|
|
59
|
+
message: 'Success',
|
|
60
|
+
app_instance_id: @appinstance.id
|
|
61
|
+
}, status: 200
|
|
62
|
+
end
|
|
63
|
+
rescue StandardError => e
|
|
64
|
+
message = 'Failed to provision new instance'
|
|
65
|
+
if performed?
|
|
66
|
+
Rails.logger.error("#{message}: #{performed?}", e)
|
|
67
|
+
else
|
|
68
|
+
Rails.logger.error(message, e)
|
|
69
|
+
render json: {
|
|
70
|
+
status: 500,
|
|
71
|
+
message: message
|
|
72
|
+
}, status: 500
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def instance_user
|
|
77
|
+
ZuoraConnect::AppInstance.read_master_db do
|
|
78
|
+
ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
|
|
79
|
+
Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
|
|
80
|
+
|
|
81
|
+
if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
|
|
82
|
+
ElasticAPM.set_label(:trace_id, request.uuid)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
unless params[:id].present?
|
|
86
|
+
render json: {
|
|
87
|
+
status: 400,
|
|
88
|
+
message: 'No app instance id provided'
|
|
89
|
+
}, status: :bad_request
|
|
90
|
+
return
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
@appinstance = ZuoraConnect::AppInstance.find(params[:id]).new_session
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
zuora_client = @appinstance.send(ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION).client
|
|
97
|
+
client_describe, = zuora_client.rest_call(
|
|
98
|
+
url: zuora_client.rest_endpoint('genesis/user/info').gsub('v1/', ''),
|
|
99
|
+
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
render json: {
|
|
103
|
+
status: 200,
|
|
104
|
+
message: 'Success',
|
|
105
|
+
user_id: client_describe['coreUserId'],
|
|
106
|
+
username: client_describe['username'],
|
|
107
|
+
email: client_describe['workEmail']
|
|
108
|
+
}, status: 200
|
|
109
|
+
rescue ActiveRecord::RecordNotFound
|
|
110
|
+
render json: {
|
|
111
|
+
status: 400,
|
|
112
|
+
message: 'No app instance found'
|
|
113
|
+
}, status: :bad_request
|
|
114
|
+
rescue StandardError => e
|
|
115
|
+
Rails.logger.error('Error occurred getting user details', e)
|
|
116
|
+
render json: {
|
|
117
|
+
status: 500,
|
|
118
|
+
message: 'Failed to get user details'
|
|
119
|
+
}, status: 500
|
|
120
|
+
end
|
|
121
|
+
|
|
55
122
|
private
|
|
56
123
|
|
|
57
124
|
def clear_connect_app_session
|
|
@@ -11,8 +11,7 @@ module ZuoraConnect
|
|
|
11
11
|
before_destroy :prune_data
|
|
12
12
|
|
|
13
13
|
self.table_name = "zuora_connect_app_instances"
|
|
14
|
-
attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message, :new_session_message, :connect_user, :logitems
|
|
15
|
-
@@telegraf_host = nil
|
|
14
|
+
attr_accessor :options, :mode, :logins, :task_data, :last_refresh, :username, :password, :s3_client, :api_version, :drop_message, :new_session_message, :connect_user, :logitems, :user_timezone
|
|
16
15
|
REFRESH_TIMEOUT = 2.minute #Used to determine how long to wait on current refresh call before executing another
|
|
17
16
|
INSTANCE_REFRESH_WINDOW = 1.hours #Used to set how how long till app starts attempting to refresh cached task connect data
|
|
18
17
|
INSTANCE_REDIS_CACHE_PERIOD = 24.hours #Used to determine how long to cached task data will live for
|
|
@@ -21,6 +20,12 @@ module ZuoraConnect
|
|
|
21
20
|
HOLDING_PATTERN_SLEEP = 5.seconds
|
|
22
21
|
CONNECT_APPLICATION_ID = 0
|
|
23
22
|
CONNECT_COMMUNICATION_SLEEP = Rails.env.test? ? 0.seconds : 5.seconds
|
|
23
|
+
CATALOG_LOOKUP_PAGE_SIZE = 10_000
|
|
24
|
+
CATALOG_LOOKUP_CACHE_TIME_KEY = 'CatalogCachedAt'
|
|
25
|
+
CATALOG_LOOKUP_TTL = 60.seconds
|
|
26
|
+
CATALOG_LOOKUP_CACHE_RESULT_KEY = 'CatalogCache'
|
|
27
|
+
TIMEZONE_LOG_RATE_LIMIT_KEY = 'TimezoneLoggedAt'
|
|
28
|
+
TIMEZONE_LOG_PERIOD = 4.hours
|
|
24
29
|
IGNORED_LOCALS = ['fr', 'ja', 'es', 'zh', 'de']
|
|
25
30
|
INTERNAL_HOSTS = []
|
|
26
31
|
LOGIN_TENANT_DESTINATION = 'target_login'
|
|
@@ -29,7 +34,7 @@ module ZuoraConnect
|
|
|
29
34
|
Aws::Errors::MissingCredentialsError,
|
|
30
35
|
Aws::S3::Errors::AccessDenied,
|
|
31
36
|
Aws::SES::Errors::AccessDenied,
|
|
32
|
-
Aws::KMS::Errors::AccessDeniedException
|
|
37
|
+
Aws::KMS::Errors::AccessDeniedException
|
|
33
38
|
].freeze
|
|
34
39
|
AWS_AUTH_ERRORS_MSG = "AWS Auth Errors".freeze
|
|
35
40
|
|
|
@@ -147,7 +152,8 @@ module ZuoraConnect
|
|
|
147
152
|
if ZuoraConnect.configuration.mode != "Production"
|
|
148
153
|
mock_task_data = {
|
|
149
154
|
"id" => ZuoraConnect.configuration.dev_mode_appinstance,
|
|
150
|
-
"mode" => ZuoraConnect.configuration.dev_mode_mode
|
|
155
|
+
"mode" => ZuoraConnect.configuration.dev_mode_mode,
|
|
156
|
+
"name" => "Developer Instance"
|
|
151
157
|
}
|
|
152
158
|
|
|
153
159
|
case ZuoraConnect.configuration.dev_mode_options.class
|
|
@@ -163,6 +169,7 @@ module ZuoraConnect
|
|
|
163
169
|
end
|
|
164
170
|
|
|
165
171
|
self.build_task(task_data: mock_task_data, session: session)
|
|
172
|
+
self.set_backup_creds if !self['zuora_logins'].present?
|
|
166
173
|
self.last_refresh = Time.now.to_i
|
|
167
174
|
else
|
|
168
175
|
time_expire = (session["#{self.id}::last_refresh"] || Time.now).to_i - INSTANCE_REFRESH_WINDOW.ago.to_i
|
|
@@ -240,7 +247,9 @@ module ZuoraConnect
|
|
|
240
247
|
rescue I18n::InvalidLocale => ex
|
|
241
248
|
ZuoraConnect.logger.error(ex) if !IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
|
242
249
|
end
|
|
243
|
-
|
|
250
|
+
|
|
251
|
+
self.set_timezone
|
|
252
|
+
|
|
244
253
|
if self.task_data.present?
|
|
245
254
|
tenants = self.task_data.fetch('tenant_ids', [])
|
|
246
255
|
organizations = self.task_data.fetch('organizations', [])
|
|
@@ -255,7 +264,7 @@ module ZuoraConnect
|
|
|
255
264
|
end
|
|
256
265
|
|
|
257
266
|
params = {
|
|
258
|
-
name: self.task_data.dig('name'),
|
|
267
|
+
name: self.task_data.dig('name'),
|
|
259
268
|
zuora_entity_ids: (self.task_data.dig(LOGIN_TENANT_DESTINATION,'entities') || []).map{|e| e['id']}.uniq,
|
|
260
269
|
zuora_tenant_ids: tenants.map(&:to_s).uniq,
|
|
261
270
|
organizations: organizations
|
|
@@ -264,7 +273,7 @@ module ZuoraConnect
|
|
|
264
273
|
client = self.send(LOGIN_TENANT_DESTINATION).client
|
|
265
274
|
if defined?(client.rest_domain)
|
|
266
275
|
ZuoraConnect::RequestIdMiddleware.zuora_rest_domain = client.rest_domain
|
|
267
|
-
params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
|
|
276
|
+
params.merge!({zuora_domain: client.rest_domain, environment: client.environment })
|
|
268
277
|
end
|
|
269
278
|
end
|
|
270
279
|
params = params.reject{|k,v| !self.attributes.keys.member?(k.to_s) || self[k] == v}
|
|
@@ -272,12 +281,77 @@ module ZuoraConnect
|
|
|
272
281
|
end
|
|
273
282
|
end
|
|
274
283
|
|
|
275
|
-
def
|
|
284
|
+
def set_timezone(timezone: self.timezone, type: :default)
|
|
285
|
+
if timezone.blank?
|
|
286
|
+
timezone = self.timezone
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
if type == :default
|
|
290
|
+
Time.zone = timezone
|
|
291
|
+
elsif type == :user
|
|
292
|
+
begin
|
|
293
|
+
sql = <<-eos
|
|
294
|
+
SELECT zuora_users.zuora_identity_response FROM "#{self.id}".zuora_users ORDER BY zuora_users.updated_at DESC LIMIT 1;
|
|
295
|
+
eos
|
|
296
|
+
user = ActiveRecord::Base.connection.execute(sql).to_a.first
|
|
297
|
+
|
|
298
|
+
if user.present?
|
|
299
|
+
zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}'))
|
|
300
|
+
self.user_timezone = zuora_identity_response.values.first&.dig('timeZone')
|
|
301
|
+
else
|
|
302
|
+
if (Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
|
|
303
|
+
Rails.logger.error('Cannot find any user to set the timezone', app_instance_id: self.id)
|
|
304
|
+
Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
rescue => ex
|
|
308
|
+
Rails.logger.error('There is an error while getting timezone users', ex)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
if self.user_timezone.present?
|
|
312
|
+
# connect instance which has a custom timezone
|
|
313
|
+
if !self.auto_deployed? && (
|
|
314
|
+
ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset !=
|
|
315
|
+
ActiveSupport::TimeZone[self.user_timezone]&.utc_offset
|
|
316
|
+
)
|
|
317
|
+
if self.environment == 'Production' &&
|
|
318
|
+
(Redis.current.hget(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id).to_i + TIMEZONE_LOG_PERIOD.to_i) <= Time.now.to_i
|
|
319
|
+
ZuoraConnect.logger.error(
|
|
320
|
+
"Instance and user timezones are different. User has '#{self.user_timezone}' and " \
|
|
321
|
+
"instance has '#{self.task_data.dig('user_settings', 'timezone')}'",
|
|
322
|
+
app_instance_id: self.id
|
|
323
|
+
)
|
|
324
|
+
Redis.current.hset(TIMEZONE_LOG_RATE_LIMIT_KEY, self.id, Time.now.to_i)
|
|
325
|
+
end
|
|
326
|
+
self.user_timezone = nil
|
|
327
|
+
Time.zone = timezone
|
|
328
|
+
else
|
|
329
|
+
begin
|
|
330
|
+
Time.zone = self.user_timezone
|
|
331
|
+
rescue ArgumentError
|
|
332
|
+
Rails.logger.error('Malformed user timezone', app_instance_id: self.id)
|
|
333
|
+
Time.zone = timezone
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
else
|
|
337
|
+
Time.zone = timezone
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
rescue => e
|
|
341
|
+
Rails.logger.error('Malformed timezone used', e, app_instance_id: self.id)
|
|
342
|
+
Time.zone = self.timezone
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def auto_deployed?
|
|
346
|
+
self.id >= 25000000
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def refresh(session: {})
|
|
276
350
|
refresh_count ||= 0
|
|
277
351
|
skip_connect ||= false
|
|
278
352
|
begin
|
|
279
353
|
#Check how app was deployed
|
|
280
|
-
if self.
|
|
354
|
+
if !self.auto_deployed? && !skip_connect
|
|
281
355
|
self.check_oauth_state
|
|
282
356
|
response = HTTParty.get(ZuoraConnect.configuration.url + "/api/#{self.api_version}/tools/tasks/#{self.id}.json",:body => {:access_token => self.access_token})
|
|
283
357
|
|
|
@@ -289,16 +363,8 @@ module ZuoraConnect
|
|
|
289
363
|
end
|
|
290
364
|
|
|
291
365
|
self.build_task(task_data: parsed_json, session: session)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
self.zuora_logins = self.strip_cache_data(object: parsed_json.dup, keys: ['applications', 'tokens', 'user_settings'])
|
|
295
|
-
self.save(:validate => false)
|
|
296
|
-
rescue Aws::KMS::Errors::ValidationException, *AWS_AUTH_ERRORS => ex
|
|
297
|
-
Rails.logger.warn(AWS_AUTH_ERRORS_MSG, ex)
|
|
298
|
-
rescue => ex
|
|
299
|
-
Rails.logger.error(AWS_AUTH_ERRORS_MSG, ex)
|
|
300
|
-
end
|
|
301
|
-
end
|
|
366
|
+
self.set_backup_creds
|
|
367
|
+
self.save(validate: false) if self.changed?
|
|
302
368
|
else
|
|
303
369
|
raise ZuoraConnect::Exceptions::ConnectCommunicationError.new("Error Communicating with Connect", response.body, response.code)
|
|
304
370
|
end
|
|
@@ -338,9 +404,21 @@ module ZuoraConnect
|
|
|
338
404
|
raise
|
|
339
405
|
end
|
|
340
406
|
|
|
407
|
+
def aws_secrets
|
|
408
|
+
(Rails.application.secrets.aws || {}).transform_keys { |key| key.to_s }
|
|
409
|
+
end
|
|
410
|
+
|
|
341
411
|
#### START KMS ENCRYPTION Methods ####
|
|
412
|
+
def set_backup_creds
|
|
413
|
+
if self.kms_key.present? && self.kms_key.match(/^arn:aws:.*/) && self.task_data.present?
|
|
414
|
+
self.zuora_logins = self.strip_cache_data(object: self.task_data.dup, keys: ['applications', 'tokens', 'user_settings'])
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
342
418
|
def zuora_logins=(val)
|
|
343
419
|
write_attribute(:zuora_logins, kms_encrypt(val.to_json))
|
|
420
|
+
rescue Aws::KMS::Errors::ValidationException, Aws::KMS::Errors::NotFoundException, *AWS_AUTH_ERRORS => ex
|
|
421
|
+
Rails.logger.warn(AWS_AUTH_ERRORS_MSG, ex)
|
|
344
422
|
end
|
|
345
423
|
|
|
346
424
|
def zuora_logins
|
|
@@ -350,7 +428,7 @@ module ZuoraConnect
|
|
|
350
428
|
|
|
351
429
|
def kms_decrypt(value)
|
|
352
430
|
kms_tries ||= 0
|
|
353
|
-
kms_client = Aws::KMS::Client.new({region:
|
|
431
|
+
kms_client = Aws::KMS::Client.new({region: aws_secrets['AWS_REGION'], credentials: self.aws_auth_client}.delete_if { |k, v| v.blank? })
|
|
354
432
|
resp = kms_client.decrypt({ciphertext_blob: [value].pack("H*") })
|
|
355
433
|
return resp.plaintext
|
|
356
434
|
rescue *AWS_AUTH_ERRORS => ex
|
|
@@ -365,7 +443,7 @@ module ZuoraConnect
|
|
|
365
443
|
|
|
366
444
|
def kms_encrypt(value)
|
|
367
445
|
kms_tries ||= 0
|
|
368
|
-
kms_client = Aws::KMS::Client.new({region:
|
|
446
|
+
kms_client = Aws::KMS::Client.new({region: aws_secrets['AWS_REGION'], credentials: self.aws_auth_client}.delete_if {|k,v| v.blank? })
|
|
369
447
|
|
|
370
448
|
resp = kms_client.encrypt({key_id: kms_key, plaintext: value})
|
|
371
449
|
return resp.ciphertext_blob.unpack('H*').first
|
|
@@ -380,12 +458,12 @@ module ZuoraConnect
|
|
|
380
458
|
end
|
|
381
459
|
|
|
382
460
|
def kms_key
|
|
383
|
-
return ENV['AWS_KMS_ARN'] ||
|
|
461
|
+
return ENV['AWS_KMS_ARN'] || aws_secrets['AWS_KMS_ARN']
|
|
384
462
|
end
|
|
385
463
|
|
|
386
464
|
def aws_auth_client
|
|
387
465
|
if Rails.env.to_s == 'development'
|
|
388
|
-
return Aws::Credentials.new(
|
|
466
|
+
return Aws::Credentials.new(aws_secrets['AWS_ACCESS_KEY_ID'], aws_secrets['AWS_SECRET_ACCESS_KEY'])
|
|
389
467
|
else
|
|
390
468
|
return nil
|
|
391
469
|
end
|
|
@@ -400,82 +478,6 @@ module ZuoraConnect
|
|
|
400
478
|
end
|
|
401
479
|
Thread.current[:appinstance] = self
|
|
402
480
|
end
|
|
403
|
-
|
|
404
|
-
def self.write_to_telegraf(*args)
|
|
405
|
-
if ZuoraConnect.configuration.enable_metrics
|
|
406
|
-
@@telegraf_host = ZuoraConnect::Telegraf.new() if @@telegraf_host == nil
|
|
407
|
-
unicorn_stats = self.unicorn_listener_stats() if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
|
408
|
-
@@telegraf_host.write(direction: 'Raindrops', tags: {}, values: unicorn_stats) unless unicorn_stats.blank?
|
|
409
|
-
return @@telegraf_host.write(*args)
|
|
410
|
-
end
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
def self.unicorn_listener_stats ()
|
|
414
|
-
stats_hash = {}
|
|
415
|
-
stats_hash["total_active"] = 0
|
|
416
|
-
stats_hash["total_queued"] = 0
|
|
417
|
-
|
|
418
|
-
begin
|
|
419
|
-
tmp = Unicorn.listener_names
|
|
420
|
-
unix = tmp.grep(%r{\A/})
|
|
421
|
-
tcp = tmp.grep(/\A.+:\d+\z/)
|
|
422
|
-
tcp = nil if tcp.empty?
|
|
423
|
-
unix = nil if unix.empty?
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
Raindrops::Linux.tcp_listener_stats(tcp).each do |addr,stats|
|
|
427
|
-
stats_hash["active_#{addr}"] = stats.active
|
|
428
|
-
stats_hash["queued_#{addr}"] = stats.queued
|
|
429
|
-
stats_hash["total_active"] = stats.active + stats_hash["total_active"]
|
|
430
|
-
stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
|
|
431
|
-
end if tcp
|
|
432
|
-
|
|
433
|
-
Raindrops::Linux.unix_listener_stats(unix).each do |addr,stats|
|
|
434
|
-
stats_hash["active_#{addr}"] = stats.active
|
|
435
|
-
stats_hash["queued_#{addr}"] = stats.queued
|
|
436
|
-
stats_hash["total_active"] = stats.active + stats_hash["total_active"]
|
|
437
|
-
stats_hash["total_queued"] = stats.queued + stats_hash["total_queued"]
|
|
438
|
-
end if unix
|
|
439
|
-
rescue IOError => ex
|
|
440
|
-
rescue => ex
|
|
441
|
-
ZuoraConnect.logger.error(ex)
|
|
442
|
-
end
|
|
443
|
-
return stats_hash
|
|
444
|
-
end
|
|
445
|
-
|
|
446
|
-
def self.get_metrics(type)
|
|
447
|
-
@data = {}
|
|
448
|
-
|
|
449
|
-
if type == "versions"
|
|
450
|
-
@data = {
|
|
451
|
-
app_name: ZuoraConnect::Telegraf.app_name,
|
|
452
|
-
url: "dummy",
|
|
453
|
-
Version_Gem: ZuoraConnect::VERSION,
|
|
454
|
-
Version_Zuora: ZuoraAPI::VERSION ,
|
|
455
|
-
Version_Ruby: RUBY_VERSION,
|
|
456
|
-
Version_Rails: Rails.version,
|
|
457
|
-
hold: 1
|
|
458
|
-
}
|
|
459
|
-
elsif type == "stats"
|
|
460
|
-
begin
|
|
461
|
-
Resque.redis.ping
|
|
462
|
-
@resque = Resque.info
|
|
463
|
-
@data = {
|
|
464
|
-
app_name: ZuoraConnect::Telegraf.app_name,
|
|
465
|
-
url: "dummy",
|
|
466
|
-
Resque:{
|
|
467
|
-
Jobs_Finished: @resque[:processed] ,
|
|
468
|
-
Jobs_Failed: @resque[:failed],
|
|
469
|
-
Jobs_Pending: @resque[:pending],
|
|
470
|
-
Workers_Active: @resque[:working],
|
|
471
|
-
Workers_Total: @resque[:workers]
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
rescue
|
|
475
|
-
end
|
|
476
|
-
end
|
|
477
|
-
return @data
|
|
478
|
-
end
|
|
479
481
|
#### END Task Methods ####
|
|
480
482
|
|
|
481
483
|
#### START Task Methods ####
|
|
@@ -518,7 +520,7 @@ module ZuoraConnect
|
|
|
518
520
|
end
|
|
519
521
|
rescue ZuoraConnect::Exceptions::MissMatch => ex
|
|
520
522
|
raise
|
|
521
|
-
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
|
523
|
+
rescue ZuoraConnect::Exceptions::InvalidCredentialSet => ex
|
|
522
524
|
raise
|
|
523
525
|
rescue => ex
|
|
524
526
|
ZuoraConnect.logger.error("Build Task Error", ex)
|
|
@@ -574,12 +576,12 @@ module ZuoraConnect
|
|
|
574
576
|
self.refresh if !defined?(self.target_login)
|
|
575
577
|
|
|
576
578
|
response = HTTParty.get("#{ZuoraConnect.configuration.url}/api/#{self.api_version}/tenants/search?hostname=#{self.target_login.client.hostname}&node_id=#{self.zuora_entity_ids.first}")
|
|
577
|
-
|
|
579
|
+
|
|
578
580
|
if response.success?
|
|
579
581
|
parsed_json = JSON.parse(response.body)
|
|
580
|
-
|
|
582
|
+
|
|
581
583
|
#Set Org
|
|
582
|
-
if self.
|
|
584
|
+
if self.auto_deployed? && parsed_json['organization'].present?
|
|
583
585
|
login_cache = self.zuora_logins
|
|
584
586
|
login_cache.delete('organization')
|
|
585
587
|
self.zuora_logins = login_cache.merge({'organizations' => [parsed_json['organization']]})
|
|
@@ -599,7 +601,7 @@ module ZuoraConnect
|
|
|
599
601
|
end
|
|
600
602
|
end
|
|
601
603
|
self.save(:validate => false)
|
|
602
|
-
|
|
604
|
+
|
|
603
605
|
return parsed_json
|
|
604
606
|
end
|
|
605
607
|
rescue *(ZuoraAPI::Login::CONNECTION_EXCEPTIONS + ZuoraAPI::Login::CONNECTION_READ_EXCEPTIONS) => ex
|
|
@@ -653,7 +655,7 @@ module ZuoraConnect
|
|
|
653
655
|
end
|
|
654
656
|
|
|
655
657
|
def refresh_oauth
|
|
656
|
-
refresh_oauth_count ||= 0
|
|
658
|
+
refresh_oauth_count ||= 0
|
|
657
659
|
response = HTTParty.post("#{ZuoraConnect.configuration.url}/oauth/token", body: {
|
|
658
660
|
:grant_type => "refresh_token",
|
|
659
661
|
:redirect_uri => ZuoraConnect.configuration.oauth_client_redirect_uri,
|
|
@@ -955,13 +957,81 @@ module ZuoraConnect
|
|
|
955
957
|
# object_id: The id or id's of the object/objects to be returned.
|
|
956
958
|
# child_objects: Whether to include child objects of the object in question.
|
|
957
959
|
# cache: Store individual "1" object lookup in redis for caching.
|
|
958
|
-
def catalog_lookup(entity_id: nil, object: :product, object_id: nil, child_objects: false, cache: false)
|
|
960
|
+
def catalog_lookup(entity_id: nil, object: :product, object_id: nil, child_objects: false, cache: false, source: 'DB')
|
|
959
961
|
entity_reference = entity_id.blank? ? 'Default' : entity_id
|
|
960
962
|
|
|
961
963
|
if object_id.present? && ![Array, String].include?(object_id.class)
|
|
962
964
|
raise "Object Id can only be a string or an array of strings"
|
|
963
965
|
end
|
|
964
966
|
|
|
967
|
+
if source == 'API'
|
|
968
|
+
catalog_container = {}
|
|
969
|
+
|
|
970
|
+
if (Redis.current.hget(CATALOG_LOOKUP_CACHE_TIME_KEY, self.id).to_i + CATALOG_LOOKUP_TTL.to_i) > Time.now.to_i
|
|
971
|
+
begin
|
|
972
|
+
catalog_container = JSON.parse(Redis.current.hget(CATALOG_LOOKUP_CACHE_RESULT_KEY, self.id))
|
|
973
|
+
rescue JSON::ParserError => ex
|
|
974
|
+
Rails.logger.warn('Failed to parse catalog cache', ex)
|
|
975
|
+
end
|
|
976
|
+
else
|
|
977
|
+
zuora_login = self.login_lookup(type: 'Zuora').first
|
|
978
|
+
login = zuora_login.client(entity_reference)
|
|
979
|
+
|
|
980
|
+
response = {
|
|
981
|
+
'nextPage' => login.rest_endpoint("catalog/products?pageSize=#{CATALOG_LOOKUP_PAGE_SIZE}")
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
while response['nextPage'].present?
|
|
985
|
+
url = login.rest_endpoint(response['nextPage'].split('/v1/').last)
|
|
986
|
+
output_json, response = login.rest_call(debug: false, url: url, timeout_retry: true)
|
|
987
|
+
|
|
988
|
+
case object
|
|
989
|
+
when :product
|
|
990
|
+
output_json.fetch('products', []).each do |product|
|
|
991
|
+
rate_plans = {}
|
|
992
|
+
product['productRatePlans'].each do |rate_plan|
|
|
993
|
+
charges = {}
|
|
994
|
+
rate_plan['productRatePlanCharges'].each do |charge|
|
|
995
|
+
charges[charge['id']] = charge.merge(
|
|
996
|
+
{
|
|
997
|
+
'productId' => product['id'],
|
|
998
|
+
'productName' => product['name'],
|
|
999
|
+
'productRatePlanId' => rate_plan['id'],
|
|
1000
|
+
'productRatePlanName' => rate_plan['name'],
|
|
1001
|
+
}
|
|
1002
|
+
)
|
|
1003
|
+
end
|
|
1004
|
+
|
|
1005
|
+
rate_plan['productRatePlanCharges'] = charges
|
|
1006
|
+
rate_plans[rate_plan['id']] = rate_plan.merge(
|
|
1007
|
+
{
|
|
1008
|
+
'productId' => product['id'],
|
|
1009
|
+
'productName' => product['name']
|
|
1010
|
+
}
|
|
1011
|
+
)
|
|
1012
|
+
end
|
|
1013
|
+
|
|
1014
|
+
product['productRatePlans'] = rate_plans
|
|
1015
|
+
catalog_container[product['id']] = product
|
|
1016
|
+
end
|
|
1017
|
+
else
|
|
1018
|
+
raise "Available objects include [:product]"
|
|
1019
|
+
end
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
Redis.current.hset(CATALOG_LOOKUP_CACHE_RESULT_KEY, self.id, catalog_container.to_json)
|
|
1023
|
+
Redis.current.hset(CATALOG_LOOKUP_CACHE_TIME_KEY, self.id, Time.now.to_i)
|
|
1024
|
+
end
|
|
1025
|
+
|
|
1026
|
+
if object_id.nil?
|
|
1027
|
+
catalog_container.transform_values! { |v| v.except('productRatePlans') }
|
|
1028
|
+
elsif object_id.is_a?(String)
|
|
1029
|
+
catalog_container = catalog_container[object_id]
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
return catalog_container || {}
|
|
1033
|
+
end
|
|
1034
|
+
|
|
965
1035
|
if defined?(Redis.current) && object_id.present? && object_id.class == String && object_id.present?
|
|
966
1036
|
stub_catalog = cache ? decrypt_data(data: Redis.current.get("Catalog:#{self.id}:#{object_id}:Children:#{child_objects}")) : nil
|
|
967
1037
|
object_hierarchy = decrypt_data(data: Redis.current.get("Catalog:#{self.id}:#{object_id}:Hierarchy"))
|
|
@@ -1221,7 +1291,7 @@ module ZuoraConnect
|
|
|
1221
1291
|
|
|
1222
1292
|
def self.without_sticking
|
|
1223
1293
|
if self.connection.respond_to?(:without_sticking)
|
|
1224
|
-
self.connection.without_sticking do
|
|
1294
|
+
self.connection.without_sticking do
|
|
1225
1295
|
yield
|
|
1226
1296
|
end
|
|
1227
1297
|
else
|