apipie-bindings 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +5 -0
- data/README.md +83 -0
- data/lib/apipie-bindings.rb +1 -0
- data/lib/apipie_bindings.rb +15 -0
- data/lib/apipie_bindings/action.rb +76 -0
- data/lib/apipie_bindings/api.rb +178 -0
- data/lib/apipie_bindings/example.rb +21 -0
- data/lib/apipie_bindings/param.rb +34 -0
- data/lib/apipie_bindings/resource.rb +49 -0
- data/lib/apipie_bindings/route.rb +37 -0
- data/lib/apipie_bindings/version.rb +5 -0
- data/test/unit/action_test.rb +61 -0
- data/test/unit/api_test.rb +109 -0
- data/test/unit/data/architecture.json +153 -0
- data/test/unit/example_test.rb +25 -0
- data/test/unit/main_test.rb +5 -0
- data/test/unit/param_test.rb +57 -0
- data/test/unit/resource_test.rb +49 -0
- data/test/unit/route_test.rb +36 -0
- data/test/unit/test_helper.rb +19 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f00c3378b7cf3f91734f1a97d241da813a71e53d
|
4
|
+
data.tar.gz: 9530ae0e0a9a00c5c73986bdde9f072064c0bcb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f54f73e6605fa985aa4fc17f68776184eae491ba1cdfc277756182106e21bc57e202402f13d522643a274e5ba4f268e4bb86861c141c0ea7a46fd79d4ad83cc4
|
7
|
+
data.tar.gz: acbb649416de9369c3905173bbc3477dac2a05883cc85b5713413bea0bd83cd6fc3741c2f65050086880fd0c02a0e3289808fa257dd3ec7c06a45eb5e89c8f32
|
data/LICENSE
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
This program and entire repository is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
|
2
|
+
|
3
|
+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
4
|
+
|
5
|
+
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
Apipie Bindings
|
2
|
+
===============
|
3
|
+
|
4
|
+
The Ruby bindings for Apipie documented APIs.
|
5
|
+
|
6
|
+
Features
|
7
|
+
--------
|
8
|
+
|
9
|
+
#### Caching
|
10
|
+
The bindings cache the apidoc from the server. It has separated caches for each server it connects to. If the server sends apidoc hash in the headers ```Apipie-Apidoc-Hash: <md5>``` , the bindings can expire the cache and reload updated version before next request. If the server does not send the hashes, the cache does not expire and has to be deleted manually when necessary.
|
11
|
+
|
12
|
+
Sample patch for the server can be found here https://github.com/mbacovsky/foreman/commit/d35d76b9032bb3d3de2da7fb1dc780600eb08bdd
|
13
|
+
|
14
|
+
#### API introspection
|
15
|
+
It is possible to list available resources, actions, params, routes and its attributes
|
16
|
+
|
17
|
+
##### Getting started
|
18
|
+
```
|
19
|
+
$ rake install
|
20
|
+
$ irb
|
21
|
+
irb(main):003:0> require 'apipie-bindings'
|
22
|
+
|
23
|
+
irb(main):001:0> api = ApipieBindings::API.new({:uri => 'http://localhost:3000/', :username => 'admin', :password => :changeme})
|
24
|
+
```
|
25
|
+
|
26
|
+
##### Listing resources
|
27
|
+
|
28
|
+
```
|
29
|
+
irb(main):005:0> api.resources
|
30
|
+
=> [<Resource :roles>, <Resource :images>, <Resource :reports>, <Resource :hosts>, .... <Resource :architectures>]
|
31
|
+
```
|
32
|
+
|
33
|
+
##### Listing actions
|
34
|
+
|
35
|
+
```
|
36
|
+
irb(main):006:0> api.resource(:architectures).actions
|
37
|
+
=> [<Action :index>, <Action :show>, <Action :create>, <Action :update>, <Action :destroy>]
|
38
|
+
```
|
39
|
+
|
40
|
+
##### Listing routes
|
41
|
+
```
|
42
|
+
irb(main):008:0> api.resource(:architectures).action(:show).routes
|
43
|
+
=> [<Route /api/architectures/:id>]
|
44
|
+
```
|
45
|
+
|
46
|
+
##### Listing params
|
47
|
+
|
48
|
+
```
|
49
|
+
irb(main):007:0> api.resource(:architectures).action(:show).params
|
50
|
+
=> [<Param *id (String)>]
|
51
|
+
|
52
|
+
|
53
|
+
irb(main):009:0> api.resource(:architectures).action(:show).params.first.required?
|
54
|
+
=> true
|
55
|
+
```
|
56
|
+
|
57
|
+
##### Calling methods (all the calls bellow are equivalent)
|
58
|
+
|
59
|
+
```
|
60
|
+
irb(main):012:0> api.resource(:architectures).call(:show, :id => 1)
|
61
|
+
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
62
|
+
|
63
|
+
irb(main):013:0> api.call(:architectures, :show, :id => 1)
|
64
|
+
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
65
|
+
|
66
|
+
irb(main):014:0> api.resource(:architectures).action(:show).call(:id => 1)
|
67
|
+
=> {"name"=>"x86_64", "id"=>1, "created_at"=>"2013-12-03T15:00:08Z", "updated_at"=>"2013-12-03T15:00:08Z"}
|
68
|
+
|
69
|
+
```
|
70
|
+
|
71
|
+
TODO
|
72
|
+
----
|
73
|
+
* parameter validation
|
74
|
+
* better configurability
|
75
|
+
* error handling
|
76
|
+
* logging
|
77
|
+
* lots of other things
|
78
|
+
|
79
|
+
|
80
|
+
License
|
81
|
+
-------
|
82
|
+
|
83
|
+
This project is licensed under the GPLv3+.
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'apipie_bindings'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ApipieBindings
|
2
|
+
|
3
|
+
def self.log
|
4
|
+
Logging.logger['API']
|
5
|
+
end
|
6
|
+
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'apipie_bindings/version'
|
10
|
+
require 'apipie_bindings/api'
|
11
|
+
require 'apipie_bindings/resource'
|
12
|
+
require 'apipie_bindings/action'
|
13
|
+
require 'apipie_bindings/route'
|
14
|
+
require 'apipie_bindings/param'
|
15
|
+
require 'apipie_bindings/example'
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module ApipieBindings
|
2
|
+
|
3
|
+
class Action
|
4
|
+
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize(resource, name, api)
|
8
|
+
@resource = resource
|
9
|
+
@name = name.to_sym
|
10
|
+
@api = api
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(params={}, headers={}, options={})
|
14
|
+
@api.call(@resource, @name, params, headers, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def apidoc
|
18
|
+
methods = @api.apidoc[:docs][:resources][@resource][:methods].select do |action|
|
19
|
+
action[:name].to_sym == @name
|
20
|
+
end
|
21
|
+
methods.first
|
22
|
+
end
|
23
|
+
|
24
|
+
def routes
|
25
|
+
apidoc[:apis].map do |api|
|
26
|
+
ApipieBindings::Route.new(
|
27
|
+
api[:api_url], api[:http_method], api[:short_description])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def params
|
32
|
+
apidoc[:params].map do |param|
|
33
|
+
ApipieBindings::Param.new(param)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def examples
|
38
|
+
apidoc[:examples].map do |example|
|
39
|
+
ApipieBindings::Example.parse(example)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_route(params={})
|
44
|
+
sorted_routes = routes.sort_by { |r| [-1 * r.params_in_path.count, r.path] }
|
45
|
+
|
46
|
+
suitable_route = sorted_routes.find do |route|
|
47
|
+
route.params_in_path.all? { |path_param| params.keys.map(&:to_s).include?(path_param) }
|
48
|
+
end
|
49
|
+
|
50
|
+
suitable_route ||= sorted_routes.last
|
51
|
+
return suitable_route
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate!(params)
|
55
|
+
# return unless params.is_a?(Hash)
|
56
|
+
|
57
|
+
# invalid_keys = params.keys.map(&:to_s) - (rules.is_a?(Hash) ? rules.keys : rules)
|
58
|
+
# raise ArgumentError, "Invalid keys: #{invalid_keys.join(", ")}" unless invalid_keys.empty?
|
59
|
+
|
60
|
+
# if rules.is_a? Hash
|
61
|
+
# rules.each do |key, sub_keys|
|
62
|
+
# validate_params!(params[key], sub_keys) if params[key]
|
63
|
+
# end
|
64
|
+
# end
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s
|
68
|
+
"<Action :#{@name}>"
|
69
|
+
end
|
70
|
+
|
71
|
+
def inspect
|
72
|
+
to_s
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'oauth'
|
4
|
+
require 'logging'
|
5
|
+
require 'awesome_print'
|
6
|
+
module ApipieBindings
|
7
|
+
|
8
|
+
class API
|
9
|
+
|
10
|
+
attr_reader :apidoc_cache_name, :fake_responses
|
11
|
+
attr_writer :dry_run
|
12
|
+
|
13
|
+
def initialize(config, options={})
|
14
|
+
@uri = config[:uri]
|
15
|
+
@api_version = config[:api_version] || 2
|
16
|
+
@apidoc_cache_dir = config[:apidoc_cache_dir] || File.join('/tmp/apipie_bindings', @uri.tr(':/', '_'))
|
17
|
+
@apidoc_cache_name = config[:apidoc_cache_name] || set_default_name
|
18
|
+
@dry_run = config[:dry_run] || false
|
19
|
+
@fake_responses = {}
|
20
|
+
|
21
|
+
config = config.dup
|
22
|
+
|
23
|
+
headers = {
|
24
|
+
:content_type => 'application/json',
|
25
|
+
:accept => "application/json;version=#{@api_version}"
|
26
|
+
}
|
27
|
+
headers.merge!(config[:headers]) unless config[:headers].nil?
|
28
|
+
headers.merge!(options.delete(:headers)) unless options[:headers].nil?
|
29
|
+
|
30
|
+
resource_config = {
|
31
|
+
:user => config[:username],
|
32
|
+
:password => config[:password],
|
33
|
+
:oauth => config[:oauth],
|
34
|
+
:headers => headers
|
35
|
+
}.merge(options)
|
36
|
+
|
37
|
+
@client = RestClient::Resource.new(config[:uri], resource_config)
|
38
|
+
@config = config
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_default_name(default='default')
|
42
|
+
cache_file = Dir["#{@apidoc_cache_dir}/*.json"].first
|
43
|
+
if cache_file
|
44
|
+
File.basename(cache_file, ".json")
|
45
|
+
else
|
46
|
+
default
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def apidoc_cache_file
|
51
|
+
File.join(@apidoc_cache_dir, "#{@apidoc_cache_name}.json")
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_apidoc
|
55
|
+
if File.exist?(apidoc_cache_file)
|
56
|
+
JSON.parse(File.read(apidoc_cache_file), :symbolize_names => true)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def retrieve_apidoc
|
61
|
+
FileUtils.mkdir_p(@apidoc_cache_dir) unless File.exists?(@apidoc_cache_dir)
|
62
|
+
path = "/apidoc/v#{@api_version}.json"
|
63
|
+
begin
|
64
|
+
response = http_call('get', path, {},
|
65
|
+
{:accept => "application/json;version=1"}, {:response => :raw})
|
66
|
+
rescue
|
67
|
+
raise "Could not load data from #{@uri}#{path}"
|
68
|
+
end
|
69
|
+
File.open(apidoc_cache_file, "w") { |f| f.write(response.body) }
|
70
|
+
ApipieBindings.log.debug "New apidoc loaded from the server"
|
71
|
+
load_apidoc
|
72
|
+
end
|
73
|
+
|
74
|
+
def apidoc
|
75
|
+
@apidoc = @apidoc || load_apidoc || retrieve_apidoc
|
76
|
+
@apidoc
|
77
|
+
end
|
78
|
+
|
79
|
+
def dry_run?
|
80
|
+
@dry_run ? true : false
|
81
|
+
end
|
82
|
+
|
83
|
+
def has_resource?(name)
|
84
|
+
apidoc[:docs][:resources].has_key? name
|
85
|
+
end
|
86
|
+
|
87
|
+
def resource(name)
|
88
|
+
ApipieBindings::Resource.new(name, self)
|
89
|
+
end
|
90
|
+
|
91
|
+
def resources
|
92
|
+
apidoc[:docs][:resources].keys.map { |res| resource(res) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def call(resource_name, action_name, params={}, headers={}, options={})
|
96
|
+
resource = resource(resource_name)
|
97
|
+
action = resource.action(action_name)
|
98
|
+
route = action.find_route(params)
|
99
|
+
#action.validate(params)
|
100
|
+
options[:fake_response] = find_match(fake_responses, resource_name, action_name, params) || action.examples.first if dry_run?
|
101
|
+
return http_call(
|
102
|
+
route.method,
|
103
|
+
route.path(params),
|
104
|
+
params.reject { |par, _| route.params_in_path.include? par.to_s },
|
105
|
+
headers, options)
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def http_call(http_method, path, params={}, headers={}, options={})
|
110
|
+
headers ||= { }
|
111
|
+
|
112
|
+
args = [http_method]
|
113
|
+
if %w[post put].include?(http_method.to_s)
|
114
|
+
args << params.to_json
|
115
|
+
else
|
116
|
+
headers[:params] = params if params
|
117
|
+
end
|
118
|
+
|
119
|
+
ApipieBindings.log.info "#{http_method.to_s.upcase} #{path}"
|
120
|
+
ApipieBindings.log.debug "Params: #{params.ai}"
|
121
|
+
# logger.debug "Headers: #{headers.inspect}"
|
122
|
+
|
123
|
+
args << headers if headers
|
124
|
+
|
125
|
+
if dry_run?
|
126
|
+
empty_response = ApipieBindings::Example.new('', '', '', 200, '')
|
127
|
+
ex = options[:fake_response ] || empty_response
|
128
|
+
response = RestClient::Response.create(ex.response, ex.status, ex.args)
|
129
|
+
else
|
130
|
+
response = @client[path].send(*args)
|
131
|
+
update_cache(response.headers[:apipie_apidoc_hash])
|
132
|
+
end
|
133
|
+
|
134
|
+
result = options[:response] == :raw ? response : process_data(response)
|
135
|
+
ApipieBindings.log.debug "Response #{result.ai}"
|
136
|
+
result
|
137
|
+
end
|
138
|
+
|
139
|
+
def process_data(response)
|
140
|
+
data = begin
|
141
|
+
JSON.parse(response.body)
|
142
|
+
rescue JSON::ParserError
|
143
|
+
response.body
|
144
|
+
end
|
145
|
+
# logger.debug "Returned data: #{data.inspect}"
|
146
|
+
return data
|
147
|
+
end
|
148
|
+
|
149
|
+
def update_cache(cache_name)
|
150
|
+
if !cache_name.nil? && (cache_name != @apidoc_cache_name)
|
151
|
+
clean_cache
|
152
|
+
ApipieBindings.log.debug "Cache expired. (#{@apidoc_cache_name} -> #{cache_name})"
|
153
|
+
@apidoc_cache_name = cache_name
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def clean_cache
|
158
|
+
@apidoc = nil
|
159
|
+
Dir["#{@apidoc_cache_dir}/*.json"].each { |f| File.delete(f) }
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def find_match(fakes, resource, action, params)
|
165
|
+
resource = fakes[[resource, action]]
|
166
|
+
if resource
|
167
|
+
if resource.has_key?(params)
|
168
|
+
return resource[params]
|
169
|
+
elsif resource.has_key?(:default)
|
170
|
+
return resource[:default]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
return nil
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ApipieBindings
|
2
|
+
|
3
|
+
class Example
|
4
|
+
|
5
|
+
attr_reader :http_method, :path, :args, :status, :response
|
6
|
+
|
7
|
+
def initialize(http_method, path, args, status, response)
|
8
|
+
@http_method = http_method
|
9
|
+
@path = path
|
10
|
+
@args = args
|
11
|
+
@status = status.to_i
|
12
|
+
@response = response
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.parse(example)
|
16
|
+
prep = /(\w+)\ ([^\n]*)\n?(.*)?\n(\d+)\n(.*)/m.match(example)
|
17
|
+
new(*prep[1..5])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
|
3
|
+
module ApipieBindings
|
4
|
+
|
5
|
+
class Param
|
6
|
+
|
7
|
+
attr_reader :name, :params, :expected_type, :description, :validator
|
8
|
+
|
9
|
+
def initialize(param)
|
10
|
+
param = param.with_indifferent_access
|
11
|
+
@name = param[:name]
|
12
|
+
params = param[:params] || []
|
13
|
+
@params = params.map { |p| ApipieBindings::Param.new(p) }
|
14
|
+
@expected_type = param[:expected_type].to_sym
|
15
|
+
@description = param[:description].gsub(/<\/?[^>]+?>/, "")
|
16
|
+
@required = param[:required]
|
17
|
+
@validator = param[:validator]
|
18
|
+
end
|
19
|
+
|
20
|
+
def required?
|
21
|
+
@required
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"<Param #{ required? ? '*' : '' }#{@name} (#{@expected_type.capitalize})>"
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_support/core_ext/string'
|
2
|
+
|
3
|
+
module ApipieBindings
|
4
|
+
|
5
|
+
class Resource
|
6
|
+
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize(name, api)
|
10
|
+
raise NameError.new("Resource '#{name}' does not exist in the API") unless api.apidoc[:docs][:resources].key?(name)
|
11
|
+
@name = name
|
12
|
+
@api = api
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(action, params={}, headers={}, options={})
|
16
|
+
@api.call(@name, action, params, headers, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def apidoc
|
20
|
+
@api.apidoc[:docs][:resources][@name]
|
21
|
+
end
|
22
|
+
|
23
|
+
def actions
|
24
|
+
apidoc[:methods].map { |a| action(a[:name].to_sym) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_action?(name)
|
28
|
+
apidoc[:methods].any? { |action| action[:name].to_sym == name }
|
29
|
+
end
|
30
|
+
|
31
|
+
def action(name)
|
32
|
+
ApipieBindings::Action.new(@name, name, @api)
|
33
|
+
end
|
34
|
+
|
35
|
+
def singular_name
|
36
|
+
@name.to_s.singularize
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"<Resource :#{@name}>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect
|
44
|
+
to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ApipieBindings
|
2
|
+
|
3
|
+
class Route
|
4
|
+
|
5
|
+
attr_reader :method, :description
|
6
|
+
|
7
|
+
def initialize(path, method, description="")
|
8
|
+
@path = path
|
9
|
+
@method = method.downcase
|
10
|
+
@description = description
|
11
|
+
end
|
12
|
+
|
13
|
+
def params_in_path
|
14
|
+
@path.scan(/:([^\/]*)/).map { |m| m.first }
|
15
|
+
end
|
16
|
+
|
17
|
+
def path(params=nil)
|
18
|
+
return @path if params.nil?
|
19
|
+
|
20
|
+
path = params_in_path.inject(@path) do |p, param_name|
|
21
|
+
param_value = (params[param_name.to_sym] or params[param_name.to_s]) or
|
22
|
+
raise ArgumentError, "missing param '#{param_name}' in parameters"
|
23
|
+
p.sub(":#{param_name}", URI.escape(param_value.to_s))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"<Route #{@path}>"
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Action do
|
4
|
+
|
5
|
+
let(:resource) { ApipieBindings::API.new({:apidoc_cache_dir => 'test/unit/data',
|
6
|
+
:apidoc_cache_name => 'architecture'}).resource(:architectures) }
|
7
|
+
|
8
|
+
it "should allow user to call the action" do
|
9
|
+
params = { :a => 1 }
|
10
|
+
headers = { :content_type => 'application/json' }
|
11
|
+
ApipieBindings::API.any_instance.expects(:call).with(:architectures, :index, params, headers, {})
|
12
|
+
resource.action(:index).call(params, headers)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return routes" do
|
16
|
+
resource.action(:index).routes.first.must_be_kind_of ApipieBindings::Route
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should find suitable route" do
|
20
|
+
resource.action(:index).find_route.path.must_equal "/api/architectures"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return params" do
|
24
|
+
resource.action(:create).params.map(&:name).must_equal ['architecture']
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO add tests for more find_route cases
|
28
|
+
# @param possible_apis [Array] Array of hasahs in form of
|
29
|
+
# [{:api_url => '/path1', :http_method => 'GET'}, {...}]
|
30
|
+
# @param params [Hash] enterred params
|
31
|
+
# @return api that suits the enterred params mosts
|
32
|
+
#
|
33
|
+
# Given this paths:
|
34
|
+
# 1. +/comments+
|
35
|
+
# 2. +/users/:user_id/comments+
|
36
|
+
# 3. +/users/:user_id/posts/:post_id/comments+
|
37
|
+
#
|
38
|
+
# If +:user_id+ and +:post_id+ is pecified, the third path is
|
39
|
+
# used. If only +:user_id+ is specified, the second one is used.
|
40
|
+
# The selection defaults to the path with the least number of
|
41
|
+
# incuded params in alphanumeric order.
|
42
|
+
|
43
|
+
|
44
|
+
it "should validate the params" do
|
45
|
+
resource.action(:create).validate!({ :architecture => { :name => 'i386' } })
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have name visible in puts" do
|
49
|
+
out, err = capture_io { puts resource.action(:index) }
|
50
|
+
out.must_equal "<Action :index>\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have name visible in inspect" do
|
54
|
+
resource.action(:index).inspect.must_equal "<Action :index>"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have examples" do
|
58
|
+
resource.action(:index).examples.length.must_equal 1
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::API do
|
4
|
+
|
5
|
+
let(:api) { ApipieBindings::API.new({:apidoc_cache_dir => 'test/unit/data', :apidoc_cache_name => 'architecture'}) }
|
6
|
+
|
7
|
+
it "should provide resource" do
|
8
|
+
result = api.resource(:architectures)
|
9
|
+
result.must_be_kind_of ApipieBindings::Resource
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should test if resource is available" do
|
13
|
+
api.has_resource?(:architectures).must_equal true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should list resources" do
|
17
|
+
api.resources.map(&:name).must_equal [:architectures]
|
18
|
+
end
|
19
|
+
|
20
|
+
# it "should have apidoc_cache_file available" do
|
21
|
+
# end
|
22
|
+
|
23
|
+
it "should call the method" do
|
24
|
+
params = { :a => 1 }
|
25
|
+
headers = { :content_type => 'application/json' }
|
26
|
+
ApipieBindings::API.any_instance.expects(:http_call).with('get', '/api/architectures', params, headers, {})
|
27
|
+
api.call(:architectures, :index, params, headers)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should call the method and fill in the params" do
|
31
|
+
params = { :id => 1 }
|
32
|
+
headers = { :content_type => 'application/json' }
|
33
|
+
ApipieBindings::API.any_instance.expects(:http_call).with('get', '/api/architectures/1', {}, headers, {})
|
34
|
+
api.call(:architectures, :show, params, headers)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return values from examples in dry_run mode" do
|
38
|
+
api.dry_run = true
|
39
|
+
result = api.call(:architectures, :index)
|
40
|
+
result.must_be_kind_of Array
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should allow to set dry_run mode in config params" do
|
44
|
+
api = ApipieBindings::API.new({
|
45
|
+
:apidoc_cache_dir => 'test/unit/data',
|
46
|
+
:apidoc_cache_name => 'architecture',
|
47
|
+
:dry_run => true })
|
48
|
+
result = api.call(:architectures, :index)
|
49
|
+
result.must_be_kind_of Array
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should allow to set fake response in config params" do
|
53
|
+
api = ApipieBindings::API.new({
|
54
|
+
:apidoc_cache_dir => 'test/unit/data',
|
55
|
+
:apidoc_cache_name => 'architecture',
|
56
|
+
:dry_run => true,
|
57
|
+
:fake_params => { [:architectures, :index] => {:default => [] } }} )
|
58
|
+
result = api.call(:architectures, :index)
|
59
|
+
result.must_be_kind_of Array
|
60
|
+
end
|
61
|
+
|
62
|
+
context "update_cache" do
|
63
|
+
|
64
|
+
before :each do
|
65
|
+
@dir = Dir.mktmpdir
|
66
|
+
@api = ApipieBindings::API.new({:apidoc_cache_dir => @dir, :apidoc_cache_name => 'cache'})
|
67
|
+
@api.stubs(:retrieve_apidoc).returns(nil)
|
68
|
+
File.open(@api.apidoc_cache_file, "w") { |f| f.write(['test'].to_json) }
|
69
|
+
end
|
70
|
+
|
71
|
+
after :each do
|
72
|
+
Dir["#{@dir}/*"].each { |f| File.delete(f) }
|
73
|
+
Dir.delete(@dir)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should clean the internal cache when the name has changed" do
|
77
|
+
@api.update_cache('new_name')
|
78
|
+
@api.apidoc.must_equal nil
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should clean the cache dir when the name has changed" do
|
82
|
+
@api.update_cache('new_name')
|
83
|
+
Dir["#{@dir}/*"].must_be_empty
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should set the new cache name when the name has changed" do
|
87
|
+
@api.update_cache('new_name')
|
88
|
+
@api.apidoc_cache_file.must_equal File.join(@dir, 'new_name.json')
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should not touch enything if the name is same" do
|
92
|
+
@api.update_cache('cache')
|
93
|
+
@api.apidoc.must_equal ['test']
|
94
|
+
end
|
95
|
+
|
96
|
+
# caching is turned off on server
|
97
|
+
it "should not touch enything if the name is nil" do
|
98
|
+
@api.update_cache(nil)
|
99
|
+
@api.apidoc.must_equal ['test']
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should load cache and its name from cache dir" do
|
103
|
+
FileUtils.cp('test/unit/data/architecture.json', File.join(@dir, 'api_cache.json'))
|
104
|
+
@api = ApipieBindings::API.new({:apidoc_cache_dir => @dir})
|
105
|
+
@api.apidoc_cache_name.must_equal 'api_cache'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
{
|
2
|
+
"docs": {
|
3
|
+
"api_url": "/api",
|
4
|
+
"copyright": "",
|
5
|
+
"doc_url": "/apidoc/v2",
|
6
|
+
"info": "Another API description",
|
7
|
+
"name": "Foreman",
|
8
|
+
"resources": {
|
9
|
+
"architectures": {
|
10
|
+
"api_url": "/api",
|
11
|
+
"doc_url": "/apidoc/v2/architectures",
|
12
|
+
"formats": null,
|
13
|
+
"full_description": null,
|
14
|
+
"methods": [
|
15
|
+
{
|
16
|
+
"apis": [
|
17
|
+
{
|
18
|
+
"api_url": "/api/architectures",
|
19
|
+
"http_method": "GET",
|
20
|
+
"short_description": "List all architectures."
|
21
|
+
}
|
22
|
+
],
|
23
|
+
"doc_url": "/apidoc/v2/architectures/index",
|
24
|
+
"errors": [],
|
25
|
+
"examples": [
|
26
|
+
"GET /api/architectures\n200\n[\n {\n \"architecture\": {\n \"name\": \"s390\",\n \"id\": 381564594,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n },\n {\n \"architecture\": {\n \"name\": \"sparc\",\n \"id\": 331892513,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 442321401\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n },\n {\n \"architecture\": {\n \"name\": \"x86_64\",\n \"id\": 501905019,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 331303656,\n 309172073,\n 1073012828\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n }\n]"
|
27
|
+
],
|
28
|
+
"formats": null,
|
29
|
+
"full_description": "",
|
30
|
+
"name": "index",
|
31
|
+
"params": [
|
32
|
+
{
|
33
|
+
"allow_nil": false,
|
34
|
+
"description": "\n<p>filter results</p>\n",
|
35
|
+
"expected_type": "string",
|
36
|
+
"full_name": "search",
|
37
|
+
"name": "search",
|
38
|
+
"required": false,
|
39
|
+
"validator": "Must be String"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"allow_nil": false,
|
43
|
+
"description": "\n<p>sort results</p>\n",
|
44
|
+
"expected_type": "string",
|
45
|
+
"full_name": "order",
|
46
|
+
"name": "order",
|
47
|
+
"required": false,
|
48
|
+
"validator": "Must be String"
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"allow_nil": false,
|
52
|
+
"description": "\n<p>paginate results</p>\n",
|
53
|
+
"expected_type": "string",
|
54
|
+
"full_name": "page",
|
55
|
+
"name": "page",
|
56
|
+
"required": false,
|
57
|
+
"validator": "Must be String"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"allow_nil": false,
|
61
|
+
"description": "\n<p>number of entries per request</p>\n",
|
62
|
+
"expected_type": "string",
|
63
|
+
"full_name": "per_page",
|
64
|
+
"name": "per_page",
|
65
|
+
"required": false,
|
66
|
+
"validator": "Must be String"
|
67
|
+
}
|
68
|
+
],
|
69
|
+
"see": []
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"apis": [
|
73
|
+
{
|
74
|
+
"api_url": "/api/architectures/:id",
|
75
|
+
"http_method": "GET",
|
76
|
+
"short_description": "Show an architecture."
|
77
|
+
}
|
78
|
+
],
|
79
|
+
"doc_url": "/apidoc/v2/architectures/show",
|
80
|
+
"errors": [],
|
81
|
+
"examples": [
|
82
|
+
"GET /api/architectures/x86_64\n200\n{\n \"architecture\": {\n \"name\": \"x86_64\",\n \"id\": 501905019,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 309172073,\n 1073012828,\n 331303656\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n}"
|
83
|
+
],
|
84
|
+
"formats": null,
|
85
|
+
"full_description": "",
|
86
|
+
"name": "show",
|
87
|
+
"params": [
|
88
|
+
{
|
89
|
+
"allow_nil": false,
|
90
|
+
"description": "",
|
91
|
+
"expected_type": "string",
|
92
|
+
"full_name": "id",
|
93
|
+
"name": "id",
|
94
|
+
"required": true,
|
95
|
+
"validator": "Must be an identifier, string from 1 to 128 characters containing only alphanumeric characters, space, underscore(_), hypen(-) with no leading or trailing space."
|
96
|
+
}
|
97
|
+
],
|
98
|
+
"see": []
|
99
|
+
},
|
100
|
+
{
|
101
|
+
"apis": [
|
102
|
+
{
|
103
|
+
"api_url": "/api/architectures",
|
104
|
+
"http_method": "POST",
|
105
|
+
"short_description": "Create an architecture."
|
106
|
+
}
|
107
|
+
],
|
108
|
+
"doc_url": "/apidoc/v2/architectures/create",
|
109
|
+
"errors": [],
|
110
|
+
"examples": [
|
111
|
+
"POST /api/architectures\n{\n \"architecture\": {\n \"name\": \"i386\"\n }\n}\n200\n{\n \"architecture\": {\n \"name\": \"i386\",\n \"id\": 501905020,\n \"updated_at\": \"2012-12-18T15:24:43Z\",\n \"operatingsystem_ids\": [],\n \"created_at\": \"2012-12-18T15:24:43Z\"\n }\n}"
|
112
|
+
],
|
113
|
+
"formats": null,
|
114
|
+
"full_description": "",
|
115
|
+
"name": "create",
|
116
|
+
"params": [
|
117
|
+
{
|
118
|
+
"allow_nil": false,
|
119
|
+
"description": "",
|
120
|
+
"expected_type": "hash",
|
121
|
+
"full_name": "architecture",
|
122
|
+
"name": "architecture",
|
123
|
+
"params": [
|
124
|
+
{
|
125
|
+
"allow_nil": false,
|
126
|
+
"description": "",
|
127
|
+
"expected_type": "string",
|
128
|
+
"full_name": "architecture[name]",
|
129
|
+
"name": "name",
|
130
|
+
"required": true,
|
131
|
+
"validator": "Must be String"
|
132
|
+
},
|
133
|
+
{
|
134
|
+
"allow_nil": false,
|
135
|
+
"description": "\n<p>Operatingsystem ID\u2019s</p>\n",
|
136
|
+
"expected_type": "array",
|
137
|
+
"full_name": "architecture[operatingsystem_ids]",
|
138
|
+
"name": "operatingsystem_ids",
|
139
|
+
"required": false,
|
140
|
+
"validator": "Must be Array"
|
141
|
+
}
|
142
|
+
],
|
143
|
+
"required": true,
|
144
|
+
"validator": "Must be a Hash"
|
145
|
+
}
|
146
|
+
],
|
147
|
+
"see": []
|
148
|
+
}
|
149
|
+
]
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
153
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Example do
|
4
|
+
|
5
|
+
it "should parse the example format from apidoc POST" do
|
6
|
+
example_string = "POST /api/architectures\n{\n \"architecture\": {\n \"name\": \"i386\"\n }\n}\n200\n{\n \"architecture\": {\n \"name\": \"i386\",\n \"id\": 501905020,\n \"updated_at\": \"2012-12-18T15:24:43Z\",\n \"operatingsystem_ids\": [],\n \"created_at\": \"2012-12-18T15:24:43Z\"\n }\n}"
|
7
|
+
ex = ApipieBindings::Example.parse(example_string)
|
8
|
+
ex.http_method.must_equal 'POST'
|
9
|
+
ex.path.must_equal '/api/architectures'
|
10
|
+
ex.args.must_equal "{\n \"architecture\": {\n \"name\": \"i386\"\n }\n}"
|
11
|
+
ex.status.must_equal 200
|
12
|
+
ex.response.must_include "{\n \"architecture\": "
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should parse the example format from apidoc GET" do
|
16
|
+
example_string = "GET /api/architectures/x86_64\n200\n{\n \"architecture\": {\n \"name\": \"x86_64\",\n \"id\": 501905019,\n \"updated_at\": \"2012-12-18T15:24:42Z\",\n \"operatingsystem_ids\": [\n 309172073,\n 1073012828,\n 331303656\n ],\n \"created_at\": \"2012-12-18T15:24:42Z\"\n }\n}"
|
17
|
+
ex = ApipieBindings::Example.parse(example_string)
|
18
|
+
ex.http_method.must_equal 'GET'
|
19
|
+
ex.path.must_equal '/api/architectures/x86_64'
|
20
|
+
ex.args.must_equal ""
|
21
|
+
ex.status.must_equal 200
|
22
|
+
ex.response.must_include "{\n \"architecture\": "
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Param do
|
4
|
+
|
5
|
+
let(:param) {ApipieBindings::Param.new({
|
6
|
+
"allow_nil" => false,
|
7
|
+
"description" => "<p>Architecture</p>",
|
8
|
+
"expected_type" => "hash",
|
9
|
+
"full_name" => "architecture",
|
10
|
+
"name" => "architecture",
|
11
|
+
"params" => [
|
12
|
+
{
|
13
|
+
"allow_nil" => false,
|
14
|
+
"description" => "",
|
15
|
+
"expected_type" => "string",
|
16
|
+
"full_name" => "architecture[name]",
|
17
|
+
"name" => "name",
|
18
|
+
"required" => false,
|
19
|
+
"validator" => "Must be String"
|
20
|
+
}
|
21
|
+
|
22
|
+
],
|
23
|
+
"required" => true,
|
24
|
+
"validator" => "Must be a Hash"
|
25
|
+
}
|
26
|
+
)}
|
27
|
+
it "should create nested params" do
|
28
|
+
param.params.first.name.must_equal 'name'
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should have expected_type" do
|
32
|
+
param.expected_type.must_equal :hash
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have description taht strip html tags" do
|
36
|
+
param.description.must_equal "Architecture"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should have required?" do
|
40
|
+
param.required?.must_equal true
|
41
|
+
param.params.first.required?.must_equal false
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have validator" do
|
45
|
+
param.validator.must_equal "Must be a Hash"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have full name, type and required visible in puts" do
|
49
|
+
out, err = capture_io { puts param }
|
50
|
+
out.must_equal "<Param *architecture (Hash)>\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should have full name, type and required visible in inspect" do
|
54
|
+
param.inspect.must_equal "<Param *architecture (Hash)>"
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Resource do
|
4
|
+
|
5
|
+
let(:resource) { ApipieBindings::API.new({:apidoc_cache_dir => 'test/unit/data',
|
6
|
+
:apidoc_cache_name => 'architecture'}).resource(:architectures) }
|
7
|
+
|
8
|
+
it "should list actions" do
|
9
|
+
resource.actions.map(&:name).must_equal [:index, :show, :create]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should test action existence" do
|
13
|
+
resource.has_action?(:index).must_equal true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return action" do
|
17
|
+
resource.action(:index).must_be_kind_of ApipieBindings::Action
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow user to call the action" do
|
21
|
+
params = { :a => 1 }
|
22
|
+
headers = { :content_type => 'application/json' }
|
23
|
+
ApipieBindings::API.any_instance.expects(:call).with(:architectures, :index, params, headers, {})
|
24
|
+
resource.call(:index, params, headers)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow user to call the action with minimal params" do
|
28
|
+
ApipieBindings::API.any_instance.expects(:call).with(:architectures, :index, {}, {}, {})
|
29
|
+
resource.call(:index)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should print name in singular on demand" do
|
33
|
+
resource.singular_name.must_equal 'architecture'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should have name visible in puts" do
|
37
|
+
out, err = capture_io { puts resource }
|
38
|
+
out.must_equal "<Resource :architectures>\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have name visible in inspect" do
|
42
|
+
resource.inspect.must_equal "<Resource :architectures>"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should rise error when the resource does no exist" do
|
46
|
+
assert_raises( NameError ){ ApipieBindings::API.new({:apidoc_cache_dir => 'test/unit/data',
|
47
|
+
:apidoc_cache_name => 'architecture'}).resource(:none) }
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe ApipieBindings::Route do
|
4
|
+
|
5
|
+
let(:route) { ApipieBindings::Route.new("/api/architectures/:id", "GET") }
|
6
|
+
it "should list params in path" do
|
7
|
+
route.params_in_path.must_equal ['id']
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should downcase the method" do
|
11
|
+
route.method.must_equal 'get'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should fill in the params" do
|
15
|
+
route.path({ "id" => 1 }).must_equal "/api/architectures/1"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should fill in the params as symbols" do
|
19
|
+
route.path({ :id => 1 }).must_equal "/api/architectures/1"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return the path as is without the params" do
|
23
|
+
route.path.must_equal "/api/architectures/:id"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have path visible in puts" do
|
27
|
+
out, err = capture_io { puts route }
|
28
|
+
out.must_equal "<Route /api/architectures/:id>\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should have path visible in inspect" do
|
32
|
+
route.inspect.must_equal "<Route /api/architectures/:id>"
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
SimpleCov.use_merging true
|
5
|
+
SimpleCov.start do
|
6
|
+
command_name 'MiniTest'
|
7
|
+
add_filter 'test'
|
8
|
+
end
|
9
|
+
SimpleCov.root Pathname.new(File.dirname(__FILE__) + "../../../")
|
10
|
+
|
11
|
+
|
12
|
+
require 'minitest/autorun'
|
13
|
+
require 'minitest/spec'
|
14
|
+
require "minitest-spec-context"
|
15
|
+
require "mocha/setup"
|
16
|
+
|
17
|
+
require 'apipie_bindings'
|
18
|
+
|
19
|
+
Logging.logger.root.appenders = Logging::Appenders['__test__'] || Logging::Appenders::StringIo.new('__test__')
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apipie-bindings
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Martin Bačovský
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rest-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.6.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.6.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: oauth
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: i18n
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |
|
84
|
+
Bindings for API calls that are documented with Apipie. Bindings are generated on the fly.
|
85
|
+
email: mbacovsk@redhat.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files:
|
89
|
+
- README.md
|
90
|
+
files:
|
91
|
+
- LICENSE
|
92
|
+
- README.md
|
93
|
+
- lib/apipie-bindings.rb
|
94
|
+
- lib/apipie_bindings.rb
|
95
|
+
- lib/apipie_bindings/action.rb
|
96
|
+
- lib/apipie_bindings/api.rb
|
97
|
+
- lib/apipie_bindings/example.rb
|
98
|
+
- lib/apipie_bindings/param.rb
|
99
|
+
- lib/apipie_bindings/resource.rb
|
100
|
+
- lib/apipie_bindings/route.rb
|
101
|
+
- lib/apipie_bindings/version.rb
|
102
|
+
- test/unit/action_test.rb
|
103
|
+
- test/unit/api_test.rb
|
104
|
+
- test/unit/data/architecture.json
|
105
|
+
- test/unit/example_test.rb
|
106
|
+
- test/unit/main_test.rb
|
107
|
+
- test/unit/param_test.rb
|
108
|
+
- test/unit/resource_test.rb
|
109
|
+
- test/unit/route_test.rb
|
110
|
+
- test/unit/test_helper.rb
|
111
|
+
homepage: http://github.com/Apipie/apipie-bindings
|
112
|
+
licenses:
|
113
|
+
- GPL-3
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.0.14
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: The Ruby bindings for Apipie documented APIs
|
135
|
+
test_files:
|
136
|
+
- test/unit/action_test.rb
|
137
|
+
- test/unit/api_test.rb
|
138
|
+
- test/unit/data/architecture.json
|
139
|
+
- test/unit/example_test.rb
|
140
|
+
- test/unit/main_test.rb
|
141
|
+
- test/unit/param_test.rb
|
142
|
+
- test/unit/resource_test.rb
|
143
|
+
- test/unit/route_test.rb
|
144
|
+
- test/unit/test_helper.rb
|
145
|
+
has_rdoc:
|