3scale_toolbox 0.4.0 → 0.5.0

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.
@@ -0,0 +1,20 @@
1
+ require 'cri'
2
+ require '3scale_toolbox/base_command'
3
+ require '3scale_toolbox/commands/update_command/update_service'
4
+
5
+ module ThreeScaleToolbox
6
+ module Commands
7
+ module UpdateCommand
8
+ extend ThreeScaleToolbox::Command
9
+ def self.command
10
+ Cri::Command.define do
11
+ name 'update'
12
+ usage 'update <command> [options]'
13
+ summary '3scale update command'
14
+ description '3scale update command.'
15
+ end
16
+ end
17
+ add_subcommand(UpdateServiceSubcommand)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ require '3scale_toolbox/commands/3scale_command'
2
+ require '3scale_toolbox/commands/help_command'
3
+ require '3scale_toolbox/commands/copy_command'
4
+ require '3scale_toolbox/commands/import_command'
5
+ require '3scale_toolbox/commands/update_command'
6
+
7
+ module ThreeScaleToolbox
8
+ module Commands
9
+ BUILTIN_COMMANDS = [ # :nodoc:
10
+ ThreeScaleToolbox::Commands::HelpCommand,
11
+ ThreeScaleToolbox::Commands::CopyCommand,
12
+ ThreeScaleToolbox::Commands::ImportCommand,
13
+ ThreeScaleToolbox::Commands::UpdateCommand
14
+ ].freeze
15
+
16
+ def self.service_valid_params
17
+ %w[
18
+ name backend_version deployment_option description
19
+ system_name end_user_registration_required
20
+ support_email tech_support_email admin_support_email
21
+ ]
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module ThreeScaleToolbox
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -1,5 +1,9 @@
1
- require '3scale_toolbox/version'
2
-
3
1
  module ThreeScaleToolbox
4
- # Your code goes here...
2
+ def self.load_plugins
3
+ plugin_paths.each { |plugin_path| require plugin_path }
4
+ end
5
+
6
+ def self.plugin_paths
7
+ Gem.find_files('3scale_toolbox_plugin')
8
+ end
5
9
  end
metadata CHANGED
@@ -1,29 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: 3scale_toolbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Cichra
8
+ - Eguzki Astiz Lezaun
8
9
  autorequire:
9
10
  bindir: exe
10
11
  cert_chain: []
11
- date: 2018-01-23 00:00:00.000000000 Z
12
+ date: 2018-10-25 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - "~>"
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
- version: '1.11'
20
+ version: '0'
20
21
  type: :development
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - "~>"
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
- version: '1.11'
27
+ version: '0'
27
28
  - !ruby/object:Gem::Dependency
28
29
  name: rake
29
30
  requirement: !ruby/object:Gem::Requirement
@@ -38,40 +39,71 @@ dependencies:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
41
  version: '10.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.7'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.7'
41
56
  - !ruby/object:Gem::Dependency
42
57
  name: 3scale-api
43
58
  requirement: !ruby/object:Gem::Requirement
44
59
  requirements:
45
60
  - - "~>"
46
61
  - !ruby/object:Gem::Version
47
- version: 0.1.2
62
+ version: '0.1'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '0.1'
70
+ - !ruby/object:Gem::Dependency
71
+ name: cri
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.10'
48
77
  type: :runtime
49
78
  prerelease: false
50
79
  version_requirements: !ruby/object:Gem::Requirement
51
80
  requirements:
52
81
  - - "~>"
53
82
  - !ruby/object:Gem::Version
54
- version: 0.1.2
83
+ version: '2.10'
55
84
  description: 3scale CLI tools to manage your API from the terminal.
56
85
  email:
57
86
  - michal@3scale.net
87
+ - eastizle@redhat.com
58
88
  executables:
59
89
  - 3scale
60
- - 3scale-copy
61
- - 3scale-help
62
- - 3scale-import
63
- - 3scale-update
64
90
  extensions: []
65
91
  extra_rdoc_files: []
66
92
  files:
67
93
  - README.md
