3scale_toolbox 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2041609888563be7ca7b60bbd7cdb6ddd8f60911
4
+ data.tar.gz: 417e59c876b5111b84af2472ca3df9e51dd1f4e8
5
+ SHA512:
6
+ metadata.gz: 7ffdb592223d2a9bf649bba41c8984d63b13c27863fb146a73623a98b561a62bc56f3ae4544dd9679fa8ffa65c782b5dbf4baebcdc826272ef65a059e36c1eea
7
+ data.tar.gz: 47750f59a33e3839b0e4cfa3b2005b247a20f4476029ea3e546d34290dca615d0406c466e2109fff9f04e591917ac0a0e38d00163372a02bd35bc1b8ee8a1d4c
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # 3scale toolbox
2
+
3
+ 3scale toolbox is a set of tools to help you manage your 3scale product.
4
+
5
+ ## Installation
6
+
7
+
8
+ Install the CLI:
9
+
10
+ $ gem install 3scale_toolbox
11
+
12
+ ## Usage
13
+
14
+ ```shell
15
+ 3scale help
16
+ ```
17
+
18
+ ### Copy a service
19
+
20
+ Will create a new service, copy existing methods, metrics, application plans and their usage limits.
21
+
22
+ ```shell
23
+ 3scale copy service NUMBER --endpoint=https://foo-admin.3scale.net --provider-key=your-key
24
+ ```
25
+
26
+ ## Development
27
+
28
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec threescale_toolbox` to use the gem in this directory, ignoring other installed copies of this gem.
29
+
30
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
31
+
32
+ ## Contributing
33
+
34
+ Bug reports and pull requests are welcome on GitHub at https://github.com/3scale/3scale_toolbox.
35
+
data/exe/3scale ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '3scale_toolbox/cli'
4
+
5
+ options, argv = ThreeScaleToolbox::CLI.parse
6
+
7
+ unless options.command
8
+ puts 'Available subcommands: '
9
+ puts ThreeScaleToolbox::CLI.subcommands
10
+ puts
11
+ ThreeScaleToolbox::CLI.print_help!
12
+ end
13
+
14
+ exec options.command.full_path, *ARGV
data/exe/3scale-copy ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '3scale_toolbox/cli'
4
+
5
+ require 'optparse'
6
+
7
+ options = {}
8
+ OptionParser.new do |parser|
9
+ parser.banner = '3scale copy <command> [options]'
10
+
11
+ parser.on('-e', '--endpoint ENDPOINT', "Endpoint") do |domain|
12
+ options[:endpoint] = domain
13
+ end
14
+
15
+ parser.on('-p', '--provider-key PROVIDER_KEY', "Provider Key") do |provider_key|
16
+ options[:provider_key] = provider_key
17
+ end
18
+
19
+ parser.on('-h', '--help', 'Prints this help') do
20
+ puts parser
21
+ exit
22
+ end
23
+ end.parse!
24
+
25
+ endpoint = options.fetch(:endpoint) { raise OptionParser::MissingArgument, 'endpoint' }
26
+ provider_key = options.fetch(:provider_key) { raise OptionParser::MissingArgument, 'provider_key' }
27
+
28
+ require '3scale/api'
29
+
30
+ client = ThreeScale::API.new(endpoint: endpoint, provider_key: provider_key)
31
+
32
+ case (command = ARGV.shift)
33
+ when 'service'
34
+ service_id = ARGV.shift or raise OptionParser::MissingArgument, 'service_id'
35
+
36
+ service = client.show_service(service_id)
37
+
38
+ name = "#{service['name']} (copy)"
39
+
40
+ copy = client.list_services.find do |service|
41
+ service['name'] == name
42
+ end
43
+
44
+ copy ||= client.create_service(name: name,
45
+ end_user_registration_required: service['end_user_registration_required'])
46
+ service_copy_id = copy.fetch('id')
47
+
48
+ puts "new service id #{service_copy_id}"
49
+
50
+ metrics = client.list_metrics(service_id)
51
+ metrics_copies = client.list_metrics(service_copy_id)
52
+
53
+ hits = metrics.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
54
+ hits_copy = metrics_copies.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
55
+
56
+ methods = client.list_methods(service_id, hits['id'])
57
+ methods_copies = client.list_methods(service_copy_id, hits_copy['id'])
58
+
59
+ puts "original service hits metric #{hits['id']} has #{methods.size} methods"
60
+ puts "copied service hits metric #{hits_copy['id']} has #{methods_copies.size} methods"
61
+
62
+ missing_methods = methods.reject { |method| methods_copies.find{|copy| method.fetch('system_name') == copy.fetch('system_name') } }
63
+
64
+ puts "creating #{missing_methods.size} missing methods on copied service"
65
+
66
+ missing_methods.each do |method|
67
+ copy = { friendly_name: method['friendly_name'], system_name: method['system_name'] }
68
+ client.create_method(service_copy_id, hits_copy['id'], copy)
69
+ end
70
+
71
+ metrics_copies = client.list_metrics(service_copy_id)
72
+
73
+ puts "original service has #{metrics.size} metrics"
74
+ puts "copied service has #{metrics.size} metrics"
75
+
76
+ missing_metrics = metrics.reject { |metric| metrics_copies.find{|copy| metric.fetch('system_name') == copy.fetch('system_name') } }
77
+
78
+ missing_metrics.map do |metric|
79
+ metric.delete('links')
80
+ client.create_metric(service_copy_id, metric)
81
+ end
82
+
83
+ puts "created #{missing_metrics.size} metrics on the copied service"
84
+
85
+ plans = client.list_service_application_plans(service_id)
86
+ plan_copies = client.list_service_application_plans(service_copy_id)
87
+
88
+ puts "original service has #{plans.size} application plans "
89
+ puts "copied service has #{plan_copies.size} application plans"
90
+
91
+ missing_application_plans = plans.reject { |plan| plan_copies.find{|copy| plan.fetch('system_name') == copy.fetch('system_name') } }
92
+
93
+ puts "copied service missing #{missing_application_plans.size} application plans"
94
+
95
+ missing_application_plans.each do |plan|
96
+ plan.delete('links')
97
+ plan.delete('default') # TODO: handle default plan
98
+
99
+ if plan.delete('custom') # TODO: what to do with custom plans?
100
+ puts "skipping custom plan #{plan}"
101
+ else
102
+ client.create_application_plan(service_copy_id, plan)
103
+ end
104
+ end
105
+
106
+ application_plan_mapping = client.list_service_application_plans(service_copy_id).map do |plan_copy|
107
+ plan = plans.find{|plan| plan.fetch('system_name') == plan_copy.fetch('system_name') }
108
+
109
+ [plan['id'], plan_copy['id']]
110
+ end
111
+
112
+
113
+ metrics_mapping = client.list_metrics(service_copy_id).map do |copy|
114
+ metric = metrics.find{|metric| metric.fetch('system_name') == copy.fetch('system_name') }
115
+
116
+ [metric['id'], copy['id']]
117
+ end.to_h
118
+
119
+ application_plan_mapping.each do |original_id, copy_id|
120
+ limits = client.list_application_plan_limits(original_id)
121
+ limits_copy = client.list_application_plan_limits(copy_id)
122
+
123
+ missing_limits = limits.reject { |limit| limits_copy.find{|limit_copy| limit.fetch('period') == limit_copy.fetch('period') } }
124
+
125
+ missing_limits.each do |limit|
126
+ limit.delete('links')
127
+ client.create_application_plan_limit(copy_id, metrics_mapping.fetch(limit.fetch('metric_id')), limit)
128
+ end
129
+ puts "copied application plan #{copy_id} is missing #{missing_limits.size} from the original plan #{original_id}"
130
+ end
131
+
132
+
133
+
134
+ else
135
+
136
+ end
data/exe/3scale-help ADDED
@@ -0,0 +1,9 @@
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)
@@ -0,0 +1,5 @@
1
+ require '3scale_toolbox/version'
2
+
3
+ module ThreeScaleToolbox
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,78 @@
1
+ require 'optparse'
2
+
3
+ module ThreeScaleToolbox
4
+ module CLI
5
+ Options = Struct.new(:command)
6
+
7
+ class Parser
8
+ def self.parse(options)
9
+ args = Options.new(nil)
10
+
11
+ opt_parser = OptionParser.new do |opts|
12
+ opts.banner = "Usage: 3scale <command> [options]"
13
+
14
+
15
+ opts.on("-h", "--help", "Prints this help") do
16
+ puts opts
17
+ exit
18
+ end
19
+ end
20
+
21
+ begin
22
+ opt_parser.order!(options)
23
+ rescue OptionParser::InvalidOption => e
24
+ p e
25
+ end
26
+
27
+ return args
28
+ end
29
+ end
30
+
31
+ def self.parse(argv = ARGV)
32
+ options = Parser.parse(argv)
33
+ options.command = argv.shift
34
+ options.command = subcommands.find { |subcommand| subcommand.name == options.command }
35
+
36
+ [ options, argv ]
37
+ end
38
+
39
+ def self.print_help!
40
+ Parser.parse %w[--help]
41
+ end
42
+
43
+ def self.plugins
44
+ Gem.loaded_specs.select{ |name, _| name.start_with?('3scale') }.values
45
+ end
46
+
47
+ def self.current_command
48
+ File.expand_path($0, Dir.pwd)
49
+ end
50
+
51
+ def self.subcommands
52
+ plugins
53
+ .flat_map { |spec| spec.executables.flat_map{ |bin| Subcommand.new(bin, spec) } }
54
+ .reject { |subcommand| subcommand.full_path == current_command || subcommand.name.nil? }
55
+ end
56
+
57
+ class Subcommand
58
+ attr_reader :executable, :spec
59
+
60
+ def initialize(executable, spec)
61
+ @executable = executable
62
+ @spec = spec
63
+ end
64
+
65
+ def to_s
66
+ name
67
+ end
68
+
69
+ def name
70
+ executable.split('-', 2)[1]
71
+ end
72
+
73
+ def full_path
74
+ spec.bin_file(executable)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ module ThreeScaleToolbox
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: 3scale_toolbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michal Cichra
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: 3scale-api
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
55
+ description: 3scale CLI tools to manage your API from the terminal.
56
+ email:
57
+ - michal@3scale.net
58
+ executables:
59
+ - 3scale
60
+ - 3scale-copy
61
+ - 3scale-help
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - README.md
66
+ - exe/3scale
67
+ - exe/3scale-copy
68
+ - exe/3scale-help
69
+ - lib/3scale_toolbox.rb
70
+ - lib/3scale_toolbox/cli.rb
71
+ - lib/3scale_toolbox/version.rb
72
+ homepage: https://github.com/3scale/3scale_toolbox
73
+ licenses: []
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 2.5.1
92
+ signing_key:
93
+ specification_version: 4
94
+ summary: 3scale CLI Toolbox.
95
+ test_files: []
96
+ has_rdoc: