kong 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.
@@ -0,0 +1,210 @@
1
+ # Kong Client for Ruby
2
+
3
+ [Kong](http://getkong.org) API client for Ruby
4
+
5
+ [![Build Status](https://travis-ci.org/kontena/kong-client-ruby.svg?branch=master)](https://travis-ci.org/kontena/kong-client-ruby)
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'kong'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install kong
19
+
20
+ ## Usage
21
+
22
+ By default Kong client tries to connect `http://localhost:8001` or address provided by environment variable: `KONG_URI='http://your-kong-url:8001'`.
23
+
24
+ You can set it also in your code:
25
+ ```ruby
26
+ require 'kong'
27
+ Kong::Client.api_url = 'http://your-kong-url:8001'
28
+ ```
29
+
30
+ ### Desing
31
+
32
+ Kong client follows a design of resoures as Plain Old Ruby objects(tm). For examples to create a new Consumer resource you can do it like this:
33
+
34
+ ```ruby
35
+ consumer = Kong::Consumer.create({ username: 'testuser', custom_id: 'custom_id' })
36
+ ```
37
+
38
+ OR
39
+
40
+ ```ruby
41
+ consumer = Kong::Consumer.new({ username: 'testuser'})
42
+ consumer.custom_id = '12345'
43
+ consumer.save
44
+ ```
45
+
46
+ To find existing consumer:
47
+
48
+ ```ruby
49
+ consumer = Kong::Consumer.find_by_username('testuser')
50
+ consumer = Kong::Consumer.find_by_custom_id('custom_id')
51
+ ```
52
+
53
+ ### All Resources and Actions
54
+
55
+ #### Consumer
56
+
57
+ ```ruby
58
+ Kong::Consumer.list(filters)
59
+ Kong::Consumer.all()
60
+ Kong::Consumer.find(id)
61
+ Kong::Consumer.find_by_*(value)
62
+ Kong::Consumer.create(attributes)
63
+
64
+ consumer = Kong::Consumer.new({ username: 'test-user' })
65
+ consumer.get # reloads resource
66
+ consumer.create
67
+ consumer.update
68
+ consumer.save # requests create_or_update action
69
+ consumer.delete
70
+
71
+ consumer.plugins
72
+ consumer.oauth_apps
73
+ consumer.key_auths
74
+ consumer.basic_auths
75
+ consumer.oauth2_tokens
76
+ ```
77
+
78
+ #### API
79
+
80
+ ```ruby
81
+ Kong::Api.list(filters)
82
+ Kong::Api.all()
83
+ Kong::Api.find(id)
84
+ Kong::Api.find_by_*(value)
85
+ Kong::Api.create(attributes)
86
+
87
+ api = Kong::Api.new({
88
+ name: 'Mockbin',
89
+ request_host: 'mockbin.com',
90
+ request_path: '/someservice',
91
+ strip_request_path: false,
92
+ preserve_host: false,
93
+ upstream_url: 'https://mockbin.com'
94
+ })
95
+ api.get # reloads resource
96
+ api.create
97
+ api.update
98
+ api.save # requests create_or_update action
99
+ api.delete
100
+
101
+ api.plugins
102
+ ```
103
+
104
+ #### Plugin
105
+
106
+ ```ruby
107
+ Kong::Plugin.list(filters)
108
+ Kong::Plugin.all()
109
+ Kong::Plugin.find(id)
110
+ Kong::Plugin.find_by_*(value)
111
+ Kong::Plugin.create(attributes)
112
+
113
+ plugin = Kong::Plugin.new({
114
+ api_id: '5fd1z584-1adb-40a5-c042-63b19db49x21',
115
+ consumer_id: 'a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4',
116
+ name: 'rate-limiting',
117
+ config: {
118
+ minute: 20,
119
+ hour: 500
120
+ }
121
+ })
122
+
123
+ plugin.get # reloads resource
124
+ plugin.create
125
+ plugin.update
126
+ plugin.save # requests create_or_update action
127
+ plugin.delete
128
+ ```
129
+
130
+ #### OAuthApp
131
+
132
+ ```ruby
133
+ Kong::OAuthApp.list(filters)
134
+ Kong::OAuthApp.all()
135
+ Kong::OAuthApp.find(consumer_id)
136
+ Kong::OAuthApp.find_by_*(value)
137
+ Kong::OAuthApp.create(attributes)
138
+
139
+ app = Kong::OAuthApp.new({
140
+ consumer_id: 'a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4',
141
+ redirect_uri: 'http://some-domain/endpoint/'
142
+ })
143
+
144
+ app.create
145
+ app.get # reloads resource
146
+ app.update
147
+ app.save # requests create_or_update action
148
+ app.delete
149
+ ```
150
+
151
+ #### KeyAuth
152
+
153
+ ```ruby
154
+ Kong::KeyAuth.create(attributes)
155
+
156
+ auth = Kong::KeyAuth.new({
157
+ consumer_id: 'a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4',
158
+ })
159
+
160
+ auth.create
161
+ auth.get # reloads resource
162
+ auth.update
163
+ auth.save # requests create_or_update action
164
+ auth.delete
165
+ ```
166
+
167
+ #### BasicAuth
168
+
169
+ ```ruby
170
+ Kong::KeyAuth.create(attributes)
171
+
172
+ auth = Kong::BasicAuth.new({
173
+ consumer_id: 'a3dX2dh2-1adb-40a5-c042-63b19dbx83hF4',
174
+ username: 'user123',
175
+ password: 'secret'
176
+ })
177
+
178
+ auth.create
179
+ auth.get # reloads resource
180
+ auth.update
181
+ auth.save # requests create_or_update action
182
+ auth.delete
183
+ ```
184
+
185
+ #### OAuth2Token
186
+
187
+ ```ruby
188
+ token = Kong::OAuth2Token.find_by_access_token('SOME-TOKEN')
189
+
190
+ token = Kong::OAuth2Token.new({
191
+ credential_id: 'KONG-APPLICATION-ID',
192
+ token_type: 'bearer',
193
+ access_token: 'SOME-TOKEN',
194
+ refresh_token: 'SOME-TOKEN',
195
+ expires_in: 3600
196
+ })
197
+
198
+ token.create
199
+ token.update
200
+ token.save # requests create_or_update action
201
+ token.delete
202
+ ```
203
+
204
+ ## Contributing
205
+
206
+ 1. Fork it ( https://github.com/kontena/kong-client-ruby/fork )
207
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
208
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
209
+ 4. Push to the branch (`git push origin my-new-feature`)
210
+ 5. Create a new Pull Request
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir.glob('tasks/*.rake').each { |r| import r }
4
+
5
+ task :default => :spec
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kong/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kong"
8
+ spec.version = Kong::VERSION
9
+ spec.authors = ["Lauri Nevala"]
10
+ spec.email = ["lauri@kontena.io"]
11
+ spec.summary = %q{A Ruby client for the Kong API }
12
+ spec.description = %q{A Ruby client for the Kong API}
13
+ spec.homepage = "https://github.com/kontena/kong-client-ruby"
14
+ spec.license = "Apache-2.0"
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.required_ruby_version = ">= 2.0.0"
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_runtime_dependency "excon", "~> 0.49.0"
24
+ end
@@ -0,0 +1,13 @@
1
+ require 'kong/version'
2
+ require 'kong/base'
3
+ require 'kong/api'
4
+ require 'kong/belongs_to_api'
5
+ require 'kong/client'
6
+ require 'kong/consumer'
7
+ require 'kong/belongs_to_consumer'
8
+ require 'kong/plugin'
9
+ require 'kong/error'
10
+ require 'kong/oauth_app'
11
+ require 'kong/oauth2_token'
12
+ require 'kong/basic_auth'
13
+ require 'kong/key_auth'
@@ -0,0 +1,14 @@
1
+ module Kong
2
+ class Api
3
+ include Base
4
+
5
+ ATTRIBUTE_NAMES = %w(id name request_host request_path strip_request_path preserve_host upstream_url).freeze
6
+ API_END_POINT = '/apis/'.freeze
7
+
8
+ ##
9
+ # @return [Array<Kong::Plugin>]
10
+ def plugins
11
+ Plugin.list({ api_id: self.id })
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,153 @@
1
+ module Kong
2
+ module Base
3
+ module ClassMethods
4
+
5
+ # List resources
6
+ # @return [Array]
7
+ def list(params = {})
8
+ result = []
9
+ json_data = Client.instance.get(self::API_END_POINT, params)
10
+ if json_data['data']
11
+ json_data['data'].each do |instance|
12
+ result << self.new(instance)
13
+ end
14
+ end
15
+ result
16
+ end
17
+
18
+ alias_method :all, :list
19
+
20
+ # Create resource
21
+ # @param [Hash] attributes
22
+ def create(attributes = {})
23
+ self.new(attributes).create
24
+ end
25
+
26
+ # Find resource
27
+ # @param [String] id
28
+ def find(id)
29
+ self.new.get(id)
30
+ end
31
+
32
+ def method_missing(method, *arguments, &block)
33
+ if method.to_s.start_with?('find_by_')
34
+ attribute = method.to_s.sub('find_by_', '')
35
+ if self.attribute_names.include?(attribute)
36
+ self.list({ attribute => arguments[0] })[0]
37
+ else
38
+ super
39
+ end
40
+ else
41
+ super
42
+ end
43
+ end
44
+ end
45
+
46
+ attr_accessor :attributes, :api_end_point
47
+
48
+ def self.included(base)
49
+ base.extend(ClassMethods)
50
+
51
+ base.send(:define_singleton_method, :attribute_names) do
52
+ base::ATTRIBUTE_NAMES
53
+ end
54
+
55
+ base.send(:define_method, :init_api_end_point) do
56
+ @api_end_point = base::API_END_POINT
57
+ end
58
+ end
59
+
60
+ ##
61
+ # @param [Hash] attributes
62
+ def initialize(attributes = {})
63
+ init_api_end_point
64
+ init_attributes(attributes)
65
+ end
66
+
67
+ # Get Kong API client
68
+ # @return [Kong::Client]
69
+ def client
70
+ Client.instance
71
+ end
72
+
73
+
74
+ # Get resource
75
+ # @param [String] key
76
+ def get(key = nil)
77
+ key = self.id if key.nil?
78
+ path = @api_end_point + key
79
+ response = client.get(path) rescue nil
80
+ return nil if response.nil?
81
+ init_attributes(response)
82
+ self
83
+ end
84
+
85
+ # Delete resource
86
+ def delete
87
+ client.delete("#{@api_end_point}#{self.id}")
88
+ end
89
+
90
+ def new?
91
+ self.id.nil?
92
+ end
93
+
94
+ # Save resource to Kong
95
+ def save
96
+ create_or_update
97
+ end
98
+
99
+ # Create resource
100
+ def create
101
+ headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
102
+ response = client.post(@api_end_point, nil, attributes, headers)
103
+ init_attributes(response)
104
+ self
105
+ end
106
+
107
+ # Create or update resource
108
+ # Data is sent to Kong in JSON format and HTTP PUT request is used
109
+ def create_or_update
110
+ headers = { 'Content-Type' => 'application/json' }
111
+ response = client.put("#{@api_end_point}", attributes, nil, headers)
112
+ init_attributes(response)
113
+ self
114
+ end
115
+
116
+ # Update resource
117
+ def update
118
+ headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
119
+ response = client.patch("#{@api_end_point}#{self.id}", nil, attributes, headers)
120
+ init_attributes(response)
121
+ self
122
+ end
123
+
124
+ def method_missing(method, *arguments, &block)
125
+ if self.class.attribute_names.include?(method.to_s)
126
+ @attributes[method.to_s]
127
+ elsif method.to_s.end_with?('=') && self.class.attribute_names.include?(attribute = method.to_s.split('=').first)
128
+ @attributes[attribute] = arguments[0]
129
+ else
130
+ super
131
+ end
132
+ end
133
+
134
+ def respond_to?(method, include_private = false)
135
+ if self.class.attribute_names.include?(method.to_s.split('=')[0])
136
+ true
137
+ else
138
+ super
139
+ end
140
+ end
141
+
142
+ private
143
+
144
+ def init_attributes(attributes)
145
+ @attributes = {}
146
+ attributes.each do |key, value|
147
+ @attributes[key.to_s] = value
148
+ end
149
+ use_consumer_end_point if respond_to?(:use_consumer_end_point)
150
+ use_api_end_point if respond_to?(:use_api_end_point)
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,8 @@
1
+ module Kong
2
+ class BasicAuth
3
+ include Base
4
+ include BelongsToConsumer
5
+ ATTRIBUTE_NAMES = %w(id username password consumer_id).freeze
6
+ API_END_POINT = "/basic-auth/".freeze
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ module Kong
2
+ module BelongsToApi
3
+ attr_accessor :api
4
+
5
+ # Convert API end point relative to Kong API resource
6
+ def use_api_end_point
7
+ self.api_end_point = "/apis/#{self.api_id}#{self.class::API_END_POINT}" if self.api_id
8
+ end
9
+
10
+ # Get Api resource
11
+ # @return [Kong::Api]
12
+ def api
13
+ @api ||= Api.find(self.api_id)
14
+ end
15
+
16
+ # Set Api resource
17
+ # @param [Kong::Api] api
18
+ def api=(api)
19
+ @api = api
20
+ self.api_id = api.id
21
+ end
22
+
23
+ # Set Api id
24
+ # @param [String] id
25
+ def api_id=(id)
26
+ super(id)
27
+ use_api_end_point
28
+ end
29
+ end
30
+ end