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.
- checksums.yaml +4 -4
- data/README.md +155 -5
- data/exe/3scale +3 -9
- data/lib/3scale_toolbox/base_command.rb +28 -0
- data/lib/3scale_toolbox/cli.rb +16 -72
- data/lib/3scale_toolbox/commands/3scale_command.rb +28 -0
- data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +218 -0
- data/lib/3scale_toolbox/commands/copy_command.rb +20 -0
- data/lib/3scale_toolbox/commands/help_command.rb +13 -0
- data/lib/3scale_toolbox/commands/import_command/import_csv.rb +175 -0
- data/lib/3scale_toolbox/commands/import_command.rb +20 -0
- data/lib/3scale_toolbox/commands/update_command/update_service.rb +247 -0
- data/lib/3scale_toolbox/commands/update_command.rb +20 -0
- data/lib/3scale_toolbox/commands.rb +24 -0
- data/lib/3scale_toolbox/version.rb +1 -1
- data/lib/3scale_toolbox.rb +7 -3
- metadata +49 -17
- data/exe/3scale-copy +0 -222
- data/exe/3scale-help +0 -9
- data/exe/3scale-import +0 -178
- data/exe/3scale-update +0 -270
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc76523728a2d5fa59805175676eac19b02a689db6c2b6045d821f8b6d5b8fc3
|
4
|
+
data.tar.gz: 33908dec9c0714102d0899643e40bcc933b90a412b440325ef8476b4427d8596
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff2630a709bb3af2a8e93cc650359f8d3461444a41438aa261415922a02b9ea9f425dbd027f6d8d46652462544d4e388e9b15ef5066f772bd1ae99457794ead5
|
7
|
+
data.tar.gz: 22c140218478ee375e3762e5cb5ffe674e9d1502e7b702d7303341c98d84ad4680ef3887f6608f9ed42cf7bb584a195a099e33d6dfc4196c11201be21b2ca920
|
data/README.md
CHANGED
@@ -2,9 +2,18 @@
|
|
2
2
|
|
3
3
|
3scale toolbox is a set of tools to help you manage your 3scale product. Using the [3scale API Ruby Client](https://github.com/3scale/3scale-api-ruby).
|
4
4
|
|
5
|
-
##
|
6
|
-
|
5
|
+
## Table of contents
|
6
|
+
* [Installation](#installation)
|
7
|
+
* [Usage](#usage)
|
8
|
+
* [Copy a service](#copy-a-service)
|
9
|
+
* [Update a service](#update-a-service)
|
10
|
+
* [Import from CSV](#import-from-csv)
|
11
|
+
* [Development](#development)
|
12
|
+
* [Plugins](#plugins)
|
13
|
+
* [Troubleshooting](#troubleshooting)
|
14
|
+
* [Contributing](#contributing)
|
7
15
|
|
16
|
+
## Installation
|
8
17
|
Install the CLI:
|
9
18
|
|
10
19
|
$ gem install 3scale_toolbox
|
@@ -12,20 +21,150 @@ Install the CLI:
|
|
12
21
|
## Usage
|
13
22
|
|
14
23
|
```shell
|
15
|
-
3scale help
|
24
|
+
$ 3scale help
|
25
|
+
NAME
|
26
|
+
3scale - 3scale CLI Toolbox
|
27
|
+
|
28
|
+
USAGE
|
29
|
+
3scale <command> [options]
|
30
|
+
|
31
|
+
DESCRIPTION
|
32
|
+
3scale CLI tools to manage your API from the terminal.
|
33
|
+
|
34
|
+
COMMANDS
|
35
|
+
copy 3scale copy command
|
36
|
+
help show help
|
37
|
+
import 3scale import command
|
38
|
+
update 3scale update command
|
39
|
+
|
40
|
+
OPTIONS
|
41
|
+
-k --insecure Proceed and operate even for server connections
|
42
|
+
otherwise considered insecure
|
43
|
+
-v --version Prints the version of this command
|
16
44
|
```
|
17
45
|
|
18
46
|
### Copy a service
|
47
|
+
Will create a new services, copy existing proxy settings, metrics, methods, application plans and mapping rules.
|
48
|
+
|
49
|
+
Help message:
|
19
50
|
|
20
|
-
|
51
|
+
```shell
|
52
|
+
$ 3scale copy service --help
|
53
|
+
NAME
|
54
|
+
service - Copy service
|
55
|
+
|
56
|
+
USAGE
|
57
|
+
3scale copy service [opts] -s <src> -d <dst>
|
58
|
+
<service_id>
|
59
|
+
|
60
|
+
DESCRIPTION
|
61
|
+
Will create a new services, copy existing proxy settings, metrics,
|
62
|
+
methods, application plans and mapping rules.
|
63
|
+
|
64
|
+
OPTIONS
|
65
|
+
-d --destination=<value> 3scale target instance. Format:
|
66
|
+
"http[s]://<provider_key>@3scale_url"
|
67
|
+
-s --source=<value> 3scale source instance. Format:
|
68
|
+
"http[s]://<provider_key>@3scale_url"
|
69
|
+
-t --target_system_name=<value> Target system name
|
70
|
+
|
71
|
+
OPTIONS FOR COPY
|
72
|
+
-h --help show help for this command
|
73
|
+
-k --insecure Proceed and operate even for server
|
74
|
+
connections otherwise considered
|
75
|
+
insecure
|
76
|
+
-v --version Prints the version of this command
|
77
|
+
```
|
21
78
|
|
22
79
|
```shell
|
23
80
|
3scale copy service NUMBER --source=https://provider_key@foo-admin.3scale.net --destination=https://provider_key@foo2-admin.3scale.net
|
24
81
|
```
|
25
82
|
|
83
|
+
### Update a service
|
84
|
+
|
85
|
+
Will update existing service, update proxy settings, metrics, methods, application plans and mapping rules.
|
86
|
+
|
87
|
+
Help message:
|
88
|
+
|
89
|
+
```shell
|
90
|
+
NAME
|
91
|
+
service - Update service
|
92
|
+
|
93
|
+
USAGE
|
94
|
+
3scale update service [opts] -s <src> -d <dst>
|
95
|
+
<src_service_id> <dst_service_id>
|
96
|
+
|
97
|
+
DESCRIPTION
|
98
|
+
Will update existing service, update proxy settings, metrics, methods,
|
99
|
+
application plans and mapping rules.
|
100
|
+
|
101
|
+
OPTIONS
|
102
|
+
-d --destination=<value> 3scale target instance. Format:
|
103
|
+
"http[s]://<provider_key>@3scale_url"
|
104
|
+
-f --force Overwrites the mapping rules by deleting
|
105
|
+
all rules from target service first
|
106
|
+
-r --rules-only Updates only the mapping rules
|
107
|
+
-s --source=<value> 3scale source instance. Format:
|
108
|
+
"http[s]://<provider_key>@3scale_url"
|
109
|
+
|
110
|
+
OPTIONS FOR UPDATE
|
111
|
+
-h --help show help for this command
|
112
|
+
-k --insecure Proceed and operate even for server
|
113
|
+
connections otherwise considered insecure
|
114
|
+
-v --version Prints the version of this command
|
115
|
+
```
|
116
|
+
|
117
|
+
Example:
|
118
|
+
|
119
|
+
```shell
|
120
|
+
$ 3scale update service -s https://9874598743@source.example.com -d https://2342342342342@destination.example.com 3 2
|
121
|
+
```
|
122
|
+
|
26
123
|
### Import from CSV
|
27
124
|
|
28
|
-
Will create
|
125
|
+
Will create new services, metrics, methods, and mapping rules having as source comma separated values (CSV) formatted file.
|
126
|
+
|
127
|
+
CSV header
|
128
|
+
|
129
|
+
```csv
|
130
|
+
service_name,endpoint_name,endpoint_http_method,endpoint_path,auth_mode,endpoint_system_name,type
|
131
|
+
```
|
132
|
+
|
133
|
+
File example
|
134
|
+
|
135
|
+
```csv
|
136
|
+
service_name,endpoint_name,endpoint_http_method,endpoint_path,auth_mode,endpoint_system_name,type
|
137
|
+
Movies ,Movies (Biography),GET,/movies/biography/,api_key,movies_biography,metric
|
138
|
+
Movies ,Movies (Drama),GET,/movies/drama/,api_key,movies_drama,method
|
139
|
+
```
|
140
|
+
|
141
|
+
Help message:
|
142
|
+
|
143
|
+
```shell
|
144
|
+
$ 3scale import csv -h
|
145
|
+
NAME
|
146
|
+
csv - Import csv file
|
147
|
+
|
148
|
+
USAGE
|
149
|
+
3scale import csv [opts] -d <dst> -f <file>
|
150
|
+
|
151
|
+
DESCRIPTION
|
152
|
+
Create new services, metrics, methods and mapping rules from CSV
|
153
|
+
formatted file
|
154
|
+
|
155
|
+
OPTIONS
|
156
|
+
-d --destination=<value> 3scale target instance. Format:
|
157
|
+
"http[s]://<provider_key>@3scale_url"
|
158
|
+
-f --file=<value> CSV formatted file
|
159
|
+
|
160
|
+
OPTIONS FOR IMPORT
|
161
|
+
-h --help show help for this command
|
162
|
+
-k --insecure Proceed and operate even for server
|
163
|
+
connections otherwise considered insecure
|
164
|
+
-v --version Prints the version of this command
|
165
|
+
```
|
166
|
+
|
167
|
+
Example:
|
29
168
|
|
30
169
|
```shell
|
31
170
|
3scale import csv --destination=https://provider_key@user-admin.3scale.net --file=examples/import_example.csv
|
@@ -37,6 +176,17 @@ After checking out the repo, run `bin/setup` to install dependencies. You can al
|
|
37
176
|
|
38
177
|
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).
|
39
178
|
|
179
|
+
## Plugins
|
180
|
+
|
181
|
+
As of 3scale Toolbox 0.5.0, 3scale Toolbox will load plugins installed in gems or $LOAD_PATH. Plugins are discovered via Gem::find_files then loaded.
|
182
|
+
Install, uninstall and update plugins using tools like [RubyGems](https://guides.rubygems.org/rubygems-basics/) and/or [Bundler](https://bundler.io/).
|
183
|
+
|
184
|
+
[Make your own plugin](docs/plugins.md)
|
185
|
+
|
186
|
+
## Troubleshooting
|
187
|
+
|
188
|
+
* [SSL errors](docs/ssl_errors.md): If you run into SSL issues with the toolbox, you can take actions to resolve them.
|
189
|
+
|
40
190
|
## Contributing
|
41
191
|
|
42
192
|
Bug reports and pull requests are welcome on GitHub at https://github.com/3scale/3scale_toolbox.
|
data/exe/3scale
CHANGED
@@ -1,14 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require '3scale_toolbox'
|
3
4
|
require '3scale_toolbox/cli'
|
4
5
|
|
5
|
-
|
6
|
+
args = ARGV.clone
|
6
7
|
|
7
|
-
|
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
|
8
|
+
ThreeScaleToolbox::CLI.run args
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module ThreeScaleToolbox
|
3
|
+
module Command
|
4
|
+
def subcommands
|
5
|
+
@subcommands ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_subcommand(command)
|
9
|
+
subcommands << command
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Override to command
|
14
|
+
#
|
15
|
+
def command
|
16
|
+
raise Exception, 'base command has no command definition'
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Iterate recursively over command tree
|
21
|
+
#
|
22
|
+
def build_command
|
23
|
+
subcommands.each_with_object(command) do |subcommand, root_command|
|
24
|
+
root_command.add_command(subcommand.build_command)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/3scale_toolbox/cli.rb
CHANGED
@@ -1,78 +1,22 @@
|
|
1
|
-
require '
|
1
|
+
require '3scale_toolbox'
|
2
|
+
require '3scale_toolbox/commands'
|
2
3
|
|
3
|
-
module ThreeScaleToolbox
|
4
|
-
|
5
|
-
|
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
|
4
|
+
module ThreeScaleToolbox::CLI
|
5
|
+
def self.root_command
|
6
|
+
ThreeScaleToolbox::Commands::ThreeScaleCommand
|
7
|
+
end
|
64
8
|
|
65
|
-
|
66
|
-
|
67
|
-
|
9
|
+
def self.add_command(command)
|
10
|
+
root_command.add_subcommand(command)
|
11
|
+
end
|
68
12
|
|
69
|
-
|
70
|
-
|
71
|
-
|
13
|
+
def self.load_builtin_commands
|
14
|
+
ThreeScaleToolbox::Commands::BUILTIN_COMMANDS.each(&method(:add_command))
|
15
|
+
end
|
72
16
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
17
|
+
def self.run(args)
|
18
|
+
load_builtin_commands
|
19
|
+
ThreeScaleToolbox.load_plugins
|
20
|
+
root_command.build_command.run args
|
77
21
|
end
|
78
22
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cri'
|
2
|
+
require '3scale_toolbox/version'
|
3
|
+
require '3scale_toolbox/base_command'
|
4
|
+
|
5
|
+
module ThreeScaleToolbox
|
6
|
+
module Commands
|
7
|
+
module ThreeScaleCommand
|
8
|
+
extend ThreeScaleToolbox::Command
|
9
|
+
def self.command
|
10
|
+
Cri::Command.define do
|
11
|
+
name '3scale'
|
12
|
+
usage '3scale <command> [options]'
|
13
|
+
summary '3scale CLI Toolbox'
|
14
|
+
description '3scale CLI tools to manage your API from the terminal.'
|
15
|
+
flag :v, :version, 'Prints the version of this command' do |_, _|
|
16
|
+
puts ThreeScaleToolbox::VERSION
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
flag :k, :insecure, 'Proceed and operate even for server connections otherwise considered insecure'
|
20
|
+
flag :h, :help, 'show help for this command' do |_, cmd|
|
21
|
+
puts cmd.help
|
22
|
+
exit 0
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'cri'
|
2
|
+
require '3scale_toolbox/base_command'
|
3
|
+
|
4
|
+
module ThreeScaleToolbox
|
5
|
+
module Commands
|
6
|
+
module CopyCommand
|
7
|
+
module CopyServiceSubcommand
|
8
|
+
extend ThreeScaleToolbox::Command
|
9
|
+
def self.command
|
10
|
+
Cri::Command.define do
|
11
|
+
name 'service'
|
12
|
+
usage 'service [opts] -s <src> -d <dst> <service_id>'
|
13
|
+
summary 'Copy service'
|
14
|
+
description 'Will create a new services, copy existing proxy settings, metrics, methods, application plans and mapping rules.'
|
15
|
+
|
16
|
+
required :s, :source, '3scale source instance. Format: "http[s]://<provider_key>@3scale_url"'
|
17
|
+
required :d, :destination, '3scale target instance. Format: "http[s]://<provider_key>@3scale_url"'
|
18
|
+
required :t, 'target_system_name', 'Target system name'
|
19
|
+
|
20
|
+
run do |opts, args, _|
|
21
|
+
CopyServiceSubcommand.run opts, args
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.run(opts, args)
|
27
|
+
source = fetch_required_option(opts, :source)
|
28
|
+
destination = fetch_required_option(opts, :destination)
|
29
|
+
system_name = fetch_required_option(opts, :target_system_name)
|
30
|
+
insecure = opts[:insecure] || false
|
31
|
+
exit_with_message 'error: missing service_id argument' if args.empty?
|
32
|
+
service_id = args[0]
|
33
|
+
copy_service(service_id, source, destination, system_name, insecure)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.exit_with_message(message)
|
37
|
+
puts message
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.fetch_required_option(options, key)
|
42
|
+
options.fetch(key) { exit_with_message "error: Missing argument #{key}" }
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.compare_hashes(first, second, keys)
|
46
|
+
keys.map{ |key| first.fetch(key) } == keys.map{ |key| second.fetch(key) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.provider_key_from_url(url)
|
50
|
+
url[/\w*@/][0..-2]
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.endpoint_from_url(url)
|
54
|
+
url.sub /\w*@/, ''
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Returns new hash object with not nil valid params
|
59
|
+
def self.filter_params(valid_params, source)
|
60
|
+
valid_params.each_with_object({}) do |key, target|
|
61
|
+
target[key] = source[key] unless source[key].nil?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.copy_service_params(original, system_name)
|
66
|
+
service_params = filter_params(Commands.service_valid_params, original)
|
67
|
+
service_params.tap do |hash|
|
68
|
+
hash['system_name'] = system_name if system_name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.copy_service(service_id, source, destination, system_name, insecure)
|
73
|
+
require '3scale/api'
|
74
|
+
|
75
|
+
source_client = ThreeScale::API.new(
|
76
|
+
endpoint: endpoint_from_url(source),
|
77
|
+
provider_key: provider_key_from_url(source),
|
78
|
+
verify_ssl: !insecure
|
79
|
+
)
|
80
|
+
client = ThreeScale::API.new(
|
81
|
+
endpoint: endpoint_from_url(destination),
|
82
|
+
provider_key: provider_key_from_url(destination),
|
83
|
+
verify_ssl: !insecure
|
84
|
+
)
|
85
|
+
|
86
|
+
service = source_client.show_service(service_id)
|
87
|
+
copy = client.create_service(copy_service_params(service, system_name))
|
88
|
+
|
89
|
+
raise "Service has not been saved. Errors: #{copy['errors']}" unless copy['errors'].nil?
|
90
|
+
|
91
|
+
service_copy_id = copy.fetch('id')
|
92
|
+
|
93
|
+
puts "new service id #{service_copy_id}"
|
94
|
+
|
95
|
+
proxy = source_client.show_proxy(service_id)
|
96
|
+
client.update_proxy(service_copy_id, proxy)
|
97
|
+
puts "updated proxy of #{service_copy_id} to match the original"
|
98
|
+
|
99
|
+
metrics = source_client.list_metrics(service_id)
|
100
|
+
metrics_copies = client.list_metrics(service_copy_id)
|
101
|
+
|
102
|
+
hits = metrics.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
|
103
|
+
hits_copy = metrics_copies.find{ |metric| metric['system_name'] == 'hits' } or raise 'missing hits metric'
|
104
|
+
|
105
|
+
methods = source_client.list_methods(service_id, hits['id'])
|
106
|
+
methods_copies = client.list_methods(service_copy_id, hits_copy['id'])
|
107
|
+
|
108
|
+
puts "original service hits metric #{hits['id']} has #{methods.size} methods"
|
109
|
+
puts "copied service hits metric #{hits_copy['id']} has #{methods_copies.size} methods"
|
110
|
+
|
111
|
+
missing_methods = methods.reject { |method| methods_copies.find{|copy| compare_hashes(method, copy, ['system_name']) } }
|
112
|
+
|
113
|
+
puts "creating #{missing_methods.size} missing methods on copied service"
|
114
|
+
|
115
|
+
missing_methods.each do |method|
|
116
|
+
copy = { friendly_name: method['friendly_name'], system_name: method['system_name'] }
|
117
|
+
client.create_method(service_copy_id, hits_copy['id'], copy)
|
118
|
+
end
|
119
|
+
|
120
|
+
metrics_copies = client.list_metrics(service_copy_id)
|
121
|
+
|
122
|
+
puts "original service has #{metrics.size} metrics"
|
123
|
+
puts "copied service has #{metrics_copies.size} metrics"
|
124
|
+
|
125
|
+
missing_metrics = metrics.reject { |metric| metrics_copies.find{|copy| compare_hashes(metric, copy, ['system_name']) } }
|
126
|
+
|
127
|
+
missing_metrics.map do |metric|
|
128
|
+
metric.delete('links')
|
129
|
+
client.create_metric(service_copy_id, metric)
|
130
|
+
end
|
131
|
+
|
132
|
+
puts "created #{missing_metrics.size} metrics on the copied service"
|
133
|
+
|
134
|
+
plans = source_client.list_service_application_plans(service_id)
|
135
|
+
plan_copies = client.list_service_application_plans(service_copy_id)
|
136
|
+
|
137
|
+
puts "original service has #{plans.size} application plans "
|
138
|
+
puts "copied service has #{plan_copies.size} application plans"
|
139
|
+
|
140
|
+
missing_application_plans = plans.reject { |plan| plan_copies.find{|copy| plan.fetch('system_name') == copy.fetch('system_name') } }
|
141
|
+
|
142
|
+
puts "copied service missing #{missing_application_plans.size} application plans"
|
143
|
+
|
144
|
+
missing_application_plans.each do |plan|
|
145
|
+
plan.delete('links')
|
146
|
+
plan.delete('default') # TODO: handle default plan
|
147
|
+
|
148
|
+
if plan.delete('custom') # TODO: what to do with custom plans?
|
149
|
+
puts "skipping custom plan #{plan}"
|
150
|
+
else
|
151
|
+
client.create_application_plan(service_copy_id, plan)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
application_plan_mapping = client.list_service_application_plans(service_copy_id).map do |plan_copy|
|
156
|
+
plan = plans.find{|plan| plan.fetch('system_name') == plan_copy.fetch('system_name') }
|
157
|
+
|
158
|
+
[plan['id'], plan_copy['id']]
|
159
|
+
end
|
160
|
+
|
161
|
+
metrics_mapping = client.list_metrics(service_copy_id).map do |copy|
|
162
|
+
metric = metrics.find{|metric| metric.fetch('system_name') == copy.fetch('system_name') }
|
163
|
+
metric ||= {}
|
164
|
+
|
165
|
+
[metric['id'], copy['id']]
|
166
|
+
end.to_h
|
167
|
+
|
168
|
+
puts "destroying all mapping rules of the copy which have been created by default"
|
169
|
+
client.list_mapping_rules(service_copy_id).each do |mapping_rule|
|
170
|
+
client.delete_mapping_rule(service_copy_id, mapping_rule['id'])
|
171
|
+
end
|
172
|
+
|
173
|
+
mapping_rules = source_client.list_mapping_rules(service_id)
|
174
|
+
mapping_rules_copy = client.list_mapping_rules(service_copy_id)
|
175
|
+
|
176
|
+
puts "the original service has #{mapping_rules.size} mapping rules"
|
177
|
+
puts "the copy has #{mapping_rules_copy.size} mapping rules"
|
178
|
+
|
179
|
+
unique_mapping_rules_copy = mapping_rules_copy.dup
|
180
|
+
|
181
|
+
missing_mapping_rules = mapping_rules.reject do |mapping_rule|
|
182
|
+
matching_metric = unique_mapping_rules_copy.find do |copy|
|
183
|
+
compare_hashes(mapping_rule, copy, %w(pattern http_method delta)) &&
|
184
|
+
metrics_mapping.fetch(mapping_rule.fetch('metric_id')) == copy.fetch('metric_id')
|
185
|
+
end
|
186
|
+
|
187
|
+
unique_mapping_rules_copy.delete(matching_metric)
|
188
|
+
end
|
189
|
+
|
190
|
+
puts "missing #{missing_mapping_rules.size} mapping rules"
|
191
|
+
|
192
|
+
missing_mapping_rules.each do |mapping_rule|
|
193
|
+
mapping_rule.delete('links')
|
194
|
+
mapping_rule['metric_id'] = metrics_mapping.fetch(mapping_rule.delete('metric_id'))
|
195
|
+
client.create_mapping_rule(service_copy_id, mapping_rule)
|
196
|
+
end
|
197
|
+
puts "created #{missing_mapping_rules.size} mapping rules"
|
198
|
+
|
199
|
+
puts "extra #{unique_mapping_rules_copy.size} mapping rules"
|
200
|
+
puts unique_mapping_rules_copy.each{|rule| rule.delete('links') }
|
201
|
+
|
202
|
+
application_plan_mapping.each do |original_id, copy_id|
|
203
|
+
limits = source_client.list_application_plan_limits(original_id)
|
204
|
+
limits_copy = client.list_application_plan_limits(copy_id)
|
205
|
+
|
206
|
+
missing_limits = limits.reject { |limit| limits_copy.find{|limit_copy| limit.fetch('period') == limit_copy.fetch('period') } }
|
207
|
+
|
208
|
+
missing_limits.each do |limit|
|
209
|
+
limit.delete('links')
|
210
|
+
client.create_application_plan_limit(copy_id, metrics_mapping.fetch(limit.fetch('metric_id')), limit)
|
211
|
+
end
|
212
|
+
puts "copied application plan #{copy_id} is missing #{missing_limits.size} from the original plan #{original_id}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|