kongfigure 0.0.8 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ceeaed03095ba7f32fa8239ce1f184f20c871384643279724bbab85b81707f45
4
- data.tar.gz: f0ce60043dff56cd391c6d5800725bd267e8f752f9d1a77968ea1d246821a1df
3
+ metadata.gz: ebd0fda03353da5cf51cc19302e048edcce67f2fc49284d7567151c340178575
4
+ data.tar.gz: eba528613e4170c540396f4e506ae256349a2b1ca8cb7737fb5e5b2ce318d8a3
5
5
  SHA512:
6
- metadata.gz: a6c0f2f1b00cb18a0f7cbf362dc75a189824de4fe89ca90e6b0ae439889b908670968d835507faee2697ff2d06679dc8994744edebd3cee096bb5ded4aab2f08
7
- data.tar.gz: 83ce0094643344c188c7a3fbbc215160e4b0ce4e6fd5e5af0292cfd38f2287c426b74a92dd6bf14ece5aee6e98bcf9d7b354da71ce386769b6f70d984a51aa76
6
+ metadata.gz: c53ebed51301866e1461261964151d532479f33d7b3e510a8b908e1d997254042746156b9b5cf4e74e7180a096f6f6e8b13e1abcf54b28e007ca9cf8bbb4e8ea
7
+ data.tar.gz: 7b31b90435a1ca0dc5d2a4c7882048972ce24b1d8f14ac40c83945c321e7ffe319297530c9e32ec39a906795a25dbfefde19a04ff500e41c3ff1d3ec720968f6
data/.gitignore CHANGED
@@ -52,3 +52,5 @@ build-iPhoneSimulator/
52
52
 
53
53
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
54
54
  .rvmrc
55
+ test.yml
56
+ test_backup.yml
data/README.md CHANGED
@@ -1,3 +1,39 @@
1
1
  # Kongfigure
2
2
 
3
+ ## Test
4
+ ```
5
+ docker run -d --name kong-database \
6
+ -p 5432:5432 \
7
+ -e "POSTGRES_USER=kong" \
8
+ -e "POSTGRES_DB=kong" \
9
+ -e "POSTGRES_PASSWORD=kong" \
10
+ postgres:9.6
11
+ docker run --rm \
12
+ --link kong-database:kong-database \
13
+ -e "KONG_DATABASE=postgres" \
14
+ -e "KONG_PG_HOST=kong-database" \
15
+ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
16
+ -e "KONG_PG_PASSWORD"=kong \
17
+ registry.ibanity.net/docker-images/kong:latest kong migrations bootstrap
18
+
19
+ docker run -ti --name kong \
20
+ --link kong-database:kong-database \
21
+ -e "KONG_DATABASE=postgres" \
22
+ -e "KONG_PG_HOST=kong-database" \
23
+ -e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
24
+ -e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
25
+ -e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
26
+ -e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
27
+ -e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
28
+ -e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
29
+ -e "KONG_PG_PASSWORD"=kong \
30
+ -p 8000:8000 \
31
+ -p 8443:8443 \
32
+ -p 8001:8001 \
33
+ -p 8444:8444 \
34
+ registry.ibanity.net/docker-images/kong:latest
35
+ ```
36
+ ```
37
+ ./exe/kongfigure_local -f test.yml
38
+ ```
3
39
  ## WIP :)
@@ -9,12 +9,14 @@ require_relative "kongfigure/resources/route.rb"
9
9
  require_relative "kongfigure/resources/service.rb"
10
10
  require_relative "kongfigure/resources/target.rb"
11
11
  require_relative "kongfigure/resources/upstream.rb"
12
- require_relative "kongfigure/services/base.rb"
13
- require_relative "kongfigure/services/consumer.rb"
14
- require_relative "kongfigure/services/plugin.rb"
15
- require_relative "kongfigure/services/route.rb"
16
- require_relative "kongfigure/services/service.rb"
17
- require_relative "kongfigure/services/upstream.rb"
12
+ require_relative "kongfigure/synchronizers/base.rb"
13
+ require_relative "kongfigure/synchronizers/consumer.rb"
14
+ require_relative "kongfigure/synchronizers/plugin.rb"
15
+ require_relative "kongfigure/synchronizers/route.rb"
16
+ require_relative "kongfigure/synchronizers/service.rb"
17
+ require_relative "kongfigure/synchronizers/upstream.rb"
18
+ require_relative "kongfigure/synchronizers/consumers/key_auth.rb"
19
+ require_relative "kongfigure/synchronizers/consumers/acl.rb"
18
20
  require_relative "kongfigure/configuration.rb"
19
21
  require_relative "kongfigure/parser.rb"
20
22
  require_relative "kongfigure/http_client.rb"
@@ -32,6 +34,8 @@ require "erb"
32
34
  require "optparse"
33
35
  require "pp"
34
36
  require "awesome_print"
37
+ require "digest"
38
+ require "dry/inflector"
35
39
 
36
40
  module Kongfigure
37
41
  def self.logger
@@ -43,5 +43,14 @@ module Kongfigure
43
43
  upstreams: @upstreams.map do |upstream| upstream.to_s end
44
44
  }.ai
45
45
  end
46
+
47
+ def to_yaml
48
+ {
49
+ services: @services.map do |service| service.to_yaml end,
50
+ consumers: @consumers.map do |consumer| consumer.to_yaml end,
51
+ plugins: @plugins.map do |plugin| plugin.to_yaml end,
52
+ upstreams: @upstreams.map do |upstream| upstream.to_yaml end
53
+ }
54
+ end
46
55
  end