68
94
  - exe/3scale
69
- - exe/3scale-copy
70
- - exe/3scale-help
71
- - exe/3scale-import
72
- - exe/3scale-update
73
95
  - lib/3scale_toolbox.rb
96
+ - lib/3scale_toolbox/base_command.rb
74
97
  - lib/3scale_toolbox/cli.rb
98
+ - lib/3scale_toolbox/commands.rb
99
+ - lib/3scale_toolbox/commands/3scale_command.rb
100
+ - lib/3scale_toolbox/commands/copy_command.rb
101
+ - lib/3scale_toolbox/commands/copy_command/copy_service.rb
102
+ - lib/3scale_toolbox/commands/help_command.rb
103
+ - lib/3scale_toolbox/commands/import_command.rb
104
+ - lib/3scale_toolbox/commands/import_command/import_csv.rb
105
+ - lib/3scale_toolbox/commands/update_command.rb
106
+ - lib/3scale_toolbox/commands/update_command/update_service.rb
75
107
  - lib/3scale_toolbox/version.rb
76
108
  homepage: https://github.com/3scale/3scale_toolbox
77
109
  licenses:
@@ -93,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
125
  version: '0'
94
126
  requirements: []
95
127
  rubyforge_project:
96
- rubygems_version: 2.7.3
128
+ rubygems_version: 2.7.6
97
129
  signing_key:
98
130
  specification_version: 4
99
131
  summary: 3scale CLI Toolbox.
