elasticsearch-api 7.3.0 → 7.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +16 -23
  3. data/elasticsearch-api.gemspec +1 -1
  4. data/lib/elasticsearch/api/actions/abort_benchmark.rb +1 -2
  5. data/lib/elasticsearch/api/actions/benchmark.rb +2 -3
  6. data/lib/elasticsearch/api/actions/bulk.rb +35 -68
  7. data/lib/elasticsearch/api/actions/cat/aliases.rb +30 -52
  8. data/lib/elasticsearch/api/actions/cat/allocation.rb +36 -50
  9. data/lib/elasticsearch/api/actions/cat/count.rb +25 -46
  10. data/lib/elasticsearch/api/actions/cat/fielddata.rb +31 -33
  11. data/lib/elasticsearch/api/actions/cat/health.rb +27 -37
  12. data/lib/elasticsearch/api/actions/cat/help.rb +14 -10
  13. data/lib/elasticsearch/api/actions/cat/indices.rb +45 -62
  14. data/lib/elasticsearch/api/actions/cat/master.rb +24 -34
  15. data/lib/elasticsearch/api/actions/cat/nodeattrs.rb +20 -16
  16. data/lib/elasticsearch/api/actions/cat/nodes.rb +34 -46
  17. data/lib/elasticsearch/api/actions/cat/params_registry.rb +0 -1
  18. data/lib/elasticsearch/api/actions/cat/pending_tasks.rb +29 -35
  19. data/lib/elasticsearch/api/actions/cat/plugins.rb +21 -18
  20. data/lib/elasticsearch/api/actions/cat/recovery.rb +40 -56
  21. data/lib/elasticsearch/api/actions/cat/repositories.rb +21 -24
  22. data/lib/elasticsearch/api/actions/cat/segments.rb +29 -22
  23. data/lib/elasticsearch/api/actions/cat/shards.rb +38 -59
  24. data/lib/elasticsearch/api/actions/cat/snapshots.rb +32 -27
  25. data/lib/elasticsearch/api/actions/cat/tasks.rb +25 -19
  26. data/lib/elasticsearch/api/actions/cat/templates.rb +26 -18
  27. data/lib/elasticsearch/api/actions/cat/thread_pool.rb +36 -46
  28. data/lib/elasticsearch/api/actions/clear_scroll.rb +21 -8
  29. data/lib/elasticsearch/api/actions/cluster/allocation_explain.rb +15 -13
  30. data/lib/elasticsearch/api/actions/cluster/get_settings.rb +18 -18
  31. data/lib/elasticsearch/api/actions/cluster/health.rb +42 -44
  32. data/lib/elasticsearch/api/actions/cluster/params_registry.rb +0 -1
  33. data/lib/elasticsearch/api/actions/cluster/pending_tasks.rb +15 -17
  34. data/lib/elasticsearch/api/actions/cluster/put_settings.rb +20 -17
  35. data/lib/elasticsearch/api/actions/cluster/remote_info.rb +8 -6
  36. data/lib/elasticsearch/api/actions/cluster/reroute.rb +25 -37
  37. data/lib/elasticsearch/api/actions/cluster/state.rb +37 -41
  38. data/lib/elasticsearch/api/actions/cluster/stats.rb +20 -12
  39. data/lib/elasticsearch/api/actions/count.rb +52 -39
  40. data/lib/elasticsearch/api/actions/create.rb +25 -26
  41. data/lib/elasticsearch/api/actions/delete.rb +43 -36
  42. data/lib/elasticsearch/api/actions/delete_by_query.rb +74 -62
  43. data/lib/elasticsearch/api/actions/delete_by_query_rethrottle.rb +39 -0
  44. data/lib/elasticsearch/api/actions/delete_by_rethrottle.rb +4 -3
  45. data/lib/elasticsearch/api/actions/delete_script.rb +19 -13
  46. data/lib/elasticsearch/api/actions/exists.rb +44 -34
  47. data/lib/elasticsearch/api/actions/exists_source.rb +43 -25
  48. data/lib/elasticsearch/api/actions/explain.rb +46 -51
  49. data/lib/elasticsearch/api/actions/field_caps.rb +27 -20
  50. data/lib/elasticsearch/api/actions/get.rb +42 -41
  51. data/lib/elasticsearch/api/actions/get_script.rb +19 -14
  52. data/lib/elasticsearch/api/actions/get_source.rb +38 -44
  53. data/lib/elasticsearch/api/actions/index.rb +60 -89
  54. data/lib/elasticsearch/api/actions/indices/analyze.rb +19 -48
  55. data/lib/elasticsearch/api/actions/indices/clear_cache.rb +29 -41
  56. data/lib/elasticsearch/api/actions/indices/clone.rb +50 -0
  57. data/lib/elasticsearch/api/actions/indices/close.rb +28 -32
  58. data/lib/elasticsearch/api/actions/indices/create.rb +22 -70
  59. data/lib/elasticsearch/api/actions/indices/delete.rb +23 -35
  60. data/lib/elasticsearch/api/actions/indices/delete_alias.rb +24 -20
  61. data/lib/elasticsearch/api/actions/indices/delete_template.rb +18 -20
  62. data/lib/elasticsearch/api/actions/indices/exists.rb +32 -34
  63. data/lib/elasticsearch/api/actions/indices/exists_alias.rb +33 -29
  64. data/lib/elasticsearch/api/actions/indices/exists_template.rb +21 -16
  65. data/lib/elasticsearch/api/actions/indices/exists_type.rb +29 -29
  66. data/lib/elasticsearch/api/actions/indices/flush.rb +28 -28
  67. data/lib/elasticsearch/api/actions/indices/flush_synced.rb +23 -12
  68. data/lib/elasticsearch/api/actions/indices/forcemerge.rb +26 -41
  69. data/lib/elasticsearch/api/actions/indices/freeze.rb +7 -8
  70. data/lib/elasticsearch/api/actions/indices/get.rb +25 -19
  71. data/lib/elasticsearch/api/actions/indices/get_alias.rb +31 -23
  72. data/lib/elasticsearch/api/actions/indices/get_field_mapping.rb +42 -38
  73. data/lib/elasticsearch/api/actions/indices/get_mapping.rb +39 -31
  74. data/lib/elasticsearch/api/actions/indices/get_settings.rb +34 -37
  75. data/lib/elasticsearch/api/actions/indices/get_template.rb +21 -23
  76. data/lib/elasticsearch/api/actions/indices/get_upgrade.rb +48 -0
  77. data/lib/elasticsearch/api/actions/indices/open.rb +24 -21
  78. data/lib/elasticsearch/api/actions/indices/params_registry.rb +0 -1
  79. data/lib/elasticsearch/api/actions/indices/put_alias.rb +25 -27
  80. data/lib/elasticsearch/api/actions/indices/put_mapping.rb +40 -39
  81. data/lib/elasticsearch/api/actions/indices/put_settings.rb +30 -37
  82. data/lib/elasticsearch/api/actions/indices/put_template.rb +23 -23
  83. data/lib/elasticsearch/api/actions/indices/recovery.rb +20 -23
  84. data/lib/elasticsearch/api/actions/indices/refresh.rb +22 -26
  85. data/lib/elasticsearch/api/actions/indices/rollover.rb +28 -19
  86. data/lib/elasticsearch/api/actions/indices/segments.rb +24 -17
  87. data/lib/elasticsearch/api/actions/indices/shard_stores.rb +27 -15
  88. data/lib/elasticsearch/api/actions/indices/shrink.rb +23 -17
  89. data/lib/elasticsearch/api/actions/indices/split.rb +23 -17
  90. data/lib/elasticsearch/api/actions/indices/stats.rb +53 -104
  91. data/lib/elasticsearch/api/actions/indices/unfreeze.rb +7 -7
  92. data/lib/elasticsearch/api/actions/indices/update_aliases.rb +15 -32
  93. data/lib/elasticsearch/api/actions/indices/upgrade.rb +26 -16
  94. data/lib/elasticsearch/api/actions/indices/validate_query.rb +46 -59
  95. data/lib/elasticsearch/api/actions/info.rb +9 -6
  96. data/lib/elasticsearch/api/actions/ingest/delete_pipeline.rb +18 -12
  97. data/lib/elasticsearch/api/actions/ingest/get_pipeline.rb +21 -11
  98. data/lib/elasticsearch/api/actions/ingest/params_registry.rb +0 -1
  99. data/lib/elasticsearch/api/actions/ingest/processor_grok.rb +12 -13
  100. data/lib/elasticsearch/api/actions/ingest/put_pipeline.rb +19 -14
  101. data/lib/elasticsearch/api/actions/ingest/simulate.rb +23 -13
  102. data/lib/elasticsearch/api/actions/mget.rb +37 -44
  103. data/lib/elasticsearch/api/actions/msearch.rb +54 -54
  104. data/lib/elasticsearch/api/actions/msearch_template.rb +46 -35
  105. data/lib/elasticsearch/api/actions/mtermvectors.rb +39 -35
  106. data/lib/elasticsearch/api/actions/nodes/hot_threads.rb +30 -25
  107. data/lib/elasticsearch/api/actions/nodes/info.rb +29 -63
  108. data/lib/elasticsearch/api/actions/nodes/params_registry.rb +0 -1
  109. data/lib/elasticsearch/api/actions/nodes/reload_secure_settings.rb +24 -22
  110. data/lib/elasticsearch/api/actions/nodes/shutdown.rb +4 -4
  111. data/lib/elasticsearch/api/actions/nodes/stats.rb +43 -36
  112. data/lib/elasticsearch/api/actions/nodes/usage.rb +31 -10
  113. data/lib/elasticsearch/api/actions/params_registry.rb +0 -1
  114. data/lib/elasticsearch/api/actions/ping.rb +12 -13
  115. data/lib/elasticsearch/api/actions/put_script.rb +26 -30
  116. data/lib/elasticsearch/api/actions/rank_eval.rb +24 -15
  117. data/lib/elasticsearch/api/actions/reindex.rb +25 -48
  118. data/lib/elasticsearch/api/actions/reindex_rethrottle.rb +18 -12
  119. data/lib/elasticsearch/api/actions/remote/info.rb +1 -2
  120. data/lib/elasticsearch/api/actions/render_search_template.rb +17 -15
  121. data/lib/elasticsearch/api/actions/scripts_painless_execute.rb +8 -6
  122. data/lib/elasticsearch/api/actions/scroll.rb +28 -51
  123. data/lib/elasticsearch/api/actions/search.rb +104 -165
  124. data/lib/elasticsearch/api/actions/search_shards.rb +31 -28
  125. data/lib/elasticsearch/api/actions/search_template.rb +48 -40
  126. data/lib/elasticsearch/api/actions/snapshot/cleanup_repository.rb +44 -0
  127. data/lib/elasticsearch/api/actions/snapshot/create.rb +22 -29
  128. data/lib/elasticsearch/api/actions/snapshot/create_repository.rb +19 -24
  129. data/lib/elasticsearch/api/actions/snapshot/delete.rb +20 -22
  130. data/lib/elasticsearch/api/actions/snapshot/delete_repository.rb +16 -18
  131. data/lib/elasticsearch/api/actions/snapshot/get.rb +22 -31
  132. data/lib/elasticsearch/api/actions/snapshot/get_repository.rb +21 -25
  133. data/lib/elasticsearch/api/actions/snapshot/params_registry.rb +0 -1
  134. data/lib/elasticsearch/api/actions/snapshot/restore.rb +21 -32
  135. data/lib/elasticsearch/api/actions/snapshot/status.rb +23 -24
  136. data/lib/elasticsearch/api/actions/snapshot/verify_repository.rb +18 -13
  137. data/lib/elasticsearch/api/actions/tasks/cancel.rb +19 -13
  138. data/lib/elasticsearch/api/actions/tasks/get.rb +16 -13
  139. data/lib/elasticsearch/api/actions/tasks/list.rb +20 -18
  140. data/lib/elasticsearch/api/actions/tasks/params_registry.rb +0 -1
  141. data/lib/elasticsearch/api/actions/termvectors.rb +52 -70
  142. data/lib/elasticsearch/api/actions/update.rb +53 -98
  143. data/lib/elasticsearch/api/actions/update_by_query.rb +77 -66
  144. data/lib/elasticsearch/api/actions/update_by_query_rethrottle.rb +17 -11
  145. data/lib/elasticsearch/api/version.rb +1 -1
  146. data/spec/elasticsearch/api/actions/cat/segments_spec.rb +9 -11
  147. data/spec/elasticsearch/api/actions/cluster/put_settings_spec.rb +1 -1
  148. data/spec/elasticsearch/api/actions/count_spec.rb +8 -8
  149. data/spec/elasticsearch/api/actions/delete_by_query_spec.rb +12 -7
  150. data/spec/elasticsearch/api/actions/delete_script_spec.rb +0 -14
  151. data/spec/elasticsearch/api/actions/exists_document_spec.rb +1 -1
  152. data/spec/elasticsearch/api/actions/get_document_source_spec.rb +1 -1
  153. data/spec/elasticsearch/api/actions/index_document_spec.rb +6 -15
  154. data/spec/elasticsearch/api/actions/indices/analyze_spec.rb +0 -4
  155. data/spec/elasticsearch/api/actions/indices/clear_cache_spec.rb +1 -5
  156. data/spec/elasticsearch/api/actions/indices/clone_spec.rb +109 -0
  157. data/spec/elasticsearch/api/actions/indices/delete_alias_spec.rb +2 -2
  158. data/spec/elasticsearch/api/actions/indices/get_spec.rb +0 -11
  159. data/spec/elasticsearch/api/actions/indices/put_alias_spec.rb +3 -3
  160. data/spec/elasticsearch/api/actions/indices/put_mapping_spec.rb +3 -3
  161. data/spec/elasticsearch/api/actions/indices/stats_spec.rb +0 -1
  162. data/spec/elasticsearch/api/actions/nodes/hot_threads_spec.rb +3 -3
  163. data/spec/elasticsearch/api/actions/put_script_spec.rb +20 -15
  164. data/spec/elasticsearch/api/actions/render_search_template_spec.rb +23 -7
  165. data/spec/elasticsearch/api/actions/scroll_spec.rb +37 -0
  166. data/spec/elasticsearch/api/actions/search_spec.rb +0 -15
  167. data/spec/elasticsearch/api/actions/tasks/list_spec.rb +0 -11
  168. data/spec/elasticsearch/api/actions/update_document_spec.rb +3 -7
  169. data/spec/elasticsearch/api/rest_api_yaml_spec.rb +1 -1
  170. data/spec/rest_yaml_tests_helper.rb +12 -0
  171. data/utils/Gemfile +1 -0
  172. data/utils/Thorfile +0 -1
  173. data/utils/thor/generate_source.rb +192 -85
  174. data/utils/thor/generator/endpoint_specifics.rb +157 -0
  175. data/utils/thor/generator/files_helper.rb +37 -0
  176. data/utils/thor/lister.rb +3 -4
  177. data/utils/thor/templates/_documentation_top.erb +27 -0
  178. data/utils/thor/templates/_method_setup.erb +35 -0
  179. data/utils/thor/templates/_params_registry.erb +12 -0
  180. data/utils/thor/templates/_perform_request.erb +37 -0
  181. data/utils/thor/templates/method.erb +59 -0
  182. data/utils/thor/templates/{ruby/test.erb → test.erb} +0 -0
  183. data/utils/thor/templates/{ruby/test_helper.rb → test_helper.rb} +0 -0
  184. metadata +31 -14
  185. data/spec/elasticsearch/api/actions/scoll_spec.rb +0 -21
  186. data/utils/thor/generate_api.rb +0 -193
  187. data/utils/thor/templates/ruby/method.erb +0 -62
