3scale_toolbox 0.16.0 → 0.18.3
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/3scale_toolbox.gemspec +2 -2
- data/README.md +11 -8
- data/lib/3scale_toolbox.rb +3 -0
- data/lib/3scale_toolbox/3scale_client_factory.rb +3 -4
- data/lib/3scale_toolbox/cli/error_handler.rb +17 -14
- data/lib/3scale_toolbox/commands.rb +2 -0
- data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_mapping_rules_task.rb +11 -27
- data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_methods_task.rb +5 -10
- data/lib/3scale_toolbox/commands/backend_command/copy_command/copy_metrics_task.rb +4 -4
- data/lib/3scale_toolbox/commands/backend_command/copy_command/create_or_update_target_backend_task.rb +3 -2
- data/lib/3scale_toolbox/commands/backend_command/copy_command/task.rb +10 -32
- data/lib/3scale_toolbox/commands/import_command/issuer_type_transformer.rb +16 -0
- data/lib/3scale_toolbox/commands/import_command/openapi.rb +3 -0
- data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +3 -2
- data/lib/3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step.rb +2 -1
- data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +5 -14
- data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -0
- data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +1 -0
- data/lib/3scale_toolbox/commands/methods_command/apply_command.rb +2 -4
- data/lib/3scale_toolbox/commands/methods_command/create_command.rb +0 -2
- data/lib/3scale_toolbox/commands/methods_command/delete_command.rb +1 -1
- data/lib/3scale_toolbox/commands/methods_command/list_command.rb +1 -9
- data/lib/3scale_toolbox/commands/metrics_command/list_command.rb +1 -1
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +1 -1
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +2 -2
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +2 -2
- data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +1 -2
- data/lib/3scale_toolbox/commands/plans_command/export/step.rb +8 -20
- data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +12 -14
- data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +6 -13
- data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +12 -20
- data/lib/3scale_toolbox/commands/plans_command/import/step.rb +2 -22
- data/lib/3scale_toolbox/commands/plans_command/list_command.rb +1 -1
- data/lib/3scale_toolbox/commands/plans_command/show_command.rb +1 -1
- data/lib/3scale_toolbox/commands/policies_command.rb +24 -0
- data/lib/3scale_toolbox/commands/policies_command/export_command.rb +98 -0
- data/lib/3scale_toolbox/commands/policies_command/import_command.rb +61 -0
- data/lib/3scale_toolbox/commands/product_command.rb +4 -0
- data/lib/3scale_toolbox/commands/product_command/copy_command.rb +7 -3
- data/lib/3scale_toolbox/commands/product_command/copy_command/copy_backends_task.rb +22 -5
- data/lib/3scale_toolbox/commands/product_command/export_command.rb +81 -0
- data/lib/3scale_toolbox/commands/product_command/import_command.rb +125 -0
- data/lib/3scale_toolbox/commands/proxy_config_command.rb +5 -0
- data/lib/3scale_toolbox/commands/proxy_config_command/deploy_command.rb +54 -0
- data/lib/3scale_toolbox/commands/proxy_config_command/export_command.rb +74 -0
- data/lib/3scale_toolbox/commands/proxy_config_command/helper.rb +15 -0
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_activedocs_task.rb +15 -12
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_app_plans_task.rb +15 -15
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_limits_task.rb +12 -13
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_mapping_rules_task.rb +11 -11
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_methods_task.rb +9 -12
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_metrics_task.rb +8 -8
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_policies_task.rb +1 -1
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_pricingrules_task.rb +15 -18
- data/lib/3scale_toolbox/commands/service_command/copy_command/copy_service_proxy_task.rb +17 -2
- data/lib/3scale_toolbox/commands/service_command/copy_command/create_or_update_service_task.rb +2 -1
- data/lib/3scale_toolbox/commands/service_command/copy_command/destroy_mapping_rules_task.rb +9 -5
- data/lib/3scale_toolbox/commands/service_command/copy_command/task.rb +20 -34
- data/lib/3scale_toolbox/commands/update_command.rb +1 -1
- data/lib/3scale_toolbox/commands/update_command/service_command.rb +3 -2
- data/lib/3scale_toolbox/commands/update_command/service_command/delete_activedocs_task.rb +1 -3
- data/lib/3scale_toolbox/crds.rb +16 -0
- data/lib/3scale_toolbox/crds/application_plan_dump.rb +19 -0
- data/lib/3scale_toolbox/crds/backend_dump.rb +39 -0
- data/lib/3scale_toolbox/crds/backend_mapping_rule_dump.rb +26 -0
- data/lib/3scale_toolbox/crds/backend_method_dump.rb +12 -0
- data/lib/3scale_toolbox/crds/backend_metric_dump.rb +13 -0
- data/lib/3scale_toolbox/crds/backend_parser.rb +55 -0
- data/lib/3scale_toolbox/crds/backend_usage_dump.rb +11 -0
- data/lib/3scale_toolbox/crds/limit_dump.rb +37 -0
- data/lib/3scale_toolbox/crds/mapping_rule_dump.rb +26 -0
- data/lib/3scale_toolbox/crds/method_dump.rb +12 -0
- data/lib/3scale_toolbox/crds/metric_dump.rb +13 -0
- data/lib/3scale_toolbox/crds/pricing_rule_dump.rb +38 -0
- data/lib/3scale_toolbox/crds/product_deployment_parser.rb +329 -0
- data/lib/3scale_toolbox/crds/product_dump.rb +157 -0
- data/lib/3scale_toolbox/crds/product_parser.rb +114 -0
- data/lib/3scale_toolbox/crds/remote.rb +682 -0
- data/lib/3scale_toolbox/entities.rb +3 -0
- data/lib/3scale_toolbox/entities/activedocs.rb +12 -0
- data/lib/3scale_toolbox/entities/application_plan.rb +74 -39
- data/lib/3scale_toolbox/entities/backend.rb +65 -30
- data/lib/3scale_toolbox/entities/backend_mapping_rule.rb +29 -3
- data/lib/3scale_toolbox/entities/backend_method.rb +25 -16
- data/lib/3scale_toolbox/entities/backend_metric.rb +12 -2
- data/lib/3scale_toolbox/entities/backend_usage.rb +7 -1
- data/lib/3scale_toolbox/entities/limit.rb +71 -0
- data/lib/3scale_toolbox/entities/mapping_rule.rb +90 -0
- data/lib/3scale_toolbox/entities/method.rb +33 -19
- data/lib/3scale_toolbox/entities/metric.rb +29 -18
- data/lib/3scale_toolbox/entities/pricing_rule.rb +63 -0
- data/lib/3scale_toolbox/entities/proxy_config.rb +0 -1
- data/lib/3scale_toolbox/entities/service.rb +149 -46
- data/lib/3scale_toolbox/error.rb +50 -0
- data/lib/3scale_toolbox/helper.rb +13 -16
- data/lib/3scale_toolbox/openapi/oas3.rb +1 -1
- data/lib/3scale_toolbox/proxy_logger.rb +4 -0
- data/lib/3scale_toolbox/remote_cache.rb +157 -0
- data/lib/3scale_toolbox/remotes.rb +2 -2
- data/lib/3scale_toolbox/version.rb +1 -1
- data/licenses.xml +113 -45
- metadata +37 -8
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module ThreeScaleToolbox
|
|
2
|
+
module CRD
|
|
3
|
+
class ProductParser
|
|
4
|
+
Metric = Struct.new(:system_name, :friendly_name, :description, :unit)
|
|
5
|
+
Method = Struct.new(:system_name, :friendly_name, :description)
|
|
6
|
+
MappingRule = Struct.new(:metric_ref, :http_method, :pattern, :delta, :last)
|
|
7
|
+
BackendUsage = Struct.new(:backend_system_name, :path)
|
|
8
|
+
ApplicationPlan = Struct.new(:system_name, :name, :approval_required, :trial_period_days, :setup_fee, :custom, :state, :cost_per_month, :limits, :pricing_rules)
|
|
9
|
+
Limit = Struct.new(:period, :value, :metric_system_name, :backend_system_name) do
|
|
10
|
+
def to_s
|
|
11
|
+
{period: period, value: value}.to_json
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
PricingRule = Struct.new(:from, :to, :price_per_unit, :metric_system_name, :backend_system_name) do
|
|
15
|
+
def to_s
|
|
16
|
+
{from: from, to: to, price_per_unit: price_per_unit}.to_json
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
PolicyChainItem = Struct.new(:name, :version, :configuration, :enabled)
|
|
20
|
+
|
|
21
|
+
attr_reader :cr, :deployment_parser
|
|
22
|
+
|
|
23
|
+
def initialize(cr)
|
|
24
|
+
@cr = cr
|
|
25
|
+
@deployment_parser = ProductDeploymentParser.new(cr.dig('spec', 'deployment') || {})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def system_name
|
|
29
|
+
cr.dig('spec', 'systemName')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def name
|
|
33
|
+
cr.dig('spec', 'name')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def description
|
|
37
|
+
cr.dig('spec', 'description')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def metrics
|
|
41
|
+
@metrics ||= (cr.dig('spec', 'metrics') || {}).map do |system_name, metric|
|
|
42
|
+
Metric.new(system_name, metric['friendlyName'], metric['description'], metric['unit'])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def methods
|
|
47
|
+
@methods ||= (cr.dig('spec', 'methods') || {}).map do |system_name, method|
|
|
48
|
+
Method.new(system_name, method['friendlyName'], method['description'])
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def mapping_rules
|
|
53
|
+
@mapping_rules ||= (cr.dig('spec', 'mappingRules') || []).map do |mapping_rule|
|
|
54
|
+
MappingRule.new(mapping_rule['metricMethodRef'], mapping_rule['httpMethod'],
|
|
55
|
+
mapping_rule['pattern'], mapping_rule['increment'], mapping_rule['last'])
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Metrics and methods index by system_name
|
|
60
|
+
def metrics_index
|
|
61
|
+
@metrics_index ||= (methods + metrics).each_with_object({}) { |metric, h| h[metric.system_name] = metric }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def application_plans
|
|
65
|
+
@application_plans ||= (cr.dig('spec', 'applicationPlans') || {}).map do |system_name, plan|
|
|
66
|
+
ApplicationPlan.new(system_name, plan['name'], plan['appsRequireApproval'],
|
|
67
|
+
plan['trialPeriod'], plan['setupFee'], plan['custom'], plan['state'],
|
|
68
|
+
plan['costMonth'], parse_limits(plan), parse_pricing_rules(plan))
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def backend_usages
|
|
73
|
+
@backend_usages ||= (cr.dig('spec', 'backendUsages') || {}).map do |backend_system_name, usage|
|
|
74
|
+
BackendUsage.new(backend_system_name, usage['path'])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
%i[deployment_option backend_version credentials_location auth_app_key
|
|
79
|
+
auth_app_id auth_user_key error_auth_failed error_auth_missing error_status_auth_failed
|
|
80
|
+
error_headers_auth_failed error_status_auth_missing error_headers_auth_missing error_no_match
|
|
81
|
+
error_status_no_match error_headers_no_match error_limits_exceeded
|
|
82
|
+
error_status_limits_exceeded error_headers_limits_exceeded secret_token hostname_rewrite
|
|
83
|
+
endpoint sandbox_endpoint oidc_issuer_endpoint oidc_issuer_type jwt_claim_with_client_id
|
|
84
|
+
jwt_claim_with_client_id_type standard_flow_enabled implicit_flow_enabled
|
|
85
|
+
service_accounts_enabled direct_access_grants_enabled].each do |method_name|
|
|
86
|
+
define_method method_name do
|
|
87
|
+
deployment_parser.public_send(method_name)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def policy_chain
|
|
92
|
+
@policy_chain ||= (cr.dig('spec', 'policies') || []).map do |item|
|
|
93
|
+
PolicyChainItem.new(item['name'], item['version'], item['configuration'], item['enabled'])
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def parse_limits(plan)
|
|
100
|
+
plan.fetch('limits', []).map do |limit|
|
|
101
|
+
Limit.new(limit['period'], limit['value'],
|
|
102
|
+
limit.dig('metricMethodRef', 'systemName'), limit.dig('metricMethodRef', 'backend'))
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def parse_pricing_rules(plan)
|
|
107
|
+
plan.fetch('pricingRules', []).map do |pr|
|
|
108
|
+
PricingRule.new(pr['from'], pr['to'], pr['pricePerUnit'],
|
|
109
|
+
pr.dig('metricMethodRef', 'systemName'), pr.dig('metricMethodRef', 'backend'))
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
module ThreeScaleToolbox
|
|
2
|
+
module CRD
|
|
3
|
+
class Remote
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# Product CRD Format
|
|
7
|
+
# https://github.com/3scale/3scale-operator/blob/3scale-2.10.0-CR2/doc/product-reference.md
|
|
8
|
+
#
|
|
9
|
+
# apiVersion: capabilities.3scale.net/v1beta1
|
|
10
|
+
# kind: Product
|
|
11
|
+
# metadata:
|
|
12
|
+
# annotations:
|
|
13
|
+
# 3scale_toolbox_created_at: '2021-02-10T09:16:59Z'
|
|
14
|
+
# 3scale_toolbox_version: 0.17.1
|
|
15
|
+
# name: api.vygczmih
|
|
16
|
+
# spec:
|
|
17
|
+
# name: Default API
|
|
18
|
+
# systemName: api
|
|
19
|
+
# description: ''
|
|
20
|
+
# mappingRules:
|
|
21
|
+
# - httpMethod: GET
|
|
22
|
+
# pattern: "/v1"
|
|
23
|
+
# metricMethodRef: servicemethod01
|
|
24
|
+
# increment: 1
|
|
25
|
+
# last: false
|
|
26
|
+
# metrics:
|
|
27
|
+
# hits:
|
|
28
|
+
# friendlyName: Hits
|
|
29
|
+
# unit: hit
|
|
30
|
+
# description: Number of API hits
|
|
31
|
+
# methods:
|
|
32
|
+
# servicemethod01:
|
|
33
|
+
# friendlyName: servicemethod01
|
|
34
|
+
# description: ''
|
|
35
|
+
# policies:
|
|
36
|
+
# - name: apicast
|
|
37
|
+
# version: builtin
|
|
38
|
+
# configuration: {}
|
|
39
|
+
# enabled: true
|
|
40
|
+
# backendUsages:
|
|
41
|
+
# backend_01:
|
|
42
|
+
# path: "/v1/pets"
|
|
43
|
+
# backend_02:
|
|
44
|
+
# path: "/v1/cats"
|
|
45
|
+
# deployment:
|
|
46
|
+
# apicastSelfManaged:
|
|
47
|
+
# authentication:
|
|
48
|
+
# appKeyAppID:
|
|
49
|
+
# appID: app_id
|
|
50
|
+
# appKey: app_key
|
|
51
|
+
# credentials: query
|
|
52
|
+
# security:
|
|
53
|
+
# hostHeader: ''
|
|
54
|
+
# secretToken: some_secret
|
|
55
|
+
# gatewayResponse:
|
|
56
|
+
# errorStatusAuthFailed: 403
|
|
57
|
+
# errorHeadersAuthFailed: text/plain; charset=us-ascii
|
|
58
|
+
# errorAuthFailed: Authentication failed
|
|
59
|
+
# errorStatusAuthMissing: 403
|
|
60
|
+
# errorHeadersAuthMissing: text/plain; charset=us-ascii
|
|
61
|
+
# errorAuthMissing: Authentication parameters missing
|
|
62
|
+
# errorStatusNoMatch: 404
|
|
63
|
+
# errorHeadersNoMatch: text/plain; charset=us-ascii
|
|
64
|
+
# errorNoMatch: No Mapping Rule matched
|
|
65
|
+
# errorStatusLimitsExceeded: 429
|
|
66
|
+
# errorHeadersLimitsExceeded: text/plain; charset=us-ascii
|
|
67
|
+
# errorLimitsExceeded: Usage limit exceeded
|
|
68
|
+
# stagingPublicBaseURL: http://staging.example.com:80
|
|
69
|
+
# productionPublicBaseURL: http://example.com:80
|
|
70
|
+
# applicationPlans:
|
|
71
|
+
# basic:
|
|
72
|
+
# name: Basic
|
|
73
|
+
# appsRequireApproval: false
|
|
74
|
+
# trialPeriod: 0
|
|
75
|
+
# setupFee: 0.0
|
|
76
|
+
# custom: false
|
|
77
|
+
# state: published
|
|
78
|
+
# costMonth: 0.0
|
|
79
|
+
# pricingRules:
|
|
80
|
+
# - from: 1
|
|
81
|
+
# to: 1000
|
|
82
|
+
# pricePerUnit: 1.0
|
|
83
|
+
# metricMethodRef:
|
|
84
|
+
# systemName: hits
|
|
85
|
+
# limits:
|
|
86
|
+
# - period: eternity
|
|
87
|
+
# value: 10000
|
|
88
|
+
# metricMethodRef:
|
|
89
|
+
# systemName: hits
|
|
90
|
+
#
|
|
91
|
+
# Backend CRD format
|
|
92
|
+
# https://github.com/3scale/3scale-operator/blob/3scale-2.10.0-CR2/doc/backend-reference.md
|
|
93
|
+
#
|
|
94
|
+
# apiVersion: capabilities.3scale.net/v1beta1
|
|
95
|
+
# kind: Backend
|
|
96
|
+
# metadata:
|
|
97
|
+
# annotations:
|
|
98
|
+
# 3scale_toolbox_created_at: '2021-02-10T09:17:12Z'
|
|
99
|
+
# 3scale_toolbox_version: 0.17.1
|
|
100
|
+
# name: backend.01.rxoeasvk
|
|
101
|
+
# spec:
|
|
102
|
+
# name: Backend 01
|
|
103
|
+
# systemName: backend_01
|
|
104
|
+
# privateBaseURL: https://echo-api.3scale.net:443
|
|
105
|
+
# description: new desc
|
|
106
|
+
# mappingRules:
|
|
107
|
+
# - httpMethod: GET
|
|
108
|
+
# pattern: "/v1/pets"
|
|
109
|
+
# metricMethodRef: mybackendmethod01
|
|
110
|
+
# increment: 1
|
|
111
|
+
# last: false
|
|
112
|
+
# metrics:
|
|
113
|
+
# hits:
|
|
114
|
+
# friendlyName: Hits
|
|
115
|
+
# unit: hit
|
|
116
|
+
# description: Number of API hits
|
|
117
|
+
# methods:
|
|
118
|
+
# mybackendmethod01:
|
|
119
|
+
# friendlyName: mybackendmethod01
|
|
120
|
+
# description: ''
|
|
121
|
+
|
|
122
|
+
attr_reader :product_index, :backend_index
|
|
123
|
+
|
|
124
|
+
def initialize(products, backends)
|
|
125
|
+
# Index of backends by id (by sequence order)
|
|
126
|
+
@backend_index = backends.each_with_object({}) { |backend, hash| hash[new_index] = backend }
|
|
127
|
+
|
|
128
|
+
# Index of products by id (by sequence order)
|
|
129
|
+
@product_index = products.each_with_object({}) { |product, hash| hash[new_index] = product }
|
|
130
|
+
|
|
131
|
+
validate!
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def http_client
|
|
135
|
+
Struct.new(:endpoint).new('http://fromCR')
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def show_service(service_id)
|
|
139
|
+
service = product_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
140
|
+
{
|
|
141
|
+
'id' => service_id,
|
|
142
|
+
'name' => service.name,
|
|
143
|
+
'system_name' => service.system_name,
|
|
144
|
+
'description' => service.description,
|
|
145
|
+
'deployment_option' => service.deployment_option,
|
|
146
|
+
'backend_version' => service.backend_version
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def list_services(page:, per_page:)
|
|
151
|
+
product_index.keys.map(&method(:show_service))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def backend(backend_id)
|
|
155
|
+
b = backend_index.fetch(backend_id) { raise_backend_missing(backend_id) }
|
|
156
|
+
{
|
|
157
|
+
'id' => backend_id,
|
|
158
|
+
'name' => b.name,
|
|
159
|
+
'system_name' => b.system_name,
|
|
160
|
+
'description' => b.description,
|
|
161
|
+
'private_endpoint' => b.private_endpoint
|
|
162
|
+
}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def list_backend_usages(service_id)
|
|
166
|
+
service = product_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
167
|
+
service.backend_usages.each_with_index.map do |backend_usage, idx|
|
|
168
|
+
{
|
|
169
|
+
'id' => idx + 1,
|
|
170
|
+
'path' => backend_usage.path,
|
|
171
|
+
'service_id' => service_id,
|
|
172
|
+
'backend_id' => backend_index.find { |k, b| b.system_name == backend_usage.backend_system_name }.first
|
|
173
|
+
}
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# return metrics and methods
|
|
178
|
+
def list_backend_metrics(backend_id)
|
|
179
|
+
metric_index = backend_metric_index.fetch(backend_id) { raise_backend_missing(backend_id) }
|
|
180
|
+
|
|
181
|
+
# only metrics, not methods
|
|
182
|
+
backend_metric_system_name_list = backend_index.fetch(backend_id).metrics.map(&:system_name)
|
|
183
|
+
|
|
184
|
+
# select only metrics
|
|
185
|
+
backend_metric_only_index = metric_index.select do |_, metric|
|
|
186
|
+
backend_metric_system_name_list.include? metric.system_name
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
backend_metric_only_index.map do |metric_id, metric|
|
|
190
|
+
{
|
|
191
|
+
'id' => metric_id,
|
|
192
|
+
'friendly_name' => metric.friendly_name,
|
|
193
|
+
'system_name' => metric.system_name,
|
|
194
|
+
'description' => metric.description,
|
|
195
|
+
'unit' => metric.unit
|
|
196
|
+
}
|
|
197
|
+
end + list_backend_methods(backend_id, 0)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def list_backend_methods(backend_id, _)
|
|
201
|
+
metric_index = backend_metric_index.fetch(backend_id) { raise_backend_missing(backend_id) }
|
|
202
|
+
|
|
203
|
+
backend_method_system_name_list = backend_index.fetch(backend_id).methods.map(&:system_name)
|
|
204
|
+
|
|
205
|
+
# select only methods
|
|
206
|
+
backend_method_index = metric_index.select do |_, metric|
|
|
207
|
+
backend_method_system_name_list.include? metric.system_name
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
backend_method_index.map do |method_id, method|
|
|
211
|
+
{
|
|
212
|
+
'id' => method_id,
|
|
213
|
+
'parent_id' => 1, # should not be used
|
|
214
|
+
'friendly_name' => method.friendly_name,
|
|
215
|
+
'system_name' => method.system_name,
|
|
216
|
+
'description' => method.description
|
|
217
|
+
}
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def list_backend_mapping_rules(backend_id)
|
|
222
|
+
metric_index = backend_metric_index.fetch(backend_id) { raise_backend_missing(backend_id) }
|
|
223
|
+
|
|
224
|
+
backend_index.fetch(backend_id).mapping_rules.each_with_index.map do |mapping_rule, mapping_id|
|
|
225
|
+
{
|
|
226
|
+
# 0 is not valid id
|
|
227
|
+
'id' => mapping_id + 1,
|
|
228
|
+
'pattern' => mapping_rule.pattern,
|
|
229
|
+
'http_method' => mapping_rule.http_method,
|
|
230
|
+
'delta' => mapping_rule.delta,
|
|
231
|
+
'last' => mapping_rule.last,
|
|
232
|
+
# Previous validation assures mapping rule metric references are valid
|
|
233
|
+
'metric_id' => metric_index.find { |_, metric| metric.system_name == mapping_rule.metric_ref }.first
|
|
234
|
+
}
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def show_proxy(service_id)
|
|
239
|
+
service = product_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
240
|
+
{
|
|
241
|
+
'endpoint' => service.endpoint,
|
|
242
|
+
'credentials_location' => service.credentials_location,
|
|
243
|
+
'auth_app_key' => service.auth_app_key,
|
|
244
|
+
'auth_app_id' => service.auth_app_id,
|
|
245
|
+
'auth_user_key' => service.auth_user_key,
|
|
246
|
+
'error_auth_failed' => service.error_auth_failed,
|
|
247
|
+
'error_auth_missing' => service.error_auth_missing,
|
|
248
|
+
'error_status_auth_failed' => service.error_status_auth_failed,
|
|
249
|
+
'error_headers_auth_failed' => service.error_headers_auth_failed,
|
|
250
|
+
'error_status_auth_missing' => service.error_status_auth_missing,
|
|
251
|
+
'error_headers_auth_missing' => service.error_headers_auth_missing,
|
|
252
|
+
'error_no_match' => service.error_no_match,
|
|
253
|
+
'error_status_no_match' => service.error_status_no_match,
|
|
254
|
+
'error_headers_no_match' => service.error_headers_no_match,
|
|
255
|
+
'error_limits_exceeded' => service.error_limits_exceeded,
|
|
256
|
+
'error_status_limits_exceeded' => service.error_status_limits_exceeded,
|
|
257
|
+
'error_headers_limits_exceeded' => service.error_headers_limits_exceeded,
|
|
258
|
+
'secret_token' => service.secret_token,
|
|
259
|
+
'hostname_rewrite' => service.hostname_rewrite,
|
|
260
|
+
'sandbox_endpoint' => service.sandbox_endpoint,
|
|
261
|
+
'oidc_issuer_endpoint' => service.oidc_issuer_endpoint,
|
|
262
|
+
'oidc_issuer_type' => service.oidc_issuer_type,
|
|
263
|
+
'jwt_claim_with_client_id' => service.jwt_claim_with_client_id,
|
|
264
|
+
'jwt_claim_with_client_id_type' => service.jwt_claim_with_client_id_type
|
|
265
|
+
}.delete_if { |k,v| v.nil? }
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def show_oidc(service_id)
|
|
269
|
+
service = product_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
270
|
+
{
|
|
271
|
+
'id' => service_id, #should not be used
|
|
272
|
+
'standard_flow_enabled' => service.standard_flow_enabled,
|
|
273
|
+
'implicit_flow_enabled' => service.implicit_flow_enabled,
|
|
274
|
+
'service_accounts_enabled' => service.service_accounts_enabled,
|
|
275
|
+
'direct_access_grants_enabled' => service.direct_access_grants_enabled
|
|
276
|
+
}
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def list_metrics(service_id)
|
|
280
|
+
metric_index = product_metric_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
281
|
+
|
|
282
|
+
# only metrics, not methods
|
|
283
|
+
product_metric_system_name_list = product_index.fetch(service_id).metrics.map(&:system_name)
|
|
284
|
+
|
|
285
|
+
# select only metrics
|
|
286
|
+
product_metric_only_index = metric_index.select do |_, metric|
|
|
287
|
+
product_metric_system_name_list.include? metric.system_name
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
product_metric_only_index.map do |metric_id, metric|
|
|
291
|
+
{
|
|
292
|
+
'id' => metric_id,
|
|
293
|
+
'friendly_name' => metric.friendly_name,
|
|
294
|
+
'system_name' => metric.system_name,
|
|
295
|
+
'description' => metric.description,
|
|
296
|
+
'unit' => metric.unit
|
|
297
|
+
}
|
|
298
|
+
end + list_methods(service_id, 0)
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def list_methods(service_id, _)
|
|
302
|
+
metric_index = product_metric_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
303
|
+
|
|
304
|
+
product_method_system_name_list = product_index.fetch(service_id).methods.map(&:system_name)
|
|
305
|
+
|
|
306
|
+
# select only methods
|
|
307
|
+
product_method_index = metric_index.select do |_, metric|
|
|
308
|
+
product_method_system_name_list.include? metric.system_name
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
product_method_index.map do |method_id, method|
|
|
312
|
+
{
|
|
313
|
+
'id' => method_id,
|
|
314
|
+
'parent_id' => 1, # should not be used
|
|
315
|
+
'friendly_name' => method.friendly_name,
|
|
316
|
+
'system_name' => method.system_name,
|
|
317
|
+
'description' => method.description
|
|
318
|
+
}
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def list_mapping_rules(service_id)
|
|
323
|
+
metric_index = product_metric_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
324
|
+
|
|
325
|
+
product_index.fetch(service_id).mapping_rules.each_with_index.map do |mapping_rule, mapping_id|
|
|
326
|
+
{
|
|
327
|
+
# 0 is not valid id
|
|
328
|
+
'id' => mapping_id + 1,
|
|
329
|
+
'pattern' => mapping_rule.pattern,
|
|
330
|
+
'http_method' => mapping_rule.http_method,
|
|
331
|
+
'delta' => mapping_rule.delta,
|
|
332
|
+
'last' => mapping_rule.last,
|
|
333
|
+
# Previous validation assures mapping rule metric references are valid
|
|
334
|
+
'metric_id' => metric_index.find { |_, metric| metric.system_name == mapping_rule.metric_ref }.first
|
|
335
|
+
}
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def list_service_application_plans(service_id)
|
|
340
|
+
plan_index = product_plan_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
341
|
+
|
|
342
|
+
plan_index.map do |plan_id, plan|
|
|
343
|
+
{
|
|
344
|
+
'id' => plan_id,
|
|
345
|
+
'name' => plan.name,
|
|
346
|
+
'setup_fee' => plan.setup_fee,
|
|
347
|
+
'custom' => plan.custom,
|
|
348
|
+
'state' => plan.state,
|
|
349
|
+
'cost_per_month' => plan.cost_per_month,
|
|
350
|
+
'trial_period_days' => plan.trial_period_days,
|
|
351
|
+
'approval_required' => plan.approval_required,
|
|
352
|
+
'system_name' => plan.system_name
|
|
353
|
+
}
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def list_application_plan_limits(plan_id)
|
|
358
|
+
plan = application_plan_index.fetch(plan_id) { raise_plan_missing(plan_id) }
|
|
359
|
+
plan.limits.map do |limit|
|
|
360
|
+
{
|
|
361
|
+
'id' => 1, # should not be used
|
|
362
|
+
'period' => limit.period,
|
|
363
|
+
'value' => limit.value,
|
|
364
|
+
'metric_id' => find_metric_id_from_ref(plan_id, limit.metric_system_name, limit.backend_system_name),
|
|
365
|
+
'plan_id' => plan_id
|
|
366
|
+
}
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
def show_policies(service_id)
|
|
371
|
+
service = product_index.fetch(service_id) { raise_product_missing(service_id) }
|
|
372
|
+
service.policy_chain.map do |policy_chain_item|
|
|
373
|
+
{
|
|
374
|
+
'name' => policy_chain_item.name,
|
|
375
|
+
'version' => policy_chain_item.version,
|
|
376
|
+
'configuration' => policy_chain_item.configuration,
|
|
377
|
+
'enabled' => policy_chain_item.enabled
|
|
378
|
+
}
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def list_pricingrules_per_application_plan(plan_id)
|
|
383
|
+
plan = application_plan_index.fetch(plan_id) { raise_plan_missing(plan_id) }
|
|
384
|
+
plan.pricing_rules.map do |pr|
|
|
385
|
+
{
|
|
386
|
+
'id' => 1, # should not be used
|
|
387
|
+
'cost_per_unit' => pr.price_per_unit,
|
|
388
|
+
'min' => pr.from,
|
|
389
|
+
'max' => pr.to,
|
|
390
|
+
'metric_id' => find_metric_id_from_ref(plan_id, pr.metric_system_name, pr.backend_system_name),
|
|
391
|
+
'plan_id' => plan_id
|
|
392
|
+
}
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def list_activedocs
|
|
397
|
+
[]
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
def delete_service(id)
|
|
401
|
+
true
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def delete_backend(id)
|
|
405
|
+
true
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
def delete_backend_usage(product_id, id)
|
|
409
|
+
true
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
private
|
|
413
|
+
|
|
414
|
+
def validate!
|
|
415
|
+
validate_product_metric_method_uniqueness!
|
|
416
|
+
|
|
417
|
+
validate_product_mapping_rule_references!
|
|
418
|
+
|
|
419
|
+
validate_product_backend_usage_references!
|
|
420
|
+
|
|
421
|
+
validate_product_application_plan_limit_backend_references!
|
|
422
|
+
|
|
423
|
+
validate_product_application_plan_limit_backend_metric_references!
|
|
424
|
+
|
|
425
|
+
validate_product_application_plan_limit_metric_references!
|
|
426
|
+
|
|
427
|
+
validate_product_application_plan_pricingrule_backend_references!
|
|
428
|
+
|
|
429
|
+
validate_product_application_plan_pricingrule_backend_metric_references!
|
|
430
|
+
|
|
431
|
+
validate_product_application_plan_pricingrule_metric_references!
|
|
432
|
+
|
|
433
|
+
validate_backend_metric_method_uniqueness!
|
|
434
|
+
|
|
435
|
+
validate_backend_mapping_rule_references!
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
def validate_product_metric_method_uniqueness!
|
|
439
|
+
product_index.each_value do |product|
|
|
440
|
+
system_name_list = product.metrics.map(&:system_name) + product.methods.map(&:system_name)
|
|
441
|
+
if system_name_list.length != system_name_list.uniq.length
|
|
442
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
443
|
+
"Product #{product.system_name} contains metrics and method system names that are not unique"
|
|
444
|
+
end
|
|
445
|
+
end
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def validate_product_mapping_rule_references!
|
|
449
|
+
product_index.each_value do |product|
|
|
450
|
+
product.mapping_rules.each do |mapping_rule|
|
|
451
|
+
product.metrics_index.fetch(mapping_rule.metric_ref) do
|
|
452
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
453
|
+
"Product {#{product.system_name} " \
|
|
454
|
+
"Mapping rule {#{mapping_rule.http_method} #{mapping_rule.pattern}} " \
|
|
455
|
+
"referencing to metric #{mapping_rule.metric_ref} has not been found"
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def validate_product_backend_usage_references!
|
|
462
|
+
product_index.each_value do |product|
|
|
463
|
+
product.backend_usages.each do |backend_usage|
|
|
464
|
+
if backend_index.values.none? { |backend| backend.system_name == backend_usage.backend_system_name }
|
|
465
|
+
raise ThreeScaleToolbox::Error, "Invalid content. Product {#{product.system_name}" \
|
|
466
|
+
"backend usage reference to backend #{backend_usage.backend_system_name} has not been found"
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
# validate limit backend references
|
|
473
|
+
def validate_product_application_plan_limit_backend_references!
|
|
474
|
+
product_index.each_value do |product|
|
|
475
|
+
product.application_plans.each do |plan|
|
|
476
|
+
limits_with_backend_ref = plan.limits.reject { |limit| limit.backend_system_name.nil? }
|
|
477
|
+
limits_with_backend_ref.each do |limit|
|
|
478
|
+
unless product.backend_usages.map(&:backend_system_name).include? limit.backend_system_name
|
|
479
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
480
|
+
"Product {#{product.system_name} " \
|
|
481
|
+
"Limit {#{limit.to_s}}, the backend #{limit.backend_system_name} " \
|
|
482
|
+
"has not been found in backend usages"
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
# validate limit metric with backend references
|
|
490
|
+
def validate_product_application_plan_limit_backend_metric_references!
|
|
491
|
+
product_index.each_value do |product|
|
|
492
|
+
product.application_plans.each do |plan|
|
|
493
|
+
limits_with_backend_ref = plan.limits.reject { |limit| limit.backend_system_name.nil? }
|
|
494
|
+
limits_with_backend_ref.each do |limit|
|
|
495
|
+
# It is already validated that backend references are correct, hence it must exist
|
|
496
|
+
limit_backend_ref = backend_index.values.find { |b| b.system_name == limit.backend_system_name }
|
|
497
|
+
unless (limit_backend_ref.methods + limit_backend_ref.metrics).map(&:system_name).include? limit.metric_system_name
|
|
498
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
499
|
+
"Product {#{product.system_name} " \
|
|
500
|
+
"Limit {#{limit.to_s}}, the metric #{limit.metric_system_name} " \
|
|
501
|
+
"has not been found in backend #{limit_backend_ref.system_name}"
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
# validate limit metric references in product metrics and methods
|
|
509
|
+
def validate_product_application_plan_limit_metric_references!
|
|
510
|
+
product_index.each_value do |product|
|
|
511
|
+
product.application_plans.each do |plan|
|
|
512
|
+
limits_with_product_ref = plan.limits.select { |limit| limit.backend_system_name.nil? }
|
|
513
|
+
limits_with_product_ref.each do |limit|
|
|
514
|
+
unless (product.methods + product.metrics).map(&:system_name).include? limit.metric_system_name
|
|
515
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
516
|
+
"Product {#{product.system_name} " \
|
|
517
|
+
"Limit {#{limit.to_s}}, the metric #{limit.metric_system_name} " \
|
|
518
|
+
"has not been found"
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# validate pricing rules backend references
|
|
526
|
+
def validate_product_application_plan_pricingrule_backend_references!
|
|
527
|
+
product_index.each_value do |product|
|
|
528
|
+
product.application_plans.each do |plan|
|
|
529
|
+
pr_list_with_backend_ref = plan.pricing_rules.reject { |pr| pr.backend_system_name.nil? }
|
|
530
|
+
pr_list_with_backend_ref.each do |pr|
|
|
531
|
+
unless product.backend_usages.map(&:backend_system_name).include? pr.backend_system_name
|
|
532
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
533
|
+
"Product {#{product.system_name} " \
|
|
534
|
+
"PricingRule {#{pr.to_s}}, the backend #{pr.backend_system_name} " \
|
|
535
|
+
"has not been found in backend usages"
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
# validate pricing rule metric with backend references
|
|
543
|
+
def validate_product_application_plan_pricingrule_backend_metric_references!
|
|
544
|
+
product_index.each_value do |product|
|
|
545
|
+
product.application_plans.each do |plan|
|
|
546
|
+
pr_list_with_backend_ref = plan.pricing_rules.reject { |pr| pr.backend_system_name.nil? }
|
|
547
|
+
pr_list_with_backend_ref.each do |pr|
|
|
548
|
+
# It is already validated that backend references are correct, hence it must exist
|
|
549
|
+
pr_backend_ref = backend_index.values.find { |b| b.system_name == pr.backend_system_name }
|
|
550
|
+
unless (pr_backend_ref.methods + pr_backend_ref.metrics).map(&:system_name).include? pr.metric_system_name
|
|
551
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
552
|
+
"Product {#{product.system_name} " \
|
|
553
|
+
"PricingRule {#{pr.to_s}}, the metric #{pr.metric_system_name} " \
|
|
554
|
+
"has not been found in backend #{pr_backend_ref.system_name}"
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
# validate pricing rule metric references in product metrics and methods
|
|
562
|
+
def validate_product_application_plan_pricingrule_metric_references!
|
|
563
|
+
product_index.each_value do |product|
|
|
564
|
+
product.application_plans.each do |plan|
|
|
565
|
+
pr_list_with_product_ref = plan.pricing_rules.select { |pr| pr.backend_system_name.nil? }
|
|
566
|
+
pr_list_with_product_ref.each do |pr|
|
|
567
|
+
unless (product.methods + product.metrics).map(&:system_name).include? pr.metric_system_name
|
|
568
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
569
|
+
"Product {#{product.system_name} " \
|
|
570
|
+
"PricingRule {#{pr.to_s}}, the metric #{pr.metric_system_name} " \
|
|
571
|
+
"has not been found"
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def validate_backend_metric_method_uniqueness!
|
|
579
|
+
backend_index.each_value do |backend|
|
|
580
|
+
system_name_list = backend.metrics.map(&:system_name) + backend.methods.map(&:system_name)
|
|
581
|
+
if system_name_list.length != system_name_list.uniq.length
|
|
582
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
583
|
+
"Backend #{backend.system_name} contains metrics and method system names that are not unique"
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
def validate_backend_mapping_rule_references!
|
|
589
|
+
backend_index.each_value do |backend|
|
|
590
|
+
backend.mapping_rules.each do |mapping_rule|
|
|
591
|
+
backend.metrics_index.fetch(mapping_rule.metric_ref) do
|
|
592
|
+
raise ThreeScaleToolbox::Error, "Invalid content. " \
|
|
593
|
+
"Backend {#{backend.system_name} " \
|
|
594
|
+
"Mapping rule {#{mapping_rule.http_method} #{mapping_rule.pattern}} " \
|
|
595
|
+
"referencing to metric #{mapping_rule.metric_ref} has not been found"
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
# Index: backend_id -> metric_id -> metric or method
|
|
603
|
+
# metric and methods have unique indexes
|
|
604
|
+
def backend_metric_index
|
|
605
|
+
@backend_metric_index ||= backend_index.each_with_object({}) do |(backend_id, backend), backend_index|
|
|
606
|
+
metric_method_list = backend.metrics + backend.methods
|
|
607
|
+
backend_index[backend_id] = metric_method_list.each_with_object({}) do |metric, metric_index|
|
|
608
|
+
metric_index[new_index] = metric
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
# Index: plan_id -> plan
|
|
614
|
+
def application_plan_index
|
|
615
|
+
product_plan_index.values.inject({}) { |acc, plan_index| acc.merge(plan_index) }
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
# Index: product_id -> plan_id -> plan
|
|
619
|
+
def product_plan_index
|
|
620
|
+
@product_plan_index ||= product_index.each_with_object({}) do |(product_id, product), product_index|
|
|
621
|
+
product_index[product_id] = product.application_plans.each_with_object({}) do |plan, plan_index|
|
|
622
|
+
plan_index[new_index] = plan
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
# Index: plan_id -> product_id
|
|
628
|
+
def plan_product_index
|
|
629
|
+
@plan_product_index ||= product_plan_index.each_with_object({}) do |(product_id, plan_index), hash|
|
|
630
|
+
plan_index.keys.each { |plan_id| hash[plan_id] = product_id }
|
|
631
|
+
end
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
# Index: product_id -> metric_id -> metric
|
|
635
|
+
def product_metric_index
|
|
636
|
+
@product_metric_index ||= product_index.each_with_object({}) do |(product_id, product), product_index|
|
|
637
|
+
metric_method_list = product.metrics + product.methods
|
|
638
|
+
product_index[product_id] = metric_method_list.each_with_object({}) do |metric, metric_index|
|
|
639
|
+
metric_index[new_index] = metric
|
|
640
|
+
end
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
def new_index
|
|
645
|
+
# starts on 1
|
|
646
|
+
@new_index ||= 0
|
|
647
|
+
@new_index += 1
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def find_metric_id_from_ref(plan_id, system_name, backend_system_name)
|
|
651
|
+
if backend_system_name.nil?
|
|
652
|
+
product_id = plan_product_index.fetch(plan_id)
|
|
653
|
+
product_metric_index.fetch(product_id).find do |_, metric|
|
|
654
|
+
metric.system_name == system_name
|
|
655
|
+
end.first
|
|
656
|
+
else
|
|
657
|
+
# it is validated that backend is in application backend usages
|
|
658
|
+
# so it can be safely search in the whole backend index, and must exist
|
|
659
|
+
backend_id = backend_index.find { |_, b| b.system_name == backend_system_name }.first
|
|
660
|
+
backend_metric_index.fetch(backend_id).find do |_, metric|
|
|
661
|
+
metric.system_name == system_name
|
|
662
|
+
end.first
|
|
663
|
+
end
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def raise_backend_missing(backend_id)
|
|
667
|
+
raise ThreeScaleToolbox::Error, "Unexpected event in CRDRemote class. " \
|
|
668
|
+
"Backend #{backend_id} not found in the index"
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def raise_product_missing(product_id)
|
|
672
|
+
raise ThreeScaleToolbox::Error, "Unexpected event in CRDRemote class. " \
|
|
673
|
+
"Service #{product_id} not found in the index"
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
def raise_plan_missing(plan_id)
|
|
677
|
+
raise ThreeScaleToolbox::Error, "Unexpected event in CRDRemote class. " \
|
|
678
|
+
"ApplicationPlan #{plan_id} not found in the index"
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
end
|