data/exe/3scale-copy DELETED
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require '3scale_toolbox/cli'
4
-
5
- require 'optparse'
6
-
7
- options = {}
8
-
9
- parser = OptionParser.new do |parser|
10
- parser.banner = '3scale copy <command> [options]'
11
-
12
- parser.on('-s', '--source SOURCE', "Source") do |domain|
13
- options[:source] = domain
14
- end
15
-
16
- parser.on('-d', '--destination DESTINATION', "Destination") do |domain|
17
- options[:destination] = domain
18
- end
19
-
20
- parser.on('-t', '--target-system-name TARGET_SYSTEM_NAME', 'Target system name') do |name|
21
- options[:target_system_name] = name
22
- end
23
-
24
- parser.on('-h', '--help', 'Prints this help') do
25
- puts parser
26
- puts
27
- puts 'Available Commands:', ['service <service_id>', 'help']
28
- exit
29
- end
30
- end
31
-
32
- print_help = ->(error = nil) do
33
- if error
34
- puts "Error: #{error}"
35
- puts
36
- end
37
- parser.parse(['--help'])
38
- end
39
-
40
-
41
- parser.parse!
42
-
43
- def compare_hashes(first, second, keys)
44
- keys.map{ |key| first.fetch(key) } == keys.map{ |key| second.fetch(key) }
45
- end
46
-
47
- def fetch_option(options, key)
48
- options.fetch(key) { raise OptionParser::MissingArgument, key }
49
- end
50
-
51
- def provider_key_from_url(url)
52
- url[/\w*@/][0..-2]
53
- end
54
-
55
- def endpoint_from_url(url)
56
- url.sub /\w*@/, ''
57
- end
58
-
59
- def copy_service_params(original, system_name)
60
- {
61
- name: original['name'],
62
- system_name: system_name,
63
- backend_version: original['backend_version'],
64
- end_user_registration_required: original['end_user_registration_required']
65
- }.reject { |key, value| !value }
66
- end
67
-
68
- case (command = ARGV.shift)
69
- when 'service'
70
- source = fetch_option options, :source
71
- destination = fetch_option options, :destination
72
- system_name = options[:target_system_name]
73
-
74
- require '3scale/api'
75
-
76
- service_id = ARGV.shift or raise OptionParser::MissingArgument, 'service_id'
77
-
78
- source_client = ThreeScale::API.new(
79
- endpoint: endpoint_from_url(source),
80
- provider_key: provider_key_from_url(source)
81
- )
82
- client = ThreeScale::API.new(
83
- endpoint: endpoint_from_url(destination),
84
- provider_key: provider_key_from_url(destination)
85
- )
86
-
87
- service = source_client.show_service(service_id)
88
- copy = client.create_service(copy_service_params(service, system_name))
89
-
90
- raise "Service has not been saved. Errors: #{copy['errors']}" unless copy['errors'].nil?
91
-
92
- service_copy_id = copy.fetch('id')
93
-
94
- puts "new service id #{service_copy_id}"
95
-
96
- proxy = source_client.show_proxy(service_id)
97
- client.update_proxy(service_copy_id, proxy)
98
- puts "updated proxy of #{service_copy_id} to match the original"
99
-
100
- metrics = source_client.list_metrics(service_id)
101
- metrics_copies = client.list_metrics(service_copy_id)
102
-
103
- hits = metrics.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
104
- hits_copy = metrics_copies.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
105
-
106
- methods = source_client.list_methods(service_id, hits['id'])
107
- methods_copies = client.list_methods(service_copy_id, hits_copy['id'])
108
-
109
- puts "original service hits metric #{hits['id']} has #{methods.size} methods"
110
- puts "copied service hits metric #{hits_copy['id']} has #{methods_copies.size} methods"
111
-
112
- missing_methods = methods.reject { |method| methods_copies.find{|copy| compare_hashes(method, copy, ['system_name']) } }
113
-
114
- puts "creating #{missing_methods.size} missing methods on copied service"
115
-
116
- missing_methods.each do |method|
117
- copy = { friendly_name: method['friendly_name'], system_name: method['system_name'] }
118
- client.create_method(service_copy_id, hits_copy['id'], copy)
119
- end
120
-
121
- metrics_copies = client.list_metrics(service_copy_id)
122
-
123
- puts "original service has #{metrics.size} metrics"
124
- puts "copied service has #{metrics_copies.size} metrics"
125
-
126
- missing_metrics = metrics.reject { |metric| metrics_copies.find{|copy| compare_hashes(metric, copy, ['system_name']) } }
127
-
128
- missing_metrics.map do |metric|
129
- metric.delete('links')
130
- client.create_metric(service_copy_id, metric)
131
- end
132
-
133
- puts "created #{missing_metrics.size} metrics on the copied service"
134
-
135
- plans = source_client.list_service_application_plans(service_id)
136
- plan_copies = client.list_service_application_plans(service_copy_id)
137
-
138
- puts "original service has #{plans.size} application plans "
139
- puts "copied service has #{plan_copies.size} application plans"
140
-
141
- missing_application_plans = plans.reject { |plan| plan_copies.find{|copy| plan.fetch('system_name') == copy.fetch('system_name') } }
142
-
143
- puts "copied service missing #{missing_application_plans.size} application plans"
144
-
145
- missing_application_plans.each do |plan|
146
- plan.delete('links')
147
- plan.delete('default') # TODO: handle default plan
148
-
149
- if plan.delete('custom') # TODO: what to do with custom plans?
150
- puts "skipping custom plan #{plan}"
151
- else
152
- client.create_application_plan(service_copy_id, plan)
153
- end
154
- end
155
-
156
- application_plan_mapping = client.list_service_application_plans(service_copy_id).map do |plan_copy|
157
- plan = plans.find{|plan| plan.fetch('system_name') == plan_copy.fetch('system_name') }
158
-
159
- [plan['id'], plan_copy['id']]
160
- end
161
-
162
-
163
- metrics_mapping = client.list_metrics(service_copy_id).map do |copy|
164
- metric = metrics.find{|metric| metric.fetch('system_name') == copy.fetch('system_name') }
165
- metric ||= {}
166
-
167
- [metric['id'], copy['id']]
168
- end.to_h
169
-
170
- puts "destroying all mapping rules of the copy which have been created by default"
171
- client.list_mapping_rules(service_copy_id).each do |mapping_rule|
172
- client.delete_mapping_rule(service_copy_id, mapping_rule['id'])
173
- end
174
-
175
- mapping_rules = source_client.list_mapping_rules(service_id)
176
- mapping_rules_copy = client.list_mapping_rules(service_copy_id)
177
-
178
- puts "the original service has #{mapping_rules.size} mapping rules"
179
- puts "the copy has #{mapping_rules_copy.size} mapping rules"
180
-
181
- unique_mapping_rules_copy = mapping_rules_copy.dup
182
-
183
- missing_mapping_rules = mapping_rules.reject do |mapping_rule|
184
- matching_metric = unique_mapping_rules_copy.find do |copy|
185
- compare_hashes(mapping_rule, copy, %w(pattern http_method delta)) &&
186
- metrics_mapping.fetch(mapping_rule.fetch('metric_id')) == copy.fetch('metric_id')
187
- end
188
-
189
- unique_mapping_rules_copy.delete(matching_metric)
190
- end
191
-
192
- puts "missing #{missing_mapping_rules.size} mapping rules"
193
-
194
- missing_mapping_rules.each do |mapping_rule|
195
- mapping_rule.delete('links')
196
- mapping_rule['metric_id'] = metrics_mapping.fetch(mapping_rule.delete('metric_id'))
197
- client.create_mapping_rule(service_copy_id, mapping_rule)
198
- end
199
- puts "created #{missing_mapping_rules.size} mapping rules"
200
-
201
- puts "extra #{unique_mapping_rules_copy.size} mapping rules"
202
- puts unique_mapping_rules_copy.each{|rule| rule.delete('links') }
203
-
204
- application_plan_mapping.each do |original_id, copy_id|
205
- limits = source_client.list_application_plan_limits(original_id)
206
- limits_copy = client.list_application_plan_limits(copy_id)
207
-
208
- missing_limits = limits.reject { |limit| limits_copy.find{|limit_copy| limit.fetch('period') == limit_copy.fetch('period') } }
209
-
210
- missing_limits.each do |limit|
211
- limit.delete('links')
212
- client.create_application_plan_limit(copy_id, metrics_mapping.fetch(limit.fetch('metric_id')), limit)
213
- end
214
- puts "copied application plan #{copy_id} is missing #{missing_limits.size} from the original plan #{original_id}"
215
- end
216
- when 'help'
217
- print_help.call
218
- when nil
219
- print_help.call("missing subcommand")
220
- else
221
- print_help.call("unknown command #{command}")
222
- end
data/exe/3scale-help DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require '3scale_toolbox/cli'
4
-
5
- puts '3scale toolbox help'
6
- puts
7
-
8
- puts 'Available subcommands: '
9
- puts ThreeScaleToolbox::CLI.subcommands.map(&:name)
data/exe/3scale-import DELETED
@@ -1,178 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require '3scale_toolbox/cli'
4
- require 'optparse'
5
- require '3scale/api'
6
- require 'uri'
7
- require 'csv'
8
-
9
- options = {}
10
-
11
- parser = OptionParser.new do |parser|
12
- parser.banner = '3scale import <command> [options]'
13
-
14
- parser.on('-d', '--destination DESTINATION') do |domain|
15
- options[:destination] = domain
16
- end
17
-
18
- parser.on('-f', '--file FILE') do |file|
19
- options[:file] = file
20
- end
21
-
22
- parser.on('-h', '--help', 'Prints this help') do
23
- puts parser
24
- puts
25
- puts 'Available Commands:', ['csv', 'help']
26
- exit
27
- end
28
- end
29
-
30
- print_help = ->(error = nil) do
31
- if error
32
- puts "Error: #{error}"
33
- puts
34
- end
35
- parser.parse(['--help'])
36
- end
37
-
38
- parser.parse!
39
-
40
- def fetch_option(options, key)
41
- options.fetch(key) { raise OptionParser::MissingArgument, key }
42
- end
43
-
44
- def provider_key_from_url(url)
45
- URI(url).user
46
- end
47
-
48
- def endpoint_from_url(url)
49
- uri = URI(url)
50
- uri.user = nil
51
-
52
- uri.to_s
53
- end
54
-
55
- def auth_app_key_according_service(service)
56
- case service['backend_version']
57
- when '1'
58
- 'user_key'
59
- when '2'
60
- 'app_id'
61
- when 'oauth'
62
- 'oauth'
63
- end
64
- end
65
-
66
- case (command = ARGV.shift)
67
- when 'csv'
68
- destination = fetch_option options, :destination
69
- file_path = fetch_option options, :file
70
- endpoint = endpoint_from_url destination
71
- provider_key = provider_key_from_url destination
72
-
73
- client = ThreeScale::API.new(endpoint: endpoint, provider_key: provider_key)
74
- data = CSV.read file_path
75
- headings = data.shift
76
- services = {}
77
- stats = { services: 0, metrics: 0, methods: 0 , mapping_rules: 0 }
78
-
79
- # prepare services data
80
- data.each do |row|
81
- service_name = row[headings.find_index('service_name')]
82
- item = {}
83
-
84
- services[service_name] ||= {}
85
- services[service_name][:items] ||= []
86
-
87
- (headings - ['service_name']).each do |heading|
88
- item[heading] = row[headings.find_index(heading)]
89
- end
90
-
91
- services[service_name][:items].push item
92
- end
93
-
94
- services.keys.each do |service_name|
95
- # create service
96
- service = client.create_service name: service_name
97
-
98
- if service['errors'].nil?
99
- stats[:services] += 1
100
- puts "Service #{service_name} has been created."
101
- else
102
- abort "Service has not been saved. Errors: #{service['errors']}"
103
- end
104
-
105
- # find hits metric (default)
106
- hits_metric = client.list_metrics(service['id']).find do |metric|
107
- metric['system_name'] == 'hits'
108
- end
109
-
110
- services[service_name][:items].each do |item|
111
-
112
- metric, method = {}
113
-
114
- case item['type']
115
- # create a metric
116
- when 'metric'
117
- metric = client.create_metric(service['id'], {
118
- system_name: item['endpoint_system_name'],
119
- friendly_name: item['endpoint_name'],
120
- unit: 'unit'
121
- })
122
-
123
- if metric['errors'].nil?
124
- stats[:metrics] += 1
125
- puts "Metric #{item['endpoint_name']} has been created."
126
- else
127
- puts "Metric has not been saved. Errors: #{metric['errors']}"
128
- end
129
- # create a method
130
- when 'method'
131
- method = client.create_method(service['id'], hits_metric['id'], {
132
- system_name: item['endpoint_system_name'],
133
- friendly_name: item['endpoint_name'],
134
- unit: 'unit'
135
- })
136
-
137
- if method['errors'].nil?
138
- stats[:methods] += 1
139
- puts "Method #{item['endpoint_name']} has been created."
140
- else
141
- puts "Method has not been saved. Errors: #{method['errors']}"
142
- end
143
- end
144
-
145
- # create a mapping rule
146
- if (metric_id = metric['id'] || method['id'])
147
- mapping_rule = client.create_mapping_rule(service['id'], {
148
- metric_id: metric_id,
149
- pattern: item['endpoint_path'],
150
- http_method: item['endpoint_http_method'],
151
- metric_system_name: item['endpoint_system_name'],
152
- auth_app_key: auth_app_key_according_service(service),
153
- delta: 1
154
- })
155
-
156
- if mapping_rule['errors'].nil?
157
- stats[:mapping_rules] += 1
158
- puts "Mapping rule #{item['endpoint_system_name']} has been created."
159
- else
160
- puts "Mapping rule has not been saved. Errors: #{mapping_rule['errors']}"
161
- end
162
- end
163
- end
164
- end
165
-
166
- puts "#{services.keys.count} services in CSV file"
167
- puts "#{stats[:services]} services have been created"
168
- puts "#{stats[:metrics]} metrics have been created"
169
- puts "#{stats[:methods]} methods have beeen created"
170
- puts "#{stats[:mapping_rules]} mapping rules have been created"
171
-
172
- when 'help'
173
- print_help.call
174
- when nil
175
- print_help.call('missing subcommand')
176
- else
177
- print_help.call("unknown command #{command}")
178
- end