skull_island 1.2.0 → 1.2.2
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/.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
|