@@ -53,16 +53,12 @@ describe 'client#update' do
53
53
  'foo/bar/1/_update'
54
54
  end
55
55
 
56
- let(:params) do
57
- { version: 100 }
58
- end
59
-
60
56
  let(:body) do
61
57
  {}
62
58
  end
63
59
 
64
60
  it 'performs the request' do
65
- expect(client_double.update(index: 'foo', type: 'bar', id: '1', version: 100, body: {}))
61
+ expect(client_double.update(index: 'foo', type: 'bar', id: '1', body: {}))
66
62
  end
67
63
  end
68
64
 
@@ -98,14 +94,14 @@ describe 'client#update' do
98
94
 
99
95
  it 'raises it to the user' do
100
96
  expect {
101
- client.update(index: 'foo', type: 'bar', id: 'XXX')
97
+ client.update(index: 'foo', type: 'bar', id: 'XXX', body: {})
102
98
  }.to raise_exception(NotFound)
103
99
  end
104
100
 
105
101
  context 'when the :ignore parameter is specified' do
106
102
 
107
103
  it 'does not raise the error to the user' do
108
- expect(client.update(index: 'foo', type: 'bar', id: 'XXX', ignore: 404)).to eq(false)
104
+ expect(client.update(index: 'foo', type: 'bar', id: 'XXX', body: {}, ignore: 404)).to eq(false)
109
105
  end
