3scale_toolbox 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|