47
56
  end
@@ -19,23 +19,24 @@ module Kongfigure
19
19
  end
20
20
 
21
21
  def post(path, payload)
22
- execute(request_options(:post, path, payload))
22
+ execute(request_options(:post, path, nil, payload))
23
23
  end
24
24
 
25
25
  def put(path, payload)
26
- execute(request_options(:put, path, payload))
26
+ execute(request_options(:put, path, nil, payload))
27
27
  end
28
28
 
29
29
  def patch(path, payload)
30
- execute(request_options(:patch, path, payload))
30
+ execute(request_options(:patch, path, nil, payload))
31
31
  end
32
32
 
33
- def get(path)
34
- execute(request_options(:get, path))
33
+ def get(path, size=nil)
34
+ size = size = 1000
35
+ execute(request_options(:get, path, size))
35
36
  end
36
37
 
37
38
  def delete(path)
38
- execute(request_options(:delete, path))
39
+ execute(request_options(:delete, path, nil))
39
40
  end
40
41
 
41
42
  private
@@ -53,10 +54,13 @@ module Kongfigure
53
54
  }
54
55
  end
55
56
 
56
- def request_options(method, path, payload = nil)
57
+ def request_options(method, path, size, payload = nil)
57
58
  uri = URI.join(@configuration[:url], path)
