zuora_connect 2.0.60l → 2.0.60
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/app/controllers/zuora_connect/static_controller.rb +12 -83
- data/app/models/zuora_connect/app_instance_base.rb +7 -58
- data/config/initializers/postgresql_adapter.rb +1 -71
- data/config/initializers/prometheus.rb +23 -78
- data/config/initializers/resque.rb +0 -14
- data/config/initializers/unicorn.rb +1 -29
- data/config/routes.rb +0 -5
- data/lib/middleware/json_parse_errors.rb +2 -13
- data/lib/middleware/metrics_middleware.rb +31 -45
- data/lib/resque/dynamic_queues.rb +1 -1
- data/lib/zuora_connect/controllers/helpers.rb +73 -211
- data/lib/zuora_connect/railtie.rb +5 -24
- data/lib/zuora_connect/version.rb +1 -1
- metadata +29 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bae96287832facbb0f512eedca7038f2bd566650d4e057f0d623613cb3acb559
|
4
|
+
data.tar.gz: d3b1f756842c3231a23719669d81c7aa206dfc677ae19ae2e537d3c3f6c089ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 872a07f80dfbe1c12428cacc4369fe83a0f59eb20d953c0c43f609d19cd75556138e1162f4e175c6fdf10844f4bf2a01c0f8f1529c7a6e0774d7b53b47f4e68a
|
7
|
+
data.tar.gz: c2f5653b77bbc93521c37062542d12697fb21e055cff18a55846837e6f454dd2ce15963580f6623e523d6b30f677bce8e1fb7820a28b981cfa69c73bd6f7333a
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module ZuoraConnect
|
2
2
|
class StaticController < ApplicationController
|
3
|
-
before_action :authenticate_connect_app_request, :except => [:metrics, :health, :initialize_app
|
4
|
-
before_action :clear_connect_app_session, :only => [:metrics, :health, :initialize_app
|
5
|
-
after_action :persist_connect_app_session, :except => [:metrics, :health, :initialize_app
|
6
|
-
|
7
|
-
skip_before_action :verify_authenticity_token, :only => [:initialize_app
|
8
|
-
http_basic_authenticate_with name: ENV['PROVISION_USER'], password: ENV['PROVISION_SECRET'], :only => [:provision, :instance_user]
|
3
|
+
before_action :authenticate_connect_app_request, :except => [:metrics, :health, :initialize_app]
|
4
|
+
before_action :clear_connect_app_session, :only => [:metrics, :health, :initialize_app]
|
5
|
+
after_action :persist_connect_app_session, :except => [:metrics, :health, :initialize_app]
|
6
|
+
|
7
|
+
skip_before_action :verify_authenticity_token, :only => [:initialize_app]
|
9
8
|
|
10
9
|
def metrics
|
11
10
|
type = params[:type].present? ? params[:type] : "versions"
|
@@ -14,11 +13,11 @@ module ZuoraConnect
|
|
14
13
|
|
15
14
|
def health
|
16
15
|
if params[:error].present?
|
17
|
-
begin
|
16
|
+
begin
|
18
17
|
raise ZuoraConnect::Exceptions::Error.new('This is an error')
|
19
18
|
rescue => ex
|
20
19
|
case params[:error]
|
21
|
-
when 'Log'
|
20
|
+
when 'Log'
|
22
21
|
Rails.logger.error("Error in Health", ex)
|
23
22
|
when 'Exception'
|
24
23
|
raise
|
@@ -35,13 +34,11 @@ module ZuoraConnect
|
|
35
34
|
def initialize_app
|
36
35
|
begin
|
37
36
|
authenticate_connect_app_request
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
}, status: 200
|
44
|
-
end
|
37
|
+
@appinstance.new_session(:session => @appinstance.data_lookup(:session => session))
|
38
|
+
render json: {
|
39
|
+
message: "Success",
|
40
|
+
status: 200
|
41
|
+
}, status: 200
|
45
42
|
rescue => ex
|
46
43
|
Rails.logger.error("Failed to Initialize application", ex)
|
47
44
|
if performed?
|
@@ -55,74 +52,6 @@ module ZuoraConnect
|
|
55
52
|
end
|
56
53
|
end
|
57
54
|
|
58
|
-
def provision
|
59
|
-
create_new_instance
|
60
|
-
unless performed?
|
61
|
-
render json: {
|
62
|
-
status: 200,
|
63
|
-
message: 'Success',
|
64
|
-
app_instance_id: @appinstance.id
|
65
|
-
}, status: 200
|
66
|
-
end
|
67
|
-
rescue StandardError => e
|
68
|
-
message = 'Failed to provision new instance'
|
69
|
-
if performed?
|
70
|
-
Rails.logger.error("#{message}: #{performed?}", e)
|
71
|
-
else
|
72
|
-
Rails.logger.error(message, e)
|
73
|
-
render json: {
|
74
|
-
status: 500,
|
75
|
-
message: message
|
76
|
-
}, status: 500
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def instance_user
|
81
|
-
ZuoraConnect::AppInstance.read_master_db do
|
82
|
-
ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
|
83
|
-
Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
|
84
|
-
|
85
|
-
if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
|
86
|
-
ElasticAPM.set_label(:trace_id, request.uuid)
|
87
|
-
end
|
88
|
-
|
89
|
-
unless params[:id].present?
|
90
|
-
render json: {
|
91
|
-
status: 400,
|
92
|
-
message: 'No app instance id provided'
|
93
|
-
}, status: :bad_request
|
94
|
-
return
|
95
|
-
end
|
96
|
-
|
97
|
-
@appinstance = ZuoraConnect::AppInstance.find(params[:id]).new_session
|
98
|
-
end
|
99
|
-
|
100
|
-
zuora_client = @appinstance.send(ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION).client
|
101
|
-
client_describe, = zuora_client.rest_call(
|
102
|
-
url: zuora_client.rest_endpoint('genesis/user/info').gsub('v1/', ''),
|
103
|
-
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic
|
104
|
-
)
|
105
|
-
|
106
|
-
render json: {
|
107
|
-
status: 200,
|
108
|
-
message: 'Success',
|
109
|
-
user_id: client_describe['coreUserId'],
|
110
|
-
username: client_describe['username'],
|
111
|
-
email: client_describe['workEmail']
|
112
|
-
}, status: 200
|
113
|
-
rescue ActiveRecord::RecordNotFound
|
114
|
-
render json: {
|
115
|
-
status: 400,
|
116
|
-
message: 'No app instance found'
|
117
|
-
}, status: :bad_request
|
118
|
-
rescue StandardError => e
|
119
|
-
Rails.logger.error('Error occurred getting user details', e)
|
120
|
-
render json: {
|
121
|
-
status: 500,
|
122
|
-
message: 'Failed to get user details'
|
123
|
-
}, status: 500
|
124
|
-
end
|
125
|
-
|
126
55
|
private
|
127
56
|
|
128
57
|
def clear_connect_app_session
|
@@ -11,7 +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
|
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
15
|
@@telegraf_host = nil
|
16
16
|
REFRESH_TIMEOUT = 2.minute #Used to determine how long to wait on current refresh call before executing another
|
17
17
|
INSTANCE_REFRESH_WINDOW = 1.hours #Used to set how how long till app starts attempting to refresh cached task connect data
|
@@ -240,50 +240,7 @@ module ZuoraConnect
|
|
240
240
|
rescue I18n::InvalidLocale => ex
|
241
241
|
ZuoraConnect.logger.error(ex) if !IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
242
242
|
end
|
243
|
-
|
244
|
-
begin
|
245
|
-
sql = <<-eos
|
246
|
-
SELECT zuora_users.zuora_identity_response
|
247
|
-
FROM "#{self.id}".zuora_users
|
248
|
-
ORDER BY zuora_users.updated_at DESC
|
249
|
-
LIMIT 1;
|
250
|
-
eos
|
251
|
-
user = ActiveRecord::Base.connection.execute(sql).to_a.first
|
252
|
-
|
253
|
-
if user.present?
|
254
|
-
zuora_identity_response = JSON.parse(user.fetch('zuora_identity_response', '{}'))
|
255
|
-
self.user_timezone = zuora_identity_response.values.first&.dig('timeZone')
|
256
|
-
end
|
257
|
-
rescue => ex
|
258
|
-
Rails.logger.error('Failed to get users while setting app instance timezone', ex)
|
259
|
-
end
|
260
|
-
|
261
|
-
if self.user_timezone.present?
|
262
|
-
# connect instance which has a custom timezone
|
263
|
-
if !self.auto_deployed? && (
|
264
|
-
ActiveSupport::TimeZone[self.task_data.dig('user_settings', 'timezone') || '']&.utc_offset !=
|
265
|
-
ActiveSupport::TimeZone[self.user_timezone]&.utc_offset
|
266
|
-
)
|
267
|
-
if self.environment == 'Production'
|
268
|
-
ZuoraConnect.logger.error(
|
269
|
-
"Instance and user timezones are different. User has '#{self.user_timezone}' and " \
|
270
|
-
"instance has '#{self.task_data.dig('user_settings', 'timezone')}'",
|
271
|
-
app_instance_id: self.id
|
272
|
-
)
|
273
|
-
end
|
274
|
-
self.user_timezone = nil
|
275
|
-
Time.zone = self.timezone
|
276
|
-
else
|
277
|
-
begin
|
278
|
-
Time.zone = self.user_timezone
|
279
|
-
rescue ArgumentError
|
280
|
-
Time.zone = self.timezone
|
281
|
-
end
|
282
|
-
end
|
283
|
-
else
|
284
|
-
Time.zone = self.timezone
|
285
|
-
end
|
286
|
-
|
243
|
+
Time.zone = self.timezone
|
287
244
|
if self.task_data.present?
|
288
245
|
tenants = self.task_data.fetch('tenant_ids', [])
|
289
246
|
organizations = self.task_data.fetch('organizations', [])
|
@@ -315,10 +272,6 @@ module ZuoraConnect
|
|
315
272
|
end
|
316
273
|
end
|
317
274
|
|
318
|
-
def auto_deployed?
|
319
|
-
self.id >= 25000000
|
320
|
-
end
|
321
|
-
|
322
275
|
def refresh(session: {})
|
323
276
|
refresh_count ||= 0
|
324
277
|
skip_connect ||= false
|
@@ -385,10 +338,6 @@ module ZuoraConnect
|
|
385
338
|
raise
|
386
339
|
end
|
387
340
|
|
388
|
-
def aws_secrets
|
389
|
-
(Rails.application.secrets.aws || {}).transform_keys { |key| key.to_s }
|
390
|
-
end
|
391
|
-
|
392
341
|
#### START KMS ENCRYPTION Methods ####
|
393
342
|
def zuora_logins=(val)
|
394
343
|
write_attribute(:zuora_logins, kms_encrypt(val.to_json))
|
@@ -401,7 +350,7 @@ module ZuoraConnect
|
|
401
350
|
|
402
351
|
def kms_decrypt(value)
|
403
352
|
kms_tries ||= 0
|
404
|
-
kms_client = Aws::KMS::Client.new({region:
|
353
|
+
kms_client = Aws::KMS::Client.new({region: Rails.application.secrets.aws['AWS_REGION'], credentials: self.aws_auth_client}.delete_if { |k, v| v.blank? })
|
405
354
|
resp = kms_client.decrypt({ciphertext_blob: [value].pack("H*") })
|
406
355
|
return resp.plaintext
|
407
356
|
rescue *AWS_AUTH_ERRORS => ex
|
@@ -416,7 +365,7 @@ module ZuoraConnect
|
|
416
365
|
|
417
366
|
def kms_encrypt(value)
|
418
367
|
kms_tries ||= 0
|
419
|
-
kms_client = Aws::KMS::Client.new({region:
|
368
|
+
kms_client = Aws::KMS::Client.new({region: Rails.application.secrets.aws['AWS_REGION'], credentials: self.aws_auth_client}.delete_if {|k,v| v.blank? })
|
420
369
|
|
421
370
|
resp = kms_client.encrypt({key_id: kms_key, plaintext: value})
|
422
371
|
return resp.ciphertext_blob.unpack('H*').first
|
@@ -431,12 +380,12 @@ module ZuoraConnect
|
|
431
380
|
end
|
432
381
|
|
433
382
|
def kms_key
|
434
|
-
return ENV['AWS_KMS_ARN'] ||
|
383
|
+
return ENV['AWS_KMS_ARN'] || Rails.application.secrets.dig(:aws,'AWS_KMS_ARN')
|
435
384
|
end
|
436
385
|
|
437
386
|
def aws_auth_client
|
438
387
|
if Rails.env.to_s == 'development'
|
439
|
-
return Aws::Credentials.new(
|
388
|
+
return Aws::Credentials.new(Rails.application.secrets.aws['AWS_ACCESS_KEY_ID'], Rails.application.secrets.aws['AWS_SECRET_ACCESS_KEY'])
|
440
389
|
else
|
441
390
|
return nil
|
442
391
|
end
|
@@ -453,7 +402,7 @@ module ZuoraConnect
|
|
453
402
|
end
|
454
403
|
|
455
404
|
def self.write_to_telegraf(*args)
|
456
|
-
if ZuoraConnect.configuration.enable_metrics
|
405
|
+
if ZuoraConnect.configuration.enable_metrics
|
457
406
|
@@telegraf_host = ZuoraConnect::Telegraf.new() if @@telegraf_host == nil
|
458
407
|
unicorn_stats = self.unicorn_listener_stats() if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
459
408
|
@@telegraf_host.write(direction: 'Raindrops', tags: {}, values: unicorn_stats) unless unicorn_stats.blank?
|
@@ -1,15 +1,9 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
3
|
class PostgreSQLAdapter < AbstractAdapter
|
4
|
-
|
5
|
-
SCHEMA_ADDITIONAL_TYPES = 'SchemaAdditionalTypes'.freeze
|
6
|
-
|
7
4
|
private
|
8
|
-
def
|
5
|
+
def load_additional_types(type_map, oids = nil)
|
9
6
|
initializer = OID::TypeMapInitializer.new(type_map)
|
10
|
-
|
11
|
-
return if loaded_from_cache?(initializer)
|
12
|
-
|
13
7
|
if supports_ranges?
|
14
8
|
query = <<-SQL
|
15
9
|
SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
@@ -30,73 +24,9 @@ module ActiveRecord
|
|
30
24
|
end
|
31
25
|
|
32
26
|
execute_and_clear(query, "SCHEMA", []) do |records|
|
33
|
-
cache_additional_types(records)
|
34
27
|
initializer.run(records)
|
35
28
|
end
|
36
29
|
end
|
37
|
-
|
38
|
-
def load_additional_types_deprecated(type_map, oids = nil)
|
39
|
-
initializer = OID::TypeMapInitializer.new(type_map)
|
40
|
-
|
41
|
-
return if loaded_from_cache?(initializer)
|
42
|
-
|
43
|
-
if supports_ranges?
|
44
|
-
query = <<-SQL
|
45
|
-
SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
|
46
|
-
FROM pg_type as t
|
47
|
-
LEFT JOIN pg_range as r ON oid = rngtypid
|
48
|
-
SQL
|
49
|
-
else
|
50
|
-
query = <<-SQL
|
51
|
-
SELECT DISTINCT on (t.typname) t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
|
52
|
-
FROM pg_type as t
|
53
|
-
SQL
|
54
|
-
end
|
55
|
-
|
56
|
-
if oids
|
57
|
-
query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
|
58
|
-
else
|
59
|
-
query += initializer.query_conditions_for_initial_load(type_map)
|
60
|
-
end
|
61
|
-
|
62
|
-
execute_and_clear(query, "SCHEMA", []) do |records|
|
63
|
-
cache_additional_types(records)
|
64
|
-
initializer.run(records)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def loaded_from_cache?(initializer)
|
69
|
-
if defined?(Redis.current)
|
70
|
-
begin
|
71
|
-
if Redis.current.exists(SCHEMA_ADDITIONAL_TYPES)
|
72
|
-
initializer.run(JSON.parse(Redis.current.get(SCHEMA_ADDITIONAL_TYPES)))
|
73
|
-
return true
|
74
|
-
end
|
75
|
-
rescue => ex
|
76
|
-
Rails.logger.warn('Exception occurred while loading additional types', ex)
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
false
|
81
|
-
end
|
82
|
-
|
83
|
-
def cache_additional_types(records)
|
84
|
-
if defined?(Redis.current)
|
85
|
-
begin
|
86
|
-
Redis.current.setex(SCHEMA_ADDITIONAL_TYPES, 1.hour.to_i, records.to_json)
|
87
|
-
rescue => ex
|
88
|
-
Rails.logger.warn('Exception occurred while caching additional types', ex)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
rails_version = Rails.version.split('.').map { |x| x.to_i }
|
95
|
-
if (rails_version <=> [5, 2, 0]) >= 1
|
96
|
-
alias :load_additional_types :load_additional_types_latest
|
97
|
-
else
|
98
|
-
alias :load_additional_types :load_additional_types_deprecated
|
99
|
-
end
|
100
30
|
end
|
101
31
|
end
|
102
32
|
end
|
@@ -3,93 +3,38 @@ if defined? Prometheus
|
|
3
3
|
require "zuora_connect/version"
|
4
4
|
require "zuora_api/version"
|
5
5
|
|
6
|
-
resque_path = "#{ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')}/*.prom"
|
7
|
-
prometheus_path = Rails.root.join("tmp/prometheus")
|
8
|
-
|
9
|
-
Dir[resque_path, "#{prometheus_path}/*.bin"].each do |file_path|
|
10
|
-
File.unlink(file_path)
|
11
|
-
end
|
12
|
-
|
13
|
-
require 'prometheus/client/data_stores/direct_file_store'
|
14
|
-
Prometheus::Client.config.data_store = Prometheus::Client::DataStores::DirectFileStore.new(
|
15
|
-
dir: prometheus_path
|
16
|
-
)
|
17
|
-
|
18
|
-
class ResqueExporter
|
19
|
-
require 'prometheus/client/formats/text'
|
20
|
-
require 'fileutils'
|
21
|
-
|
22
|
-
def initialize
|
23
|
-
@lock = Monitor.new
|
24
|
-
@registry = Prometheus::Client.registry
|
25
|
-
@path = ENV['RESQUE_EXPORTER_PATH'] || Rails.root.join('tmp/resque_exporter')
|
26
|
-
FileUtils.mkdir_p(@path)
|
27
|
-
end
|
28
|
-
|
29
|
-
def export
|
30
|
-
filename = File.join(@path, 'resque_export.prom')
|
31
|
-
@lock.synchronize do
|
32
|
-
File.open(filename, 'w+') do |file|
|
33
|
-
file.write(Prometheus::Client::Formats::Text.marshal(@registry))
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
most_recent_aggregation = {}
|
40
|
-
sum_aggregation = {}
|
41
|
-
if defined?(Unicorn)
|
42
|
-
most_recent_aggregation[:aggregation] = :most_recent
|
43
|
-
sum_aggregation[:aggregation] = :sum
|
44
|
-
end
|
45
|
-
|
46
6
|
# Create a default Prometheus registry for our metrics.
|
47
7
|
prometheus = Prometheus::Client.registry
|
48
8
|
|
49
9
|
# Create your metrics.
|
50
|
-
ZUORA_VERSION =
|
51
|
-
CONNECT_VERSION =
|
52
|
-
RAILS_VERSION =
|
53
|
-
RUBY_V =
|
10
|
+
ZUORA_VERSION = Prometheus::Client::Gauge.new(:zuora_version, 'The current Zuora Gem version.')
|
11
|
+
CONNECT_VERSION = Prometheus::Client::Gauge.new(:gem_version, 'The current Connect Gem version.')
|
12
|
+
RAILS_VERSION = Prometheus::Client::Gauge.new(:rails_version, 'The current Rails version.')
|
13
|
+
RUBY_V = Prometheus::Client::Gauge.new(:ruby_version, 'The current Ruby version.')
|
54
14
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
15
|
+
# Register your metrics with the registry we previously created.
|
16
|
+
prometheus.register(ZUORA_VERSION);ZUORA_VERSION.set({version: ZuoraAPI::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
|
17
|
+
prometheus.register(CONNECT_VERSION);CONNECT_VERSION.set({version: ZuoraConnect::VERSION, name: ZuoraConnect::Telegraf.app_name},0)
|
18
|
+
prometheus.register(RAILS_VERSION);RAILS_VERSION.set({version: Rails.version, name: ZuoraConnect::Telegraf.app_name},0)
|
19
|
+
prometheus.register(RUBY_V);RUBY_V.set({version: RUBY_VERSION, name: ZuoraConnect::Telegraf.app_name},0)
|
59
20
|
|
60
21
|
# Do they have resque jobs?
|
61
22
|
if defined? Resque.redis
|
62
|
-
REDIS_CONNECTION =
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
preset_labels: {type:'Unicorn-Killer', name: ZuoraConnect::Telegraf.app_name},
|
76
|
-
store_settings: sum_aggregation
|
77
|
-
)
|
23
|
+
REDIS_CONNECTION = Prometheus::Client::Gauge.new(:redis_connection, 'The status of the redis connection, 0 or 1')
|
24
|
+
FINISHED_JOBS = Prometheus::Client::Gauge.new(:finished_jobs, 'Done resque jobs')
|
25
|
+
WORKERS = Prometheus::Client::Gauge.new(:workers, 'Total resque workers')
|
26
|
+
ACTIVE_WORKERS = Prometheus::Client::Gauge.new(:active_workers, 'Active resque workers')
|
27
|
+
FAILED_JOBS = Prometheus::Client::Gauge.new(:failed_jobs, 'Failed resque jobs')
|
28
|
+
PENDING_JOBS = Prometheus::Client::Gauge.new(:pending_jobs, 'Pending resque jobs')
|
29
|
+
|
30
|
+
prometheus.register(REDIS_CONNECTION)
|
31
|
+
prometheus.register(FINISHED_JOBS)
|
32
|
+
prometheus.register(ACTIVE_WORKERS)
|
33
|
+
prometheus.register(WORKERS)
|
34
|
+
prometheus.register(FAILED_JOBS)
|
35
|
+
prometheus.register(PENDING_JOBS)
|
78
36
|
|
79
|
-
ZuoraConnect::AppInstanceBase.unicorn_listener_stats.each do |key, _|
|
80
|
-
gauge_name = "unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_')
|
81
|
-
gauge = prometheus.gauge(
|
82
|
-
gauge_name.to_sym,
|
83
|
-
docstring: 'Unicorn Stats',
|
84
|
-
labels: %i(type name),
|
85
|
-
preset_labels: { type: 'unicorn', name: ZuoraConnect::Telegraf.app_name },
|
86
|
-
store_settings: most_recent_aggregation
|
87
|
-
)
|
88
|
-
Prometheus.const_set(
|
89
|
-
gauge_name.upcase,
|
90
|
-
gauge
|
91
|
-
)
|
92
|
-
end
|
93
37
|
end
|
38
|
+
|
94
39
|
end
|
95
40
|
end
|
@@ -5,20 +5,6 @@ if defined?(Resque::Worker)
|
|
5
5
|
Resque::Job.send(:include, Resque::SelfLookup)
|
6
6
|
end
|
7
7
|
|
8
|
-
if defined?(Resque::Job) && defined?(Prometheus)
|
9
|
-
module ResquePrometheusExtensions
|
10
|
-
EXPORTER = Prometheus::ResqueExporter.new
|
11
|
-
def perform
|
12
|
-
super
|
13
|
-
EXPORTER.export
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
class Resque::Job
|
18
|
-
prepend ResquePrometheusExtensions
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
8
|
Resque.module_eval do
|
23
9
|
# Returns a hash, mapping queue names to queue sizes
|
24
10
|
def queue_sizes
|
@@ -3,35 +3,7 @@ if defined?(Unicorn::WorkerKiller)
|
|
3
3
|
self.singleton_class.send(:alias_method, :kill_self_old, :kill_self)
|
4
4
|
def self.kill_self(logger, start_time)
|
5
5
|
self.kill_self_old(logger, start_time)
|
6
|
-
|
7
|
-
Prometheus::UNICORN_KILLS.set(1)
|
8
|
-
else
|
9
|
-
ZuoraConnect::AppInstance.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
|
10
|
-
end
|
6
|
+
ZuoraConnect::AppInstance.write_to_telegraf(direction: 'Unicorn-Killer', tags: {app_instance: 0}, values: {kill: 1})
|
11
7
|
end
|
12
8
|
end
|
13
|
-
end
|
14
|
-
|
15
|
-
if defined?(Unicorn::HttpServer) && defined?(Prometheus)
|
16
|
-
module HttpServerExtensions
|
17
|
-
def kill_worker(signal, wpid)
|
18
|
-
Prometheus::UNICORN_KILLS.increment
|
19
|
-
super
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
module WorkerExtensions
|
24
|
-
def soft_kill(sig)
|
25
|
-
Prometheus::UNICORN_KILLS.increment
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class Unicorn::HttpServer
|
31
|
-
prepend HttpServerExtensions
|
32
|
-
end
|
33
|
-
|
34
|
-
class Unicorn::Worker
|
35
|
-
prepend WorkerExtensions
|
36
|
-
end
|
37
9
|
end
|
data/config/routes.rb
CHANGED
@@ -3,11 +3,6 @@ ZuoraConnect::Engine.routes.draw do
|
|
3
3
|
get '/internal/data' => 'static#metrics'
|
4
4
|
post '/initialize_app' => 'static#initialize_app'
|
5
5
|
|
6
|
-
if ENV['PROVISION_USER'].present? && ENV['PROVISION_SECRET'].present?
|
7
|
-
post '/provision' => 'static#provision'
|
8
|
-
get '/instance/:id/user' => 'static#instance_user'
|
9
|
-
end
|
10
|
-
|
11
6
|
namespace :api do
|
12
7
|
namespace :v1 do
|
13
8
|
resources :app_instance, :only => [:index], defaults: {format: :json} do
|
@@ -7,7 +7,7 @@ module ZuoraConnect
|
|
7
7
|
def call(env)
|
8
8
|
begin
|
9
9
|
@app.call(env)
|
10
|
-
rescue
|
10
|
+
rescue ActionDispatch::ParamsParser::ParseError => error
|
11
11
|
if env['HTTP_ACCEPT'] =~ /application\/json/ || env['CONTENT_TYPE'] =~ /application\/json/
|
12
12
|
return [
|
13
13
|
400, { "Content-Type" => "application/json" },
|
@@ -18,16 +18,5 @@ module ZuoraConnect
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
# Note(hartley): remove once the minimum supported version of Rails is 5.2
|
23
|
-
class DynamicRailsError < StandardError
|
24
|
-
def self.===(exception)
|
25
|
-
if Rails.version >= "5.2"
|
26
|
-
exception.is_a?(ActionDispatch::Http::Parameters::ParseError)
|
27
|
-
else
|
28
|
-
exception.is_a?(ActionDispatch::ParamsParser::ParseError)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
21
|
end
|
33
|
-
end
|
22
|
+
end
|
@@ -64,22 +64,6 @@ module ZuoraConnect
|
|
64
64
|
#Remove bad headers
|
65
65
|
@bad_headers.each { |header| env.delete(header) }
|
66
66
|
|
67
|
-
if defined?(Prometheus) && env['PATH_INFO'] == '/connect/internal/metrics'
|
68
|
-
# Prometheus Stuff
|
69
|
-
metrics = ZuoraConnect::AppInstance.get_metrics('stats')
|
70
|
-
redis_up = metrics.present? && metrics.dig(:Resque, :Workers_Total).present? ? 1 : 0
|
71
|
-
Prometheus::REDIS_CONNECTION.set(redis_up)
|
72
|
-
|
73
|
-
process_prometheus_metric(metrics: metrics)
|
74
|
-
|
75
|
-
if defined?(Unicorn) && Unicorn.respond_to?(:listener_names)
|
76
|
-
ZuoraConnect::AppInstanceBase.unicorn_listener_stats.each do |key, value|
|
77
|
-
gauge = Prometheus.const_get("unicorn_#{key}".gsub(/[^a-zA-Z0-9_]/, '_').upcase)
|
78
|
-
gauge.set(value) if gauge.present?
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
67
|
#Thread.current[:appinstance] = nil
|
84
68
|
start_time = Time.now
|
85
69
|
begin
|
@@ -93,6 +77,35 @@ module ZuoraConnect
|
|
93
77
|
ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: 'request-inbound-assets', tags: tags, values: values)
|
94
78
|
end
|
95
79
|
|
80
|
+
if defined? Prometheus
|
81
|
+
#Prometheus Stuff
|
82
|
+
if env['PATH_INFO'] == '/connect/internal/metrics'
|
83
|
+
|
84
|
+
#Do something before each scrape
|
85
|
+
if defined? Resque.redis
|
86
|
+
begin
|
87
|
+
|
88
|
+
Resque.redis.ping
|
89
|
+
|
90
|
+
Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},1)
|
91
|
+
Prometheus::FINISHED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:processed])
|
92
|
+
Prometheus::PENDING_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:pending])
|
93
|
+
Prometheus::ACTIVE_WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:working])
|
94
|
+
Prometheus::WORKERS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:workers])
|
95
|
+
Prometheus::FAILED_JOBS.set({type:'resque',name: ZuoraConnect::Telegraf.app_name},Resque.info[:failed])
|
96
|
+
|
97
|
+
rescue Redis::CannotConnectError
|
98
|
+
Prometheus::REDIS_CONNECTION.set({connection:'redis',name: ZuoraConnect::Telegraf.app_name},0)
|
99
|
+
end
|
100
|
+
|
101
|
+
if ZuoraConnect.configuration.custom_prometheus_update_block != nil
|
102
|
+
ZuoraConnect.configuration.custom_prometheus_update_block.call()
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
96
109
|
# Uncomment following block of code for handling engine requests/requests without controller
|
97
110
|
# else
|
98
111
|
# # Handling requests which do not have controllers (engines)
|
@@ -106,10 +119,10 @@ module ZuoraConnect
|
|
106
119
|
content_type = @headers['Content-Type'].split(';')[0] if @headers['Content-Type']
|
107
120
|
content_type = content_type.gsub('text/javascript', 'application/javascript')
|
108
121
|
tags = {status: @status, content_type: content_type}
|
109
|
-
|
122
|
+
|
110
123
|
tags = tags.merge({controller: 'ActionController'})
|
111
124
|
tags = tags.merge({action: 'RoutingError' }) if @status == 404
|
112
|
-
|
125
|
+
|
113
126
|
values = {response_time: ((Time.now - start_time)*1000).round(2) }
|
114
127
|
|
115
128
|
ZuoraConnect::AppInstanceBase.write_to_telegraf(direction: :inbound, tags: tags, values: values)
|
@@ -120,32 +133,5 @@ module ZuoraConnect
|
|
120
133
|
[@status, @headers, @response]
|
121
134
|
end
|
122
135
|
end
|
123
|
-
|
124
|
-
def process_prometheus_metric(type: 'none', metrics: {})
|
125
|
-
return if metrics.blank?
|
126
|
-
|
127
|
-
prometheus = Prometheus::Client.registry
|
128
|
-
most_recent_aggregation = {}
|
129
|
-
if Prometheus::Client.config.data_store.is_a?(Prometheus::Client::DataStores::DirectFileStore)
|
130
|
-
most_recent_aggregation[:aggregation] = :most_recent
|
131
|
-
end
|
132
|
-
metrics.each do |key, value|
|
133
|
-
next if %w[app_name url].include?(key.to_s)
|
134
|
-
|
135
|
-
if value.is_a?(Hash)
|
136
|
-
process_prometheus_metric(type: key.to_s, metrics: value)
|
137
|
-
else
|
138
|
-
gauge_name = key.to_s.downcase.gsub(/[^a-z0-9_]/, '_')
|
139
|
-
gauge = prometheus.get(gauge_name.to_sym) || prometheus.gauge(
|
140
|
-
gauge_name.to_sym,
|
141
|
-
docstring: "#{key} metric",
|
142
|
-
labels: %i(type name),
|
143
|
-
preset_labels: { type: type, name: ZuoraConnect::Telegraf.app_name },
|
144
|
-
store_settings: most_recent_aggregation
|
145
|
-
)
|
146
|
-
gauge.set(value)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
136
|
end
|
151
137
|
end
|
@@ -124,24 +124,14 @@ module ZuoraConnect
|
|
124
124
|
ElasticAPM.set_user(session["#{@appinstance.id}::user::email"]) if defined?(ElasticAPM) && ElasticAPM.running?
|
125
125
|
PaperTrail.whodunnit = session["#{@appinstance.id}::user::email"] if defined?(PaperTrail)
|
126
126
|
end
|
127
|
-
|
128
|
-
locale = (session["#{@appinstance.id}::user::locale"] || "").gsub("_", "-")
|
129
127
|
begin
|
128
|
+
locale = session["#{@appinstance.id}::user::locale"]
|
130
129
|
I18n.locale = locale.present? ? locale : @appinstance.locale
|
131
130
|
rescue I18n::InvalidLocale => ex
|
132
|
-
if locale.include?("-")
|
133
|
-
locale = locale.split("-").first
|
134
|
-
retry
|
135
|
-
elsif locale != session["#{@appinstance.id}::user::language"]
|
136
|
-
locale = session["#{@appinstance.id}::user::language"]
|
137
|
-
retry
|
138
|
-
end
|
139
131
|
ZuoraConnect.logger.error(ex) if !ZuoraConnect::AppInstance::IGNORED_LOCALS.include?(ex.locale.to_s.downcase)
|
140
132
|
end
|
141
133
|
begin
|
142
|
-
|
143
|
-
Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
|
144
|
-
end
|
134
|
+
Time.zone = session["#{@appinstance.id}::user::timezone"] ? session["#{@appinstance.id}::user::timezone"] : @appinstance.timezone
|
145
135
|
rescue
|
146
136
|
ZuoraConnect.logger.error(ex)
|
147
137
|
end
|
@@ -229,80 +219,6 @@ module ZuoraConnect
|
|
229
219
|
return (request.headers['ZuoraCurrentEntity'].present? || cookies['ZuoraCurrentEntity'].present?)
|
230
220
|
end
|
231
221
|
|
232
|
-
def create_new_instance
|
233
|
-
ZuoraConnect::AppInstance.read_master_db do
|
234
|
-
Thread.current[:appinstance] = nil
|
235
|
-
ZuoraConnect.logger.with_fields = {} if ZuoraConnect.logger.is_a?(Ougai::Logger)
|
236
|
-
Rails.logger.with_fields = {} if Rails.logger.is_a?(Ougai::Logger)
|
237
|
-
|
238
|
-
if defined?(ElasticAPM) && ElasticAPM.running? && ElasticAPM.respond_to?(:set_label)
|
239
|
-
ElasticAPM.set_label(:trace_id, request.uuid)
|
240
|
-
end
|
241
|
-
|
242
|
-
zuora_host = request.headers['zuora-host']
|
243
|
-
zuora_entity_id = (request.headers['zuora-entity-ids'] || '').gsub(
|
244
|
-
'-',
|
245
|
-
''
|
246
|
-
).split(',').first
|
247
|
-
|
248
|
-
# Validate host present
|
249
|
-
if zuora_host.blank?
|
250
|
-
render json: {
|
251
|
-
status: 401,
|
252
|
-
message: 'zuora-host header was not supplied.'
|
253
|
-
}, status: :unauthorized
|
254
|
-
return
|
255
|
-
end
|
256
|
-
|
257
|
-
# Validate entity-ids present
|
258
|
-
if zuora_entity_id.blank?
|
259
|
-
render json: {
|
260
|
-
status: 401,
|
261
|
-
message: 'zuora-entity-ids header was not supplied.'
|
262
|
-
}, status: :unauthorized
|
263
|
-
return
|
264
|
-
end
|
265
|
-
|
266
|
-
rest_domain = ZuoraAPI::Login.new(url: "https://#{zuora_host}").rest_domain
|
267
|
-
app_instance_id = ZuoraConnect::AppInstance.where(
|
268
|
-
'zuora_entity_ids ?& array[:entities] AND zuora_domain = :host',
|
269
|
-
entities: [zuora_entity_id],
|
270
|
-
host: rest_domain
|
271
|
-
).pluck(:id).first
|
272
|
-
|
273
|
-
if app_instance_id.present?
|
274
|
-
render json: {
|
275
|
-
status: 409,
|
276
|
-
message: 'Instance already exists.',
|
277
|
-
app_instance_id: app_instance_id
|
278
|
-
}, status: 409
|
279
|
-
else
|
280
|
-
Apartment::Tenant.switch!("public")
|
281
|
-
retry_count = 3
|
282
|
-
begin
|
283
|
-
@appinstance = new_instance(
|
284
|
-
next_instance_id,
|
285
|
-
zuora_entity_id,
|
286
|
-
rest_domain,
|
287
|
-
retry_count: retry_count
|
288
|
-
)
|
289
|
-
rescue ActiveRecord::RecordNotUnique
|
290
|
-
retry if (retry_count -= 1).positive?
|
291
|
-
return
|
292
|
-
end
|
293
|
-
|
294
|
-
app_instance_id = @appinstance.id
|
295
|
-
end
|
296
|
-
|
297
|
-
begin
|
298
|
-
Apartment::Tenant.switch!('public')
|
299
|
-
Apartment::Tenant.create(app_instance_id.to_s)
|
300
|
-
rescue Apartment::TenantExists
|
301
|
-
ZuoraConnect.logger.debug('Tenant Already Exists')
|
302
|
-
end
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
222
|
private
|
307
223
|
def setup_instance_via_prod_mode
|
308
224
|
zuora_entity_id = request.headers['ZuoraCurrentEntity'] || cookies['ZuoraCurrentEntity']
|
@@ -310,7 +226,7 @@ module ZuoraConnect
|
|
310
226
|
if zuora_entity_id.present?
|
311
227
|
zuora_tenant_id = cookies['Zuora-Tenant-Id']
|
312
228
|
zuora_user_id = cookies['Zuora-User-Id']
|
313
|
-
zuora_host = request.headers[
|
229
|
+
zuora_host = request.headers["HTTP_X_FORWARDED_HOST"] || "apisandbox.zuora.com"
|
314
230
|
|
315
231
|
zuora_details = {'host' => zuora_host, 'user_id' => zuora_user_id, 'tenant_id' => zuora_tenant_id, 'entity_id' => zuora_entity_id}
|
316
232
|
auth_headers = {}
|
@@ -412,16 +328,13 @@ module ZuoraConnect
|
|
412
328
|
|
413
329
|
zuora_user_id = cookies['Zuora-User-Id'] || session["ZuoraCurrentIdentity"]['userId']
|
414
330
|
|
331
|
+
#One deployed instance
|
415
332
|
if appinstances.size == 1
|
416
333
|
ZuoraConnect.logger.debug("Instance is #{appinstances.to_h.keys.first}")
|
417
334
|
@appinstance = ZuoraConnect::AppInstance.find(appinstances.to_h.keys.first)
|
418
|
-
end
|
419
335
|
|
420
|
-
# One deployed instance with credentials
|
421
|
-
if defined?(@appinstance) && !@appinstance['zuora_logins'].nil?
|
422
336
|
#Add user/update
|
423
337
|
begin
|
424
|
-
ZuoraConnect::ZuoraUser.reset_table_name
|
425
338
|
@zuora_user = ZuoraConnect::ZuoraUser.where(:zuora_user_id => zuora_user_id).first
|
426
339
|
rescue ActiveRecord::StatementInvalid => ex
|
427
340
|
if ex.message.include?("PG::UndefinedTable") && ex.message.include?("zuora_users")
|
@@ -445,8 +358,7 @@ module ZuoraConnect
|
|
445
358
|
session["#{@appinstance.id}::user::localUserId"] = @zuora_user.id
|
446
359
|
session["#{@appinstance.id}::user::email"] = session['ZuoraCurrentIdentity']["username"]
|
447
360
|
session["#{@appinstance.id}::user::timezone"] = session['ZuoraCurrentIdentity']["timeZone"]
|
448
|
-
session["#{@appinstance.id}::user::
|
449
|
-
session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["locale"]
|
361
|
+
session["#{@appinstance.id}::user::locale"] = session['ZuoraCurrentIdentity']["language"]
|
450
362
|
session["appInstance"] = @appinstance.id
|
451
363
|
|
452
364
|
#We have multiple, user must pick
|
@@ -468,85 +380,79 @@ module ZuoraConnect
|
|
468
380
|
return
|
469
381
|
end
|
470
382
|
Apartment::Tenant.switch!("public")
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
ActiveRecord::Base.transaction do
|
475
|
-
ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
|
383
|
+
ActiveRecord::Base.transaction do
|
384
|
+
ActiveRecord::Base.connection.execute('LOCK public.zuora_users IN ACCESS EXCLUSIVE MODE')
|
385
|
+
appinstances = ZuoraConnect::AppInstance.where("zuora_entity_ids ?& array[:entities] = true AND zuora_domain = :host", entities: [zuora_entity_id], host: zuora_client.rest_domain).pluck(:id, :name)
|
476
386
|
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
|
482
|
-
return
|
483
|
-
end
|
484
|
-
end
|
387
|
+
if appinstances.size > 0
|
388
|
+
redirect_to "https://#{zuora_host}/apps/newlogin.do?retURL=#{request.fullpath}"
|
389
|
+
return
|
390
|
+
end
|
485
391
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
)
|
506
|
-
|
507
|
-
new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
|
508
|
-
if session["ZuoraCurrentUserInfo"].blank?
|
509
|
-
client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
|
510
|
-
else
|
511
|
-
client_describe = session["ZuoraCurrentUserInfo"]
|
512
|
-
end
|
392
|
+
next_id = (ZuoraConnect::AppInstance.all.where('id > 24999999').order(id: :desc).limit(1).pluck(:id).first || 24999999) + 1
|
393
|
+
user = (ENV['DEIS_APP'] || "Application").split('-').map(&:capitalize).join(' ')
|
394
|
+
body = {
|
395
|
+
'userId' => zuora_user_id,
|
396
|
+
'entityIds' => [zuora_entity_id.unpack("a8a4a4a4a12").join('-')],
|
397
|
+
'customAuthorities' => [],
|
398
|
+
'additionalInformation' => {
|
399
|
+
'description' => "This user is for #{user} application.",
|
400
|
+
'name' => "#{user} API User #{next_id}"
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
oauth_response, response = zuora_client.rest_call(
|
405
|
+
method: :post,
|
406
|
+
body: body.to_json,
|
407
|
+
url: zuora_client.rest_endpoint("genesis/clients").gsub('v1/', ''),
|
408
|
+
session_type: zuora_client.class == ZuoraAPI::Oauth ? :bearer : :basic,
|
409
|
+
headers: auth_headers
|
410
|
+
)
|
513
411
|
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
|
521
|
-
"tenant_type": "Zuora",
|
522
|
-
"username": session["ZuoraCurrentIdentity"]["username"],
|
523
|
-
"url": new_zuora_client.url,
|
524
|
-
"status": "Active",
|
525
|
-
"oauth_client_id": oauth_response['clientId'],
|
526
|
-
"oauth_secret": oauth_response['clientSecret'],
|
527
|
-
"authentication_type": "OAUTH",
|
528
|
-
"entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
|
529
|
-
},
|
530
|
-
"tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
|
531
|
-
}
|
532
|
-
end
|
412
|
+
new_zuora_client = ZuoraAPI::Oauth.new(url: "https://#{zuora_host}", oauth_client_id: oauth_response["clientId"], oauth_secret: oauth_response["clientSecret"] )
|
413
|
+
if session["ZuoraCurrentUserInfo"].blank?
|
414
|
+
client_describe, response = new_zuora_client.rest_call(url: zuora_client.rest_endpoint("genesis/user/info").gsub('v1/', ''), session_type: :bearer)
|
415
|
+
else
|
416
|
+
client_describe = session["ZuoraCurrentUserInfo"]
|
417
|
+
end
|
533
418
|
|
534
|
-
|
535
|
-
|
536
|
-
|
419
|
+
available_entities = client_describe["accessibleEntities"].select {|entity| entity['id'] == zuora_entity_id}
|
420
|
+
task_data = {
|
421
|
+
"id": next_id,
|
422
|
+
"name": client_describe["tenantName"],
|
423
|
+
"mode": "Collections",
|
424
|
+
"status": "Running",
|
425
|
+
ZuoraConnect::AppInstance::LOGIN_TENANT_DESTINATION => {
|
426
|
+
"tenant_type": "Zuora",
|
427
|
+
"username": session["ZuoraCurrentIdentity"]["username"],
|
428
|
+
"url": new_zuora_client.url,
|
429
|
+
"status": "Active",
|
430
|
+
"oauth_client_id": oauth_response['clientId'],
|
431
|
+
"oauth_secret": oauth_response['clientSecret'],
|
432
|
+
"authentication_type": "OAUTH",
|
433
|
+
"entities": available_entities.map {|e| e.merge({'displayName' => client_describe["tenantName"]})}
|
434
|
+
},
|
435
|
+
"tenant_ids": available_entities.map{|e| e['entityId']}.uniq,
|
436
|
+
}
|
437
|
+
mapped_values = {:id => next_id, :api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36), :zuora_logins => task_data, :oauth_expires_at => Time.now + 1000.years, :zuora_domain => zuora_client.rest_domain, :zuora_entity_ids => [zuora_entity_id]}
|
438
|
+
@appinstance = ZuoraConnect::AppInstance.new(mapped_values)
|
439
|
+
retry_count = 0
|
440
|
+
begin
|
441
|
+
@appinstance.save(:validate => false)
|
442
|
+
rescue ActiveRecord::RecordNotUnique => ex
|
443
|
+
if (retry_count += 1) < 3
|
444
|
+
@appinstance.assign_attributes({:api_token => rand(36**64).to_s(36), :token => rand(36**64).to_s(36)})
|
445
|
+
retry
|
537
446
|
else
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
447
|
+
Thread.current[:appinstance] = nil
|
448
|
+
session["appInstance"] = nil
|
449
|
+
render "zuora_connect/static/error_handled", :locals => {
|
450
|
+
:title => "Application could not create unique tokens.",
|
451
|
+
:message => "Please contact support or retry launching application."
|
452
|
+
}, :layout => false
|
453
|
+
return
|
545
454
|
end
|
546
455
|
end
|
547
|
-
rescue ActiveRecord::RecordNotUnique
|
548
|
-
retry if (retry_count -= 1).positive?
|
549
|
-
return
|
550
456
|
end
|
551
457
|
|
552
458
|
Apartment::Tenant.switch!("public")
|
@@ -577,8 +483,8 @@ module ZuoraConnect
|
|
577
483
|
|
578
484
|
rescue ZuoraAPI::Exceptions::ZuoraAPIError, Exception => ex
|
579
485
|
if ex.message.include?("Referenced User resource(s) not found") && ex.class == ZuoraAPI::Exceptions::ZuoraAPIError
|
580
|
-
locals = {title: "Provisioning Error", message: "New
|
581
|
-
render "zuora_connect/static/error_handled", locals: locals, status:
|
486
|
+
locals = {title: "Provisioning Error", message: "New tenats need to be provisioned by API Gateway('#{ex.message}'). Please contact support."}
|
487
|
+
render "zuora_connect/static/error_handled", locals: locals, status: 400, layout: false
|
582
488
|
else
|
583
489
|
session.clear
|
584
490
|
if defined?(ex.response) && ex.response.present? && defined?(ex.response.body)
|
@@ -634,50 +540,6 @@ module ZuoraConnect
|
|
634
540
|
end
|
635
541
|
end
|
636
542
|
|
637
|
-
def next_instance_id
|
638
|
-
min_instance_id = 24_999_999
|
639
|
-
(ZuoraConnect::AppInstance.all.where("id > #{min_instance_id}").order(id: :desc).limit(1).pluck(:id).first || min_instance_id) + 1
|
640
|
-
end
|
641
|
-
|
642
|
-
def new_instance(id, zuora_entity_id, rest_domain, task_data: nil, retry_count: 0)
|
643
|
-
app_instance = ZuoraConnect::AppInstance.new(
|
644
|
-
:id => id,
|
645
|
-
:api_token => generate_token,
|
646
|
-
:token => generate_token,
|
647
|
-
:oauth_expires_at => Time.now + 1000.years,
|
648
|
-
:zuora_domain => rest_domain,
|
649
|
-
:zuora_entity_ids => [zuora_entity_id]
|
650
|
-
)
|
651
|
-
|
652
|
-
if task_data.nil?
|
653
|
-
# no encryption
|
654
|
-
app_instance['zuora_logins'] = task_data
|
655
|
-
else
|
656
|
-
# kms encrypt
|
657
|
-
app_instance.zuora_logins = task_data
|
658
|
-
end
|
659
|
-
|
660
|
-
begin
|
661
|
-
app_instance.save(:validate => false)
|
662
|
-
rescue ActiveRecord::RecordNotUnique
|
663
|
-
raise if retry_count > 1
|
664
|
-
|
665
|
-
Thread.current[:appinstance] = nil
|
666
|
-
session['appInstance'] = nil
|
667
|
-
render 'zuora_connect/static/error_handled', :locals => {
|
668
|
-
:title => 'Application could not create unique tokens.',
|
669
|
-
:message => 'Please contact support or retry launching application.'
|
670
|
-
}, :layout => false
|
671
|
-
return
|
672
|
-
end
|
673
|
-
|
674
|
-
app_instance
|
675
|
-
end
|
676
|
-
|
677
|
-
def generate_token
|
678
|
-
rand(36**64).to_s(36)
|
679
|
-
end
|
680
|
-
|
681
543
|
def setup_instance_via_dev_mode
|
682
544
|
session["appInstance"] = ZuoraConnect.configuration.dev_mode_appinstance
|
683
545
|
user = ZuoraConnect.configuration.dev_mode_user
|
@@ -28,6 +28,11 @@ module ZuoraConnect
|
|
28
28
|
::Rails.configuration.action_dispatch.x_sendfile_header = nil
|
29
29
|
end
|
30
30
|
|
31
|
+
if defined? Prometheus
|
32
|
+
initializer "prometheus.configure_rails_initialization" do |app|
|
33
|
+
app.middleware.use Prometheus::Middleware::Exporter,(options ={:path => '/connect/internal/metrics'})
|
34
|
+
end
|
35
|
+
end
|
31
36
|
initializer "zuora_connect.configure_rails_initialization" do |app|
|
32
37
|
app.middleware.insert_after Rack::Sendfile, ZuoraConnect::MetricsMiddleware
|
33
38
|
app.middleware.insert_after ActionDispatch::RequestId, ZuoraConnect::RequestIdMiddleware
|
@@ -35,15 +40,6 @@ module ZuoraConnect
|
|
35
40
|
app.config.middleware.use ZuoraConnect::JsonParseErrors
|
36
41
|
end
|
37
42
|
|
38
|
-
if defined? Prometheus
|
39
|
-
require 'rack'
|
40
|
-
require 'prometheus/middleware/exporter'
|
41
|
-
initializer "prometheus.configure_rails_initialization" do |app|
|
42
|
-
app.middleware.insert_after ZuoraConnect::MetricsMiddleware, Prometheus::Middleware::Exporter, path: '/connect/internal/metrics'
|
43
|
-
app.config.middleware.use Rack::Deflater, if: ->(env, *) { env['PATH_INFO'] == '/connect/internal/metrics' }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
43
|
# hook to process_action
|
48
44
|
ActiveSupport::Notifications.subscribe('process_action.action_controller', ZuoraConnect::PageRequest.new)
|
49
45
|
|
@@ -81,21 +77,6 @@ module ZuoraConnect
|
|
81
77
|
request_headers =
|
82
78
|
event.payload[:headers].env.
|
83
79
|
reject { |key| key.to_s.include?('.') || REQUEST_HEADERS_TO_IGNORE.include?(key.to_s) }
|
84
|
-
begin
|
85
|
-
if request_headers["HTTP_AUTHORIZATION"].present?
|
86
|
-
if request_headers["HTTP_AUTHORIZATION"].include?("Basic")
|
87
|
-
user_password = request_headers["HTTP_AUTHORIZATION"].split("Basic").last.strip
|
88
|
-
user, password = Base64.decode64(user_password).split(":")
|
89
|
-
request_headers["HTTP_AUTHORIZATION"] = "Basic #{user}:ValueFiltered"
|
90
|
-
elsif
|
91
|
-
request_headers["HTTP_AUTHORIZATION"] = "ValueFiltered"
|
92
|
-
end
|
93
|
-
end
|
94
|
-
request_headers["HTTP_API_TOKEN"] = "ValueFiltered" if request_headers["HTTP_API_TOKEN"].present?
|
95
|
-
rescue
|
96
|
-
request_headers.delete("HTTP_API_TOKEN")
|
97
|
-
request_headers.delete("HTTP_AUTHORIZATION")
|
98
|
-
end
|
99
80
|
items.merge!({ headers: request_headers.to_s })
|
100
81
|
end
|
101
82
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zuora_connect
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.60
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Connect Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: apartment
|
@@ -429,53 +429,53 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
429
429
|
version: '0'
|
430
430
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
431
431
|
requirements:
|
432
|
-
- - "
|
432
|
+
- - ">="
|
433
433
|
- !ruby/object:Gem::Version
|
434
|
-
version:
|
434
|
+
version: '0'
|
435
435
|
requirements: []
|
436
436
|
rubygems_version: 3.0.3
|
437
437
|
signing_key:
|
438
438
|
specification_version: 4
|
439
439
|
summary: Summary of Connect.
|
440
440
|
test_files:
|
441
|
-
- test/fixtures/zuora_connect/app_instances.yml
|
442
|
-
- test/models/zuora_connect/app_instance_test.rb
|
443
441
|
- test/integration/navigation_test.rb
|
444
442
|
- test/controllers/zuora_connect/api/v1/app_instance_controller_test.rb
|
445
|
-
- test/
|
443
|
+
- test/fixtures/zuora_connect/app_instances.yml
|
446
444
|
- test/lib/generators/zuora_connect/datatable_generator_test.rb
|
447
|
-
- test/
|
448
|
-
- test/
|
449
|
-
- test/dummy/public/favicon.ico
|
450
|
-
- test/dummy/public/422.html
|
445
|
+
- test/models/zuora_connect/app_instance_test.rb
|
446
|
+
- test/zuora_connect_test.rb
|
451
447
|
- test/dummy/Rakefile
|
452
448
|
- test/dummy/config.ru
|
449
|
+
- test/dummy/public/422.html
|
450
|
+
- test/dummy/public/404.html
|
451
|
+
- test/dummy/public/500.html
|
452
|
+
- test/dummy/public/favicon.ico
|
453
|
+
- test/dummy/app/controllers/application_controller.rb
|
454
|
+
- test/dummy/app/helpers/application_helper.rb
|
455
|
+
- test/dummy/app/views/layouts/application.html.erb
|
456
|
+
- test/dummy/app/assets/javascripts/application.js
|
457
|
+
- test/dummy/app/assets/stylesheets/application.css
|
458
|
+
- test/dummy/README.rdoc
|
459
|
+
- test/dummy/bin/rails
|
460
|
+
- test/dummy/bin/rake
|
461
|
+
- test/dummy/bin/bundle
|
462
|
+
- test/dummy/bin/setup
|
453
463
|
- test/dummy/config/secrets.yml
|
454
464
|
- test/dummy/config/boot.rb
|
455
|
-
- test/dummy/config/
|
465
|
+
- test/dummy/config/initializers/mime_types.rb
|
466
|
+
- test/dummy/config/initializers/filter_parameter_logging.rb
|
456
467
|
- test/dummy/config/initializers/session_store.rb
|
468
|
+
- test/dummy/config/initializers/inflections.rb
|
469
|
+
- test/dummy/config/initializers/cookies_serializer.rb
|
457
470
|
- test/dummy/config/initializers/assets.rb
|
458
471
|
- test/dummy/config/initializers/wrap_parameters.rb
|
459
|
-
- test/dummy/config/initializers/filter_parameter_logging.rb
|
460
472
|
- test/dummy/config/initializers/backtrace_silencers.rb
|
461
|
-
- test/dummy/config/initializers/mime_types.rb
|
462
|
-
- test/dummy/config/initializers/inflections.rb
|
463
|
-
- test/dummy/config/initializers/cookies_serializer.rb
|
464
|
-
- test/dummy/config/routes.rb
|
465
473
|
- test/dummy/config/database.yml
|
466
|
-
- test/dummy/config/
|
474
|
+
- test/dummy/config/environment.rb
|
475
|
+
- test/dummy/config/application.rb
|
476
|
+
- test/dummy/config/routes.rb
|
467
477
|
- test/dummy/config/environments/production.rb
|
468
478
|
- test/dummy/config/environments/development.rb
|
469
|
-
- test/dummy/config/
|
479
|
+
- test/dummy/config/environments/test.rb
|
470
480
|
- test/dummy/config/locales/en.yml
|
471
|
-
- test/dummy/README.rdoc
|
472
|
-
- test/dummy/bin/rake
|
473
|
-
- test/dummy/bin/setup
|
474
|
-
- test/dummy/bin/rails
|
475
|
-
- test/dummy/bin/bundle
|
476
|
-
- test/dummy/app/views/layouts/application.html.erb
|
477
|
-
- test/dummy/app/assets/javascripts/application.js
|
478
|
-
- test/dummy/app/assets/stylesheets/application.css
|
479
|
-
- test/dummy/app/helpers/application_helper.rb
|
480
|
-
- test/dummy/app/controllers/application_controller.rb
|
481
481
|
- test/test_helper.rb
|