From d428c577f5ee6cacf29342bf29fe8796695610e2 Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Tue, 17 Jun 2025 15:30:20 -0700 Subject: [PATCH 1/7] Updating Spect Insert tool to support client code translations Signed-off-by: Daniel Jackson --- _api-reference/cat/cat-allocation.md | 34 +++ spec-insert/lib/insert_arguments.rb | 2 +- spec-insert/lib/jekyll-spec-insert.rb | 3 +- spec-insert/lib/renderers/example_code.rb | 225 ++++++++++++++++++ spec-insert/lib/renderers/spec_insert.rb | 5 +- .../renderers/templates/example_code.mustache | 16 ++ spec-insert/lib/utils.rb | 3 +- 7 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 spec-insert/lib/renderers/example_code.rb create mode 100644 spec-insert/lib/renderers/templates/example_code.mustache diff --git a/_api-reference/cat/cat-allocation.md b/_api-reference/cat/cat-allocation.md index 965310d53ff..e5daecac3db 100644 --- a/_api-reference/cat/cat-allocation.md +++ b/_api-reference/cat/cat-allocation.md @@ -27,6 +27,40 @@ GET /_cat/allocation/{node_id} ``` + +{% capture step1_rest %} +POST _snapshot///_restore +{% endcapture %} + +{% capture step1_python %} +response = client.snapshot.restore( + repository = "", + snapshot = "", + body = { + "indices": "opendistro-reports-definitions", + "ignore_unavailable": true, + "include_global_state": false, + "rename_pattern": "(.+)", + "rename_replacement": "$1_restored", + "include_aliases": false + } +) + +{% endcapture %} + +{% capture step1_javascript %} +JavaScript example code not yet implemented +{% endcapture %} + +{% include code-block.html +rest=step1_rest +python=step1_python +%} + /) }&.last&.- 1 args = lines[1..end_index].filter { |line| line.include?(':') }.to_h do |line| - key, value = line.split(':') + key, value = line.split(':',2) [key.strip, value.strip] end new(args) diff --git a/spec-insert/lib/jekyll-spec-insert.rb b/spec-insert/lib/jekyll-spec-insert.rb index f474fdd1235..1ac8d4ea884 100644 --- a/spec-insert/lib/jekyll-spec-insert.rb +++ b/spec-insert/lib/jekyll-spec-insert.rb @@ -30,6 +30,7 @@ def self.process_file(file, fail_on_error: false) raise e if fail_on_error relative_path = Pathname(file).relative_path_from(Pathname.new(Dir.pwd)) Jekyll.logger.error "Error processing #{relative_path}: #{e.message}" + Jekyll.logger.error "Error backtrace: #{e.backtrace.join("\n")}" end def self.watch(fail_on_error: false) @@ -43,4 +44,4 @@ def self.watch(fail_on_error: false) trap('TERM') { exit } sleep end -end +end \ No newline at end of file diff --git a/spec-insert/lib/renderers/example_code.rb b/spec-insert/lib/renderers/example_code.rb new file mode 100644 index 00000000000..25c62195dbe --- /dev/null +++ b/spec-insert/lib/renderers/example_code.rb @@ -0,0 +1,225 @@ +# frozen_string_literal: true + +require 'json' + +class ExampleCode < BaseMustacheRenderer + self.template_file = "#{__dir__}/templates/example_code.mustache" + + def initialize(action, args) + super(action, args) + end + + # Resolves the correct OpenSearch client method call + def client_method_call + segments = @action.full_name.to_s.split('.') + return "client" if segments.empty? + + if segments.size == 1 + "client.#{segments.first}" + else + "client.#{se gments.first}.#{segments[1]}" + end + end + + def rest_lines + @args.raw['rest']&.split("\n")&.map(&:strip) || [] + end + + def rest_code + rest_lines.join("\n") + end + + # Uses the declared HTTP method in the OpenAPI spec + def http_method + @action.http_verbs.first&.upcase || "GET" + end + + # Converts OpenAPI-style path (/index/{id}) into Ruby-style interpolation (/index/#{id}) + def path_only + url = @action.urls.first + return '' unless url + url.gsub(/\{(\w+)\}/, '#{\1}') + end + def javascript_code + "JavaScript example code not yet implemented" + end + # Assembles a query string from the declared query parameters + def query_string + return '' if @action.query_parameters.empty? + @action.query_parameters.map { |param| "#{param.name}=example" }.join('&') + end + + # Combines path and query string for display + def path_with_query + qs = query_string + qs.empty? ? path_only : "#{path_only}?#{qs}" + end + + # Hash version of query params + def query_params + @action.query_parameters.to_h { |param| [param.name, "example"] } + end + + # Parses the body from the REST example (only for preserving raw formatting) + def body + body_lines = rest_lines[1..] + return nil if body_lines.empty? + begin + JSON.parse(body_lines.join("\n")) + rescue + nil + end + end + + def action_expects_body?(verb) + verb = verb.downcase + @action.operations.any? do |op| + op.http_verb.to_s.downcase == verb && + op.spec&.requestBody && + op.spec.requestBody.respond_to?(:content) + end + end + + def matching_spec_path + return @matching_spec_path if defined?(@matching_spec_path) + + # Extract raw request path from rest line + raw_line = rest_lines.first.to_s + _, request_path = raw_line.split + request_segments = request_path.split('?').first.split('/').reject(&:empty?) + + # Choose the best matching spec URL + best = nil + best_score = -1 + + @action.urls.each do |spec_path| + spec_segments = spec_path.split('/').reject(&:empty?) + next unless spec_segments.size == request_segments.size + + score = 0 + spec_segments.each_with_index do |seg, i| + if seg.start_with?('{') + score += 1 # parameter match + elsif seg == request_segments[i] + score += 2 # exact match + else + score = -1 + break + end + end + + if score > best_score + best = spec_path + best_score = score + end + end + + @matching_spec_path = best + end + + # Final Python code using action metadata + def python_code + return "# Invalid action" unless @action&.full_name + + client_setup = <<~PYTHON + from opensearchpy import OpenSearch + + host = 'localhost' + port = 9200 + auth = ('admin', 'admin') # For testing only. Don't store credentials in code. + ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA. + + # Create the client with SSL/TLS enabled, but hostname verification disabled. + client = OpenSearch( + hosts = [{'host': host, 'port': port}], + http_compress = True, # enables gzip compression for request bodies + http_auth = auth, + use_ssl = True, + verify_certs = True, + ssl_assert_hostname = False, + ssl_show_warn = False, + ca_certs = ca_certs_path + ) + + PYTHON + + if @args.raw['body'] == '{"hello"}' + puts "# This is a debug example" + end + + namespace, method = @action.full_name.split('.') + client_call = "client" + client_call += ".#{namespace}" if namespace + client_call += ".#{method}" + + args = [] + + # Extract actual path and query from the first line of the REST input + raw_line = rest_lines.first.to_s + http_verb, full_path = raw_line.split + path_part, query_string = full_path.to_s.split('?', 2) + + # Extract used path values from the path part + path_values = path_part.split('/').reject(&:empty?) + + # Match spec path (e.g. /_cat/aliases/{name}) to determine which param this value belongs to + spec_path = matching_spec_path.to_s + spec_parts = spec_path.split('/').reject(&:empty?) + + param_mapping = {} + spec_parts.each_with_index do |part, i| + if part =~ /\{(.+?)\}/ && path_values[i] + param_mapping[$1] = path_values[i] + end + end + + # Add path parameters if they were present in the example + @action.path_parameters.each do |param| + if param_mapping.key?(param.name) + args << "#{param.name} = \"#{param_mapping[param.name]}\"" + end + end + + # Add query parameters from query string + if query_string + query_pairs = query_string.split('&').map { |s| s.split('=', 2) } + query_hash = query_pairs.map do |k, v| + "#{k}: #{v ? "\"#{v}\"" : "True"}" + end.join(', ') + args << "params = { #{query_hash} }" unless query_hash.empty? + end + + # Add body if spec allows it AND it's present in REST + if action_expects_body?(http_verb) + if @args.raw['body'] + begin + parsed = JSON.parse(@args.raw['body']) + pretty = JSON.pretty_generate(parsed).gsub(/^/, ' ') + args << "body = #{pretty}" + rescue JSON::ParserError + args << "body = #{JSON.dump(@args.raw['body'])}" + end + else + args << 'body = { "Insert body here" }' + end + end + + # Final result + call_code = if args.empty? + "response = #{client_call}()" + else + final_args = args.map { |line| " #{line}" }.join(",\n") + <<~PYTHON + response = #{client_call}( + #{final_args} + ) + PYTHON + end + # Prepend client if requested + if @args.raw['include_client_setup'] + client_setup + call_code + else + call_code + end + end +end \ No newline at end of file diff --git a/spec-insert/lib/renderers/spec_insert.rb b/spec-insert/lib/renderers/spec_insert.rb index 87289a9baf8..02303052140 100644 --- a/spec-insert/lib/renderers/spec_insert.rb +++ b/spec-insert/lib/renderers/spec_insert.rb @@ -7,6 +7,7 @@ require_relative 'path_parameters' require_relative 'query_parameters' require_relative 'body_parameters' +require_relative 'example_code' # Class to render spec insertions class SpecInsert < BaseMustacheRenderer @@ -40,8 +41,10 @@ def content BodyParameters.new(@action, @args, is_request: true).render when :response_body_parameters BodyParameters.new(@action, @args, is_request: false).render + when :example_code + ExampleCode.new(@action, @args).render else - raise SpecInsertError, "Invalid component: #{@args.component}" + raise SpecInsertError, "Invalid component: #{@args.component}, from spec_insert.rb " end end end diff --git a/spec-insert/lib/renderers/templates/example_code.mustache b/spec-insert/lib/renderers/templates/example_code.mustache new file mode 100644 index 00000000000..19ac77add65 --- /dev/null +++ b/spec-insert/lib/renderers/templates/example_code.mustache @@ -0,0 +1,16 @@ +{% capture step1_rest %} +{{{rest_code}}} +{% endcapture %} + +{% capture step1_python %} +{{{python_code}}} +{% endcapture %} + +{% capture step1_javascript %} +{{{javascript_code}}} +{% endcapture %} + +{% include code-block.html +rest=step1_rest +python=step1_python +%} \ No newline at end of file diff --git a/spec-insert/lib/utils.rb b/spec-insert/lib/utils.rb index 22bd273db2b..8f53d71931f 100644 --- a/spec-insert/lib/utils.rb +++ b/spec-insert/lib/utils.rb @@ -13,7 +13,8 @@ module Utils 'query_parameters' => 'Query Parameters', 'path_parameters' => 'Path Parameters', 'request_body_parameters' => 'Request Body Parameters', - 'response_body_parameters' => 'Response Body Parameters' + 'response_body_parameters' => 'Response Body Parameters', + 'example_code' => 'Example Code' }.freeze # @return [Array] list of markdown files to insert the spec components into From 46b0106670d41438ed584881ee1e0118e4843fcd Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Tue, 22 Jul 2025 15:12:25 -0700 Subject: [PATCH 2/7] Continued working on the Spect Insert feature for automatic conversion of API calls into Language SDK. Signed-off-by: Daniel Jackson --- _api-reference/cat/cat-allocation.md | 34 --- spec-insert/lib/insert_arguments.rb | 32 ++- spec-insert/lib/renderers/example_code.rb | 215 +----------------- .../lib/renderers/example_code_python.rb | 152 +++++++++++++ .../renderers/templates/example_code.mustache | 4 - .../templates/example_code.python.mustache | 3 + 6 files changed, 196 insertions(+), 244 deletions(-) create mode 100644 spec-insert/lib/renderers/example_code_python.rb create mode 100644 spec-insert/lib/renderers/templates/example_code.python.mustache diff --git a/_api-reference/cat/cat-allocation.md b/_api-reference/cat/cat-allocation.md index e5daecac3db..965310d53ff 100644 --- a/_api-reference/cat/cat-allocation.md +++ b/_api-reference/cat/cat-allocation.md @@ -27,40 +27,6 @@ GET /_cat/allocation/{node_id} ``` - -{% capture step1_rest %} -POST _snapshot///_restore -{% endcapture %} - -{% capture step1_python %} -response = client.snapshot.restore( - repository = "", - snapshot = "", - body = { - "indices": "opendistro-reports-definitions", - "ignore_unavailable": true, - "include_global_state": false, - "rename_pattern": "(.+)", - "rename_replacement": "$1_restored", - "include_aliases": false - } -) - -{% endcapture %} - -{% capture step1_javascript %} -JavaScript example code not yet implemented -{% endcapture %} - -{% include code-block.html -rest=step1_rest -python=step1_python -%} - Signed-off-by: Daniel Jackson --- spec-insert/lib/api/action.rb | 20 +++++++++++++++++++ spec-insert/lib/insert_arguments.rb | 11 +++++++++- spec-insert/lib/renderers/spec_insert.rb | 2 +- .../renderers/templates/example_code.mustache | 5 ++--- 4 files changed, 33 insertions(+), 5 deletions(-) diff --git a/spec-insert/lib/api/action.rb b/spec-insert/lib/api/action.rb index f0a8fdcf1df..b6a5b5f9661 100644 --- a/spec-insert/lib/api/action.rb +++ b/spec-insert/lib/api/action.rb @@ -103,6 +103,26 @@ def deprecated; @spec.deprecated; end # @return [String] Deprecation message def deprecation_message; @spec['x-deprecation-message']; end + def self.find_by_rest(rest_line) + method, raw_path = rest_line.strip.split(' ', 2) + return nil unless method && raw_path + + # Remove query parameters + path = raw_path.split('?').first + + all.find do |action| + action.operations.any? do |op| + op.http_verb.casecmp?(method) && + path_template_matches?(op.url, path) + end + end + end + + def self.path_template_matches?(template, actual) + # "/{index}/_doc/{id}" => "^/[^/]+/_doc/[^/]+$" + regex = Regexp.new("^" + template.gsub(/\{[^\/]+\}/, '[^/]+') + "$") + regex.match?(actual) + end # @return [String] API reference def api_reference; @operation.external_docs.url; end end diff --git a/spec-insert/lib/insert_arguments.rb b/spec-insert/lib/insert_arguments.rb index 78f5a07ec45..81b5002b2a7 100644 --- a/spec-insert/lib/insert_arguments.rb +++ b/spec-insert/lib/insert_arguments.rb @@ -27,7 +27,16 @@ def self.from_marker(lines) # @return [String] def api - @raw['api'] + return @raw['api'] if @raw['api'].present? + + if rest_line = rest&.raw_lines&.first + inferred_action = Api::Action.find_by_rest(rest_line) + raise SpecInsertError, "Could not infer API from rest line: #{rest_line}" unless inferred_action + + return inferred_action.full_name + end + + nil end # @return [String] diff --git a/spec-insert/lib/renderers/spec_insert.rb b/spec-insert/lib/renderers/spec_insert.rb index 02303052140..f40a09700a5 100644 --- a/spec-insert/lib/renderers/spec_insert.rb +++ b/spec-insert/lib/renderers/spec_insert.rb @@ -17,7 +17,7 @@ class SpecInsert < BaseMustacheRenderer def initialize(args) action = Api::Action.by_full_name[args.api] super(action, args) - raise SpecInsertError, '`api` argument not specified.' unless @args.api + raise SpecInsertError, '`api` argument could not be resolved.' unless @action raise SpecInsertError, "API Action '#{@args.api}' does not exist in the spec." unless @action end diff --git a/spec-insert/lib/renderers/templates/example_code.mustache b/spec-insert/lib/renderers/templates/example_code.mustache index 1764e6022a9..5076450346d 100644 --- a/spec-insert/lib/renderers/templates/example_code.mustache +++ b/spec-insert/lib/renderers/templates/example_code.mustache @@ -7,6 +7,5 @@ {% endcapture %} {% include code-block.html -rest=step1_rest -python=step1_python -%} \ No newline at end of file + rest=step1_rest + python=step1_python %} \ No newline at end of file From d83404b4d3ec7d0c5b9cc253510816aabfa6fa2c Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Thu, 7 Aug 2025 12:22:59 -0700 Subject: [PATCH 4/7] Continued working on the Spec-Insert tool. - Added test examples to test files. Signed-off-by: Daniel Jackson --- _api-reference/cat/cat-aliases.md | 2 +- _api-reference/cat/cat-allocation.md | 2 +- _api-reference/cat/cat-cluster_manager.md | 2 +- _api-reference/cat/cat-count.md | 2 +- _api-reference/cat/cat-field-data.md | 2 +- _api-reference/cat/cat-health.md | 2 +- _api-reference/cat/cat-indices.md | 2 +- _api-reference/cat/cat-nodeattrs.md | 2 +- _api-reference/cat/cat-nodes.md | 4 +- _api-reference/cat/cat-pending-tasks.md | 4 +- _api-reference/cat/cat-pit-segments.md | 2 +- _api-reference/cat/cat-plugins.md | 2 +- _api-reference/cat/cat-recovery.md | 4 +- _api-reference/cat/cat-repositories.md | 2 +- _api-reference/cat/cat-segment-replication.md | 6 +- _api-reference/cat/cat-segments.md | 2 +- _api-reference/cat/cat-shards.md | 4 +- _api-reference/cat/cat-snapshots.md | 2 +- _api-reference/cat/cat-tasks.md | 4 +- _api-reference/cat/cat-templates.md | 2 +- _api-reference/cat/cat-thread-pool.md | 2 +- _api-reference/document-apis/mtermvectors.md | 4 +- .../security/authentication/auth-info.md | 2 +- _api-reference/snapshots/clone-snapshot.md | 4 +- _api-reference/tasks/cancel-tasks.md | 4 +- _api-reference/tasks/get-tasks.md | 2 +- _api-reference/tasks/list-tasks.md | 2 +- .../_fixtures/expected_output/example_code.md | 71 +++++++++++++++++++ .../spec/_fixtures/input/example_code.md | 19 +++++ spec-insert/spec/doc_processor_spec.rb | 4 ++ 30 files changed, 131 insertions(+), 37 deletions(-) create mode 100644 spec-insert/spec/_fixtures/expected_output/example_code.md create mode 100644 spec-insert/spec/_fixtures/input/example_code.md diff --git a/_api-reference/cat/cat-aliases.md b/_api-reference/cat/cat-aliases.md index 0e758f2d673..ac2f63088f6 100644 --- a/_api-reference/cat/cat-aliases.md +++ b/_api-reference/cat/cat-aliases.md @@ -37,7 +37,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-allocation.md b/_api-reference/cat/cat-allocation.md index 965310d53ff..7f9c5b57a91 100644 --- a/_api-reference/cat/cat-allocation.md +++ b/_api-reference/cat/cat-allocation.md @@ -36,7 +36,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-cluster_manager.md b/_api-reference/cat/cat-cluster_manager.md index 0a27ba1ccd5..4c7111f89c0 100644 --- a/_api-reference/cat/cat-cluster_manager.md +++ b/_api-reference/cat/cat-cluster_manager.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-count.md b/_api-reference/cat/cat-count.md index 7c4231a9587..6ec0879e6ea 100644 --- a/_api-reference/cat/cat-count.md +++ b/_api-reference/cat/cat-count.md @@ -36,7 +36,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-field-data.md b/_api-reference/cat/cat-field-data.md index 62cf9712196..f409a0690ad 100644 --- a/_api-reference/cat/cat-field-data.md +++ b/_api-reference/cat/cat-field-data.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-health.md b/_api-reference/cat/cat-health.md index e0c913ef28f..d313c1f7f5f 100644 --- a/_api-reference/cat/cat-health.md +++ b/_api-reference/cat/cat-health.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-indices.md b/_api-reference/cat/cat-indices.md index 562d81f2f48..79e297f220d 100644 --- a/_api-reference/cat/cat-indices.md +++ b/_api-reference/cat/cat-indices.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-nodeattrs.md b/_api-reference/cat/cat-nodeattrs.md index 2d09bb0324b..b4bc9c45481 100644 --- a/_api-reference/cat/cat-nodeattrs.md +++ b/_api-reference/cat/cat-nodeattrs.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-nodes.md b/_api-reference/cat/cat-nodes.md index ec39ab8c521..a1f16e306d8 100644 --- a/_api-reference/cat/cat-nodes.md +++ b/_api-reference/cat/cat-nodes.md @@ -36,7 +36,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -47,7 +47,7 @@ The following table lists the available query parameters. All query parameters a | `h` | List | A comma-separated list of column names to display. | N/A | | `help` | Boolean | Returns help information. | `false` | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-pending-tasks.md b/_api-reference/cat/cat-pending-tasks.md index 26028f61610..d60a1873299 100644 --- a/_api-reference/cat/cat-pending-tasks.md +++ b/_api-reference/cat/cat-pending-tasks.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -44,7 +44,7 @@ The following table lists the available query parameters. All query parameters a | `help` | Boolean | Returns help information. | `false` | | `local` | Boolean | Returns local information but does not retrieve the state from the cluster manager node. | `false` | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-pit-segments.md b/_api-reference/cat/cat-pit-segments.md index e105983c4e6..14cdc84abd6 100644 --- a/_api-reference/cat/cat-pit-segments.md +++ b/_api-reference/cat/cat-pit-segments.md @@ -41,7 +41,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-plugins.md b/_api-reference/cat/cat-plugins.md index 65d68fe2e32..450b33ebd71 100644 --- a/_api-reference/cat/cat-plugins.md +++ b/_api-reference/cat/cat-plugins.md @@ -33,7 +33,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-recovery.md b/_api-reference/cat/cat-recovery.md index 40e90566db6..cf076b79b8e 100644 --- a/_api-reference/cat/cat-recovery.md +++ b/_api-reference/cat/cat-recovery.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -47,7 +47,7 @@ The following table lists the available query parameters. All query parameters a | `help` | Boolean | Returns help information. | `false` | | `index` | List | A comma-separated list of data streams, indexes, and aliases used to limit the request. Supports wildcards (`*`). To target all data streams and indexes, omit this parameter or use `*` or `_all`. | N/A | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-repositories.md b/_api-reference/cat/cat-repositories.md index fe9c0895171..7d621897cbd 100644 --- a/_api-reference/cat/cat-repositories.md +++ b/_api-reference/cat/cat-repositories.md @@ -33,7 +33,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-segment-replication.md b/_api-reference/cat/cat-segment-replication.md index 459e323370b..b2201fb5817 100644 --- a/_api-reference/cat/cat-segment-replication.md +++ b/_api-reference/cat/cat-segment-replication.md @@ -34,7 +34,7 @@ include_deprecated: false --> ## Path parameters -The following table lists the available path parameters. All path parameters are optional. +The following table lists the available path parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | @@ -51,7 +51,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -69,7 +69,7 @@ The following table lists the available query parameters. All query parameters a | `index` | List | A comma-separated list of data streams, indexes, and aliases used to limit the request. Supports wildcards (`*`). To target all data streams and indexes, omit this parameter or use `*` or `_all`. | N/A | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | | `shards` | List | A comma-separated list of shards to display. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `timeout` | String | The operation timeout. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-segments.md b/_api-reference/cat/cat-segments.md index a1aad5954fe..cfb5ce7ba04 100644 --- a/_api-reference/cat/cat-segments.md +++ b/_api-reference/cat/cat-segments.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-shards.md b/_api-reference/cat/cat-shards.md index b90d82df3da..054f40a6db9 100644 --- a/_api-reference/cat/cat-shards.md +++ b/_api-reference/cat/cat-shards.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -46,7 +46,7 @@ The following table lists the available query parameters. All query parameters a | `help` | Boolean | Returns help information. | `false` | | `local` | Boolean | Returns local information but does not retrieve the state from the cluster manager node. | `false` | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-snapshots.md b/_api-reference/cat/cat-snapshots.md index 47e1ff22f2f..70c10adb96e 100644 --- a/_api-reference/cat/cat-snapshots.md +++ b/_api-reference/cat/cat-snapshots.md @@ -46,7 +46,7 @@ The following table lists the available query parameters. | `help` | Boolean | Returns help information. | `false` | | `ignore_unavailable` | Boolean | When `true`, the response does not include information from unavailable snapshots. | `false` | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-tasks.md b/_api-reference/cat/cat-tasks.md index da267b71198..65e5975e148 100644 --- a/_api-reference/cat/cat-tasks.md +++ b/_api-reference/cat/cat-tasks.md @@ -33,7 +33,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | @@ -45,7 +45,7 @@ The following table lists the available query parameters. All query parameters a | `nodes` | List | A comma-separated list of node IDs or names used to limit the returned information. Use `_local` to return information from the node to which you're connecting, specify a specific node from which to get information, or keep the parameter empty to get information from all nodes. | N/A | | `parent_task_id` | String | The parent task identifier, which is used to limit the response. | N/A | | `s` | List | A comma-separated list of column names or column aliases to sort by. | N/A | -| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units]({{site.url}}{{site.baseurl}}/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | +| `time` | String | Specifies the time units, for example, `5d` or `7h`. For more information, see [Supported units](https://opensearch.org/docs/latest/api-reference/units/).
Valid values are: `nanos`, `micros`, `ms`, `s`, `m`, `h`, and `d`. | N/A | | `v` | Boolean | Enables verbose mode, which displays column headers. | `false` | diff --git a/_api-reference/cat/cat-templates.md b/_api-reference/cat/cat-templates.md index 90d18384c82..183396d56d9 100644 --- a/_api-reference/cat/cat-templates.md +++ b/_api-reference/cat/cat-templates.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/cat/cat-thread-pool.md b/_api-reference/cat/cat-thread-pool.md index dec78c4b15b..f343cb621ea 100644 --- a/_api-reference/cat/cat-thread-pool.md +++ b/_api-reference/cat/cat-thread-pool.md @@ -35,7 +35,7 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/document-apis/mtermvectors.md b/_api-reference/document-apis/mtermvectors.md index 36cdfabe476..ddf96b62461 100644 --- a/_api-reference/document-apis/mtermvectors.md +++ b/_api-reference/document-apis/mtermvectors.md @@ -28,7 +28,7 @@ component: path_parameters --> ## Path parameters -The following table lists the available path parameters. All path parameters are optional. +The following table lists the available path parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | @@ -43,7 +43,7 @@ columns: Parameter, Data type, Description --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | diff --git a/_api-reference/security/authentication/auth-info.md b/_api-reference/security/authentication/auth-info.md index bd1b05fac4c..9c043662f38 100644 --- a/_api-reference/security/authentication/auth-info.md +++ b/_api-reference/security/authentication/auth-info.md @@ -29,7 +29,7 @@ component: query_parameters --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | diff --git a/_api-reference/snapshots/clone-snapshot.md b/_api-reference/snapshots/clone-snapshot.md index da026bcf95c..201f9b2a5d6 100644 --- a/_api-reference/snapshots/clone-snapshot.md +++ b/_api-reference/snapshots/clone-snapshot.md @@ -46,11 +46,11 @@ include_deprecated: false --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | -| `cluster_manager_timeout` | String | The amount of time to wait for a response from the cluster manager node. For more information about supported time units, see [Common parameters]({{site.url}}{{site.baseurl}}/api-reference/common-parameters/#time-units). | +| `cluster_manager_timeout` | String | The amount of time to wait for a response from the cluster manager node. For more information about supported time units, see [Common parameters](https://opensearch.org/docs/latest/api-reference/common-parameters/#time-units). | diff --git a/_api-reference/tasks/cancel-tasks.md b/_api-reference/tasks/cancel-tasks.md index ebffd3dcde0..ad04f5d612c 100644 --- a/_api-reference/tasks/cancel-tasks.md +++ b/_api-reference/tasks/cancel-tasks.md @@ -29,7 +29,7 @@ component: path_parameters --> ## Path parameters -The following table lists the available path parameters. All path parameters are optional. +The following table lists the available path parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | @@ -43,7 +43,7 @@ component: query_parameters --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | | :--- | :--- | :--- | diff --git a/_api-reference/tasks/get-tasks.md b/_api-reference/tasks/get-tasks.md index 416614b37ae..9e227adc03f 100644 --- a/_api-reference/tasks/get-tasks.md +++ b/_api-reference/tasks/get-tasks.md @@ -41,7 +41,7 @@ component: query_parameters --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/_api-reference/tasks/list-tasks.md b/_api-reference/tasks/list-tasks.md index 396b3e60ce6..4cb9c2997b4 100644 --- a/_api-reference/tasks/list-tasks.md +++ b/_api-reference/tasks/list-tasks.md @@ -27,7 +27,7 @@ component: query_parameters --> ## Query parameters -The following table lists the available query parameters. All query parameters are optional. +The following table lists the available query parameters. | Parameter | Data type | Description | Default | | :--- | :--- | :--- | :--- | diff --git a/spec-insert/spec/_fixtures/expected_output/example_code.md b/spec-insert/spec/_fixtures/expected_output/example_code.md new file mode 100644 index 00000000000..c6b44962316 --- /dev/null +++ b/spec-insert/spec/_fixtures/expected_output/example_code.md @@ -0,0 +1,71 @@ + +{% capture step1_rest %} +GET /_cat/health?pretty=true&human=false +{% endcapture %} + +{% capture step1_python %} + +from opensearchpy import OpenSearch + +host = 'localhost' +port = 9200 +auth = ('admin', 'admin') # For testing only. Don't store credentials in code. +ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA. + +# Create the client with SSL/TLS enabled, but hostname verification disabled. +client = OpenSearch( + hosts = [{'host': host, 'port': port}], + http_compress = True, # enables gzip compression for request bodies + http_auth = auth, + use_ssl = True, + verify_certs = True, + ssl_assert_hostname = False, + ssl_show_warn = False, + ca_certs = ca_certs_path +) + + +response = client.cat.health( + params = { "pretty": "true", "human": "false" } +) + +{% endcapture %} + +{% include code-block.html + rest=step1_rest + python=step1_python %} + + + +{% capture step1_rest %} +GET /{index}/_search?analyzer=standard&expand_wildcards=all +{% endcapture %} + +{% capture step1_python %} + + +response = client.search( + index = "{index}", + params = { "analyzer": "standard", "expand_wildcards": "all" } +) + +{% endcapture %} + +{% include code-block.html + rest=step1_rest + python=step1_python %} + + + + \ No newline at end of file diff --git a/spec-insert/spec/_fixtures/input/example_code.md b/spec-insert/spec/_fixtures/input/example_code.md new file mode 100644 index 00000000000..0662fca2908 --- /dev/null +++ b/spec-insert/spec/_fixtures/input/example_code.md @@ -0,0 +1,19 @@ + + + + + + + + \ No newline at end of file diff --git a/spec-insert/spec/doc_processor_spec.rb b/spec-insert/spec/doc_processor_spec.rb index 4f2c46b9e7d..c5f2a99d2fc 100644 --- a/spec-insert/spec/doc_processor_spec.rb +++ b/spec-insert/spec/doc_processor_spec.rb @@ -25,4 +25,8 @@ def test_file(file_name) it 'inserts the body param tables correctly' do test_file('body_params_tables') end + + it 'inserts translations correctly' do + test_file('example_code') + end end From f26c32da8d4e1b8d2b00852b2585030c36480e7b Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Fri, 8 Aug 2025 01:11:34 -0700 Subject: [PATCH 5/7] Continued working on the Spec-Insert tool. - Added more test examples to fixtures file. - Included test for NDJSON files. - Included test to showcase multi-line for body tag Signed-off-by: Daniel Jackson --- .../_fixtures/expected_output/example_code.md | 94 ++++++++++++++++++- .../spec/_fixtures/input/example_code.md | 23 +++++ .../spec/_fixtures/opensearch_spec.yaml | 4 + 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/spec-insert/spec/_fixtures/expected_output/example_code.md b/spec-insert/spec/_fixtures/expected_output/example_code.md index c6b44962316..160d104de36 100644 --- a/spec-insert/spec/_fixtures/expected_output/example_code.md +++ b/spec-insert/spec/_fixtures/expected_output/example_code.md @@ -68,4 +68,96 @@ skip: true component: example_code rest: GET /{index}/_search?analyzer=standard&expand_wildcards=all --> - \ No newline at end of file + + + +{% capture step1_rest %} +PUT /_settings?expand_wildcards=all +{ + "index": { + "number_of_replicas": 2 + } +} +{% endcapture %} + +{% capture step1_python %} + + +response = client.indices.put_settings( + params = { "expand_wildcards": "all" }, + body = { + "index": { + "number_of_replicas": 2 + } + } +) + +{% endcapture %} + +{% include code-block.html + rest=step1_rest + python=step1_python %} + + + +{% capture step1_rest %} +POST /_bulk?expand_wildcards=all + {"index":{"_index":"test","_id":"1"}} + {"field1":"value1"} + {"delete":{"_index":"test","_id":"2"}} +{% endcapture %} + +{% capture step1_python %} + +from opensearchpy import OpenSearch + +host = 'localhost' +port = 9200 +auth = ('admin', 'admin') # For testing only. Don't store credentials in code. +ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA. + +# Create the client with SSL/TLS enabled, but hostname verification disabled. +client = OpenSearch( + hosts = [{'host': host, 'port': port}], + http_compress = True, # enables gzip compression for request bodies + http_auth = auth, + use_ssl = True, + verify_certs = True, + ssl_assert_hostname = False, + ssl_show_warn = False, + ca_certs = ca_certs_path +) + + +response = client.bulk( + params = { "expand_wildcards": "all" }, + body = ''' + {"index":{"_index":"test","_id":"1"}} + {"field1":"value1"} + {"delete":{"_index":"test","_id":"2"}} +''' +) + +{% endcapture %} + +{% include code-block.html + rest=step1_rest + python=step1_python %} + diff --git a/spec-insert/spec/_fixtures/input/example_code.md b/spec-insert/spec/_fixtures/input/example_code.md index 0662fca2908..c9c535fc379 100644 --- a/spec-insert/spec/_fixtures/input/example_code.md +++ b/spec-insert/spec/_fixtures/input/example_code.md @@ -16,4 +16,27 @@ skip: true component: example_code rest: GET /{index}/_search?analyzer=standard&expand_wildcards=all --> + + + + + + \ No newline at end of file diff --git a/spec-insert/spec/_fixtures/opensearch_spec.yaml b/spec-insert/spec/_fixtures/opensearch_spec.yaml index b95265eb749..6acfa03404c 100644 --- a/spec-insert/spec/_fixtures/opensearch_spec.yaml +++ b/spec-insert/spec/_fixtures/opensearch_spec.yaml @@ -69,6 +69,8 @@ paths: url: https://docs.opensearch.org/latest/api-reference/index-apis/update-settings/ requestBody: $ref: '#/components/requestBodies/indices.put_settings' + parameters: + - $ref: '#/components/parameters/cat.health___query.expand_wildcard' responses: '200': $ref: '#/components/responses/indices.put_settings___200' @@ -81,6 +83,8 @@ paths: description: Allows to perform multiple index/update/delete operations in a single request. externalDocs: url: https://docs.opensearch.org/latest/api-reference/document-apis/bulk/ + parameters: + - $ref: '#/components/parameters/cat.health___query.expand_wildcard' requestBody: $ref: '#/components/requestBodies/bulk' components: From 9f430339f894ff28f7e1be9219fea9edf2cb8bdf Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Fri, 8 Aug 2025 02:13:50 -0700 Subject: [PATCH 6/7] Finished Python Client Code Conversion from HTTP w/ some minor tweaks. - Changed "include_client_setup" to be called from "insert_arguments.rb" for scalability and clarity. Also changed it so that you have to state "true" or "false". - Included "skip" tag. This is for when you come across a spec-insert that cant be converted to a client.You can do it manually, and it won't mess with future renders - Allowed for the body tag to be in multiple lines instead of one. Signed-off-by: Daniel Jackson --- spec-insert/lib/doc_processor.rb | 3 +- spec-insert/lib/insert_arguments.rb | 40 +++++++++++++++++-- .../lib/renderers/example_code_python.rb | 13 ++++-- spec-insert/lib/renderers/spec_insert.rb | 9 ++++- .../_fixtures/expected_output/example_code.md | 4 +- .../spec/_fixtures/input/example_code.md | 4 +- 6 files changed, 60 insertions(+), 13 deletions(-) diff --git a/spec-insert/lib/doc_processor.rb b/spec-insert/lib/doc_processor.rb index 8140b85102b..0edab19525a 100644 --- a/spec-insert/lib/doc_processor.rb +++ b/spec-insert/lib/doc_processor.rb @@ -53,8 +53,9 @@ def find_insertions(lines) start_indices.zip(end_indices).map do |start, finish| args = InsertArguments.from_marker(lines[start..finish]) + next nil if args.skip? [start, finish, SpecInsert.new(args)] - end + end.compact end # @param [Array] start_indices diff --git a/spec-insert/lib/insert_arguments.rb b/spec-insert/lib/insert_arguments.rb index 81b5002b2a7..17ddd92e711 100644 --- a/spec-insert/lib/insert_arguments.rb +++ b/spec-insert/lib/insert_arguments.rb @@ -17,11 +17,37 @@ def initialize(args) # @param [Array] lines the lines between "" # @return [InsertArguments] def self.from_marker(lines) + # Extract lines between start and end marker end_index = lines.each_with_index.find { |line, _index| line.match?(/^\s*-->/) }&.last&.- 1 - args = lines[1..end_index].filter { |line| line.include?(':') }.to_h do |line| - key, value = line.split(':',2) - [key.strip, value.strip] + args = {} + i = 1 + + while i <= end_index + line = lines[i] + next unless line.include?(':') + + key, value = line.split(':', 2) + key = key.strip + value = value.strip + + if value == '|' + # Multi-line block value + multiline_value = [] + i += 1 + while i <= end_index + line = lines[i] + break if line.match?(/^\s*\w+:/) # Stop at new top-level key + multiline_value << line.rstrip + i += 1 + end + args[key] = multiline_value.join("\n") + next + else + args[key] = value + end + i += 1 end + new(args) end @@ -52,11 +78,19 @@ def columns parse_array(@raw['columns']) || [] end + def skip? + parse_boolean(@raw['skip'], default: false) + end + # @return [Boolean] def pretty parse_boolean(@raw['pretty'], default: false) end + def include_client_setup + parse_boolean(@raw['include_client_setup'], default: false) + end + # @return [Boolean] def include_global parse_boolean(@raw['include_global'], default: false) diff --git a/spec-insert/lib/renderers/example_code_python.rb b/spec-insert/lib/renderers/example_code_python.rb index bb500ac7750..ee550bc0d5d 100644 --- a/spec-insert/lib/renderers/example_code_python.rb +++ b/spec-insert/lib/renderers/example_code_python.rb @@ -69,7 +69,7 @@ def call_code if query_string query_pairs = query_string.split('&').map { |s| s.split('=', 2) } query_hash = query_pairs.map do |k, v| - "\"#{k}\": #{v ? "\"#{v}\"" : "\"false\""}" + "\"#{k}\": #{v ? "\"#{v}\"" : "\"true\""}" end.join(', ') args << "params = { #{query_hash} }" unless query_hash.empty? end @@ -77,12 +77,17 @@ def call_code body = rest.body if expects_body?(http_verb) if body + raw_body = @args.raw['body'] begin - parsed = JSON.parse(@args.raw['body']) + parsed = JSON.parse(raw_body) pretty = JSON.pretty_generate(parsed).gsub(/^/, ' ') args << "body = #{pretty}" rescue JSON::ParserError - args << "body = #{JSON.dump(@args.raw['body'])}" + if raw_body.include?("\n") + args << "body = '''\n#{raw_body.rstrip}\n'''" + else + args << "body = #{JSON.dump(raw_body)}" + end end else args << 'body = { "Insert body here" }' @@ -100,7 +105,7 @@ def call_code ) PYTHON end - if @args.raw['include_client_setup'] + if @args.include_client_setup client_setup + python_setup else python_setup diff --git a/spec-insert/lib/renderers/spec_insert.rb b/spec-insert/lib/renderers/spec_insert.rb index f40a09700a5..662da7fc1c9 100644 --- a/spec-insert/lib/renderers/spec_insert.rb +++ b/spec-insert/lib/renderers/spec_insert.rb @@ -22,13 +22,20 @@ def initialize(args) end def arguments - @args.raw.map { |key, value| { key:, value: } } + @args.raw.map do |key, value| + if value.is_a?(String) && value.include?("\n") + { key: key, value: "|\n" + value } + else + { key: key, value: value } + end + end end def api; @args.api end def component; @args.component end def content + return "" if @args.skip? raise SpecInsertError, '`component` argument not specified.' unless @args.component case @args.component.to_sym when :query_parameters diff --git a/spec-insert/spec/_fixtures/expected_output/example_code.md b/spec-insert/spec/_fixtures/expected_output/example_code.md index 160d104de36..ff5236ba1cb 100644 --- a/spec-insert/spec/_fixtures/expected_output/example_code.md +++ b/spec-insert/spec/_fixtures/expected_output/example_code.md @@ -1,7 +1,7 @@ {% capture step1_rest %} GET /_cat/health?pretty=true&human=false @@ -115,7 +115,7 @@ body: | {"index":{"_index":"test","_id":"1"}} {"field1":"value1"} {"delete":{"_index":"test","_id":"2"}} -include_client_setup: +include_client_setup: true --> {% capture step1_rest %} POST /_bulk?expand_wildcards=all diff --git a/spec-insert/spec/_fixtures/input/example_code.md b/spec-insert/spec/_fixtures/input/example_code.md index c9c535fc379..26ab936971c 100644 --- a/spec-insert/spec/_fixtures/input/example_code.md +++ b/spec-insert/spec/_fixtures/input/example_code.md @@ -1,7 +1,7 @@ @@ -37,6 +37,6 @@ body: | {"index":{"_index":"test","_id":"1"}} {"field1":"value1"} {"delete":{"_index":"test","_id":"2"}} -include_client_setup: +include_client_setup: true --> \ No newline at end of file From 1c99540e35d0f5baedee6b2f8125853e9dba8263 Mon Sep 17 00:00:00 2001 From: Daniel Jackson Date: Wed, 13 Aug 2025 14:11:02 -0700 Subject: [PATCH 7/7] Finished Python Client Code Conversion from HTTP w/ some minor tweaks. - Fixed minor query params issue. - Implemented steps in the developer guide. - Removed un-reachable code logic. - Included example with NDJSON body in test files. Signed-off-by: Daniel Jackson --- DEVELOPER_GUIDE.md | 62 ++++++++++++- spec-insert/lib/insert_arguments.rb | 2 +- .../lib/renderers/example_code_python.rb | 2 +- .../_fixtures/expected_output/example_code.md | 90 ++++++++++++++++--- .../spec/_fixtures/input/example_code.md | 23 ++++- 5 files changed, 160 insertions(+), 19 deletions(-) diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 88a67f8f50c..0617bd2453d 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -8,7 +8,8 @@ - [Query parameters](#query-parameters) - [Path parameters](#path-parameters) - [Endpoints](#endpoints) - + - [Example_Code](#example_code) + ## Introduction The `.md` documents in this repository are rendered into HTML pages using [Jekyll](https://jekyllrb.com/). These HTML pages are hosted on [opensearch.org](https://docs.opensearch.org/latest/). @@ -88,6 +89,65 @@ All spec insert components accept the following arguments: - `component` (String; required): The name of the component to render, such as `query_parameters`, `path_parameters`, or `endpoints`. - `omit_header` (Boolean; Default is `false`): If set to `true`, the markdown header of the component will not be rendered. +### Example_Code + +- `api` should not be placed for the `component: example_code` tag. `rest` is mapped to the correct API by regex mapping. +- `rest` (String; required): The HTTP request line (`HTTP method` + `endpoint path`) that is regex mapped to the `opensearch-openapi.yaml`. + +The following tags are included to help with additional needs: + +- `body` (String; optional): The request body for the API call, using YAML `|` to preserve newlines and indentation. +- `include_client_setup:` (Boolean; Default is `false`): If set to `true`, the client setup for the language will be rendered. +- `skip` (Boolean; Default is `false`): If set to `true`, the language conversions will not render/re-render. Use for manual conversions. + +To insert multi-language support for the `cat.allocation` API, use the following snippet: + +```markdown + + +``` + +To insert multi-language support for the `index` API with a request body, use the following snippet. The `|` is needed for multiline support for the body: + +```markdown + + +``` + +To insert multi-language support for the `index` API and include the client setup for each language, use the following snippet: + +```markdown + + +``` + +To insert multi-language support for the `index` API but need to manually set the multi-language example for the `index` API, use the following snippet: + +```markdown + + +``` + ### Endpoints To insert endpoints for the `search` API, use the following snippet: diff --git a/spec-insert/lib/insert_arguments.rb b/spec-insert/lib/insert_arguments.rb index 17ddd92e711..737a136df34 100644 --- a/spec-insert/lib/insert_arguments.rb +++ b/spec-insert/lib/insert_arguments.rb @@ -116,7 +116,7 @@ def rest query = (query_string || "").split('&').to_h do |pair| k, v = pair.split('=', 2) - [k, v || "false"] + [k, v || "true"] end body = begin diff --git a/spec-insert/lib/renderers/example_code_python.rb b/spec-insert/lib/renderers/example_code_python.rb index ee550bc0d5d..0e3028c7487 100644 --- a/spec-insert/lib/renderers/example_code_python.rb +++ b/spec-insert/lib/renderers/example_code_python.rb @@ -69,7 +69,7 @@ def call_code if query_string query_pairs = query_string.split('&').map { |s| s.split('=', 2) } query_hash = query_pairs.map do |k, v| - "\"#{k}\": #{v ? "\"#{v}\"" : "\"true\""}" + "\"#{k}\": \"#{v}\"" end.join(', ') args << "params = { #{query_hash} }" unless query_hash.empty? end diff --git a/spec-insert/spec/_fixtures/expected_output/example_code.md b/spec-insert/spec/_fixtures/expected_output/example_code.md index ff5236ba1cb..cce9be74519 100644 --- a/spec-insert/spec/_fixtures/expected_output/example_code.md +++ b/spec-insert/spec/_fixtures/expected_output/example_code.md @@ -72,7 +72,7 @@ rest: GET /{index}/_search?analyzer=standard&expand_wildcards=all {% capture step1_rest %} -PUT /_settings?expand_wildcards=all +PUT /_settings?expand_wildcards=all&analyze_wildcard { "index": { "number_of_replicas": 2 @@ -93,7 +93,7 @@ PUT /_settings?expand_wildcards=all response = client.indices.put_settings( - params = { "expand_wildcards": "all" }, + params = { "expand_wildcards": "all", "analyze_wildcard": "true" }, body = { "index": { "number_of_replicas": 2 @@ -112,16 +112,78 @@ response = client.indices.put_settings( component: example_code rest: POST /_bulk?expand_wildcards=all body: | - {"index":{"_index":"test","_id":"1"}} - {"field1":"value1"} - {"delete":{"_index":"test","_id":"2"}} +{"index":{"_index":"test","_id":"1"}} +{"field1":"value1"} +{"delete":{"_index":"test","_id":"2"}} +include_client_setup: true +--> +{% capture step1_rest %} +POST /_bulk?expand_wildcards=all +{"index":{"_index":"test","_id":"1"}} +{"field1":"value1"} +{"delete":{"_index":"test","_id":"2"}} +{% endcapture %} + +{% capture step1_python %} + +from opensearchpy import OpenSearch + +host = 'localhost' +port = 9200 +auth = ('admin', 'admin') # For testing only. Don't store credentials in code. +ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA. + +# Create the client with SSL/TLS enabled, but hostname verification disabled. +client = OpenSearch( + hosts = [{'host': host, 'port': port}], + http_compress = True, # enables gzip compression for request bodies + http_auth = auth, + use_ssl = True, + verify_certs = True, + ssl_assert_hostname = False, + ssl_show_warn = False, + ca_certs = ca_certs_path +) + + +response = client.bulk( + params = { "expand_wildcards": "all" }, + body = ''' +{"index":{"_index":"test","_id":"1"}} +{"field1":"value1"} +{"delete":{"_index":"test","_id":"2"}} +''' +) + +{% endcapture %} + +{% include code-block.html + rest=step1_rest + python=step1_python %} + + + {% capture step1_rest %} POST /_bulk?expand_wildcards=all - {"index":{"_index":"test","_id":"1"}} - {"field1":"value1"} - {"delete":{"_index":"test","_id":"2"}} +{ "delete": { "_index": "movies", "_id": "tt2229499" } } +{ "index": { "_index": "movies", "_id": "tt1979320" } } +{ "title": "Rush", "year": 2013 } +{ "create": { "_index": "movies", "_id": "tt1392214" } } +{ "title": "Prisoners", "year": 2013 } +{ "update": { "_index": "movies", "_id": "tt0816711" } } +{ "doc" : { "title": "World War Z" } } {% endcapture %} {% capture step1_python %} @@ -149,9 +211,13 @@ client = OpenSearch( response = client.bulk( params = { "expand_wildcards": "all" }, body = ''' - {"index":{"_index":"test","_id":"1"}} - {"field1":"value1"} - {"delete":{"_index":"test","_id":"2"}} +{ "delete": { "_index": "movies", "_id": "tt2229499" } } +{ "index": { "_index": "movies", "_id": "tt1979320" } } +{ "title": "Rush", "year": 2013 } +{ "create": { "_index": "movies", "_id": "tt1392214" } } +{ "title": "Prisoners", "year": 2013 } +{ "update": { "_index": "movies", "_id": "tt0816711" } } +{ "doc" : { "title": "World War Z" } } ''' ) diff --git a/spec-insert/spec/_fixtures/input/example_code.md b/spec-insert/spec/_fixtures/input/example_code.md index 26ab936971c..ad91834cd78 100644 --- a/spec-insert/spec/_fixtures/input/example_code.md +++ b/spec-insert/spec/_fixtures/input/example_code.md @@ -20,7 +20,7 @@ rest: GET /{index}/_search?analyzer=standard&expand_wildcards=all + + + \ No newline at end of file