skull_island 1.2.0 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +2 -2
- data/Gemfile.lock +24 -28
- data/README.md +14 -1
- data/lib/skull_island.rb +1 -0
- data/lib/skull_island/api_client_base.rb +6 -0
- data/lib/skull_island/cli.rb +28 -13
- data/lib/skull_island/helpers/meta.rb +72 -0
- data/lib/skull_island/helpers/resource.rb +11 -6
- data/lib/skull_island/resource.rb +19 -0
- data/lib/skull_island/resources/basicauth_credential.rb +11 -2
- data/lib/skull_island/resources/certificate.rb +18 -5
- data/lib/skull_island/resources/consumer.rb +37 -10
- data/lib/skull_island/resources/jwt_credential.rb +12 -3
- data/lib/skull_island/resources/keyauth_credential.rb +1 -1
- data/lib/skull_island/resources/plugin.rb +16 -3
- data/lib/skull_island/resources/route.rb +12 -3
- data/lib/skull_island/resources/service.rb +19 -5
- data/lib/skull_island/resources/upstream.rb +15 -4
- data/lib/skull_island/resources/upstream_target.rb +18 -17
- data/lib/skull_island/validations/resource.rb +1 -1
- data/lib/skull_island/version.rb +1 -1
- data/skull_island.gemspec +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 782471de2e1ce1e974ac22f0420d33ce0903f909b4286094537c7169caa872f5
|
4
|
+
data.tar.gz: 7edb2bcdb5094f27932c2a3e13f6865e969ba6f43e78f34d6a26c7416cb01bc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a83f0d13f17f858332882836b22be450c9974283c9e1a8fe0db20b007f13b080a73d4c9fe43bc3516a2a2a5768821f1a4b7494bf9262874774a63c9feb78068
|
7
|
+
data.tar.gz: 7dc758ebad1c39cbaa8b64789ac0ff7db061349cd0a086a2d50cfedf2cf822e6d8745d92a1a976d63f7398b810f7ca634bf46b7f2408709c33b8cbf2a18131d0
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -8,7 +8,7 @@ Metrics/LineLength:
|
|
8
8
|
Max: 100
|
9
9
|
|
10
10
|
Metrics/ClassLength:
|
11
|
-
Max:
|
11
|
+
Max: 190
|
12
12
|
|
13
13
|
Metrics/ModuleLength:
|
14
14
|
Max: 175
|
@@ -23,7 +23,7 @@ Metrics/PerceivedComplexity:
|
|
23
23
|
- 'lib/skull_island/cli.rb'
|
24
24
|
|
25
25
|
Metrics/AbcSize:
|
26
|
-
Max:
|
26
|
+
Max: 28
|
27
27
|
|
28
28
|
Metrics/BlockLength:
|
29
29
|
Max: 35
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
skull_island (1.2.
|
4
|
+
skull_island (1.2.2)
|
5
5
|
deepsort (~> 0.4)
|
6
6
|
erubi (~> 1.8)
|
7
7
|
json (~> 2.1)
|
@@ -15,11 +15,11 @@ GEM
|
|
15
15
|
specs:
|
16
16
|
addressable (2.4.0)
|
17
17
|
ast (2.4.0)
|
18
|
-
backports (3.
|
19
|
-
deepsort (0.4.
|
18
|
+
backports (3.15.0)
|
19
|
+
deepsort (0.4.2)
|
20
20
|
diff-lcs (1.3)
|
21
|
-
docile (1.3.
|
22
|
-
domain_name (0.5.
|
21
|
+
docile (1.3.2)
|
22
|
+
domain_name (0.5.20190701)
|
23
23
|
unf (>= 0.0.5, < 1.0.0)
|
24
24
|
erubi (1.8.0)
|
25
25
|
ethon (0.12.0)
|
@@ -28,7 +28,7 @@ GEM
|
|
28
28
|
multipart-post (>= 1.2, < 3)
|
29
29
|
faraday_middleware (0.13.1)
|
30
30
|
faraday (>= 0.7.4, < 1.0)
|
31
|
-
ffi (1.
|
31
|
+
ffi (1.11.1)
|
32
32
|
gh (0.15.1)
|
33
33
|
addressable (~> 2.4.0)
|
34
34
|
backports
|
@@ -39,7 +39,7 @@ GEM
|
|
39
39
|
highline (1.7.10)
|
40
40
|
http-cookie (1.0.3)
|
41
41
|
domain_name (~> 0.5)
|
42
|
-
jaro_winkler (1.5.
|
42
|
+
jaro_winkler (1.5.3)
|
43
43
|
json (2.2.0)
|
44
44
|
launchy (2.4.3)
|
45
45
|
addressable (~> 2.3)
|
@@ -50,15 +50,13 @@ GEM
|
|
50
50
|
mime-types-data (~> 3.2015)
|
51
51
|
mime-types-data (3.2019.0331)
|
52
52
|
multi_json (1.13.1)
|
53
|
-
multipart-post (2.
|
53
|
+
multipart-post (2.1.1)
|
54
54
|
net-http-persistent (2.9.4)
|
55
55
|
net-http-pipeline (1.0.1)
|
56
56
|
netrc (0.11.0)
|
57
|
-
parallel (1.
|
58
|
-
parser (2.6.
|
57
|
+
parallel (1.17.0)
|
58
|
+
parser (2.6.3.0)
|
59
59
|
ast (~> 2.4.0)
|
60
|
-
powerpack (0.1.2)
|
61
|
-
psych (3.1.0)
|
62
60
|
pusher-client (0.6.2)
|
63
61
|
json
|
64
62
|
websocket (~> 1.0)
|
@@ -72,32 +70,30 @@ GEM
|
|
72
70
|
rspec-core (~> 3.8.0)
|
73
71
|
rspec-expectations (~> 3.8.0)
|
74
72
|
rspec-mocks (~> 3.8.0)
|
75
|
-
rspec-core (3.8.
|
73
|
+
rspec-core (3.8.2)
|
76
74
|
rspec-support (~> 3.8.0)
|
77
|
-
rspec-expectations (3.8.
|
75
|
+
rspec-expectations (3.8.4)
|
78
76
|
diff-lcs (>= 1.2.0, < 2.0)
|
79
77
|
rspec-support (~> 3.8.0)
|
80
|
-
rspec-mocks (3.8.
|
78
|
+
rspec-mocks (3.8.1)
|
81
79
|
diff-lcs (>= 1.2.0, < 2.0)
|
82
80
|
rspec-support (~> 3.8.0)
|
83
|
-
rspec-support (3.8.
|
84
|
-
rubocop (0.
|
81
|
+
rspec-support (3.8.2)
|
82
|
+
rubocop (0.74.0)
|
85
83
|
jaro_winkler (~> 1.5.1)
|
86
84
|
parallel (~> 1.10)
|
87
|
-
parser (>= 2.
|
88
|
-
powerpack (~> 0.1)
|
89
|
-
psych (>= 3.1.0)
|
85
|
+
parser (>= 2.6)
|
90
86
|
rainbow (>= 2.2.2, < 4.0)
|
91
87
|
ruby-progressbar (~> 1.7)
|
92
|
-
unicode-display_width (
|
93
|
-
ruby-progressbar (1.10.
|
94
|
-
simplecov (0.
|
88
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
89
|
+
ruby-progressbar (1.10.1)
|
90
|
+
simplecov (0.17.0)
|
95
91
|
docile (~> 1.1)
|
96
92
|
json (>= 1.8, < 3)
|
97
93
|
simplecov-html (~> 0.10.0)
|
98
94
|
simplecov-html (0.10.2)
|
99
95
|
thor (0.20.3)
|
100
|
-
travis (1.8.
|
96
|
+
travis (1.8.10)
|
101
97
|
backports
|
102
98
|
faraday (~> 0.9)
|
103
99
|
faraday_middleware (~> 0.9, >= 0.9.1)
|
@@ -110,11 +106,11 @@ GEM
|
|
110
106
|
ethon (>= 0.8.0)
|
111
107
|
unf (0.1.4)
|
112
108
|
unf_ext
|
113
|
-
unf_ext (0.0.7.
|
114
|
-
unicode-display_width (1.
|
109
|
+
unf_ext (0.0.7.6)
|
110
|
+
unicode-display_width (1.6.0)
|
115
111
|
websocket (1.2.8)
|
116
112
|
will_paginate (3.1.7)
|
117
|
-
yard (0.9.
|
113
|
+
yard (0.9.20)
|
118
114
|
|
119
115
|
PLATFORMS
|
120
116
|
ruby
|
@@ -127,7 +123,7 @@ DEPENDENCIES
|
|
127
123
|
simplecov (~> 0.15)
|
128
124
|
skull_island!
|
129
125
|
travis (~> 1.8)
|
130
|
-
yard (~> 0.9)
|
126
|
+
yard (~> 0.9.20)
|
131
127
|
|
132
128
|
BUNDLED WITH
|
133
129
|
2.0.1
|
data/README.md
CHANGED
@@ -81,6 +81,8 @@ KONG_ADMIN_URL='https://api-admin.mydomain.com' \
|
|
81
81
|
skull_island export --verbose /path/to/export.yml
|
82
82
|
```
|
83
83
|
|
84
|
+
Exporting, by default, exports the entire configuration of a Kong gateway, but will strip out special meta-data tags added by Skull Island to track projects. If, instead, you'd like to export **only** the configuration for a specific project, you can add `--project foo` (where `foo` is the name of your project) to export only those resources associated with it and maintain the special key in the exported YAML.
|
85
|
+
|
84
86
|
### Importing
|
85
87
|
|
86
88
|
Skull Island also supports importing configurations (both partial and full) from a YAML + ERB document:
|
@@ -112,6 +114,16 @@ KONG_ADMIN_URL='https://api-admin.mydomain.com' \
|
|
112
114
|
skull_island import --verbose --test /path/to/export.yml
|
113
115
|
```
|
114
116
|
|
117
|
+
Note that `--test` has a high likelihood of generating errors with a complicated import if required/dependent resources do not exist.
|
118
|
+
|
119
|
+
#### Importing with Projects
|
120
|
+
|
121
|
+
Skull Island 1.2.1 introduces the ability to use a special top-level key in the configuration called `project` that uses meta-data to track which resources belong to a project. This meta-data can safely be added at another time as this tool will "adopt" otherwise matching resources into a project.
|
122
|
+
|
123
|
+
To use this functionality, either add the `project` key to your configuration file (usually directly below the `version` key) with some value that will be unique on your gateway, or use `--project foo` (where `foo` is the name of your project) as a CLI flag.
|
124
|
+
|
125
|
+
When using the `project` feature of Skull Island, the CLI tool will automatically clean up old resources no longer found in your config file. This is, in fact, the _only_ circumstance under which this tool actually removes resources. Use this feature with care, as it can delete large swaths of your configuration if used incorrectly. It is **critical** that this value is unique since this project functionality is used to delete resources.
|
126
|
+
|
115
127
|
### Migrating
|
116
128
|
|
117
129
|
With Skull Island, it is possible to migrate a configuration from a 0.14.x gateway to one compatible with a 1.2.x gateway. If you have a previous export, you can just run `skull_island migrate /path/to/export.yml` and you'll receive a 1.2 compatible config on standard out. If you'd prefer, you can have that config written to a file as well (just like the export command) like so:
|
@@ -133,6 +145,7 @@ The import/export/migrate CLI functions produce YAML with support for embedded R
|
|
133
145
|
```yaml
|
134
146
|
---
|
135
147
|
version: '1.2'
|
148
|
+
project: FooV2
|
136
149
|
certificates: []
|
137
150
|
consumers:
|
138
151
|
- username: foo
|
@@ -190,7 +203,7 @@ plugins:
|
|
190
203
|
service: "<%= lookup :service, 'search_api' %>"
|
191
204
|
```
|
192
205
|
|
193
|
-
All top-level keys (other than `version`) require an Array as a parameter, either by providing a list of entries or an empty Array (`[]`). The above shows how to use the `lookup()` function to refer to another resource. This "looks up" the resource type (`service` in this case) by `name` (`search_api` in this case) and resolves its `id`. This function can also be used to lookup a `route` or `upstream` by its `name`, or a `consumer` by its `username`. Note that Kong itself doesn't _require_ `route` resources to have unique names, so you'll need to enforce that practice yourself for `lookup` to be useful for Routes.
|
206
|
+
All top-level keys (other than `version` and `project`) require an Array as a parameter, either by providing a list of entries or an empty Array (`[]`). The above shows how to use the `lookup()` function to refer to another resource. This "looks up" the resource type (`service` in this case) by `name` (`search_api` in this case) and resolves its `id`. This function can also be used to lookup a `route` or `upstream` by its `name`, or a `consumer` by its `username`. Note that Kong itself doesn't _require_ `route` resources to have unique names, so you'll need to enforce that practice yourself for `lookup` to be useful for Routes.
|
194
207
|
|
195
208
|
While technically _any_ Ruby is valid, the following are pretty helpful for templating your YAML files:
|
196
209
|
|
data/lib/skull_island.rb
CHANGED
@@ -39,6 +39,7 @@ require 'skull_island/api_client_base'
|
|
39
39
|
require 'skull_island/api_client'
|
40
40
|
require 'skull_island/simple_api_client'
|
41
41
|
require 'skull_island/resource_collection'
|
42
|
+
require 'skull_island/helpers/meta'
|
42
43
|
require 'skull_island/helpers/resource'
|
43
44
|
require 'skull_island/helpers/resource_class'
|
44
45
|
require 'skull_island/helpers/migration'
|
data/lib/skull_island/cli.rb
CHANGED
@@ -15,9 +15,10 @@ module SkullIsland
|
|
15
15
|
class_option :verbose, type: :boolean
|
16
16
|
|
17
17
|
desc 'export [OPTIONS] [OUTPUT|-]', 'Export the current configuration to OUTPUT'
|
18
|
+
option :project, desc: 'Project identifier for metadata'
|
18
19
|
def export(output_file = '-')
|
19
20
|
if output_file == '-'
|
20
|
-
|
21
|
+
warn '[INFO] Outputting to STDOUT' if options['verbose']
|
21
22
|
else
|
22
23
|
full_filename = File.expand_path(output_file)
|
23
24
|
dirname = File.dirname(full_filename)
|
@@ -29,6 +30,7 @@ module SkullIsland
|
|
29
30
|
validate_server_version
|
30
31
|
|
31
32
|
output = { 'version' => '1.2' }
|
33
|
+
output['project'] = options['project'] if options['project']
|
32
34
|
|
33
35
|
[
|
34
36
|
Resources::Certificate,
|
@@ -46,6 +48,7 @@ module SkullIsland
|
|
46
48
|
end
|
47
49
|
|
48
50
|
desc 'import [OPTIONS] [INPUT|-]', 'Import a configuration from INPUT'
|
51
|
+
option :project, desc: 'Project identifier for metadata'
|
49
52
|
option :test, type: :boolean, desc: "Don't do anything, just show what would happen"
|
50
53
|
def import(input_file = '-')
|
51
54
|
raw ||= acquire_input(input_file, options['verbose'])
|
@@ -56,19 +59,23 @@ module SkullIsland
|
|
56
59
|
|
57
60
|
validate_config_version input['version']
|
58
61
|
|
62
|
+
import_time = Time.now.utc.to_i
|
63
|
+
input['project'] = options['project'] if options['project']
|
64
|
+
|
59
65
|
[
|
60
66
|
Resources::Certificate,
|
61
67
|
Resources::Consumer,
|
62
68
|
Resources::Upstream,
|
63
69
|
Resources::Service,
|
64
70
|
Resources::Plugin
|
65
|
-
].each { |clname| import_class(clname, input) }
|
71
|
+
].each { |clname| import_class(clname, input, import_time) }
|
66
72
|
end
|
67
73
|
|
68
74
|
desc(
|
69
75
|
'migrate [OPTIONS] [INPUT|-] [OUTPUT|-]',
|
70
76
|
'Migrate an older config from INPUT to OUTPUT'
|
71
77
|
)
|
78
|
+
option :project, desc: 'Project identifier for metadata'
|
72
79
|
def migrate(input_file = '-', output_file = '-')
|
73
80
|
raw ||= acquire_input(input_file, options['verbose'])
|
74
81
|
|
@@ -79,9 +86,10 @@ module SkullIsland
|
|
79
86
|
validate_migrate_version input['version']
|
80
87
|
|
81
88
|
output = migrate_config(input)
|
89
|
+
output['project'] = options['project'] if options['project']
|
82
90
|
|
83
91
|
if output_file == '-'
|
84
|
-
|
92
|
+
warn '[INFO] Outputting to STDOUT' if options['verbose']
|
85
93
|
STDOUT.puts output.to_yaml
|
86
94
|
else
|
87
95
|
full_filename = File.expand_path(output_file)
|
@@ -97,23 +105,30 @@ module SkullIsland
|
|
97
105
|
private
|
98
106
|
|
99
107
|
def export_class(class_name, output_data)
|
100
|
-
|
101
|
-
output_data[class_name.route_key] =
|
108
|
+
warn "[INFO] Processing #{class_name.route_key}" if options['verbose']
|
109
|
+
output_data[class_name.route_key] = if options['project']
|
110
|
+
class_name.where(:project, options['project'])
|
111
|
+
.collect(&:export)
|
112
|
+
else
|
113
|
+
class_name.all.collect(&:export)
|
114
|
+
end
|
102
115
|
end
|
103
116
|
|
104
|
-
def import_class(class_name, import_data)
|
105
|
-
|
117
|
+
def import_class(class_name, import_data, import_time)
|
118
|
+
warn "[INFO] Processing #{class_name.route_key}" if options['verbose']
|
106
119
|
class_name.batch_import(
|
107
120
|
import_data[class_name.route_key],
|
108
121
|
verbose: options['verbose'],
|
109
|
-
test: options['test']
|
122
|
+
test: options['test'],
|
123
|
+
time: import_time,
|
124
|
+
project: import_data['project']
|
110
125
|
)
|
111
126
|
end
|
112
127
|
|
113
128
|
# Used to pull input from either STDIN or the specified file
|
114
129
|
def acquire_input(input_file, verbose = false)
|
115
130
|
if input_file == '-'
|
116
|
-
|
131
|
+
warn '[INFO] Reading from STDIN' if verbose
|
117
132
|
STDIN.read
|
118
133
|
else
|
119
134
|
full_filename = File.expand_path(input_file)
|
@@ -133,10 +148,10 @@ module SkullIsland
|
|
133
148
|
if version && ['1.1', '1.2'].include?(version)
|
134
149
|
validate_server_version
|
135
150
|
elsif version && ['0.14', '1.0'].include?(version)
|
136
|
-
|
151
|
+
warn '[CRITICAL] Config version is too old. Try `migrate` instead of `import`.'
|
137
152
|
exit 2
|
138
153
|
else
|
139
|
-
|
154
|
+
warn '[CRITICAL] Config version is unknown or not supported.'
|
140
155
|
exit 3
|
141
156
|
end
|
142
157
|
end
|
@@ -145,7 +160,7 @@ module SkullIsland
|
|
145
160
|
if version && version == '0.14'
|
146
161
|
true
|
147
162
|
else
|
148
|
-
|
163
|
+
warn '[CRITICAL] Config version must be 0.14 for migration.'
|
149
164
|
exit 4
|
150
165
|
end
|
151
166
|
end
|
@@ -155,7 +170,7 @@ module SkullIsland
|
|
155
170
|
if server_version.match?(/^1.[12]/)
|
156
171
|
true
|
157
172
|
else
|
158
|
-
|
173
|
+
warn '[CRITICAL] Server version mismatch!'
|
159
174
|
exit 1
|
160
175
|
end
|
161
176
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SkullIsland
|
4
|
+
module Helpers
|
5
|
+
# Useful for embedding meta-data into special tags
|
6
|
+
module Meta
|
7
|
+
def add_meta(key, value)
|
8
|
+
metatag = "_meta~#{key}~#{value}"
|
9
|
+
|
10
|
+
# filter out any existing duplicate metatags
|
11
|
+
existing_tags = raw_tags.reject { |tag| tag.start_with?("_meta~#{key}~") }
|
12
|
+
|
13
|
+
# Add the new tag directly, bypassing preprocessing
|
14
|
+
raw_set('tags', existing_tags + [metatag])
|
15
|
+
end
|
16
|
+
|
17
|
+
def import_time
|
18
|
+
metatags['import_time']
|
19
|
+
end
|
20
|
+
|
21
|
+
def import_time=(time)
|
22
|
+
add_meta('import_time', time)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_meta(key)
|
26
|
+
# filter out an existing metatags
|
27
|
+
filtered_tags = raw_tags.reject { |tag| tag.start_with?("_meta~#{key}~") }
|
28
|
+
|
29
|
+
# Bypassing preprocessing
|
30
|
+
raw_set('tags', filtered_tags)
|
31
|
+
end
|
32
|
+
|
33
|
+
def metatags
|
34
|
+
metadata = {}
|
35
|
+
raw_tags.select { |tag| tag.start_with?('_meta~') }.each do |tag|
|
36
|
+
key, value = tag.gsub('_meta~', '').split('~', 2)
|
37
|
+
metadata[key] = value
|
38
|
+
end
|
39
|
+
metadata
|
40
|
+
end
|
41
|
+
|
42
|
+
def project
|
43
|
+
metatags['project']
|
44
|
+
end
|
45
|
+
|
46
|
+
def project=(project_id)
|
47
|
+
unless project_id.is_a?(String) && project_id.match?(/^[\w_\-\.~]+$/)
|
48
|
+
raise Exceptions::InvalidArguments, 'project'
|
49
|
+
end
|
50
|
+
|
51
|
+
add_meta('project', project_id)
|
52
|
+
end
|
53
|
+
|
54
|
+
def raw_tags
|
55
|
+
reload if @lazy && !@entity.key?('tags')
|
56
|
+
@entity['tags'] || []
|
57
|
+
end
|
58
|
+
|
59
|
+
def preprocess_tags(input)
|
60
|
+
input.uniq + metatags.map { |k, v| "_meta~#{k}~#{v}" }
|
61
|
+
end
|
62
|
+
|
63
|
+
def postprocess_tags(value)
|
64
|
+
(value || []).reject { |tag| tag.start_with?('_meta~') }
|
65
|
+
end
|
66
|
+
|
67
|
+
def supports_meta?
|
68
|
+
true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -30,12 +30,13 @@ module SkullIsland
|
|
30
30
|
|
31
31
|
def digest
|
32
32
|
Digest::MD5.hexdigest(
|
33
|
-
digest_properties.sort.map { |
|
33
|
+
digest_properties.sort.map { |prp| "#{prp}=#{send(prp.to_sym) || ''}" }.compact.join(':')
|
34
34
|
)
|
35
35
|
end
|
36
36
|
|
37
37
|
def digest_properties
|
38
|
-
properties.keys.reject { |k| %i[created_at updated_at].include? k }
|
38
|
+
props = properties.keys.reject { |k| %i[created_at updated_at].include? k }
|
39
|
+
supports_meta? ? props + [:project] : props
|
39
40
|
end
|
40
41
|
|
41
42
|
# Tests for an existing version of this resource based on its properties rather than its `id`
|
@@ -45,8 +46,8 @@ module SkullIsland
|
|
45
46
|
entity_data = @api_client.cache(result.first.relative_uri.to_s) do |client|
|
46
47
|
client.get(result.first.relative_uri.to_s)
|
47
48
|
end
|
48
|
-
@entity
|
49
|
-
@lazy
|
49
|
+
@entity = entity_data
|
50
|
+
@lazy = false
|
50
51
|
@tainted = false
|
51
52
|
true
|
52
53
|
else
|
@@ -172,8 +173,8 @@ module SkullIsland
|
|
172
173
|
entity_data = @api_client.cache(relative_uri.to_s) do |client|
|
173
174
|
client.get(relative_uri.to_s)
|
174
175
|
end
|
175
|
-
@entity
|
176
|
-
@lazy
|
176
|
+
@entity = entity_data
|
177
|
+
@lazy = false
|
177
178
|
@tainted = false
|
178
179
|
true
|
179
180
|
end
|
@@ -199,6 +200,10 @@ module SkullIsland
|
|
199
200
|
self.class.relative_uri
|
200
201
|
end
|
201
202
|
|
203
|
+
def supports_meta?
|
204
|
+
false
|
205
|
+
end
|
206
|
+
|
202
207
|
# ActiveRecord ActiveModel compatibility method
|
203
208
|
def update(params)
|
204
209
|
new_params = {}
|
@@ -179,6 +179,13 @@ module SkullIsland
|
|
179
179
|
)
|
180
180
|
end
|
181
181
|
|
182
|
+
def self.cleanup_except(project, keep_these)
|
183
|
+
where(:project, project).reject { |res| keep_these.include?(res.id) }.map do |res|
|
184
|
+
puts "[WARN] ! Removing #{name} (#{res.id})"
|
185
|
+
res.destroy
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
182
189
|
def initialize(options = {})
|
183
190
|
# TODO: better options validations
|
184
191
|
raise Exceptions::InvalidOptions unless options.is_a?(Hash)
|
@@ -207,5 +214,17 @@ module SkullIsland
|
|
207
214
|
def relative_uri
|
208
215
|
"#{self.class.relative_uri}/#{id}"
|
209
216
|
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
# A way to add things _without_ preprocessing them
|
221
|
+
def raw_set(key, value)
|
222
|
+
raise Exceptions::ImmutableModification if immutable?
|
223
|
+
|
224
|
+
@entity[key.to_s] = value
|
225
|
+
|
226
|
+
@modified_properties << key.to_sym
|
227
|
+
@tainted = true
|
228
|
+
end
|
210
229
|
end
|
211
230
|
end
|
@@ -18,13 +18,18 @@ module SkullIsland
|
|
18
18
|
def self.batch_import(data, verbose: false, test: false)
|
19
19
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
20
20
|
|
21
|
+
known_ids = []
|
22
|
+
|
21
23
|
data.each_with_index do |resource_data, index|
|
22
24
|
resource = new
|
23
|
-
resource.username
|
24
|
-
resource.password
|
25
|
+
resource.delayed_set(:username, resource_data, 'username')
|
26
|
+
resource.delayed_set(:password, resource_data, 'password') if resource_data['password']
|
25
27
|
resource.delayed_set(:consumer, resource_data, 'consumer')
|
26
28
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
29
|
+
known_ids << resource.id
|
27
30
|
end
|
31
|
+
|
32
|
+
known_ids
|
28
33
|
end
|
29
34
|
|
30
35
|
def self.relative_uri
|
@@ -56,6 +61,10 @@ module SkullIsland
|
|
56
61
|
false
|
57
62
|
end
|
58
63
|
|
64
|
+
def project
|
65
|
+
consumer ? consumer.project : nil
|
66
|
+
end
|
67
|
+
|
59
68
|
private
|
60
69
|
|
61
70
|
def postprocess_consumer(value)
|
@@ -7,29 +7,42 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#certificate-object Certificate API definition
|
9
9
|
class Certificate < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :cert, required: true, validate: true
|
11
13
|
property :key, required: true, validate: true
|
12
14
|
property :snis, validate: true
|
13
15
|
property :created_at, read_only: true, postprocess: true
|
14
|
-
property :tags, validate: true
|
16
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
15
17
|
|
16
|
-
|
18
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
19
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
20
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
17
21
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
18
22
|
|
23
|
+
known_ids = []
|
24
|
+
|
19
25
|
data.each_with_index do |resource_data, index|
|
20
26
|
resource = new
|
21
|
-
resource.cert
|
22
|
-
resource.key
|
27
|
+
resource.delayed_set(:cert, resource_data, 'cert')
|
28
|
+
resource.delayed_set(:key, resource_data, 'key')
|
23
29
|
resource.snis = resource_data['snis'] if resource_data['snis']
|
24
30
|
resource.tags = resource_data['tags'] if resource_data['tags']
|
31
|
+
resource.project = project if project
|
32
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
25
33
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
34
|
+
known_ids << resource.id
|
26
35
|
end
|
36
|
+
|
37
|
+
cleanup_except(project, known_ids) if project
|
27
38
|
end
|
39
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
40
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
28
41
|
|
29
42
|
def export(options = {})
|
30
43
|
hash = { 'cert' => cert, 'key' => key }
|
31
44
|
hash['snis'] = snis if snis && !snis.empty?
|
32
|
-
hash['tags'] = tags
|
45
|
+
hash['tags'] = tags unless tags.empty?
|
33
46
|
[*options[:exclude]].each do |exclude|
|
34
47
|
hash.delete(exclude.to_s)
|
35
48
|
end
|
@@ -7,22 +7,33 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#consumer-object Consumer API definition
|
9
9
|
class Consumer < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :username
|
11
13
|
property :custom_id
|
12
14
|
property :created_at, read_only: true, postprocess: true
|
13
|
-
property :tags, validate: true
|
15
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
14
16
|
|
15
|
-
|
17
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
18
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
19
|
+
# rubocop:disable Metrics/AbcSize
|
20
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
16
21
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
17
22
|
|
23
|
+
known_ids = []
|
24
|
+
|
25
|
+
# rubocop:disable Metrics/BlockLength
|
18
26
|
data.each_with_index do |resource_data, index|
|
19
27
|
resource = new
|
20
28
|
resource.username = resource_data['username']
|
21
29
|
resource.custom_id = resource_data['custom_id']
|
22
30
|
resource.tags = resource_data['tags'] if resource_data['tags']
|
31
|
+
resource.project = project if project
|
32
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
23
33
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
34
|
+
known_ids << resource.id
|
24
35
|
|
25
|
-
BasicauthCredential.batch_import(
|
36
|
+
known_basic_auths = BasicauthCredential.batch_import(
|
26
37
|
(
|
27
38
|
resource_data.dig('credentials', 'basic-auth') || []
|
28
39
|
).map { |t| t.merge('consumer' => { 'id' => resource.id }) },
|
@@ -30,7 +41,7 @@ module SkullIsland
|
|
30
41
|
test: test
|
31
42
|
)
|
32
43
|
|
33
|
-
JWTCredential.batch_import(
|
44
|
+
known_jwt_auths = JWTCredential.batch_import(
|
34
45
|
(
|
35
46
|
resource_data.dig('credentials', 'jwt') || []
|
36
47
|
).map { |t| t.merge('consumer' => { 'id' => resource.id }) },
|
@@ -38,20 +49,36 @@ module SkullIsland
|
|
38
49
|
test: test
|
39
50
|
)
|
40
51
|
|
41
|
-
KeyauthCredential.batch_import(
|
52
|
+
known_key_auths = KeyauthCredential.batch_import(
|
42
53
|
(
|
43
54
|
resource_data.dig('credentials', 'key-auth') || []
|
44
55
|
).map { |t| t.merge('consumer' => { 'id' => resource.id }) },
|
45
56
|
verbose: verbose,
|
46
57
|
test: test
|
47
58
|
)
|
59
|
+
|
60
|
+
next unless project
|
61
|
+
|
62
|
+
BasicauthCredential.all.reject { |res| known_basic_auths.include?(res.id) }.map do |res|
|
63
|
+
puts "[WARN] ! Removing #{res.class.name} (#{res.id})"
|
64
|
+
res.destroy
|
65
|
+
end
|
66
|
+
|
67
|
+
JWTCredential.all.reject { |res| known_jwt_auths.include?(res.id) }.map do |res|
|
68
|
+
puts "[WARN] ! Removing #{res.class.name} (#{res.id})"
|
69
|
+
res.destroy
|
70
|
+
end
|
71
|
+
|
72
|
+
KeyauthCredential.all.reject { |res| known_key_auths.include?(res.id) }.map do |res|
|
73
|
+
puts "[WARN] ! Removing #{res.class.name} (#{res.id})"
|
74
|
+
res.destroy
|
75
|
+
end
|
48
76
|
end
|
77
|
+
# rubocop:enable Metrics/BlockLength
|
78
|
+
|
79
|
+
cleanup_except(project, known_ids) if project
|
49
80
|
end
|
50
81
|
|
51
|
-
# Convenience method to add upstream targets
|
52
|
-
# rubocop:disable Metrics/AbcSize
|
53
|
-
# rubocop:disable Metrics/CyclomaticComplexity
|
54
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
55
82
|
def add_credential!(details)
|
56
83
|
r = if [BasicauthCredential, JWTCredential, KeyauthCredential].include? details.class
|
57
84
|
details
|
@@ -100,7 +127,7 @@ module SkullIsland
|
|
100
127
|
hash = { 'username' => username, 'custom_id' => custom_id }
|
101
128
|
creds = credentials_for_export
|
102
129
|
hash['credentials'] = creds unless creds.empty?
|
103
|
-
hash['tags'] = tags
|
130
|
+
hash['tags'] = tags unless tags.empty?
|
104
131
|
[*options[:exclude]].each do |exclude|
|
105
132
|
hash.delete(exclude.to_s)
|
106
133
|
end
|
@@ -20,17 +20,22 @@ module SkullIsland
|
|
20
20
|
def self.batch_import(data, verbose: false, test: false)
|
21
21
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
22
22
|
|
23
|
+
known_ids = []
|
24
|
+
|
23
25
|
data.each_with_index do |resource_data, index|
|
24
26
|
resource = new
|
25
27
|
resource.algorithm = resource_data['algorithm']
|
26
|
-
resource.key
|
27
|
-
resource.secret
|
28
|
+
resource.delayed_set(:key, resource_data, 'key') if resource_data['key']
|
29
|
+
resource.delayed_set(:secret, resource_data, 'secret') if resource_data['secret']
|
28
30
|
if resource_data['rsa_public_key']
|
29
|
-
resource.rsa_public_key
|
31
|
+
resource.delayed_set(:rsa_public_key, resource_data, 'rsa_public_key')
|
30
32
|
end
|
31
33
|
resource.delayed_set(:consumer, resource_data, 'consumer')
|
32
34
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
35
|
+
known_ids << resource.id
|
33
36
|
end
|
37
|
+
|
38
|
+
known_ids
|
34
39
|
end
|
35
40
|
|
36
41
|
def self.relative_uri
|
@@ -65,6 +70,10 @@ module SkullIsland
|
|
65
70
|
false
|
66
71
|
end
|
67
72
|
|
73
|
+
def project
|
74
|
+
consumer ? consumer.project : nil
|
75
|
+
end
|
76
|
+
|
68
77
|
private
|
69
78
|
|
70
79
|
def postprocess_consumer(value)
|
@@ -19,7 +19,7 @@ module SkullIsland
|
|
19
19
|
|
20
20
|
data.each_with_index do |resource_data, index|
|
21
21
|
resource = new
|
22
|
-
resource.key
|
22
|
+
resource.delayed_set(:key, resource_data, 'key')
|
23
23
|
resource.delayed_set(:consumer, resource_data, 'consumer')
|
24
24
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
25
25
|
end
|
@@ -7,6 +7,8 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#plugin-object Plugin API definition
|
9
9
|
class Plugin < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :name
|
11
13
|
property :enabled, type: :boolean
|
12
14
|
property :run_on, validate: true
|
@@ -15,11 +17,15 @@ module SkullIsland
|
|
15
17
|
property :route, validate: true, preprocess: true, postprocess: true
|
16
18
|
property :service, validate: true, preprocess: true, postprocess: true
|
17
19
|
property :created_at, read_only: true, postprocess: true
|
18
|
-
property :tags, validate: true
|
20
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
19
21
|
|
20
|
-
|
22
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
23
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
24
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
21
25
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
22
26
|
|
27
|
+
known_ids = []
|
28
|
+
|
23
29
|
data.each_with_index do |resource_data, index|
|
24
30
|
resource = new
|
25
31
|
resource.name = resource_data['name']
|
@@ -27,12 +33,19 @@ module SkullIsland
|
|
27
33
|
resource.run_on = resource_data['run_on'] if resource_data['run_on']
|
28
34
|
resource.config = resource_data['config'].deep_sort if resource_data['config']
|
29
35
|
resource.tags = resource_data['tags'] if resource_data['tags']
|
36
|
+
resource.project = project if project
|
37
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
30
38
|
resource.delayed_set(:consumer, resource_data, 'consumer')
|
31
39
|
resource.delayed_set(:route, resource_data, 'route')
|
32
40
|
resource.delayed_set(:service, resource_data, 'service')
|
33
41
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
42
|
+
known_ids << resource.id
|
34
43
|
end
|
44
|
+
|
45
|
+
cleanup_except(project, known_ids) if project
|
35
46
|
end
|
47
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
48
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
36
49
|
|
37
50
|
def self.enabled_names(api_client: APIClient.instance)
|
38
51
|
api_client.get("#{relative_uri}/enabled")['enabled_plugins']
|
@@ -55,7 +68,7 @@ module SkullIsland
|
|
55
68
|
hash['consumer'] = "<%= lookup :consumer, '#{consumer.username}' %>" if consumer
|
56
69
|
hash['route'] = "<%= lookup :route, '#{route.name}' %>" if route
|
57
70
|
hash['service'] = "<%= lookup :service, '#{service.name}' %>" if service
|
58
|
-
hash['tags'] = tags
|
71
|
+
hash['tags'] = tags unless tags.empty?
|
59
72
|
[*options[:exclude]].each do |exclude|
|
60
73
|
hash.delete(exclude.to_s)
|
61
74
|
end
|
@@ -7,6 +7,8 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#route-object Route API definition
|
9
9
|
class Route < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :name
|
11
13
|
property :methods
|
12
14
|
property :paths
|
@@ -21,14 +23,16 @@ module SkullIsland
|
|
21
23
|
property :service, validate: true, preprocess: true, postprocess: true
|
22
24
|
property :created_at, read_only: true, postprocess: true
|
23
25
|
property :updated_at, read_only: true, postprocess: true
|
24
|
-
property :tags, validate: true
|
26
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
25
27
|
|
26
28
|
# rubocop:disable Metrics/CyclomaticComplexity
|
27
29
|
# rubocop:disable Metrics/PerceivedComplexity
|
28
30
|
# rubocop:disable Metrics/AbcSize
|
29
|
-
def self.batch_import(data, verbose: false, test: false)
|
31
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
30
32
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
31
33
|
|
34
|
+
known_ids = []
|
35
|
+
|
32
36
|
data.each_with_index do |rdata, index|
|
33
37
|
resource = new
|
34
38
|
resource.name = rdata['name']
|
@@ -41,9 +45,14 @@ module SkullIsland
|
|
41
45
|
resource.preserve_host = rdata['preserve_host'] unless rdata['preserve_host'].nil?
|
42
46
|
resource.snis = rdata['snis'] if rdata['snis']
|
43
47
|
resource.tags = rdata['tags'] if rdata['tags']
|
48
|
+
resource.project = project if project
|
49
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
44
50
|
resource.delayed_set(:service, rdata, 'service')
|
45
51
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
52
|
+
known_ids << resource.id
|
46
53
|
end
|
54
|
+
|
55
|
+
cleanup_except(project, known_ids) if project
|
47
56
|
end
|
48
57
|
# rubocop:enable Metrics/CyclomaticComplexity
|
49
58
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -68,7 +77,7 @@ module SkullIsland
|
|
68
77
|
}
|
69
78
|
hash['service'] = "<%= lookup :service, '#{service.name}' %>" if service
|
70
79
|
hash['snis'] = snis if snis && !snis.empty?
|
71
|
-
hash['tags'] = tags
|
80
|
+
hash['tags'] = tags unless tags.empty?
|
72
81
|
[*options[:exclude]].each do |exclude|
|
73
82
|
hash.delete(exclude.to_s)
|
74
83
|
end
|
@@ -7,6 +7,8 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#service-object Service API definition
|
9
9
|
class Service < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :name
|
11
13
|
property :retries
|
12
14
|
property :protocol, validate: true, required: true
|
@@ -18,27 +20,32 @@ module SkullIsland
|
|
18
20
|
property :read_timeout, validate: true
|
19
21
|
property :created_at, read_only: true, postprocess: true
|
20
22
|
property :updated_at, read_only: true, postprocess: true
|
21
|
-
property :tags, validate: true
|
23
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
22
24
|
|
23
25
|
# rubocop:disable Metrics/CyclomaticComplexity
|
24
26
|
# rubocop:disable Metrics/PerceivedComplexity
|
25
27
|
# rubocop:disable Metrics/AbcSize
|
26
|
-
def self.batch_import(data, verbose: false, test: false)
|
28
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
27
29
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
28
30
|
|
31
|
+
known_ids = []
|
32
|
+
|
29
33
|
data.each_with_index do |rdata, index|
|
30
34
|
resource = new
|
31
35
|
resource.name = rdata['name']
|
32
36
|
resource.retries = rdata['retries'] if rdata['retries']
|
33
37
|
resource.protocol = rdata['protocol']
|
34
|
-
resource.host
|
35
|
-
resource.port
|
38
|
+
resource.delayed_set(:host, rdata, 'host')
|
39
|
+
resource.delayed_set(:port, rdata, 'port')
|
36
40
|
resource.path = rdata['path'] if rdata['path']
|
37
41
|
resource.connect_timeout = rdata['connect_timeout'] if rdata['connect_timeout']
|
38
42
|
resource.write_timeout = rdata['write_timeout'] if rdata['write_timeout']
|
39
43
|
resource.read_timeout = rdata['read_timeout'] if rdata['read_timeout']
|
40
44
|
resource.tags = rdata['tags'] if rdata['tags']
|
45
|
+
resource.project = project if project
|
46
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
41
47
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
48
|
+
known_ids << resource.id
|
42
49
|
|
43
50
|
Route.batch_import(
|
44
51
|
(rdata['routes'] || []).map { |r| r.merge('service' => { 'id' => resource.id }) },
|
@@ -46,6 +53,8 @@ module SkullIsland
|
|
46
53
|
test: test
|
47
54
|
)
|
48
55
|
end
|
56
|
+
|
57
|
+
cleanup_except(project, known_ids) if project
|
49
58
|
end
|
50
59
|
# rubocop:enable Metrics/CyclomaticComplexity
|
51
60
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -59,6 +68,11 @@ module SkullIsland
|
|
59
68
|
r.save
|
60
69
|
end
|
61
70
|
|
71
|
+
def destroy
|
72
|
+
routes.each(&:destroy)
|
73
|
+
super
|
74
|
+
end
|
75
|
+
|
62
76
|
# Provides a collection of related {Route} instances
|
63
77
|
def routes
|
64
78
|
Route.where(:service, self, api_client: api_client)
|
@@ -82,7 +96,7 @@ module SkullIsland
|
|
82
96
|
'read_timeout' => read_timeout
|
83
97
|
}
|
84
98
|
hash['routes'] = routes.collect { |route| route.export(exclude: 'service') }
|
85
|
-
hash['tags'] = tags
|
99
|
+
hash['tags'] = tags unless tags.empty?
|
86
100
|
[*options[:exclude]].each do |exclude|
|
87
101
|
hash.delete(exclude.to_s)
|
88
102
|
end
|
@@ -7,6 +7,8 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#upstream-objects Upstream API definition
|
9
9
|
class Upstream < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :name, required: true, validate: true
|
11
13
|
property :slots, validate: true
|
12
14
|
property :hash_on, validate: true
|
@@ -17,14 +19,16 @@ module SkullIsland
|
|
17
19
|
property :hash_on_cookie_path, validate: true
|
18
20
|
property :healthchecks, validate: true
|
19
21
|
property :created_at, read_only: true, postprocess: true
|
20
|
-
property :tags, validate: true
|
22
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
21
23
|
|
22
24
|
# rubocop:disable Metrics/CyclomaticComplexity
|
23
25
|
# rubocop:disable Metrics/PerceivedComplexity
|
24
26
|
# rubocop:disable Metrics/AbcSize
|
25
|
-
def self.batch_import(data, verbose: false, test: false)
|
27
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
26
28
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
27
29
|
|
30
|
+
known_ids = []
|
31
|
+
|
28
32
|
data.each_with_index do |rdata, index|
|
29
33
|
resource = new
|
30
34
|
resource.name = rdata['name']
|
@@ -41,15 +45,22 @@ module SkullIsland
|
|
41
45
|
end
|
42
46
|
resource.healthchecks = rdata['healthchecks'] if rdata['healthchecks']
|
43
47
|
resource.tags = rdata['tags'] if rdata['tags']
|
48
|
+
resource.project = project if project
|
49
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
44
50
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
51
|
+
known_ids << resource.id
|
45
52
|
puts '[INFO] Processing UpstreamTarget entries...' if verbose
|
46
53
|
|
47
54
|
UpstreamTarget.batch_import(
|
48
55
|
(rdata['targets'] || []).map { |t| t.merge('upstream' => { 'id' => resource.id }) },
|
49
56
|
verbose: verbose,
|
50
|
-
test: test
|
57
|
+
test: test,
|
58
|
+
project: project,
|
59
|
+
time: time
|
51
60
|
)
|
52
61
|
end
|
62
|
+
|
63
|
+
cleanup_except(project, known_ids) if project
|
53
64
|
end
|
54
65
|
# rubocop:enable Metrics/CyclomaticComplexity
|
55
66
|
# rubocop:enable Metrics/PerceivedComplexity
|
@@ -113,7 +124,7 @@ module SkullIsland
|
|
113
124
|
'healthchecks' => healthchecks
|
114
125
|
}
|
115
126
|
hash['targets'] = targets.collect { |target| target.export(exclude: 'upstream') }
|
116
|
-
hash['tags'] = tags
|
127
|
+
hash['tags'] = tags unless tags.empty?
|
117
128
|
[*options[:exclude]].each do |exclude|
|
118
129
|
hash.delete(exclude.to_s)
|
119
130
|
end
|
@@ -7,6 +7,8 @@ module SkullIsland
|
|
7
7
|
#
|
8
8
|
# @see https://docs.konghq.com/1.1.x/admin-api/#target-object Target API definition
|
9
9
|
class UpstreamTarget < Resource
|
10
|
+
include Helpers::Meta
|
11
|
+
|
10
12
|
property :target, required: true, validate: true, preprocess: true
|
11
13
|
property(
|
12
14
|
:upstream,
|
@@ -14,20 +16,31 @@ module SkullIsland
|
|
14
16
|
)
|
15
17
|
property :weight, validate: true
|
16
18
|
property :created_at, read_only: true, postprocess: true
|
17
|
-
property :tags, validate: true
|
19
|
+
property :tags, validate: true, preprocess: true, postprocess: true
|
18
20
|
|
19
|
-
|
21
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
22
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
23
|
+
def self.batch_import(data, verbose: false, test: false, project: nil, time: nil)
|
20
24
|
raise(Exceptions::InvalidArguments) unless data.is_a?(Array)
|
21
25
|
|
26
|
+
known_ids = []
|
27
|
+
|
22
28
|
data.each_with_index do |resource_data, index|
|
23
29
|
resource = new
|
24
|
-
resource.target
|
30
|
+
resource.delayed_set(:target, resource_data, 'target')
|
25
31
|
resource.delayed_set(:upstream, resource_data, 'upstream')
|
26
32
|
resource.weight = resource_data['weight'] if resource_data['weight']
|
27
33
|
resource.tags = resource_data['tags'] if resource_data['tags']
|
34
|
+
resource.project = project if project
|
35
|
+
resource.import_time = (time || Time.now.utc.to_i) if project
|
28
36
|
resource.import_update_or_skip(index: index, verbose: verbose, test: test)
|
37
|
+
known_ids << resource.id
|
29
38
|
end
|
39
|
+
|
40
|
+
cleanup_except(project, known_ids) if project
|
30
41
|
end
|
42
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
43
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
31
44
|
|
32
45
|
def self.all(options = {})
|
33
46
|
api_client = options[:api_client] || APIClient.instance
|
@@ -68,7 +81,7 @@ module SkullIsland
|
|
68
81
|
def export(options = {})
|
69
82
|
hash = { 'target' => target, 'weight' => weight }
|
70
83
|
hash['upstream'] = "<%= lookup :upstream, '#{upstream.name}' %>" if upstream
|
71
|
-
hash['tags'] = tags
|
84
|
+
hash['tags'] = tags unless tags.empty?
|
72
85
|
[*options[:exclude]].each do |exclude|
|
73
86
|
hash.delete(exclude.to_s)
|
74
87
|
end
|
@@ -79,19 +92,7 @@ module SkullIsland
|
|
79
92
|
end
|
80
93
|
|
81
94
|
def modified_existing?
|
82
|
-
|
83
|
-
|
84
|
-
# Find routes of the same name
|
85
|
-
same_target_and_upstream = self.class.where(:target, target).and(:upstream, upstream)
|
86
|
-
|
87
|
-
existing = same_target_and_upstream.size == 1 ? same_target_and_upstream.first : nil
|
88
|
-
|
89
|
-
if existing
|
90
|
-
@entity['id'] = existing.id
|
91
|
-
save
|
92
|
-
else
|
93
|
-
false
|
94
|
-
end
|
95
|
+
false # Upstream Targets can not be PATCHed, so can not be modified
|
95
96
|
end
|
96
97
|
|
97
98
|
private
|
@@ -24,7 +24,7 @@ module SkullIsland
|
|
24
24
|
def validate_tags(value)
|
25
25
|
# allow only valid hostnames
|
26
26
|
value.each do |tag|
|
27
|
-
return false unless tag.is_a?(String) && tag.match?(
|
27
|
+
return false unless tag.is_a?(String) && tag.match?(/^[\w_\-\.~]+$/)
|
28
28
|
end
|
29
29
|
true
|
30
30
|
end
|
data/lib/skull_island/version.rb
CHANGED
data/skull_island.gemspec
CHANGED
@@ -40,5 +40,5 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_development_dependency 'rubocop', '~> 0.50'
|
41
41
|
spec.add_development_dependency 'simplecov', '~> 0.15'
|
42
42
|
spec.add_development_dependency 'travis', '~> 1.8'
|
43
|
-
spec.add_development_dependency 'yard', '~> 0.9'
|
43
|
+
spec.add_development_dependency 'yard', '~> 0.9.20'
|
44
44
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: skull_island
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Gnagy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: deepsort
|
@@ -198,14 +198,14 @@ dependencies:
|
|
198
198
|
requirements:
|
199
199
|
- - "~>"
|
200
200
|
- !ruby/object:Gem::Version
|
201
|
-
version:
|
201
|
+
version: 0.9.20
|
202
202
|
type: :development
|
203
203
|
prerelease: false
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
205
205
|
requirements:
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
|
-
version:
|
208
|
+
version: 0.9.20
|
209
209
|
description: A Ruby SDK for Kong 0.14.x
|
210
210
|
email:
|
211
211
|
- jonathan.gnagy@gmail.com
|
@@ -242,6 +242,7 @@ files:
|
|
242
242
|
- lib/skull_island/exceptions/invalid_where_query.rb
|
243
243
|
- lib/skull_island/exceptions/new_instance_with_id.rb
|
244
244
|
- lib/skull_island/helpers/api_client.rb
|
245
|
+
- lib/skull_island/helpers/meta.rb
|
245
246
|
- lib/skull_island/helpers/migration.rb
|
246
247
|
- lib/skull_island/helpers/resource.rb
|
247
248
|
- lib/skull_island/helpers/resource_class.rb
|
@@ -284,7 +285,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
284
285
|
- !ruby/object:Gem::Version
|
285
286
|
version: '0'
|
286
287
|
requirements: []
|
287
|
-
|
288
|
+
rubyforge_project:
|
289
|
+
rubygems_version: 2.7.7
|
288
290
|
signing_key:
|
289
291
|
specification_version: 4
|
290
292
|
summary: Ruby SDK for Kong
|