110
106
  end
111
107
  end
@@ -18,7 +18,7 @@ describe 'Rest API YAML tests' do
18
18
  context "#{test.description}" do
19
19
 
20
20
  if test.skip_test?(ADMIN_CLIENT)
21
- skip 'Test contains feature(s) not yet support or version is not satisfied'
21
+ skip 'Test contains feature(s) not yet supported or version is not satisfied'
22
22
 
23
23
  else
24
24
 
@@ -72,6 +72,18 @@ skipped_tests << { file: 'delete/70_mix_typeless_typeful.yml',
72
72
  skipped_tests << { file: 'cat.templates/10_basic.yml',
73
73
  description: '*' }
74
74
 
75
+ # node_selector is not supported yet
76
+ skipped_tests << { file: 'cat.aliases/10_basic.yml',
77
+ description: '*' }
78
+
79
+ # Responses are there but not equal (eg.: yellow status)
80
+ skipped_tests << { file: 'cluster.health/10_basic.yml',
81
+ description: 'cluster health with closed index (pre 7.2.0)' }
82
+
83
+ # Regular expression not catching exact match:
84
+ skipped_tests << { file: 'cat.indices/10_basic.yml',
85
+ description: 'Test cat indices output for closed index (pre 7.2.0)' }
86
+
75
87
  SKIPPED_TESTS = skipped_tests
76
88
 
77
89
  # The directory of rest api YAML files.
data/utils/Gemfile CHANGED
@@ -11,3 +11,4 @@ gem 'multi_json'
11
11
  gem 'thor'
12
12
  gem 'json'
13
13
  gem 'pry'
14
+ gem 'rubocop'
data/utils/Thorfile CHANGED
@@ -2,6 +2,5 @@
2
2
  # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
3
  # See the LICENSE file in the project root for more information
4
4
 
5
- require File.expand_path('./thor/generate_api')
6
5
  require File.expand_path('./thor/generate_source')
7
6
  require File.expand_path('./thor/lister')
@@ -5,138 +5,245 @@
5
5
  # encoding: UTF-8
6
6
 
7
7
  require 'thor'
8
-
9
8
  require 'pathname'
10
9
  require 'active_support/core_ext/hash/deep_merge'
11
10
  require 'active_support/inflector'
12
11
  require 'multi_json'
13
12
  require 'coderay'
14
13
  require 'pry'
14
+ require_relative 'generator/files_helper'
15
+ require_relative 'generator/endpoint_specifics'
15
16
 
16
17
  module Elasticsearch
17
-
18
18
  module API
19
-
20
19
  # A command line application based on [Thor](https://github.com/wycats/thor),
21
20
  # which will read the JSON API spec file(s), and generate
22
21
  # the Ruby source code (one file per API endpoint) with correct
23
22
  # module namespace, method names, and RDoc documentation,
24
23
  # as well as test files for each endpoint.
25
24
  #
26
- # Currently it only generates Ruby source, but can easily be
27
- # extended and adapted to generate source code for other
28
- # programming languages.
25
+ # Specific exceptions and code snippets that need to be included are written
26
+ # in EndpointSpecifics (generator/endpoint_specifics) and the module is included
27
+ # here.
29
28
  #
30
29
  class SourceGenerator < Thor
31
30
  namespace 'api:code'
32
-
33
31
  include Thor::Actions
32
+ include EndpointSpecifics
34
33
 
35
- __root = Pathname( File.expand_path('../../..', __FILE__) )
36
-
37
- desc "generate", "Generate source code and tests from the REST API JSON specification"
38
- method_option :language, default: 'ruby', desc: 'Programming language'
39
- method_option :force, type: :boolean, default: false, desc: 'Overwrite the output'
40
- method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
41
- method_option :input, default: File.expand_path('../../../../tmp/elasticsearch/rest-api-spec/api/**/*.json', __FILE__), desc: 'Path to directory with JSON API specs'
42
- method_option :output, default: File.expand_path('../../../tmp/out', __FILE__), desc: 'Path to output directory'
43
-
44
- def generate(*files)
45
- self.class.source_root File.expand_path('../', __FILE__)
46
-
47
- @input = Pathname(options[:input])
48
- @output = Pathname(options[:output])
34
+ __root = Pathname(File.expand_path('../../..', __FILE__))
49
35
 
50
- # -- Test helper
51
- copy_file "templates/ruby/test_helper.rb", @output.join('test').join('test_helper.rb') if options[:language] == 'ruby'
36
+ desc 'generate', 'Generate source code and tests from the REST API JSON specification'
37
+ method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
38
+ method_option :tests, type: :boolean, default: false, desc: 'Generate test files'
39
+ method_option :xpack, type: :boolean, default: false, desc: 'Generate X-Pack'
52
40
 
53
- files = Dir.entries(@input.to_s).reject { |f| f.start_with?('.') || f.start_with?('_') }
41
+ def generate
42
+ self.class.source_root File.expand_path(__dir__)
43
+ @xpack = options[:xpack]
54
44
 
55
- files.each do |filepath|
56
- file = @input.join(filepath)
45
+ @input = FilesHelper.input_dir(@xpack)
46
+ @output = FilesHelper.output_dir(@xpack)
57
47
 
58
- @path = Pathname(file)
59
- @json = MultiJson.load( File.read(@path) )
60
- @spec = @json.values.first
48
+ FilesHelper.files(@xpack).each do |filepath|
49
+ @path = Pathname(@input.join(filepath))
50
+ @json = MultiJson.load(File.read(@path))
51
+ @spec = @json.values.first
61
52
  say_status 'json', @path, :yellow
62
53
 
63
54
  @spec['url'] ||= {}
64
- @spec['url']['parts'] ||= []
65
- @spec['url']['params'] ||= {}
66
55
 
67
- # say_status 'JSON', @spec.inspect, options[:verbose]
68
-
69
- @full_namespace = @json.keys.first.split('.')
70
- @namespace_depth = @full_namespace.size > 0 ? @full_namespace.size-1 : 0
56
+ @endpoint_name = @json.keys.first
57
+ @full_namespace = __full_namespace
58
+ @namespace_depth = @full_namespace.size > 0 ? @full_namespace.size - 1 : 0
71
59
  @module_namespace = @full_namespace[0, @namespace_depth]
72
60
  @method_name = @full_namespace.last
73
- @http_method = "Elasticsearch::API::HTTP_#{@spec['methods'].first}"
74
- @http_path = unless @spec['url']['parts'].empty?
75
- @spec['url']['path']
76
- .split('/')
77
- .compact
78
- .reject { |p| p =~ /^\s*$/ }
79
- .map { |p| p =~ /\{/ ? "\#\{arguments[:#{p.tr('{}', '')}]\}" : p }
80
- .join('/')
81
- .gsub(/^\//, '')
82
- else
83
- @spec['url']['path'].gsub(/^\//, '')
84
- end
85
-
86
- # -- Ruby files
87
-
88
- @path_to_file = @output.join('api').join( @module_namespace.join('/') ).join("#{@method_name}.rb")
89
-
90
- empty_directory @output.join('api').join( @module_namespace.join('/') )
91
-
92
- template "templates/#{options[:language]}/method.erb", @path_to_file
93
-
94
- if options[:verbose]
95
- colorized_output = CodeRay.scan_file(@path_to_file, :ruby).terminal
96
- lines = colorized_output.split("\n")
97
- say_status options[:language].downcase,
98
- lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n"),
99
- :yellow
100
- end
61
+ @parts = __endpoint_parts
62
+ @params = @spec['params'] || {}
63
+ @specific_params = specific_params(@module_namespace.first) # See EndpointSpecifics
64
+ @http_method = __http_method
65
+ @paths = @spec['url']['paths'].map { |b| b['path'] }
66
+ # Using Ruby's safe operator on array:
67
+ @deprecation_note = @spec['url']['paths'].last&.[]('deprecated')
68
+ @http_path = __http_path
69
+ @required_parts = __required_parts
101
70
 
102
- # --- Test files
71
+ @module_namespace.shift if @module_namespace.first == 'xpack'
72
+ @path_to_file = @output.join(@module_namespace.join('/')).join("#{@method_name}.rb")
73
+ dir = @output.join(@module_namespace.join('/'))
74
+ empty_directory(dir, verbose: false)
103
75
 
104
- @test_directory = @output.join('test/api').join( @module_namespace.join('/') )
105
- @test_file = @test_directory.join("#{@method_name}_test.rb")
76
+ # Write the file with the ERB template:
77
+ template('templates/method.erb', @path_to_file, force: true)
106
78
 
107
- empty_directory @test_directory
108
- template "templates/#{options[:language]}/test.erb", @test_file
79
+ print_source_code(@path_to_file) if options[:verbose]
109
80
 
110
- if options[:verbose]
111
- colorized_output = colorized_output = CodeRay.scan_file(@test_file, :ruby).terminal
112
- lines = colorized_output.split("\n")
113
- say_status options[:language].downcase,
114
- lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n"),
115
- :yellow
116
- say '▬'*terminal_width
117
- end
81
+ generate_tests if options[:tests]
82
+
83
+ puts
118
84
  end
119
85
 
120
- # -- Tree output
86
+ run_rubocop
121
87
 
122
- if options[:verbose] && `which tree > /dev/null 2>&1; echo $?`.to_i < 1
123
- lines = `tree #{@output}`.split("\n")
124
- say_status 'tree',
125
- lines.first + "\n" + lines[1, lines.size].map { |l| ' '*14 + l }.join("\n")
126
- end
88
+ # -- Tree output
89
+ print_tree if options[:verbose]
127
90
  end
128
91
 
129
92
  private
130
93
 
94
+ def __full_namespace
95
+ names = @endpoint_name.split('.')
96
+ if @xpack
97
+ names = (names.first == 'xpack' ? names : ['xpack', names].flatten)
98
+ # Return an array with 'ml' renamed to 'machine_learning' and 'ilm' to
99
+ # 'index_lifecycle_management'
100
+ names.map do |name|
101
+ name
102
+ .gsub(/^ml$/, 'machine_learning')
103
+ .gsub(/^ilm$/, 'index_lifecycle_management')
104
+ end
105
+ else
106
+ names
107
+ end
108
+ end
109
+
131
110
  # Create the hierarchy of directories based on API namespaces
132
111
  #
133
112
  def __create_directories(key, value)
134
- unless value['documentation']
135
- empty_directory @output.join(key)
136
- create_directory_hierarchy *value.to_a.first
113
+ return if value['documentation']
114
+
115
+ empty_directory @output.join(key)
116
+ create_directory_hierarchy * value.to_a.first
117
+ end
118
+
119
+ # Extract parts from each path
120
+ #
121
+ def __endpoint_parts
122
+ parts = @spec['url']['paths'].select do |a|
123
+ a.keys.include?('parts')
124
+ end.map do |path|
125
+ path&.[]('parts')
126
+ end
127
+ (parts.inject(&:merge) || [])
128
+ end
129
+
130
+ def __http_method
131
+ case @endpoint_name
132
+ when 'index'
133
+ '_id ? Elasticsearch::API::HTTP_PUT : Elasticsearch::API::HTTP_POST'
134
+ when 'count'
135
+ <<~SRC
136
+ if arguments[:body]
137
+ Elasticsearch::API::HTTP_POST
138
+ else
139
+ Elasticsearch::API::HTTP_GET
140
+ end
141
+ SRC
142
+ else
143
+ "Elasticsearch::API::HTTP_#{@spec['url']['paths'].map { |a| a['methods'] }.flatten.first}"
144
+ end
145
+ end
146
+
147
+ def __http_path
148
+ return "\"#{__parse_path(@paths.first)}\"" if @paths.size == 1
149
+ return termvectors_path if @method_name == 'termvectors'
150
+
151
+ result = ''
152
+ anchor_string = ''
153
+ @paths.sort { |a, b| b.length <=> a.length }.each_with_index do |path, i|
154
+ var_string = __extract_path_variables(path).map { |var| "_#{var}" }.join(' && ')
155
+ next if anchor_string == var_string
156
+
157
+ anchor_string = var_string
158
+ result += if i.zero?
159
+ "if #{var_string}\n"
160
+ elsif (i == @paths.size - 1) || var_string.empty?
161
+ "else\n"
162
+ else
163
+ "elsif #{var_string}\n"
164
+ end
165
+ result += "\"#{__parse_path(path)}\"\n"
137
166
  end
167
+ result += 'end'
168
+ result
169
+ end
170
+
171
+ def __parse_path(path)
172
+ path.gsub(/^\//, '')
173
+ .gsub(/\/$/, '')
174
+ .gsub('{', "\#{#{__utils}.__listify(_")
175
+ .gsub('}', ')}')
176
+ end
177
+
178
+ def __path_variables
179
+ @paths.map do |path|
180
+ __extract_path_variables(path)
181
+ end
182
+ end
183
+
184
+ # extract values that are in the {var} format:
185
+ def __extract_path_variables(path)
186
+ path.scan(/{(\w+)}/).flatten
187
+ end
188
+
189
+ # Find parts that are definitely required and should raise an error if
190
+ # they're not present
191
+ #
192
+ def __required_parts
193
+ required = []
194
+ return required if @endpoint_name == 'tasks.get'
195
+
196
+ required << 'body' if (@spec['body'] && @spec['body']['required'])
197
+ # Get required variables from paths:
198
+ req_variables = __path_variables.inject(:&) # find intersection
199
+ required << req_variables unless req_variables.empty?
200
+ required.flatten
138
201
  end
139
202
 
203
+ def docs_helper(name, info)
204
+ info['type'] = 'String' if info['type'] == 'enum' # Rename 'enums' to 'strings'
205
+ tipo = info['type'] ? info['type'].capitalize : 'String'
206
+ description = info['description'] ? info['description'].strip : '[TODO]'
207
+ options = info['options'] ? "\n # (options: #{info['options'].join(', '.strip)})\n" : ''
208
+ required = info['required'] ? ' (*Required*)' : ''
209
+ deprecated = info['deprecated'] ? ' *Deprecated*' : ''
210
+ "# @option arguments [#{tipo}] :#{name} #{description} #{required} #{deprecated} #{options}\n"
211
+ end
212
+
213
+ def generate_tests
214
+ copy_file 'templates/test_helper.rb', @output.join('test').join('test_helper.rb')
215
+
216
+ @test_directory = @output.join('test/api').join(@module_namespace.join('/'))
217
+ @test_file = @test_directory.join("#{@method_name}_test.rb")
218
+
219
+ empty_directory @test_directory
220
+ template 'templates/test.erb', @test_file
221
+
222
+ print_source_code(@test_file) if options[:verbose]
223
+ end
224
+
225
+ def print_source_code(path_to_file)
226
+ colorized_output = CodeRay.scan_file(path_to_file, :ruby).terminal
227
+ lines = colorized_output.split("\n")
228
+ formatted = lines.first + "\n" + lines[1, lines.size].map { |l| ' ' * 14 + l }.join("\n")
229
+
230
+ say_status('ruby', formatted, :yellow)
231
+ end
232
+
233
+ def print_tree
234
+ return unless `which tree > /dev/null 2>&1; echo $?`.to_i < 1
235
+
236
+ lines = `tree #{@output}`.split("\n")
237
+ say_status('tree', lines.first + "\n" + lines[1, lines.size].map { |l| ' ' * 14 + l }.join("\n"))
238
+ end
239
+
240
+ def __utils
241
+ @xpack ? 'Elasticsearch::API::Utils' : 'Utils'
242
+ end
243
+
244
+ def run_rubocop
245
+ system("rubocop --format autogenconf -x #{FilesHelper::output_dir(@xpack)}")
246
+ end
140
247
  end
141
248
  end
142
249
  end
@@ -0,0 +1,157 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to Elasticsearch B.V under one or more agreements.
4
+ # Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
5
+ # See the LICENSE file in the project root for more information
6
+
7
+ module Elasticsearch
8
+ module API
9
+ # Handles specific exceptional parameters and code snippets that need to be
10
+ # included in the generated code. This module is included in SourceGenerator
11
+ # so its methods can be used from the ERB template (method.erb). This will
12
+ # potentially be refactored into different templates.
13
+ module EndpointSpecifics
14
+ # Endpoints that need Utils.__rescue_from_not_found
15
+ IGNORE_404 = %w[
16
+ exists
17
+ indices.exists
18
+ indices.exists_alias
19
+ indices.exists_template
20
+ indices.exists_type
21
+ ].freeze
22
+
23
+ # Endpoints that need Utils.__rescue_from_not_found if the ignore
24
+ # parameter is included
25
+ COMPLEX_IGNORE_404 = %w[
26
+ delete
27
+ get
28
+ indices.flush_synced
29
+ indices.delete_template
30
+ indices.delete
31
+ security.get_role
32
+ security.get_user
33
+ snapshot.status
34
+ snapshot.get
35
+ snapshot.get_repository
36
+ snapshot.delete_repository
37
+ snapshot.delete
38
+ update
39
+ watcher.delete_watch
40
+ ].freeze
41
+
42
+ # Endpoints that need params[:h] listified
43
+ H_PARAMS = %w[aliases allocation count health indices nodes pending_tasks
44
+ recovery shards thread_pool].freeze
45
+
46
+ # Function that adds the listified h param code
47
+ def specific_params(namespace)
48
+ params = []
49
+ if H_PARAMS.include?(@method_name) && namespace == 'cat'
50
+ if @method_name == 'nodes'
51
+ params << 'params[:h] = Utils.__listify(params[:h], escape: false) if params[:h]'
52
+ else
53
+ params << 'params[:h] = Utils.__listify(params[:h]) if params[:h]'
54
+ end
55
+ end
56
+ params
57
+ end
58
+
59
+ def needs_ignore_404?(endpoint)
60
+ IGNORE_404.include? endpoint
61
+ end
62
+
63
+ def needs_complex_ignore_404?(endpoint)
64
+ COMPLEX_IGNORE_404.include? endpoint
65
+ end
66
+
67
+ def termvectors_path
68
+ <<~SRC
69
+ if _index && _type && _id
70
+ "\#{Utils.__listify(_index)}/\#{Utils.__listify(_type)}/\#{Utils.__listify(_id)}/\#{endpoint}"
71
+ elsif _index && _type
72
+ "\#{Utils.__listify(_index)}/\#{Utils.__listify(_type)}/\#{endpoint}"
73
+ elsif _index && _id
74
+ "\#{Utils.__listify(_index)}/\#{endpoint}/\#{Utils.__listify(_id)}"
75
+ else
76
+ "\#{Utils.__listify(_index)}/\#{endpoint}"
77
+ end
78
+ SRC
79
+ end
80
+
81
+ def ping_perform_request
82
+ <<~SRC
83
+ begin
84
+ perform_request(method, path, params, body).status == 200 ? true : false
85
+ rescue Exception => e
86
+ if e.class.to_s =~ /NotFound|ConnectionFailed/ || e.message =~ /Not\s*Found|404|ConnectionFailed/i
87
+ false
88
+ else
89
+ raise e
90
+ end
91
+ end
92
+ SRC
93
+ end
94
+
95
+ def indices_stats_params_registry
96
+ <<~SRC
97
+ ParamsRegistry.register(:stats_params, [
98
+ #{@spec['params'].keys.map { |k| ":#{k}" }.join(",\n")}
99
+ ].freeze)
100
+
101
+ ParamsRegistry.register(:stats_parts, [
102
+ #{@parts['metric']['options'].push('metric').map { |k| ":#{k}" }.join(",\n")}
103
+ ].freeze)
104
+ SRC
105
+ end
106
+
107
+ def msearch_body_helper
108
+ <<~SRC
109
+ case
110
+ when body.is_a?(Array) && body.any? { |d| d.has_key? :search }
111
+ payload = body.
112
+ inject([]) do |sum, item|
113
+ meta = item
114
+ data = meta.delete(:search)
115
+
116
+ sum << meta
117
+ sum << data
118
+ sum
119
+ end.
120
+ map { |item| Elasticsearch::API.serializer.dump(item) }
121
+ payload << "" unless payload.empty?
122
+ payload = payload.join("\n")
123
+ when body.is_a?(Array)
124
+ payload = body.map { |d| d.is_a?(String) ? d : Elasticsearch::API.serializer.dump(d) }
125
+ payload << "" unless payload.empty?
126
+ payload = payload.join("\n")
127
+ else
128
+ payload = body
129
+ end
130
+ SRC
131
+ end
132
+
133
+ def msearch_template_body_helper
134
+ <<~SRC
135
+ case
136
+ when body.is_a?(Array)
137
+ payload = body.map { |d| d.is_a?(String) ? d : Elasticsearch::API.serializer.dump(d) }
138
+ payload << "" unless payload.empty?
139
+ payload = payload.join("\n")
140
+ else
141
+ payload = body
142
+ end
143
+ SRC
144
+ end
145
+
146
+ def bulk_body_helper
147
+ <<~SRC
148
+ if body.is_a? Array
149
+ payload = Utils.__bulkify(body)
150
+ else
151
+ payload = body
152
+ end
153
+ SRC
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,37 @@
1
+ require 'pathname'
2
+
3
+ module Elasticsearch
4
+ module API
5
+ module FilesHelper
6
+ OSS_SRC_PATH = '../../../../../tmp/elasticsearch/rest-api-spec/src/main/resources/rest-api-spec/api/'.freeze
7
+ OSS_OUTPUT_DIR = '../../elasticsearch-api/lib/elasticsearch/api/actions'.freeze
8
+
9
+ XPACK_SRC_PATH = '../../../../../tmp/elasticsearch/x-pack/plugin/src/test/resources/rest-api-spec/api'.freeze
10
+ XPACK_OUTPUT_DIR = '../../elasticsearch-xpack/lib/elasticsearch/xpack/api/actions'.freeze
11
+
12
+ # Path to directory with JSON API specs
13
+ def self.input_dir(xpack = false)
14
+ input_dir = if xpack
15
+ File.expand_path(XPACK_SRC_PATH, __FILE__)
16
+ else
17
+ File.expand_path(OSS_SRC_PATH, __FILE__)
18
+ end
19
+ Pathname(input_dir)
20
+ end
21
+
22
+ # Path to directory to copy generated files
23
+ def self.output_dir(xpack = false)
24
+ xpack ? Pathname(XPACK_OUTPUT_DIR) : Pathname(OSS_OUTPUT_DIR)
25
+ end
26
+
27
+ # Only get JSON files and remove hidden files
28
+ def self.files(xpack = false)
29
+ Dir.entries(input_dir(xpack).to_s).reject do |f|
30
+ f.start_with?('.') ||
31
+ f.start_with?('_') ||
32
+ File.extname(f) != '.json'
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
data/utils/thor/lister.rb CHANGED
@@ -9,16 +9,16 @@ require 'thor'
9
9
  require 'pathname'
10
10
 
11
11
  module Elasticsearch
12
-
13
12
  module API
14
-
15
13
  class Lister < Thor
16
14
  namespace 'api'
17
15
 
16
+ DEFAULT_PATH = '../../tmp/elasticsearch/rest-api-spec/src/main/resources/rest-api-spec/api/'.freeze
17
+
18
18
  desc "list <PATH DIRECTORY WITH JSON SPEC FILES>", "List all the REST API endpoints from the JSON specification"
19
19
  method_option :verbose, type: :boolean, default: false, desc: 'Output more information'
20
20
  method_option :format, default: 'text', desc: 'Output format (text, json)'
21
- def list(directory)
21
+ def list(directory = DEFAULT_PATH)
22
22
  input = Pathname(directory).join('*.json')
23
23
  apis = Dir[input.to_s].map do |f|
24
24
  File.basename(f, '.json')
@@ -40,6 +40,5 @@ module Elasticsearch
40
40
  end
41
41
  end
42
42
  end
43
-
44
43
  end
45
44
  end
@@ -0,0 +1,27 @@
1
+ <%- if @spec['documentation']['description'] -%>
2
+ <%= ' '*(@namespace_depth+3) %># <%= @spec['documentation']['description'].gsub("\n", "\n#{' '*(@namespace_depth+3)}# ") -%>
3
+ <%- else %>
4
+ <%= ' '*(@namespace_depth+3) %># TODO: Description
5
+ <%- end %>
6
+ <%= ' '*(@namespace_depth+3) %>#
7
+ <%- unless @parts.nil? || @parts.empty? %><%# URL parts -%>
8
+ <%- @parts.each do |name, info| -%>
9
+ <%= docs_helper(name, info) -%>
10
+ <%- end -%>
11
+ <%- end -%><%# Body -%>
12
+ <%# URL parameters -%>
13
+ <%- @params.each do |name, info| -%>
14
+ <%= docs_helper(name, info) -%>
15
+ <%- end %>
16
+ <%= ' '*(@namespace_depth+3) + '# @option arguments [Hash] :body ' + (@spec['body']['description'] ? @spec['body']['description'].strip : 'TODO: Description') + (@spec['body']['required'] ? ' (*Required*)' : '') + "\n" if @spec['body'] -%>
17
+ <% if @deprecation_note -%>
18
+ #
19
+ # *Deprecation notice*:
20
+ # <%= @deprecation_note['description'] %>
21
+ # Deprecated since version <%= @deprecation_note['version'] %>
22
+ #
23
+ <% end -%>
24
+ <%= ' '*(@namespace_depth+3) -%>#
25
+ <%# Documentation link -%>
26
+ <%= ' '*(@namespace_depth+3) %># @see <%= @spec['documentation']['url'] ? @spec['documentation']['url'].gsub!(/\/(current|master)\//, '/7.5/') : "[TODO]" %>
27
+ <%= ' '*(@namespace_depth+3) %>#