kong_schema 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +31 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +85 -0
- data/LICENSE.md +14 -0
- data/README.md +197 -0
- data/bin/kong_schema +27 -0
- data/ext/kong/upstream.rb +36 -0
- data/kong_schema.gemspec +29 -0
- data/lib/kong_schema/actions.rb +44 -0
- data/lib/kong_schema/adapter.rb +35 -0
- data/lib/kong_schema/cli.rb +86 -0
- data/lib/kong_schema/client.rb +30 -0
- data/lib/kong_schema/reporter.rb +101 -0
- data/lib/kong_schema/resource/api.rb +57 -0
- data/lib/kong_schema/resource/target.rb +60 -0
- data/lib/kong_schema/resource/upstream.rb +42 -0
- data/lib/kong_schema/resource.rb +3 -0
- data/lib/kong_schema/schema.rb +103 -0
- data/lib/kong_schema/version.rb +5 -0
- data/lib/kong_schema.rb +10 -0
- data/spec/examples.txt +0 -0
- data/spec/kong_schema/reporter_spec.rb +89 -0
- data/spec/kong_schema/resource/api_spec.rb +125 -0
- data/spec/kong_schema/resource/target_spec.rb +209 -0
- data/spec/kong_schema/resource/upstream_spec.rb +122 -0
- data/spec/spec_helper.rb +109 -0
- data/spec/support/coverage.rb +18 -0
- data/spec/support/kong_schema_test_utils.rb +24 -0
- metadata +212 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kong_schema'
|
4
|
+
require 'tty-table'
|
5
|
+
require 'json'
|
6
|
+
require 'diffy'
|
7
|
+
require 'pastel'
|
8
|
+
require_relative './actions'
|
9
|
+
|
10
|
+
module KongSchema
|
11
|
+
# Helper class for printing a report of the changes to be committed to Kong
|
12
|
+
# created by {Schema.analyze}.
|
13
|
+
module Reporter
|
14
|
+
extend self
|
15
|
+
|
16
|
+
TableHeader = %w(Change Parameters).freeze
|
17
|
+
|
18
|
+
# @param [Array<KongSchema::Action>] changes
|
19
|
+
# What you get from calling {KongSchema::Schema.analyze}
|
20
|
+
#
|
21
|
+
# @return [String] The report to print to something like STDOUT.
|
22
|
+
def report(changes, object_format: :json)
|
23
|
+
pretty_print = if object_format == :json
|
24
|
+
JSONPrettyPrinter.method(:print)
|
25
|
+
else
|
26
|
+
YAMLPrettyPrinter.method(:print)
|
27
|
+
end
|
28
|
+
|
29
|
+
table = TTY::Table.new header: TableHeader do |t|
|
30
|
+
changes.each do |change|
|
31
|
+
t << print_change(change: change, pretty_print: pretty_print)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
table.render(:ascii, multiline: true, padding: [0, 1, 0, 1])
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Print objects as human-readable JSON
|
41
|
+
class JSONPrettyPrinter
|
42
|
+
def self.print(object)
|
43
|
+
JSON.pretty_generate(YAML.load(YAML.dump(object))) + "\n"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Print objects as YAML
|
48
|
+
class YAMLPrettyPrinter
|
49
|
+
def self.print(object)
|
50
|
+
YAML.dump(object)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def print_change(change:, pretty_print:)
|
55
|
+
resource_name = change.model.to_s.split('::').last
|
56
|
+
|
57
|
+
case change
|
58
|
+
when KongSchema::Actions::Create
|
59
|
+
[ "Create #{resource_name}", pretty_print.call(change.params) ]
|
60
|
+
when KongSchema::Actions::Update
|
61
|
+
record_attributes = rewrite_record_attributes(change.record)
|
62
|
+
current_attributes = change.params.keys.reduce({}) do |map, key|
|
63
|
+
map[key] = record_attributes[key]
|
64
|
+
map
|
65
|
+
end
|
66
|
+
|
67
|
+
changed_attributes = pretty_print.call(change.params)
|
68
|
+
current_attributes = pretty_print.call(current_attributes)
|
69
|
+
diff = Diffy::Diff.new(current_attributes, changed_attributes)
|
70
|
+
|
71
|
+
[ "Update #{resource_name}", diff.to_s(:color) ]
|
72
|
+
when KongSchema::Actions::Delete
|
73
|
+
[
|
74
|
+
"Delete #{resource_name}",
|
75
|
+
pretty_print.call(rewrite_record_attributes(change.record))
|
76
|
+
]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# This warrants some explanation.
|
81
|
+
#
|
82
|
+
# For some Kong API objects like Target, the API will accept "indirect"
|
83
|
+
# values for certain parameters like "upstream_id" but in the responses for
|
84
|
+
# those APIs, the payload will contain a value different than what we POSTed
|
85
|
+
# with. In this example, it will accept an upstream_id of either an actual
|
86
|
+
# Upstream.id like "c9633f63-fdaf-4c1c-b9dd-b5a0fa28c780" or an
|
87
|
+
# Upstream.name like "some-upstream.kong-service".
|
88
|
+
#
|
89
|
+
# For our purposes, the user doesn't know about Upstream.id, so we don't
|
90
|
+
# care to show that value, so we will rewrite it with the value they're
|
91
|
+
# meant to input (e.g. target.upstream_id -> target.upstream.name)
|
92
|
+
def rewrite_record_attributes(record)
|
93
|
+
case record
|
94
|
+
when Kong::Target
|
95
|
+
record.attributes.merge('upstream_id' => record.upstream.name)
|
96
|
+
else
|
97
|
+
record.attributes
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kong'
|
4
|
+
require_relative '../adapter'
|
5
|
+
|
6
|
+
module KongSchema
|
7
|
+
module Resource
|
8
|
+
module Api
|
9
|
+
extend self
|
10
|
+
|
11
|
+
def identify(record)
|
12
|
+
case record
|
13
|
+
when Kong::Api
|
14
|
+
record.name
|
15
|
+
when Hash
|
16
|
+
record['name']
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def all(*)
|
21
|
+
Kong::Api.all
|
22
|
+
end
|
23
|
+
|
24
|
+
def create(attributes)
|
25
|
+
Adapter.for(Kong::Api).create(serialize_outbound(attributes))
|
26
|
+
end
|
27
|
+
|
28
|
+
def changed?(record, attributes)
|
29
|
+
Adapter.for(Kong::Api).changed?(record, attributes)
|
30
|
+
end
|
31
|
+
|
32
|
+
def update(record, partial_attributes)
|
33
|
+
Adapter.for(Kong::Api).update(
|
34
|
+
record,
|
35
|
+
serialize_outbound(partial_attributes)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(record)
|
40
|
+
Adapter.for(Kong::Api).delete(record)
|
41
|
+
end
|
42
|
+
|
43
|
+
def serialize_outbound(attributes)
|
44
|
+
attributes.keys.reduce({}) do |map, key|
|
45
|
+
case key
|
46
|
+
when 'hosts', 'uris', 'methods'
|
47
|
+
map[key] = Array(attributes[key]).join(',')
|
48
|
+
else
|
49
|
+
map[key] = attributes[key]
|
50
|
+
end
|
51
|
+
|
52
|
+
map
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kong'
|
4
|
+
require_relative '../adapter'
|
5
|
+
|
6
|
+
module KongSchema
|
7
|
+
module Resource
|
8
|
+
module Target
|
9
|
+
extend self
|
10
|
+
|
11
|
+
def identify(record)
|
12
|
+
case record
|
13
|
+
when Kong::Target
|
14
|
+
[record.upstream.name, record.target].to_json
|
15
|
+
when Hash
|
16
|
+
[record['upstream_id'], record['target']].to_json
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def all(*)
|
21
|
+
Kong::Upstream.all.map(&:targets).flatten
|
22
|
+
end
|
23
|
+
|
24
|
+
def create(attributes)
|
25
|
+
with_upstream(attributes) do |upstream|
|
26
|
+
Adapter.for(Kong::Target).create(
|
27
|
+
attributes.merge('upstream_id' => upstream.id)
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def changed?(record, directive)
|
33
|
+
(
|
34
|
+
record.target != directive['target'] ||
|
35
|
+
record.weight != directive.fetch('weight', 100) ||
|
36
|
+
record.upstream.name != directive['upstream_id']
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def update(record, partial_attributes)
|
41
|
+
delete(record)
|
42
|
+
create(partial_attributes)
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete(target)
|
46
|
+
Adapter.for(Kong::Target).delete(target)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def with_upstream(params)
|
52
|
+
upstream = Kong::Upstream.find_by_name(params.fetch('upstream_id', ''))
|
53
|
+
|
54
|
+
fail "Can not add a target without an upstream!" if upstream.nil?
|
55
|
+
|
56
|
+
yield upstream
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kong'
|
4
|
+
require_relative '../adapter'
|
5
|
+
|
6
|
+
module KongSchema
|
7
|
+
module Resource
|
8
|
+
# https://getkong.org/docs/0.11.x/admin-api/#upstream-objects
|
9
|
+
module Upstream
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def identify(record)
|
13
|
+
case record
|
14
|
+
when Kong::Upstream
|
15
|
+
record.name
|
16
|
+
when Hash
|
17
|
+
record['name']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def all(*)
|
22
|
+
Kong::Upstream.all
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(attributes)
|
26
|
+
Adapter.for(Kong::Upstream).create(attributes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def changed?(record, attributes)
|
30
|
+
Adapter.for(Kong::Upstream).changed?(record, attributes)
|
31
|
+
end
|
32
|
+
|
33
|
+
def update(record, partial_attributes)
|
34
|
+
Adapter.for(Kong::Upstream).update(record, partial_attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(record)
|
38
|
+
Adapter.for(Kong::Upstream).delete(record)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'kong'
|
5
|
+
require 'English'
|
6
|
+
|
7
|
+
require_relative './client'
|
8
|
+
require_relative './resource'
|
9
|
+
|
10
|
+
module KongSchema
|
11
|
+
module Schema
|
12
|
+
extend self
|
13
|
+
|
14
|
+
# Scan for changes between Kong's database and the configuration. To
|
15
|
+
# commit the changes (if any) use {.commit} with the results.
|
16
|
+
#
|
17
|
+
# @param [Object] config
|
18
|
+
# The configuration directives as explain in README.
|
19
|
+
#
|
20
|
+
# @return [Array<Change>]
|
21
|
+
def scan(config)
|
22
|
+
Client.connect(config) do
|
23
|
+
[
|
24
|
+
scan_in(model: Resource::Api, directives: Array(config['apis'])),
|
25
|
+
|
26
|
+
# order matters in some of the resources; Upstream directives must be
|
27
|
+
# handled before Target ones
|
28
|
+
scan_in(model: Resource::Upstream, directives: Array(config['upstreams'])),
|
29
|
+
|
30
|
+
scan_in(model: Resource::Target, directives: Array(config['targets']))
|
31
|
+
].flatten
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Commit changes to Kong's database through its REST API.
|
36
|
+
#
|
37
|
+
# @param [Object] config
|
38
|
+
# @param [Array<Change>] changes
|
39
|
+
#
|
40
|
+
# @return NilClass
|
41
|
+
def commit(config, directives)
|
42
|
+
Client.connect(config) do |client|
|
43
|
+
directives.each do |d|
|
44
|
+
begin
|
45
|
+
d.apply(client, config)
|
46
|
+
rescue StandardError
|
47
|
+
e = $ERROR_INFO
|
48
|
+
raise e, "#{e}\nSource:\n#{YAML.dump(d)}", e.backtrace
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def scan_in(model:, directives:)
|
57
|
+
state = {
|
58
|
+
model: model,
|
59
|
+
defined: model.all.each_with_object({}) do |record, map|
|
60
|
+
map[model.identify(record)] = record
|
61
|
+
end,
|
62
|
+
declared: directives.each_with_object({}) do |directive, map|
|
63
|
+
map[model.identify(directive)] = directive
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
[
|
68
|
+
build_create_changes(state),
|
69
|
+
build_update_changes(state),
|
70
|
+
build_delete_changes(state)
|
71
|
+
].flatten
|
72
|
+
end
|
73
|
+
|
74
|
+
def build_create_changes(model:, defined:, declared:)
|
75
|
+
to_create = declared.keys - defined.keys
|
76
|
+
to_create.map do |id|
|
77
|
+
Actions::Create.new(model: model, params: declared[id])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_update_changes(model:, defined:, declared:)
|
82
|
+
to_update = declared.keys & defined.keys
|
83
|
+
changed = to_update.select do |id|
|
84
|
+
model.changed?(defined[id], declared[id])
|
85
|
+
end
|
86
|
+
|
87
|
+
changed.map do |id|
|
88
|
+
Actions::Update.new(
|
89
|
+
model: model,
|
90
|
+
record: defined[id],
|
91
|
+
params: declared[id]
|
92
|
+
)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def build_delete_changes(model:, defined:, declared:)
|
97
|
+
to_delete = defined.keys - declared.keys
|
98
|
+
to_delete.map do |id|
|
99
|
+
Actions::Delete.new(model: model, record: defined[id])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/kong_schema.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../ext/kong/upstream'
|
4
|
+
require_relative './kong_schema/actions'
|
5
|
+
require_relative './kong_schema/adapter'
|
6
|
+
require_relative './kong_schema/cli'
|
7
|
+
require_relative './kong_schema/reporter'
|
8
|
+
require_relative './kong_schema/resource'
|
9
|
+
require_relative './kong_schema/schema'
|
10
|
+
require_relative './kong_schema/version'
|
data/spec/examples.txt
ADDED
File without changes
|
@@ -0,0 +1,89 @@
|
|
1
|
+
describe KongSchema::Reporter do
|
2
|
+
subject { described_class }
|
3
|
+
|
4
|
+
let(:test_utils) { KongSchemaTestUtils.new }
|
5
|
+
let(:schema) { KongSchema::Schema }
|
6
|
+
|
7
|
+
after(:each) do
|
8
|
+
test_utils.reset_kong
|
9
|
+
end
|
10
|
+
|
11
|
+
let :config do
|
12
|
+
test_utils.generate_config({
|
13
|
+
upstreams: [{ name: 'bridge-learn.kong-service' }]
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
17
|
+
let :with_updated_config do
|
18
|
+
test_utils.generate_config({
|
19
|
+
upstreams: [{
|
20
|
+
name: 'bridge-learn.kong-service',
|
21
|
+
slots: 50,
|
22
|
+
orderlist: nil
|
23
|
+
}]
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
let :with_deleted_config do
|
28
|
+
test_utils.generate_config({
|
29
|
+
upstreams: []
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'reports a resource to be created' do
|
34
|
+
report = subject.report(schema.scan(config))
|
35
|
+
|
36
|
+
expect(report).to include('Create Upstream')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'reports a resource to be updated [JSON]' do
|
40
|
+
schema.commit(config, schema.scan(config))
|
41
|
+
|
42
|
+
report = subject.report(schema.scan(with_updated_config))
|
43
|
+
|
44
|
+
expect(report).to include('Update Upstream')
|
45
|
+
expect(report).to match(/\-[ ]*"slots": 100/)
|
46
|
+
expect(report).to match(/\+[ ]*"slots": 50/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'reports a resource to be updated [YAML]' do
|
50
|
+
schema.commit(config, schema.scan(config))
|
51
|
+
|
52
|
+
report = subject.report(schema.scan(with_updated_config), object_format: :yaml)
|
53
|
+
|
54
|
+
expect(report).to include('Update Upstream')
|
55
|
+
expect(report).to include('-slots: 100')
|
56
|
+
expect(report).to include('+slots: 50')
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'reports a resource to be deleted' do
|
60
|
+
schema.commit(config, schema.scan(config))
|
61
|
+
|
62
|
+
report = subject.report(schema.scan(with_deleted_config))
|
63
|
+
|
64
|
+
expect(report).to include('Delete Upstream')
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '.extract_record_attributes' do
|
68
|
+
context 'Kong::Target' do
|
69
|
+
it 'it rewrites "upstream_id" into the upstream name' do
|
70
|
+
with_target = test_utils.generate_config({
|
71
|
+
upstreams: [{ name: 'foo' }],
|
72
|
+
targets: [{ upstream_id: 'foo', target: '127.0.0.1' }]
|
73
|
+
})
|
74
|
+
|
75
|
+
with_updated_target = test_utils.generate_config({
|
76
|
+
upstreams: [{ name: 'foo' }],
|
77
|
+
targets: []
|
78
|
+
})
|
79
|
+
|
80
|
+
schema.commit(with_target, schema.scan(with_target))
|
81
|
+
|
82
|
+
next_changes = schema.scan(with_updated_target)
|
83
|
+
report = subject.report(next_changes, object_format: :yml)
|
84
|
+
|
85
|
+
expect(report).to include('upstream_id: foo')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
describe KongSchema::Resource::Api do
|
2
|
+
let(:schema) { KongSchema::Schema }
|
3
|
+
let(:test_utils) { KongSchemaTestUtils.new }
|
4
|
+
|
5
|
+
after(:each) do
|
6
|
+
test_utils.reset_kong
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'creating APIs' do
|
10
|
+
let :config do
|
11
|
+
test_utils.generate_config({
|
12
|
+
apis: [{
|
13
|
+
name: 'bridge-learn',
|
14
|
+
hosts: ['bridgeapp.com'],
|
15
|
+
upstream_url: 'http://bridge-learn.kong-service'
|
16
|
+
}]
|
17
|
+
})
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'adds an API if it does not exist' do
|
21
|
+
directives = schema.scan(config)
|
22
|
+
|
23
|
+
expect(directives.map(&:class)).to include(KongSchema::Actions::Create)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'does add an API' do
|
27
|
+
directives = schema.scan(config)
|
28
|
+
|
29
|
+
expect {
|
30
|
+
schema.commit(config, directives)
|
31
|
+
}.to change {
|
32
|
+
KongSchema::Client.connect(config) { Kong::Api.all.count }
|
33
|
+
}.by(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'does not add an API if it exists' do
|
37
|
+
directives = schema.scan(config)
|
38
|
+
|
39
|
+
schema.commit(config, directives)
|
40
|
+
|
41
|
+
next_directives = schema.scan(config)
|
42
|
+
|
43
|
+
expect(next_directives.map(&:class)).not_to include(KongSchema::Actions::Create)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'updating APIs' do
|
48
|
+
let :config do
|
49
|
+
test_utils.generate_config({
|
50
|
+
apis: [{
|
51
|
+
name: 'bridge-learn',
|
52
|
+
hosts: ['bridgeapp.com'],
|
53
|
+
upstream_url: 'http://bridge-learn.kong-service'
|
54
|
+
}]
|
55
|
+
})
|
56
|
+
end
|
57
|
+
|
58
|
+
let :with_updated_config do
|
59
|
+
test_utils.generate_config({
|
60
|
+
apis: [{
|
61
|
+
name: 'bridge-learn',
|
62
|
+
hosts: ['bar.com'],
|
63
|
+
upstream_url: 'http://bridge-learn.kong-service'
|
64
|
+
}]
|
65
|
+
})
|
66
|
+
end
|
67
|
+
|
68
|
+
before(:each) do
|
69
|
+
schema.commit(config, schema.scan(config))
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'updates an API' do
|
73
|
+
directives = schema.scan(with_updated_config)
|
74
|
+
expect(directives.map(&:class)).to include(KongSchema::Actions::Update)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'does update an API' do
|
78
|
+
directives = schema.scan(with_updated_config)
|
79
|
+
|
80
|
+
expect {
|
81
|
+
schema.commit(with_updated_config, directives)
|
82
|
+
}.to change {
|
83
|
+
KongSchema::Client.connect(config) { Kong::Api.all[0].hosts[0] }
|
84
|
+
}.from('bridgeapp.com').to('bar.com')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'deleting APIs' do
|
89
|
+
let :config do
|
90
|
+
test_utils.generate_config({
|
91
|
+
apis: [{
|
92
|
+
name: 'bridge-learn',
|
93
|
+
hosts: ['bar.com'],
|
94
|
+
upstream_url: 'http://bridge-learn.kong-service'
|
95
|
+
}]
|
96
|
+
})
|
97
|
+
end
|
98
|
+
|
99
|
+
let :with_deleted_config do
|
100
|
+
test_utils.generate_config({
|
101
|
+
apis: []
|
102
|
+
})
|
103
|
+
end
|
104
|
+
|
105
|
+
before(:each) do
|
106
|
+
schema.commit(config, schema.scan(config))
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'deletes an API' do
|
110
|
+
directives = schema.scan(with_deleted_config)
|
111
|
+
|
112
|
+
expect(directives.map(&:class)).to include(KongSchema::Actions::Delete)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'does delete an API' do
|
116
|
+
directives = schema.scan(with_deleted_config)
|
117
|
+
|
118
|
+
expect {
|
119
|
+
schema.commit(with_deleted_config, directives)
|
120
|
+
}.to change {
|
121
|
+
KongSchema::Client.connect(config) { Kong::Api.all.count }
|
122
|
+
}.from(1).to(0)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|