elasticsearch-api 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +16 -0
- data/Rakefile +3 -3
- data/elasticsearch-api.gemspec +4 -1
- data/lib/elasticsearch/api.rb +19 -0
- data/lib/elasticsearch/api/actions/abort_benchmark.rb +1 -1
- data/lib/elasticsearch/api/actions/benchmark.rb +1 -1
- data/lib/elasticsearch/api/actions/bulk.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/aliases.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/allocation.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/count.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/fielddata.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/health.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/help.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/indices.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/master.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/nodes.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/pending_tasks.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/recovery.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/segments.rb +34 -0
- data/lib/elasticsearch/api/actions/cat/shards.rb +1 -1
- data/lib/elasticsearch/api/actions/cat/thread_pool.rb +1 -1
- data/lib/elasticsearch/api/actions/clear_scroll.rb +12 -3
- data/lib/elasticsearch/api/actions/cluster/get_settings.rb +1 -1
- data/lib/elasticsearch/api/actions/cluster/health.rb +1 -1
- data/lib/elasticsearch/api/actions/cluster/pending_tasks.rb +1 -1
- data/lib/elasticsearch/api/actions/cluster/put_settings.rb +1 -1
- data/lib/elasticsearch/api/actions/cluster/reroute.rb +1 -1
- data/lib/elasticsearch/api/actions/cluster/state.rb +8 -2
- data/lib/elasticsearch/api/actions/count.rb +1 -1
- data/lib/elasticsearch/api/actions/count_percolate.rb +1 -1
- data/lib/elasticsearch/api/actions/delete.rb +1 -1
- data/lib/elasticsearch/api/actions/delete_by_query.rb +1 -1
- data/lib/elasticsearch/api/actions/delete_script.rb +1 -1
- data/lib/elasticsearch/api/actions/delete_template.rb +1 -1
- data/lib/elasticsearch/api/actions/exists.rb +4 -2
- data/lib/elasticsearch/api/actions/explain.rb +1 -1
- data/lib/elasticsearch/api/actions/get.rb +2 -2
- data/lib/elasticsearch/api/actions/get_script.rb +1 -1
- data/lib/elasticsearch/api/actions/get_source.rb +2 -2
- data/lib/elasticsearch/api/actions/get_template.rb +1 -1
- data/lib/elasticsearch/api/actions/index.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/analyze.rb +5 -3
- data/lib/elasticsearch/api/actions/indices/clear_cache.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/close.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/create.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/delete.rb +7 -1
- data/lib/elasticsearch/api/actions/indices/delete_alias.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/delete_mapping.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/delete_template.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/delete_warmer.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/exists.rb +3 -1
- data/lib/elasticsearch/api/actions/indices/exists_alias.rb +3 -1
- data/lib/elasticsearch/api/actions/indices/exists_template.rb +3 -2
- data/lib/elasticsearch/api/actions/indices/exists_type.rb +3 -1
- data/lib/elasticsearch/api/actions/indices/flush.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_alias.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_aliases.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_field_mapping.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_mapping.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_settings.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/get_template.rb +3 -2
- data/lib/elasticsearch/api/actions/indices/get_warmer.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/open.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/optimize.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/put_alias.rb +2 -2
- data/lib/elasticsearch/api/actions/indices/put_mapping.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/put_settings.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/put_template.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/put_warmer.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/recovery.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/refresh.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/segments.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/snapshot_index.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/stats.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/status.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/update_aliases.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/upgrade.rb +1 -1
- data/lib/elasticsearch/api/actions/indices/validate_query.rb +1 -1
- data/lib/elasticsearch/api/actions/info.rb +1 -1
- data/lib/elasticsearch/api/actions/list_benchmarks.rb +1 -1
- data/lib/elasticsearch/api/actions/mget.rb +1 -1
- data/lib/elasticsearch/api/actions/mlt.rb +1 -1
- data/lib/elasticsearch/api/actions/mpercolate.rb +1 -1
- data/lib/elasticsearch/api/actions/msearch.rb +1 -1
- data/lib/elasticsearch/api/actions/mtermvectors.rb +1 -1
- data/lib/elasticsearch/api/actions/nodes/hot_threads.rb +1 -1
- data/lib/elasticsearch/api/actions/nodes/info.rb +18 -2
- data/lib/elasticsearch/api/actions/nodes/shutdown.rb +1 -1
- data/lib/elasticsearch/api/actions/nodes/stats.rb +1 -1
- data/lib/elasticsearch/api/actions/percolate.rb +4 -5
- data/lib/elasticsearch/api/actions/ping.rb +1 -1
- data/lib/elasticsearch/api/actions/put_script.rb +1 -1
- data/lib/elasticsearch/api/actions/put_template.rb +1 -1
- data/lib/elasticsearch/api/actions/scroll.rb +2 -2
- data/lib/elasticsearch/api/actions/search.rb +4 -3
- data/lib/elasticsearch/api/actions/search_shards.rb +1 -1
- data/lib/elasticsearch/api/actions/search_template.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/create.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/create_repository.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/delete.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/delete_repository.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/get.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/get_repository.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/restore.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/status.rb +1 -1
- data/lib/elasticsearch/api/actions/snapshot/verify_repository.rb +1 -1
- data/lib/elasticsearch/api/actions/suggest.rb +1 -1
- data/lib/elasticsearch/api/actions/{termvector.rb → termvectors.rb} +24 -7
- data/lib/elasticsearch/api/actions/update.rb +1 -1
- data/lib/elasticsearch/api/utils.rb +27 -6
- data/lib/elasticsearch/api/version.rb +1 -1
- data/test/integration/yaml_test_runner.rb +3 -2
- data/test/unit/api_test.rb +24 -0
- data/test/unit/cat/segments_test.rb +26 -0
- data/test/unit/clear_scroll_test.rb +4 -4
- data/test/unit/exists_document_test.rb +5 -0
- data/test/unit/indices/delete_test.rb +7 -0
- data/test/unit/indices/exists_alias_test.rb +5 -0
- data/test/unit/indices/exists_test.rb +5 -0
- data/test/unit/indices/exists_type_test.rb +5 -0
- data/test/unit/indices/put_alias_test.rb +9 -0
- data/test/unit/nodes/info_test.rb +9 -0
- data/test/unit/scroll_test.rb +1 -2
- data/test/unit/{termvector_test.rb → termvectors_test.rb} +15 -12
- data/test/unit/utils_test.rb +22 -0
- data/utils/Gemfile +9 -0
- data/utils/Thorfile +3 -0
- data/utils/thor/generate_api.rb +189 -0
- data/utils/thor/generate_source.rb +122 -0
- data/utils/thor/lister.rb +41 -0
- data/utils/thor/templates/ruby/method.erb +62 -0
- data/utils/thor/templates/ruby/test.erb +26 -0
- data/utils/thor/templates/ruby/test_helper.rb +71 -0
- metadata +18 -5
data/utils/Gemfile
ADDED
data/utils/Thorfile
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'active_support/core_ext/hash/deep_merge'
|
5
|
+
require 'active_support/inflector/methods'
|
6
|
+
require 'rest_client'
|
7
|
+
require 'json'
|
8
|
+
require 'pry'
|
9
|
+
|
10
|
+
module Elasticsearch
|
11
|
+
|
12
|
+
module API
|
13
|
+
module Utils
|
14
|
+
# controller.registerHandler(RestRequest.Method.GET, "/_cluster/health", this);
|
15
|
+
PATTERN_REST = /.*controller.registerHandler\(.*(?<method>GET|POST|PUT|DELETE|HEAD|OPTIONS|PATCH)\s*,\s*"(?<url>.*)"\s*,\s*.+\);/
|
16
|
+
# request.param("index"), request.paramAsBoolean("docs", indicesStatsRequest.docs()), etc
|
17
|
+
PATTERN_URL_PARAMS = /request.param.*\("(?<param>[a-z_]+)".*/
|
18
|
+
# controller.registerHandler(GET, "/{index}/_refresh", this)
|
19
|
+
PATTERN_URL_PARTS = /\{(?<part>[a-zA-Z0-9\_\-]+)\}/
|
20
|
+
# request.hasContent()
|
21
|
+
PATTERN_HAS_BODY = /request\.hasContent()/
|
22
|
+
|
23
|
+
# Parses the Elasticsearch source code and returns a Hash of REST API information/specs.
|
24
|
+
#
|
25
|
+
# Example:
|
26
|
+
#
|
27
|
+
# {
|
28
|
+
# "cluster.health" => [
|
29
|
+
# { "method" => "GET",
|
30
|
+
# "path" => "/_cluster/health",
|
31
|
+
# "parts" => ["index"],
|
32
|
+
# "params" => ["index", "local", ... ],
|
33
|
+
# "body" => false
|
34
|
+
# }
|
35
|
+
#
|
36
|
+
def __parse_java_source(path)
|
37
|
+
path += '/' unless path =~ /\/$/ # Add trailing slash if missing
|
38
|
+
prefix = "src/main/java/org/elasticsearch/rest/action"
|
39
|
+
|
40
|
+
java_rest_files = Dir["#{path}#{prefix}/**/*.java"]
|
41
|
+
|
42
|
+
map = {}
|
43
|
+
|
44
|
+
java_rest_files.sort.each do |file|
|
45
|
+
content = File.read(file)
|
46
|
+
parts = file.gsub(path+prefix, '').split('/')
|
47
|
+
name = parts[0, parts.size-1].reject { |p| p =~ /^\s*$/ }.join('.')
|
48
|
+
|
49
|
+
# Remove the `admin` namespace
|
50
|
+
name.gsub! /admin\./, ''
|
51
|
+
|
52
|
+
# Extract params
|
53
|
+
url_params = content.scan(PATTERN_URL_PARAMS).map { |n| n.first }.sort
|
54
|
+
|
55
|
+
# Extract parts
|
56
|
+
url_parts = content.scan(PATTERN_URL_PARTS).map { |n| n.first }.sort
|
57
|
+
|
58
|
+
# Extract if body allowed
|
59
|
+
has_body = !!content.match(PATTERN_HAS_BODY)
|
60
|
+
|
61
|
+
# Extract HTTP method and path
|
62
|
+
content.scan(PATTERN_REST) do |method, path|
|
63
|
+
(map[name] ||= []) << { 'method' => method,
|
64
|
+
'path' => path,
|
65
|
+
'parts' => url_parts,
|
66
|
+
'params' => url_params,
|
67
|
+
'body' => has_body }
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
map
|
73
|
+
end
|
74
|
+
|
75
|
+
extend self
|
76
|
+
end
|
77
|
+
|
78
|
+
# Contains a generator which will parse the Elasticsearch *.java source files,
|
79
|
+
# extract information about REST API endpoints (URLs, HTTP methods, URL parameters, etc),
|
80
|
+
# and create a skeleton of the JSON API specification file for each endpoint.
|
81
|
+
#
|
82
|
+
# Usage:
|
83
|
+
#
|
84
|
+
# $ thor help api:generate:spec
|
85
|
+
#
|
86
|
+
# Example:
|
87
|
+
#
|
88
|
+
# time thor api:generate:spec \
|
89
|
+
# --force \
|
90
|
+
# --verbose \
|
91
|
+
# --crawl \
|
92
|
+
# --elasticsearch=/path/to/elasticsearch/source/code
|
93
|
+
#
|
94
|
+
# Features:
|
95
|
+
#
|
96
|
+
# * Extract the API name from the source filename (eg. `admin/cluster/health/RestClusterHealthAction.java` -> `cluster.health`)
|
97
|
+
# * Extract the URLs from the `registerHandler` statements
|
98
|
+
# * Extract the URL parts (eg. `{index}`) from the URLs
|
99
|
+
# * Extract the URL parameters (eg. `{timeout}`) from the `request.param("ABC")` statements
|
100
|
+
# * Detect whether HTTP body is allowed for the API from `request.hasContent()` statements
|
101
|
+
# * Search the <http://elasticsearch.org> website to get proper documentation URLs
|
102
|
+
# * Assemble the JSON format for the API spec
|
103
|
+
#
|
104
|
+
class JsonGenerator < Thor
|
105
|
+
namespace 'api:spec'
|
106
|
+
|
107
|
+
include Thor::Actions
|
108
|
+
|
109
|
+
__root = Pathname( File.expand_path('../../..', __FILE__) )
|
110
|
+
|
111
|
+
# Usage: thor help api:generate:spec
|
112
|
+
#
|
113
|
+
desc "generate", "Generate JSON API spec files from Elasticsearch source code"
|
114
|
+
method_option :force, type: :boolean, default: false, desc: 'Overwrite the output'
|
115
|
+
method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
|
116
|
+
method_option :output, default: __root.join('tmp/out'), desc: 'Path to output directory'
|
117
|
+
method_option :elasticsearch, default: __root.join('tmp/elasticsearch'), desc: 'Path to directory with Elasticsearch source code'
|
118
|
+
method_option :crawl, type: :boolean, default: false, desc: 'Extract URLs from Elasticsearch website'
|
119
|
+
|
120
|
+
def generate
|
121
|
+
self.class.source_root File.expand_path('../', __FILE__)
|
122
|
+
|
123
|
+
@output = Pathname(options[:output])
|
124
|
+
|
125
|
+
rest_actions = Utils.__parse_java_source(options[:elasticsearch].to_s)
|
126
|
+
|
127
|
+
if rest_actions.empty?
|
128
|
+
say_status 'ERROR', 'Cannot find Elasticsearch source in ' + options[:elasticsearch].to_s, :red
|
129
|
+
exit(1)
|
130
|
+
end
|
131
|
+
|
132
|
+
rest_actions.each do |name, info|
|
133
|
+
doc_url = ""
|
134
|
+
parts = info.reduce([]) { |sum, n| sum |= n['parts']; sum }.reduce({}) { |sum, n| sum[n] = {}; sum }
|
135
|
+
params = info.reduce([]) { |sum, n| sum |= n['params']; sum }.reduce({}) { |sum, n| sum[n] = {}; sum }
|
136
|
+
|
137
|
+
if options[:crawl]
|
138
|
+
begin
|
139
|
+
response = RestClient.get "http://search.elasticsearch.org/elastic-search-website/guide/_search?q=#{URI.escape(name.gsub(/\./, ' '))}"
|
140
|
+
hits = JSON.load(response)['hits']['hits']
|
141
|
+
if hit = hits.first
|
142
|
+
if hit['_score'] > 0.2
|
143
|
+
doc_title = hit['fields']['title']
|
144
|
+
doc_url = "http://elasticsearch.org" + hit['fields']['url']
|
145
|
+
end
|
146
|
+
end
|
147
|
+
rescue Exception => e
|
148
|
+
puts "[!] ERROR: #{e.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
spec = {
|
153
|
+
name => {
|
154
|
+
'documentation' => doc_url,
|
155
|
+
|
156
|
+
'methods' => info.map { |n| n['method'] }.uniq,
|
157
|
+
|
158
|
+
'url' => {
|
159
|
+
'path' => info.first['path'],
|
160
|
+
'paths' => info.map { |n| n['path'] }.uniq,
|
161
|
+
'parts' => parts,
|
162
|
+
'params' => params
|
163
|
+
},
|
164
|
+
|
165
|
+
'body' => info.first['body'] ? {} : nil
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
json = JSON.pretty_generate(spec, indent: ' ', array_nl: '', object_nl: "\n", space: ' ', space_before: ' ')
|
170
|
+
|
171
|
+
# Fix JSON array formatting
|
172
|
+
json.gsub!(/\[\s+/, '[')
|
173
|
+
json.gsub!(/, {2,}"/, ', "')
|
174
|
+
|
175
|
+
create_file @output.join( "#{name}.json" ), json + "\n"
|
176
|
+
|
177
|
+
if options[:verbose]
|
178
|
+
lines = json.split("\n")
|
179
|
+
say_status 'JSON',
|
180
|
+
lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n")
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
require 'active_support/core_ext/hash/deep_merge'
|
7
|
+
require 'active_support/inflector'
|
8
|
+
require 'multi_json'
|
9
|
+
require 'coderay'
|
10
|
+
require 'pry'
|
11
|
+
|
12
|
+
module Elasticsearch
|
13
|
+
|
14
|
+
module API
|
15
|
+
|
16
|
+
# A command line application based on [Thor](https://github.com/wycats/thor),
|
17
|
+
# which will read the JSON API spec file(s), and generate
|
18
|
+
# the Ruby source code (one file per API endpoint) with correct
|
19
|
+
# module namespace, method names, and RDoc documentation,
|
20
|
+
# as well as test files for each endpoint.
|
21
|
+
#
|
22
|
+
# Currently it only generates Ruby source, but can easily be
|
23
|
+
# extended and adapted to generate source code for other
|
24
|
+
# programming languages.
|
25
|
+
#
|
26
|
+
class SourceGenerator < Thor
|
27
|
+
namespace 'api:code'
|
28
|
+
|
29
|
+
include Thor::Actions
|
30
|
+
|
31
|
+
__root = Pathname( File.expand_path('../../..', __FILE__) )
|
32
|
+
|
33
|
+
desc "generate <PATH TO JSON SPEC FILES>", "Generate source code and tests from the REST API JSON specification"
|
34
|
+
method_option :language, default: 'ruby', desc: 'Programming language'
|
35
|
+
method_option :force, type: :boolean, default: false, desc: 'Overwrite the output'
|
36
|
+
method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
|
37
|
+
method_option :input, default: File.expand_path('../../../../tmp/elasticsearch/rest-api-spec/api/**/*.json', __FILE__), desc: 'Path to directory with JSON API specs'
|
38
|
+
method_option :output, default: File.expand_path('../../../tmp/out', __FILE__), desc: 'Path to output directory'
|
39
|
+
|
40
|
+
def generate(*files)
|
41
|
+
self.class.source_root File.expand_path('../', __FILE__)
|
42
|
+
|
43
|
+
@input = Pathname(options[:input])
|
44
|
+
@output = Pathname(options[:output])
|
45
|
+
|
46
|
+
# -- Test helper
|
47
|
+
copy_file "templates/ruby/test_helper.rb", @output.join('test').join('test_helper.rb') if options[:language] == 'ruby'
|
48
|
+
|
49
|
+
Dir[@input].each do |file|
|
50
|
+
@path = Pathname(file)
|
51
|
+
@json = MultiJson.load( File.read(@path) )
|
52
|
+
@spec = @json.values.first
|
53
|
+
say_status 'json', @path, :yellow
|
54
|
+
|
55
|
+
@spec['url'] ||= {}
|
56
|
+
@spec['url']['parts'] ||= []
|
57
|
+
@spec['url']['params'] ||= {}
|
58
|
+
|
59
|
+
# say_status 'JSON', @spec.inspect, options[:verbose]
|
60
|
+
|
61
|
+
@full_namespace = @json.keys.first.split('.')
|
62
|
+
@namespace_depth = @full_namespace.size > 0 ? @full_namespace.size-1 : 0
|
63
|
+
@module_namespace = @full_namespace[0, @namespace_depth]
|
64
|
+
@method_name = @full_namespace.last
|
65
|
+
|
66
|
+
# -- Ruby files
|
67
|
+
|
68
|
+
@path_to_file = @output.join('api').join( @module_namespace.join('/') ).join("#{@method_name}.rb")
|
69
|
+
|
70
|
+
empty_directory @output.join('api').join( @module_namespace.join('/') )
|
71
|
+
|
72
|
+
template "templates/#{options[:language]}/method.erb", @path_to_file
|
73
|
+
|
74
|
+
if options[:verbose]
|
75
|
+
colorized_output = CodeRay.scan_file(@path_to_file, :ruby).terminal
|
76
|
+
lines = colorized_output.split("\n")
|
77
|
+
say_status options[:language].downcase,
|
78
|
+
lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n"),
|
79
|
+
:yellow
|
80
|
+
end
|
81
|
+
|
82
|
+
# --- Test files
|
83
|
+
|
84
|
+
@test_directory = @output.join('test/api').join( @module_namespace.join('/') )
|
85
|
+
@test_file = @test_directory.join("#{@method_name}_test.rb")
|
86
|
+
|
87
|
+
empty_directory @test_directory
|
88
|
+
template "templates/#{options[:language]}/test.erb", @test_file
|
89
|
+
|
90
|
+
if options[:verbose]
|
91
|
+
colorized_output = colorized_output = CodeRay.scan_file(@test_file, :ruby).terminal
|
92
|
+
lines = colorized_output.split("\n")
|
93
|
+
say_status options[:language].downcase,
|
94
|
+
lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n"),
|
95
|
+
:yellow
|
96
|
+
say '▬'*terminal_width
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# -- Tree output
|
101
|
+
|
102
|
+
if options[:verbose] && `which tree > /dev/null 2>&1`
|
103
|
+
lines = `tree #{@output}`.split("\n")
|
104
|
+
say_status 'tree',
|
105
|
+
lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# Create the hierarchy of directories based on API namespaces
|
112
|
+
#
|
113
|
+
def __create_directories(key, value)
|
114
|
+
unless value['documentation']
|
115
|
+
empty_directory @output.join(key)
|
116
|
+
create_directory_hierarchy *value.to_a.first
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module Elasticsearch
|
8
|
+
|
9
|
+
module API
|
10
|
+
|
11
|
+
class Lister < Thor
|
12
|
+
namespace 'api'
|
13
|
+
|
14
|
+
desc "list <PATH DIRECTORY WITH JSON SPEC FILES>", "List all the REST API endpoints from the JSON specification"
|
15
|
+
method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
|
16
|
+
method_option :format, default: 'text', desc: 'Output format (text, json)'
|
17
|
+
def list(directory)
|
18
|
+
input = Pathname(directory).join('*.json')
|
19
|
+
apis = Dir[input.to_s].map do |f|
|
20
|
+
File.basename(f, '.json')
|
21
|
+
end.sort
|
22
|
+
|
23
|
+
if options[:verbose]
|
24
|
+
say_status 'Count', apis.size
|
25
|
+
say '▬'*terminal_width
|
26
|
+
end
|
27
|
+
|
28
|
+
case options[:format]
|
29
|
+
when 'text'
|
30
|
+
apis.each { |a| puts "* #{a}" }
|
31
|
+
when 'json'
|
32
|
+
puts apis.inspect
|
33
|
+
else
|
34
|
+
puts "[!] ERROR: Unknown output format '#{options[:format]}'"
|
35
|
+
exit(1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Elasticsearch
|
2
|
+
module API
|
3
|
+
<%- @module_namespace.each_with_index do |name, i| -%>
|
4
|
+
<%= ' '*i %>module <%= name.capitalize %>
|
5
|
+
<%- end -%>
|
6
|
+
<%= ' '*@namespace_depth %>module Actions
|
7
|
+
|
8
|
+
<%= ' '*@namespace_depth %># <%= @spec['description'] || 'TODO: Description' %>
|
9
|
+
<%= ' '*@namespace_depth %>#
|
10
|
+
<%# URL parts -%>
|
11
|
+
<%- @spec['url']['parts'].each do |name,info| -%>
|
12
|
+
<%- info['type'] = 'String' if info['type'] == 'enum' # Rename 'enums' to 'strings' -%>
|
13
|
+
<%= ' '*@namespace_depth + "# @option arguments [#{info['type'] ? info['type'].capitalize : 'String'}] :#{name} #{info['description']}" + ( info['required'] ? ' (*Required*)' : '' ) -%><%= " (options: #{info['options'].join(', ')})" if info['options'] -%>
|
14
|
+
<%= "\n" -%>
|
15
|
+
<%- end -%>
|
16
|
+
<%# Body -%>
|
17
|
+
<%= ' '*(@namespace_depth+3) + '# @option arguments [Hash] :body ' + (@spec['body']['description'] || 'TODO: Description') + (@spec['body']['required'] ? ' (*Required*)' : '') + "\n" if @spec['body'] -%>
|
18
|
+
<%# URL parameters -%>
|
19
|
+
<%- @spec['url']['params'].each do |name,info| -%>
|
20
|
+
<%- info['type'] = 'String' if info['type'] == 'enum' # Rename 'enums' to 'strings' -%>
|
21
|
+
<%= ' '*@namespace_depth + "# @option arguments [#{info['type'] ? info['type'].capitalize : 'String'}] :#{name} #{info['description']}" -%><%= " (options: #{info['options'].join(', ')})" if info['options'] -%>
|
22
|
+
<%= "\n" -%>
|
23
|
+
<%- end if @spec['url']['parts'] -%>
|
24
|
+
<%= ' '*@namespace_depth -%>#
|
25
|
+
<%# Documentation link -%>
|
26
|
+
<%= ' '*@namespace_depth %># @see <%= @spec['documentation'] %>
|
27
|
+
<%= ' '*@namespace_depth %>#
|
28
|
+
<%# Method definition -%>
|
29
|
+
<%= ' '*@namespace_depth -%>def <%= @method_name %>(arguments={})
|
30
|
+
<%# Required arguments -%>
|
31
|
+
<%- @spec['url']['parts'].select { |name, info| info['required'] }.each do |name, info| -%>
|
32
|
+
<%= ' '*(@namespace_depth+1) + "raise ArgumentError, \"Required argument '#{name}' missing\" unless arguments[:#{name}]" + "\n" -%>
|
33
|
+
<%- end -%>
|
34
|
+
<%- if @spec['body'] && @spec['body']['required'] -%>
|
35
|
+
<%= ' '*(@namespace_depth+1) + "raise ArgumentError, \"Required argument 'body' missing\" unless arguments[:body]" + "\n" -%>
|
36
|
+
<%- end -%>
|
37
|
+
<%# Method, path, params, body -%>
|
38
|
+
<%= ' '*@namespace_depth %> valid_params = [
|
39
|
+
<%= ' '*(@namespace_depth+2) %><%= @spec['url']['params'].keys.map { |k| ":#{k}" }.join(",\n#{' '*(@namespace_depth+5)}") %> ]
|
40
|
+
<%= ' '*@namespace_depth %> method = '<%= @spec['methods'].first %>'
|
41
|
+
<%- unless @spec['url']['parts'].empty? -%>
|
42
|
+
<%= ' '*@namespace_depth %> path = "<%= @spec['url']['path'].split('/').compact.reject {|p| p =~ /^\s*$/}.map do |p|
|
43
|
+
p =~ /\{/ ? "\#\{arguments[:#{p.tr('{}', '')}]\}" : p
|
44
|
+
end.join('/') %>"
|
45
|
+
<%- else -%>
|
46
|
+
<%= ' '*@namespace_depth %> path = "<%= @spec['url']['path'] %>"
|
47
|
+
<%- end -%>
|
48
|
+
<%- unless @spec['url']['params'].keys.empty? -%>
|
49
|
+
<%= ' '*@namespace_depth %> params = Utils.__validate_and_extract_params arguments, valid_params
|
50
|
+
<%- else -%>
|
51
|
+
<%= ' '*@namespace_depth %> params = {}
|
52
|
+
<%- end -%>
|
53
|
+
<%= ' '*@namespace_depth %> body = <%= @spec['body'].nil? ? 'nil' : 'arguments[:body]' %>
|
54
|
+
<%# Perform request %>
|
55
|
+
<%= ' '*@namespace_depth %> perform_request(method, path, params, body).body
|
56
|
+
<%= ' '*@namespace_depth %>end
|
57
|
+
<%- @namespace_depth.downto(1) do |i| -%>
|
58
|
+
<%= ' '*(i-1) %>end
|
59
|
+
<%- end if @namespace_depth > 0 -%>
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Elasticsearch
|
4
|
+
module Test
|
5
|
+
class <%= @module_namespace.empty? ? @method_name.camelize : @module_namespace.map {|n| n.capitalize}.join + @method_name.camelize %>Test < ::Test::Unit::TestCase
|
6
|
+
|
7
|
+
context "<%= @module_namespace.empty? ? '' : @module_namespace.map {|n| n.capitalize}.join + ': ' %><%= @method_name.humanize %>" do
|
8
|
+
subject { FakeClient.new }
|
9
|
+
|
10
|
+
should "perform correct request" do
|
11
|
+
subject.expects(:perform_request).with do |method, url, params, body|
|
12
|
+
assert_equal 'FAKE', method
|
13
|
+
assert_equal 'test', url
|
14
|
+
assert_equal Hash.new, params
|
15
|
+
<%= @spec['body'].nil? ? 'assert_nil body' : 'assert_equal Hash.new, body' %>
|
16
|
+
true
|
17
|
+
end.returns(FakeResponse.new)
|
18
|
+
|
19
|
+
subject.<%= @full_namespace.join('.') %>
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|