58
- uri.query = [uri.query, "size=1000"].compact.join("&")
59
- opts = {
59
+ query = [uri.query]
60
+ query = query + ["size=#{size}"] if size
61
+ query = query.compact
62
+ uri.query = query.join("&") if query.size > 0
63
+ opts = {
60
64
  method: method,
61
65
  url: uri.to_s,
62
66
  headers: HTTP_HEADERS
@@ -83,7 +87,7 @@ module Kongfigure
83
87
  elsif response.code == 404
84
88
  raise Kongfigure::Errors::ResourceNotFound
85
89
  elsif response.code == 409
86
- #raise Kongfigure::Errors::ResourceConflict
90
+ raise Kongfigure::Errors::ResourceConflict
87
91
  elsif response.code == 500
88
92
  raise Kongfigure::Errors::InternalServerError
89
93
  end
@@ -1,32 +1,37 @@
1
1
  module Kongfigure
2
2
  class Kong
3
3
 
4
+ SYNCHRONIZER_MODULES = [
5
+ Kongfigure::Synchronizers::Upstream,
6
+ Kongfigure::Synchronizers::Service,
7
+ Kongfigure::Synchronizers::Consumer,
8
+ Kongfigure::Synchronizers::Plugin
9
+ ]
10
+
4
11
  def initialize(parser, http_client)
5
- @parser = parser
6
- @http_client = http_client
12
+ @parser = parser
13
+ @http_client = http_client
14
+ @synchronizers = {}
15
+ @configuration = @parser.parse!
16
+ load_synchronizers
7
17
  display_information
8
18
  end
9
19
 
10
20
  def apply!
11
- @configuration = @parser.parse!
12
21
  puts @configuration.to_s
22
+ puts "Fetching actual configuration..."
23
+ puts "Do you want to apply this configuration to '#{@configuration.url}' (yes/no)".colorize(:color => :white, :background => :red)
24
+ exit 1 unless gets.strip.downcase == "yes"
13
25
  puts "Applying configuration...".colorize(:color => :white, :background => :red)
14
- apply_all(@configuration.plugins, Kongfigure::Services::Plugin)
15
- apply_all(@configuration.upstreams, Kongfigure::Services::Upstream)
16
- apply_all(@configuration.services, Kongfigure::Services::Service)
17
- apply_all(@configuration.consumers, Kongfigure::Services::Consumer)
26
+ SYNCHRONIZER_MODULES.each do |synchronizer_module|
27
+ apply_all(@synchronizers[synchronizer_module])
28
+ end
18
29
  puts "Done.".colorize(:color => :white, :background => :red)
19
30
  end
20
31
 
21
- def apply_all(resources, service_module)
22
- service = service_module.new(@http_client)
23
- puts "<- Fetching remote #{service.resource_name}..."
24
- remote_resources = service.all
25
-
26
- resources.map do |resource|
27
- service.create_or_update(@http_client, resource, remote_resources)
28
- end
29
- service.cleanup_useless_resources(@http_client, resources, remote_resources)
32
+ def apply_all(synchronizer)
33
+ puts "<- Applying #{synchronizer.resource_api_name}..."
34
+ synchronizer.synchronize_all
30
35
  end
31
36
 
32
37
  def display_information
@@ -36,5 +41,22 @@ module Kongfigure
36
41
  puts "* version: \t#{data['hostname']}"
37
42
  puts "* lua_version: \t#{data['lua_version']}"
38
43
  end
44
+
45
+ private
46
+ def load_synchronizers
47
+ SYNCHRONIZER_MODULES.each do |synchronizer_module|
48
+ resources = case synchronizer_module.to_s
49
+ when Kongfigure::Synchronizers::Upstream.to_s
50
+ @configuration.upstreams
51
+ when Kongfigure::Synchronizers::Service.to_s
52
+ @configuration.services
53
+ when Kongfigure::Synchronizers::Consumer.to_s
54
+ @configuration.consumers
55
+ when Kongfigure::Synchronizers::Plugin.to_s
56
+ @configuration.plugins
57
+ end
58
+ @synchronizers[synchronizer_module] = synchronizer_module.new(@http_client, resources || [])
59
+ end
60
+ end
39
61
  end
40
62
  end
@@ -15,7 +15,9 @@ module Kongfigure
15
15
  parsed_configuration.each do |key, value|
16
16
  case key
17
17
  when "url"
18
- @configuration.url = value
18
+ @configuration.url = parse_url(value)
19
+ when "urls"
20
+ @configuration.url = parse_url(value)
19
21
  when "services"
20
22
  @configuration.add_services(value || [])
21
23
  when "consumers"
@@ -30,5 +32,24 @@ module Kongfigure
30
32
  end
31
33
  @configuration
32
34
  end
35
+
36
+ private
37
+ def parse_url(urls)
38
+ if urls.instance_of?(String)
39
+ urls
40
+ elsif urls.instance_of?(Hash)
41
+ puts "Available URLs: "
42
+ urls.keys.each_with_index do | key, index |
43
+ puts "#{index}: #{key} -> #{urls[key]}"
44
+ end
45
+ puts "Enter the URL index:"
46
+ index = STDIN.gets.chomp
47
+ url = urls[urls.keys[index.to_i]]
48
+ raise "Wrong URL index: #{index}" if url.nil?
49
+ url
50
+ else
51
+ raise "Can't parse URL: #{urls}."
52
+ end
53
+ end
33
54
  end
34
55
  end
@@ -1,14 +1,21 @@
1
- require "dry/inflector"
2
-
3
1
  module Kongfigure::Resources
4
2
  class Base
5
3
 
6
- attr_accessor :id, :kongfigure_ignore_fields, :plugins
4
+ attr_accessor :id, :kongfigure_ignore_fields, :plugins, :updated, :unchanged
7
5
 
8
6
  def initialize(id, kongfigure_ignore_fields = nil)
9
7
  @id = id
10
8
  @kongfigure_ignore_fields = (kongfigure_ignore_fields || []).map { |field| field.split(".") }
9
+ if self.class != Kongfigure::Resources::Plugin && self.class != Kongfigure::Resources::Route
10
+ @kongfigure_ignore_fields.push("id")
11
+ end
11
12
  @plugins = []
13
+ @updated = false
14
+ @unchanged = false
15
+ end
16
+
17
+ def plugin_allowed?
18
+ true
12
19
  end
13
20
 
14
21
  def self.build_all(resources_hash)
@@ -18,10 +25,35 @@ module Kongfigure::Resources
18
25
  end
19
26
 
20
27
  def ==(other_object)
21
- differences = deep_diff(other_object.api_attributes, api_attributes, kongfigure_ignore_fields)
22
- differences.flatten.size == 0
28
+ differences = deep_diff(other_object.api_attributes, api_attributes, kongfigure_ignore_fields)
29
+ differences_count = differences.flatten.size
30
+ if differences_count > 0
31
+ ap api_attributes
32
+ ap other_object.api_attributes
33
+ ap differences
34
+ end
35
+ differences_count == 0
36
+ end
37
+
38
+ def display_name
39
+ identifier
23
40
  end
24
41
 
42
+ def mark_as_updated
43
+ @updated = true
44
+ end
45
+
46
+ def mark_as_unchanged
47
+ @unchanged = true
48
+ end
49
+
50
+ def has_to_be_deleted?
51
+ @updated == false && @unchanged == false
52
+ end
53
+
54
+ def api_name
55
+ raise NotImplementedError
56
+ end
25
57
  private
26
58
 
27
59
  def deep_diff(a, b, ignore_nested_keys=[], level=0)
@@ -18,6 +18,10 @@ module Kongfigure::Resources
18
18
  username
19
19
  end
20
20
 
21
+ def api_name
22
+ "consumers"
23
+ end
24
+
21
25
  def api_attributes
22
26
  {
23
27
  "username" => username,
@@ -9,6 +9,18 @@ module Kongfigure::Resources::Consumers
9
9
  acl
10
10
  end
11
11
 
12
+ def plugin_allowed?
13
+ false
14
+ end
15
+
16
+ def identifier
17
+ group
18
+ end
19
+
20
+ def api_name
21
+ "acls"
22
+ end
23
+
12
24
  def api_attributes
13
25
  {
14
26
  "group" => group
@@ -9,6 +9,18 @@ module Kongfigure::Resources::Consumers
9
9
  key_auth
10
10
  end
11
11
 
12
+ def plugin_allowed?
13
+ false
14
+ end
15
+
16
+ def identifier
17
+ key
18
+ end
19
+
20
+ def api_name
21
+ "key-auth"
22
+ end
23
+
12
24
  def api_attributes
13
25
  {
14
26
  "key" => key
@@ -1,9 +1,11 @@
1
1
  module Kongfigure::Resources
2
2
  class Plugin < Base
3
- attr_accessor :name, :config, :enabled, :route, :service, :consumer, :run_on
3
+ attr_accessor :name, :config, :enabled, :route, :service, :consumer, :run_on, :id
4
4
 
5
5
  def self.build(hash)
6
+ raise "Plugin ID is missing for #{hash.inspect}" if hash["id"].nil?
6
7
  plugin = new(hash["id"], hash["kongfigure_ignore_fields"])
8
+ plugin.id = hash["id"]
7
9
  plugin.config = hash["config"]
8
10
  plugin.name = hash["name"]
9
11
  plugin.enabled = hash["enabled"]
@@ -14,19 +16,24 @@ module Kongfigure::Resources
14
16
  plugin
15
17
  end
16
18
 
19
+ def plugin_allowed?
20
+ false
21
+ end
22
+
17
23
  def identifier
18
- name
24
+ id
19
25
  end
20
26
 
21
27
  def api_attributes
22
28
  {
23
- "name" => name,
24
- "config" => config,
25
- "enabled" => enabled,
26
- "route" => route,
27
- "service" => service,
29
+ "id" => id,
30
+ "name" => name,
31
+ "config" => config || {},
32
+ "enabled" => enabled,
33
+ "route" => route,
34
+ "service" => service,
28
35
  "consumer" => consumer,
29
- "run_on" => run_on
36
+ "run_on" => run_on
30
37
  }.compact
31
38
  end
32
39
 
@@ -34,8 +41,16 @@ module Kongfigure::Resources
34
41
  service.nil? && route.nil? && consumer.nil?
35
42
  end
36
43
 
44
+ def display_name
45
+ name + " (id: #{identifier})"
46
+ end
47
+
48
+ def api_name
49
+ "plugins"
50
+ end
51
+
37
52
  def to_s
38
- str = name
53
+ str = display_name
39
54
  if route
40
55
  str += " on route #{route}"
41
56
  elsif service
@@ -4,6 +4,7 @@ module Kongfigure::Resources
4
4
  :sources, :destinations, :service
5
5
 
6
6
  def self.build(hash)
7
+ raise "Route ID is missing for #{hash.inspect}" if hash["id"].nil?
7
8
  route = new(hash["id"], hash["kongfigure_ignore_fields"])
8
9
  route.name = hash["name"]
9
10
  route.protocols = hash["protocols"]
@@ -20,11 +21,24 @@ module Kongfigure::Resources
20
21
  end
21
22
 
22
23
  def identifier
23
- name
24
+ id
25
+ end
26
+
27
+ def api_name
28
+ "routes"
29
+ end
30
+
31
+ def display_name
32
+ if name.nil?
33
+ "default route"
34
+ else
35
+ "route (name: #{name})"
36
+ end
24
37
  end
25
38
 
26
39
  def api_attributes
27
40
  {
41
+ "id" => id,
28
42
  "name" => name,
29
43
  "protocols" => protocols,
30
44
  "methods" => methods,
@@ -26,6 +26,10 @@ module Kongfigure::Resources
26
26
  service
27
27
  end
28
28
 
29
+ def api_name
30
+ "services"
31
+ end
32
+
29
33
  def identifier
30
34
  name
31
35
  end
@@ -9,6 +9,10 @@ module Kongfigure::Resources
9
9
  target
10
10
  end
11
11
 
12
+ def api_name
13
+ "targets"
14
+ end
15
+
12
16
  def api_attributes
13
17
  {
14
18
  "target" => target,
@@ -31,6 +31,10 @@ module Kongfigure::Resources
31
31
  end
32
32
  end
33
33
 
34
+ def api_name
35
+ "upstreams"
36
+ end
37
+
34
38
  def api_attributes
35
39
  {
36
40
  "name" => name,
@@ -0,0 +1,107 @@
1
+ require "colorize"
2
+
3
+ module Kongfigure::Synchronizers
4
+ class Base
5
+
6
+ attr_reader :remote_resources, :resources, :parent_resource
7
+
8
+ def initialize(http_client, resources, parent_resource=nil)
9
+ @http_client = http_client
10
+ @parent_resource = parent_resource
11
+ @resources = resources
12
+ @remote_resources = load_all_remote_resources
13
+ end
14
+
15
+ def find(identifier)
16
+ module_name = Kongfigure::Resources.const_get(self.class.to_s.split("::").last)
17
+ module_name.build(@http_client.get("#{resource_api_name}/#{identifier}"))
18
+ rescue Kongfigure::Errors::ResourceNotFound
19
+ nil
20
+ end
21
+
22
+ def synchronize_resource(resource)
23
+ remote_resource = find_related_remote_resource(resource)
24
+ if remote_resource.nil?
25
+ create(resource)
26
+ elsif resource == remote_resource
27
+ unchanged(resource)
28
+ remote_resource.mark_as_unchanged
29
+ else
30
+ update(resource, remote_resource)
31
+ remote_resource.mark_as_updated
32
+ end
33
+ end
34
+
35
+ def synchronize_plugins(resource)
36
+ plugins_synchronizer = Kongfigure::Synchronizers::Plugin.new(@http_client, resource.plugins, resource)
37
+ plugins_synchronizer.synchronize_all
38
+ end
39
+
40
+ def synchronize(resource)
41
+ synchronize_resource(resource)
42
+ synchronize_plugins(resource)
43
+ end
44
+
45
+ def synchronize_all
46
+ @resources.each do |resource|
47
+ synchronize(resource)
48
+ end
49
+ @remote_resources.each do |remote_resource|
50
+ cleanup(remote_resource) if remote_resource.has_to_be_deleted?
51
+ end
52
+ end
53
+
54
+ def cleanup(remote_resource)
55
+ puts "#{parent_resource.nil? ? '' : ' *'}#{'---'.colorize(:red)} #{remote_resource.display_name}"
56
+ path = if parent_resource
57
+ "#{parent_resource.api_name}/#{parent_resource.identifier}/#{resource_api_name}/#{remote_resource.identifier}"
58
+ else
59
+ "#{resource_api_name}/#{remote_resource.identifier}"
60
+ end
61
+ @http_client.delete(path)
62
+ end
63
+
64
+ def create(resource)
65
+ puts "#{parent_resource.nil? ? '' : ' *'}#{'+++'.colorize(:green)} #{resource.display_name}"
66
+ path = if parent_resource
67
+ "#{parent_resource.api_name}/#{parent_resource.identifier}/#{resource_api_name}"
68
+ else
69
+ "#{resource_api_name}"
70
+ end
71
+ @http_client.post(path, resource.api_attributes.to_json)
72
+ end
73
+
74
+ def unchanged(resource)
75
+ puts "#{parent_resource.nil? ? '' : ' *'}#{'==='.colorize(:blue)} #{resource.display_name}"
76
+ end
77
+
78
+ def update(resource, remote_resource)
79
+ puts "#{'uuu'.colorize(:yellow)} #{resource.display_name}"
80
+ path = if parent_resource
81
+ "#{parent_resource.api_name}/#{parent_resource.identifier}/#{resource_api_name}/#{remote_resource.identifier}"
82
+ else
83
+ "#{resource_api_name}/#{remote_resource.identifier}"
84
+ end
85
+ @http_client.put(path, resource.api_attributes.to_json)
86
+ end
87
+
88
+ private
89
+ def load_all_remote_resources
90
+ if parent_resource.nil?
91
+ @http_client.get("#{resource_api_name}")["data"].map do |hash_resource|
92
+ resource_module.build(hash_resource)
93
+ end
94
+ else
95
+ @http_client.get("#{parent_resource.api_name}/#{parent_resource.identifier}/#{resource_api_name}")["data"].map do |hash_resource|
96
+ resource_module.build(hash_resource)
97
+ end
98
+ end
99
+ end
100
+
101
+ def find_related_remote_resource(resource)
102
+ remote_resources.find do|remote_resource|
103
+ resource.identifier == remote_resource.identifier
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,22 @@
1
+ module Kongfigure::Synchronizers
2
+ class Consumer < Base
3
+
4
+ def synchronize(resource)
5
+ super(resource)
6
+ key_auths_synchronizer = Kongfigure::Synchronizers::Consumers::KeyAuth.new(@http_client, resource.key_auths, resource)
7
+ key_auths_synchronizer.synchronize_all
8
+
9
+ acls_synchronizer = Kongfigure::Synchronizers::Consumers::ACL.new(@http_client, resource.acls, resource)
10
+ acls_synchronizer.synchronize_all
11
+ end
12
+
13
+ def resource_module
14
+ Kongfigure::Resources::Consumer
15
+ end
16
+
17
+ def resource_api_name
18
+ "consumers"
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,16 @@
1
+ module Kongfigure::Synchronizers::Consumers
2
+ class ACL < Kongfigure::Synchronizers::Base
3
+
4
+ def resource_module
5
+ Kongfigure::Resources::Consumers::ACL
6
+ end
7
+
8
+ def resource_api_name
9
+ "acls"
10
+ end
11
+
12
+ def synchronize(resource)
13
+ synchronize_resource(resource)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Kongfigure::Synchronizers::Consumers
2
+ class KeyAuth < Kongfigure::Synchronizers::Base
3
+
4
+ def resource_module
5
+ Kongfigure::Resources::Consumers::KeyAuth
6
+ end
7
+
8
+ def resource_api_name
9
+ "key-auth"
10
+ end
11
+
12
+ def synchronize(resource)
13
+ synchronize_resource(resource)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ module Kongfigure::Synchronizers
2
+ class Plugin < Base
3
+
4
+ def load_all_remote_resources
5
+ remote_resources = if parent_resource.nil?
6
+ super.filter do |resource|
7
+ resource.is_global?
8
+ end
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ def resource_module
15
+ Kongfigure::Resources::Plugin
16
+ end
17
+
18
+ def resource_api_name
19
+ "plugins"
20
+ end
21
+
22
+ def synchronize(resource)
23
+ synchronize_resource(resource)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ module Kongfigure::Synchronizers
2
+ class Route < Base
3
+
4
+ def resource_module
5
+ Kongfigure::Resources::Route
6
+ end
7
+
8
+ def resource_api_name
9
+ "routes"
10
+ end
11
+
12
+ def synchronize(resource)
13
+ synchronize_resource(resource)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module Kongfigure::Synchronizers
2
+ class Service < Base
3
+
4
+ def resource_module
5
+ Kongfigure::Resources::Service
6
+ end
7
+
8
+ def resource_api_name
9
+ "services"
10
+ end
11
+
12
+ def synchronize_routes(resource)
13
+ routes_synchronizer = Kongfigure::Synchronizers::Route.new(@http_client, resource.routes, resource)
14
+ routes_synchronizer.synchronize_all
15
+ end
16
+
17
+ def synchronize(resource)
18
+ synchronize_resource(resource)
19
+ synchronize_routes(resource)
20
+ synchronize_plugins(resource)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ module Kongfigure::Synchronizers
2
+ class Upstream < Base
3
+
4
+ def resource_module
5
+ Kongfigure::Resources::Upstream
6
+ end
7
+
8
+ def resource_api_name
9
+ "upstreams"
10
+ end
11
+
12
+ def synchronize(resource)
13
+ synchronize_resource(resource)
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,3 @@
1
1
  module Kongfigure
2
- VERSION = "0.0.8"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kongfigure
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ibanity
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-29 00:00:00.000000000 Z
11
+ date: 2020-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,18 +122,20 @@ files:
122
122
  - lib/kongfigure/resources/service.rb
123
123
  - lib/kongfigure/resources/target.rb
124
124
  - lib/kongfigure/resources/upstream.rb
125
- - lib/kongfigure/services/base.rb
126
- - lib/kongfigure/services/consumer.rb
127
- - lib/kongfigure/services/plugin.rb
128
- - lib/kongfigure/services/route.rb
129
- - lib/kongfigure/services/service.rb
130
- - lib/kongfigure/services/upstream.rb
125
+ - lib/kongfigure/synchronizers/base.rb
126
+ - lib/kongfigure/synchronizers/consumer.rb
127
+ - lib/kongfigure/synchronizers/consumers/acl.rb
128
+ - lib/kongfigure/synchronizers/consumers/key_auth.rb
129
+ - lib/kongfigure/synchronizers/plugin.rb
130
+ - lib/kongfigure/synchronizers/route.rb
131
+ - lib/kongfigure/synchronizers/service.rb
132
+ - lib/kongfigure/synchronizers/upstream.rb
131
133
  - lib/kongfigure/version.rb
132
134
  homepage: https://github.com/ibanity/kongfigure
133
135
  licenses:
134
136
  - MIT
135
137
  metadata: {}
136
- post_install_message:
138
+ post_install_message:
137
139
  rdoc_options: []
138
140
  require_paths:
139
141
  - lib
@@ -149,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
151
  version: '0'
150
152
  requirements: []
151
153
  rubygems_version: 3.0.3
152
- signing_key:
154
+ signing_key:
153
155
  specification_version: 4
154
156
  summary: Kongfigure.
155
157
  test_files: []
@@ -1,168 +0,0 @@
1
- require "colorize"
2
-
3
- module Kongfigure::Services
4
- class Base
5
-
6
- def initialize(http_client)
7
- @http_client = http_client
8
- end
9
-
10
- def resource_name
11
- Dry::Inflector.new.pluralize(self.class.to_s.split("::").last.downcase.gsub("_", "-"))
12
- end
13
-
14
- def self.resource_name
15
- Dry::Inflector.new.pluralize(self.to_s.split("::").last.downcase.gsub("_", "-"))
16
- end
17
-
18
- def all
19
- module_name = Kongfigure::Resources.const_get(self.class.to_s.split("::").last)
20
- @http_client.get("#{resource_name}")["data"].map do |hash_resource|
21
- case resource_name
22
- when "consumers"
23
- hash_resource["acls"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/acls")["data"]
24
- hash_resource["key_auths"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/key-auth")["data"]
25
- hash_resource["plugins"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/plugins")["data"]
26
- when "upstreams"
27
- hash_resource["targets"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/targets")["data"]
28
- when "services"
29
- hash_resource["plugins"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/plugins")["data"]
30
- hash_resource["routes"] = @http_client.get("#{resource_name}/#{hash_resource['id']}/routes")["data"]
31
- end
32
- module_name.build(hash_resource)
33
- end
34
- end
35
-
36
- def create_or_update(http_client, resource, remote_resources)
37
- handle_api_errors do
38
- related_remote_resource = find_related_resource(resource, remote_resources)
39
- if related_remote_resource && need_update?(resource, related_remote_resource)
40
- puts "-> Update #{resource.class.name} (#{resource.identifier}).".colorize(:light_blue)
41
- update(http_client, resource, related_remote_resource)
42
- elsif related_remote_resource && need_update_dependencies?(resource, related_remote_resource)
43
- puts "-> Update dependencies #{resource.class.name} (#{resource.identifier}).".colorize(:light_blue)
44
- update_dependencies(http_client, resource, related_remote_resource)
45
- elsif related_remote_resource
46
- #noop
47
- else
48
- puts "-> Create #{resource.class.name} (#{resource.identifier}).".colorize(:green)
49
- create(http_client, resource, related_remote_resource)
50
- end
51
- end
52
- end
53
-
54
- def create(http_client, resource, _related_remote_resource)
55
- module_name = Kongfigure::Resources.const_get(self.class.to_s.split("::").last)
56
- data = http_client.post("#{resource_name}", resource.api_attributes.to_json)
57
- create_dependencies(http_client, resource, module_name.build(data))
58
- end
59
-
60
- def update(http_client, resource, related_remote_resource)
61
- http_client.put("#{resource_name}/#{related_remote_resource.id}", resource.api_attributes.to_json) if need_update?(resource, related_remote_resource)
62
- update_dependencies(http_client, resource, related_remote_resource)
63
- end
64
-
65
- def cleanup(http_client, resource, related_remote_resource)
66
- puts "-> Cleanup #{related_remote_resource.class.name} (#{related_remote_resource.identifier}).".colorize(:magenta)
67
- http_client.delete("#{resource_name}/#{related_remote_resource.id}")
68
- end
69
-
70
- def cleanup_useless_resources(http_client, local_resources, remote_resources)
71
- useless_remote_resources = remote_resources.each do |remote_resource|
72
- related_local_resource = find_related_resource(remote_resource, local_resources)
73
- handle_api_errors do
74
- if need_cleanup_dependencies?(related_local_resource, remote_resource)
75
- cleanup_dependencies(http_client, related_local_resource, remote_resource)
76
- end
77
- unless related_local_resource
78
- cleanup(http_client, related_local_resource, remote_resource)
79
- end
80
- end
81
- end
82
- end
83
-
84
- def find_related_resource(target_resource, resources)
85
- resources.find do|resource|
86
- case target_resource.class
87
- when Kongfigure::Resources::Plugin
88
- resource.name == target_resource.name &&
89
- resource.service == target_resource.service &&
90
- resource.consumer == target_resource.consumer &&
91
- resource.route == target_resource.route
92
- else
93
- resource.identifier == target_resource.identifier
94
- end
95
- end
96
- end
97
-
98
- def need_update?(resource, related_remote_resource)
99
- resource != related_remote_resource
100
- end
101
-
102
- def need_update_dependencies?(resource, related_remote_resource)
103
- need_update_plugins?(resource, related_remote_resource)
104
- end
105
-
106
- def need_cleanup_dependencies?(resource, related_remote_resource)
107
- resource.nil? || need_cleanup_plugins?(resource, related_remote_resource)
108
- end
109
-
110
- def has_plugins?(resource)
111
- resource.plugins && resource.plugins.size > 0
112
- end
113
-
114
- def update_dependencies(http_client, local_resource, related_remote_resource)
115
- create_or_update_plugins(http_client, local_resource, related_remote_resource)
116
- end
117
-
118
- def create_dependencies(http_client, local_resource, related_remote_resource)
119
- create_or_update_plugins(http_client, local_resource, related_remote_resource)
120
- end
121
-
122
- def cleanup_dependencies(http_client, local_resource, related_remote_resource)
123
- puts "-> Cleanup dependencies #{related_remote_resource.class.name} (#{related_remote_resource.identifier}).".colorize(:magenta)
124
- cleanup_plugins(http_client, local_resource, related_remote_resource)
125
- end
126
-
127
- def handle_api_errors(&block)
128
- begin
129
- yield
130
- rescue Kongfigure::Errors::BadRequest => e
131
- puts "<- Bad request: #{e.message}".colorize(:red)
132
- end
133
- end
134
-
135
- def need_update_plugins?(resource, related_remote_resource)
136
- resource.plugins.reject do |plugin|
137
- related_plugin = find_related_resource(plugin, related_remote_resource.plugins)
138
- related_plugin && plugin == related_plugin
139
- end.size != 0
140
- end
141
-
142
- def need_cleanup_plugins?(resource, related_remote_resource)
143
- resource.plugins.reject do |plugin|
144
- related_remote_plugin = find_related_resource(plugin, related_remote_resource.plugins)
145
- related_remote_plugin && plugin == related_remote_plugin
146
- end.size == 0 && resource.plugins.size < related_remote_resource.plugins.size
147
- end
148
-
149
- def create_or_update_plugins(http_client, local_resource, remote_resource)
150
- local_resource.plugins.each do |plugin|
151
- related_plugin = find_related_resource(plugin, remote_resource.plugins)
152
- if related_plugin
153
- http_client.patch("#{resource_name}/#{local_resource.identifier}/plugins/#{related_plugin.id}", plugin.api_attributes.to_json)
154
- else
155
- http_client.post("#{resource_name}/#{local_resource.identifier}/plugins", plugin.api_attributes.to_json)
156
- end
157
- end
158
- end
159
-
160
- def cleanup_plugins(http_client, local_resource, remote_resource)
161
- remote_resource.plugins.each do |plugin|
162
- if local_resource.nil? || find_related_resource(plugin, local_resource.plugins).nil?
163
- http_client.delete("#{resource_name}/#{remote_resource.identifier}/plugins/#{plugin.id}")
164
- end
165
- end
166
- end
167
- end
168
- end
@@ -1,60 +0,0 @@
1
- module Kongfigure::Services
2
- class Consumer < Base
3
- def create_dependencies(http_client, resource, related_resource)
4
- super(http_client, resource, related_resource)
5
- create_key_auths(http_client, resource, related_resource)
6
- create_acls(http_client, resource, related_resource)
7
- end
8
-
9
- def update_dependencies(http_client, resource, related_resource)
10
- super(http_client, resource, related_resource)
11
- create_key_auths(http_client, resource, related_resource)
12
- create_acls(http_client, resource, related_resource)
13
- end
14
-
15
- def cleanup_dependencies(http_client, resource, related_resource)
16
- super(http_client, resource, related_resource)
17
- cleanup_key_auths(http_client, resource, related_resource)
18
- cleanup_acls(http_client, resource, related_resource)
19
- end
20
-
21
- def need_update_dependencies?(resource, related_resource)
22
- super(resource, related_resource) ||
23
- (resource && (resource.acls != related_resource.acls || resource.key_auths != related_resource.key_auths))
24
- end
25
-
26
- private
27
-
28
- def create_acls(http_client, resource, related_resource)
29
- resource.acls.each do |acl|
30
- unless related_resource.has_acl?(acl)
31
- http_client.post("#{resource_name}/#{related_resource.identifier}/acls", acl.api_attributes.to_json)
32
- end
33
- end
34
- end
35
-
36
- def create_key_auths(http_client, resource, related_resource)
37
- resource.key_auths.each do |key_auth|
38
- unless related_resource.has_key_auth?(key_auth)
39
- http_client.post("#{resource_name}/#{related_resource.identifier}/key-auth", key_auth.api_attributes.to_json)
40
- end
41
- end
42
- end
43
-
44
- def cleanup_key_auths(http_client, local_resource, remote_resource)
45
- remote_resource.key_auths.each do |remote_resource_key_auth|
46
- unless local_resource && local_resource.has_key_auth?(remote_resource_key_auth)
47
- http_client.delete("#{resource_name}/#{remote_resource.identifier}/key-auth/#{remote_resource_key_auth.id}")
48
- end
49
- end
50
- end
51
-
52
- def cleanup_acls(http_client, local_resource, remote_resource)
53
- remote_resource.acls.each do |remote_resource_acl|
54
- unless local_resource && local_resource.has_acl?(remote_resource_acl)
55
- http_client.delete("#{resource_name}/#{remote_resource.identifier}/acls/#{remote_resource_acl.id}")
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,18 +0,0 @@
1
- module Kongfigure::Services
2
- class Plugin < Base
3
-
4
- def need_update_dependencies?(resource, related_resource)
5
- false
6
- end
7
-
8
- def need_cleanup_dependencies?(resource, related_resource)
9
- false
10
- end
11
-
12
- def cleanup(http_client, resource, related_resource)
13
- return unless related_resource.is_global?
14
- puts "-> Cleanup #{related_resource.class.name} (#{related_resource.identifier}).".colorize(:magenta)
15
- http_client.delete("#{resource_name}/#{related_resource.id}")
16
- end
17
- end
18
- end
@@ -1,4 +0,0 @@
1
- module Kongfigure::Services
2
- class Route < Base
3
- end
4
- end
@@ -1,53 +0,0 @@
1
- module Kongfigure::Services
2
- class Service < Base
3
- def create_dependencies(http_client, resource, related_remote_resource)
4
- create_routes(http_client, resource, related_remote_resource)
5
- super(http_client, resource, related_remote_resource)
6
- end
7
-
8
- def update_dependencies(http_client, resource, related_remote_resource)
9
- create_routes(http_client, resource, related_remote_resource)
10
- super(http_client, resource, related_remote_resource)
11
- end
12
-
13
- def cleanup_dependencies(http_client, resource, related_remote_resource)
14
- super(http_client, resource, related_remote_resource)
15
- cleanup_routes(http_client, resource, related_remote_resource)
16
- end
17
-
18
- def need_cleanup_dependencies?(resource, related_remote_resource)
19
- super(resource, related_remote_resource) || resource.nil? || resource.routes != related_remote_resource.routes
20
- end
21
-
22
- def need_update_dependencies?(resource, related_remote_resource)
23
- super(resource, related_remote_resource) || (resource && !related_remote_resource.has_routes?(resource.routes))
24
- end
25
-
26
- private
27
-
28
- def create_routes(http_client, resource, related_remote_resource)
29
- resource.routes.each do |route|
30
- unless related_remote_resource.has_route?(route)
31
- http_client.post("#{resource_name}/#{related_remote_resource.identifier}/routes", route.api_attributes.to_json)
32
- end
33
- end
34
- end
35
-
36
- def cleanup_routes(http_client, local_resource, remote_resource)
37
- # cleanup duplicated routes
38
- duplicated_routes = remote_resource.routes.select do |route|
39
- remote_resource.routes.count(route) > 1
40
- end.uniq
41
- duplicated_routes.each do |duplicated_route|
42
- http_client.delete("routes/#{duplicated_route.id}")
43
- remote_resource.routes.delete(duplicated_route)
44
- end
45
- # cleanup useless routes
46
- remote_resource.routes.each do |remote_resource_route|
47
- if local_resource.nil? || !local_resource.has_route?(remote_resource_route)
48
- http_client.delete("routes/#{remote_resource_route.id}")
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,41 +0,0 @@
1
- module Kongfigure::Services
2
- class Upstream < Base
3
- def create_dependencies(http_client, resource, related_resource)
4
- super(http_client, resource, related_resource)
5
- create_targets(http_client, resource, related_resource)
6
- end
7
-
8
- def update_dependencies(http_client, resource, related_resource)
9
- super(http_client, resource, related_resource)
10
- create_targets(http_client, resource, related_resource)
11
- end
12
-
13
- def cleanup_dependencies(http_client, resource, related_resource)
14
- super(http_client, resource, related_resource)
15
- cleanup_targets(http_client, resource, related_resource)
16
- end
17
-
18
- def need_update_dependencies?(resource, related_resource)
19
- super(resource, related_resource) ||
20
- (resource && (resource.targets != related_resource.targets))
21
- end
22
-
23
- private
24
-
25
- def create_targets(http_client, resource, related_resource)
26
- resource.targets.each do |target|
27
- unless related_resource.has_target?(target)
28
- http_client.post("#{resource_name}/#{related_resource.identifier}/targets", target.api_attributes.to_json)
29
- end
30
- end
31
- end
32
-
33
- def cleanup_targets(http_client, local_resource, remote_resource)
34
- remote_resource.targets.each do |remote_resource_target|
35
- if (local_resource.nil? || !local_resource.has_target?(remote_resource_target)) && remote_resource_target.weight > 0
36
- http_client.delete("#{resource_name}/#{remote_resource.identifier}/targets/#{remote_resource_target.id}")
37
- end
38
- end
39
- end
40
- end
41
- end