Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spec-Insert] Param Table Updates #9076

Merged
merged 13 commits into from
Jan 17, 2025
5 changes: 5 additions & 0 deletions DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ bundle exec jekyll spec-insert --refresh-spec
### Ignoring files and folders
The `spec-insert` plugin ignores all files and folders listed in the [./_config.yml#exclude](./_config.yml) list, which is also the list of files and folders that Jekyll ignores.

### Configuration
You can update the configuration settings for this plugin through the [config.yml](./spec-insert/config.yml) file.

_Note that tests for this plugin use a mock configuration [file](./spec-insert/spec/mock_config.yml) to assure that the tests still pass when the config file is altered. The expected output for the tests is based on the mock configuration file and will look different from the actual output when the plugin is run._

## CI/CD
The `spec-insert` plugin is run as part of the CI/CD pipeline to ensure that the API components are up to date in the documentation. This is performed through the [update-api-components.yml](.github/workflows/update-api-components.yml) GitHub Actions workflow, which creates a pull request containing the updated API components every Sunday.

Expand Down
6 changes: 6 additions & 0 deletions spec-insert/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
param_table:
default_column:
empty_text: N/A
required_column:
true_text: Required
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
false_text: Optional
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 8 additions & 0 deletions spec-insert/lib/config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

require 'pathname'
require 'yaml'
require_relative 'spec_hash'

CONFIG_PATH = File.expand_path('../config.yml', __dir__).freeze
CONFIG = SpecHash.new(YAML.load_file(CONFIG_PATH))
7 changes: 1 addition & 6 deletions spec-insert/lib/insert_arguments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

# Doc Insert Arguments
class InsertArguments
COLUMNS = ['Parameter', 'Description', 'Required', 'Data type', 'Default'].freeze
DEFAULT_COLUMNS = ['Parameter', 'Data type', 'Description'].freeze
attr_reader :raw

# @param [Array<String>] lines the lines between <!-- doc_insert_start and -->
Expand All @@ -27,10 +25,7 @@ def component

# @return [Array<String>]
def columns
cols = parse_array(@raw['columns']) || DEFAULT_COLUMNS
invalid = cols - COLUMNS
raise ArgumentError, "Invalid column(s): #{invalid.join(', ')}" unless invalid.empty?
cols
parse_array(@raw['columns']) || []
end

# @return [Boolean]
Expand Down
62 changes: 55 additions & 7 deletions spec-insert/lib/renderers/parameter_table_renderer.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# frozen_string_literal: true

require_relative 'table_renderer'
require_relative '../config'

# Renders a table of parameters of an API action
class ParameterTableRenderer
COLUMNS = ['Parameter', 'Description', 'Required', 'Data type', 'Default'].freeze
DEFAULT_COLUMNS = ['Parameter', 'Data type', 'Description'].freeze

# @param [Array<Parameter>] parameters
# @param [InsertArguments] args
def initialize(parameters, args)
@columns = args.columns
@config = CONFIG.param_table
@parameters = filter_parameters(parameters, args)
@columns = determine_columns(args)
@pretty = args.pretty
@parameters = parameters
@parameters = @parameters.reject(&:deprecated) unless args.include_deprecated
@parameters = @parameters.sort_by { |arg| [arg.required ? 0 : 1, arg.deprecated ? 1 : 0, arg.name] }
end

# @return [String]
Expand All @@ -23,23 +26,68 @@ def render

private

# @param [InsertArguments] args
def determine_columns(args)
if args.columns.present?
invalid = args.columns - COLUMNS
raise ArgumentError, "Invalid column(s): #{invalid.join(', ')}." unless invalid.empty?
return args.columns
end

required = @parameters.any?(&:required) ? 'Required' : nil
default = @parameters.any? { |p| p.default.present? } ? 'Default' : nil
['Parameter', required, 'Data type', 'Description', default].compact
end

# @param [Array<Parameter>] parameters
# @param [InsertArguments] args
def filter_parameters(parameters, args)
parameters = parameters.reject(&:deprecated) unless args.include_deprecated
parameters.sort_by { |arg| [arg.required ? 0 : 1, arg.deprecated ? 1 : 0, arg.name] }
end

def row(param)
{
'Parameter' => "`#{param.name}`#{' <br> _DEPRECATED_' if param.deprecated}",
'Description' => description(param),
'Required' => param.required ? 'Required' : nil,
'Required' => param.required ? @config.required_column.true_text : @config.required_column.false_text,
'Data type' => param.doc_type,
'Default' => param.default.nil? ? nil : "`#{param.default}`"
'Default' => param.default.nil? ? @config.default_column.empty_text : "`#{param.default}`"
}
end

# @param [Parameter] param
def description(param)
deprecation = deprecation(param)
required = param.required && @columns.exclude?('Required') ? '**(Required)** ' : ''
description = param.description.gsub("\n", ' ')
valid_values = valid_values(param)
default = param.default.nil? || @columns.include?('Default') ? '' : " _(Default: `#{param.default}`)_"

"#{deprecation}#{required}#{description}#{default}"
"#{deprecation}#{required}#{description}#{default}#{valid_values}"
end

# @param [Parameter] param
def valid_values(param)
enums = extract_enum_values(param.schema)&.compact
return '' unless enums.present?
if enums.none? { |enum| enum[:description].present? }
" <br> Valid values are: #{enums.map { |enum| "`#{enum[:value]}`" }.join(', ')}"
else
" <br> Valid values are: <br> #{enums.map { |enum| "- `#{enum[:value]}`: #{enum[:description]}" }
.join(' </br> ')}"
end
end

# @param [SpecHash] schema
# @return [Hash]
def extract_enum_values(schema)
return schema.enum.map { |value| { value: } } if schema.enum.present?
if schema.const.present?
{ value: schema.const, description: schema.description }
elsif schema.oneOf.present?
schema.oneOf.map { |sch| extract_enum_values(sch) }.flatten
end
end

def deprecation(param)
Expand Down
6 changes: 3 additions & 3 deletions spec-insert/lib/renderers/table_renderer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ def calculate_column_widths

def render_column
columns = @column.map { |column| column.title.ljust(column.width) }.join(' | ')
@pretty ? "| #{columns} |" : columns
"| #{columns} |"
end

def render_divider
dividers = @column.map { |column| ":#{'-' * [column.width + 1, 3].max}" }
@pretty ? "|#{dividers.join('|')}|" : dividers.join(' | ')
@pretty ? "|#{dividers.join('|')}|" : "| #{dividers.join(' | ')} |"
end

def render_rows
@rows.map do |row|
cells = @column.map { |column| row[column.key].to_s.ljust(column.width).gsub('|', '\|') }.join(' | ')
@pretty ? "| #{cells} |" : cells
"| #{cells} |"
end
end
end
2 changes: 1 addition & 1 deletion spec-insert/lib/spec_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def [](key)
parse(@hash[key])
end

def respond_to_missing?(name)
def respond_to_missing?(name, include_private = false)
@hash.key?(name.to_s) || {}.respond_to?(name) || super
end

Expand Down
39 changes: 21 additions & 18 deletions spec-insert/spec/_fixtures/expected_output/param_tables.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

The following table lists the available path parameters. All path parameters are optional.

Parameter | Data type | Description
:--- | :--- | :---
`index` | List or String | Comma-separated list of data streams, indexes, and aliases to search. Supports wildcards (`*`). To search all data streams and indexes, omit this parameter or use `*` or `_all`.
| Parameter | Data type | Description |
| :--- | :--- | :--- |
| `index` | List or String | Comma-separated list of data streams, indexes, and aliases to search. Supports wildcards (`*`). To search all data streams and indexes, omit this parameter or use `*` or `_all`. <br> Valid values are: `_all`, `_any`, `_none` |
<!-- spec_insert_end -->

Query Parameters Example with Global Parameters, Pretty Print, and Custom Columns
Expand All @@ -26,12 +26,13 @@

The following table lists the available query parameters.

| Data type | Parameter | Description | Required | Default |
|:----------|:--------------------------|:-----------------------------------------------------------------------------------------------------------------------------------|:---------|:--------|
| Boolean | `analyze_wildcard` | If true, wildcard and prefix queries are analyzed. This parameter can only be used when the q query string parameter is specified. | Required | `false` |
| String | `analyzer` | Analyzer to use for the query string. This parameter can only be used when the q query string parameter is specified. | | |
| Boolean | `pretty` | Whether to pretty format the returned JSON response. | | |
| Boolean | `human` <br> _DEPRECATED_ | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. | | `true` |
| Data type | Parameter | Description | Required | Default |
|:---------------|:--------------------------|:-----------------------------------------------------------------------------------------------------------------------------------|:-------------|:--------|
| Boolean | `analyze_wildcard` | If true, wildcard and prefix queries are analyzed. This parameter can only be used when the q query string parameter is specified. | **Required** | `false` |
| String | `analyzer` | Analyzer to use for the query string. This parameter can only be used when the q query string parameter is specified. | _optional_ | N/A |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
| List or String | `expand_wildcards` | Comma-separated list of expand wildcard options. <br> Valid values are: `open`, `closed`, `none`, `all` | _optional_ | N/A |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
| Boolean | `pretty` | Whether to pretty format the returned JSON response. | _optional_ | N/A |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
| Boolean | `human` <br> _DEPRECATED_ | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. | _optional_ | `true` |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
<!-- spec_insert_end -->

Query Parameters Example with only Parameter and Description Columns
Expand All @@ -42,10 +43,11 @@
columns: Parameter, Description
omit_header: true
-->
Parameter | Description
:--- | :---
`analyze_wildcard` | **(Required)** If true, wildcard and prefix queries are analyzed. This parameter can only be used when the q query string parameter is specified. _(Default: `false`)_
`analyzer` | Analyzer to use for the query string. This parameter can only be used when the q query string parameter is specified.
| Parameter | Description |
| :--- | :--- |
| `analyze_wildcard` | **(Required)** If true, wildcard and prefix queries are analyzed. This parameter can only be used when the q query string parameter is specified. _(Default: `false`)_ |
| `analyzer` | Analyzer to use for the query string. This parameter can only be used when the q query string parameter is specified. |
| `expand_wildcards` | Comma-separated list of expand wildcard options. <br> Valid values are: `open`, `closed`, `none`, `all` |
<!-- spec_insert_end -->

Optional Params Text
Expand All @@ -57,10 +59,11 @@
-->
## 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
:--- | :--- | :---
`pretty` | Boolean | Whether to pretty format the returned JSON response.
`human` <br> _DEPRECATED_ | Boolean | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. _(Default: `true`)_
| Parameter | Required | Data type | Description | Default |
| :--- | :--- | :--- | :--- | :--- |
| `expand_wildcard` | **Required** | String | Whether to expand wildcard expression to concrete indices that are open, closed, or both. <br> Valid values are: <br> - `open`: Expand wildcards to open indices only. </br> - `closed`: Expand wildcards to closed indices only. </br> - `none`: Do not expand wildcards. | N/A |

Check failure on line 66 in spec-insert/spec/_fixtures/expected_output/param_tables.md

View workflow job for this annotation

GitHub Actions / style-job

[vale] reported by reviewdog 🐶 [OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'. Raw Output: {"message": "[OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'.", "location": {"path": "spec-insert/spec/_fixtures/expected_output/param_tables.md", "range": {"start": {"line": 66, "column": 97}}}, "severity": "ERROR"}

Check failure on line 66 in spec-insert/spec/_fixtures/expected_output/param_tables.md

View workflow job for this annotation

GitHub Actions / style-job

[vale] reported by reviewdog 🐶 [OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'. Raw Output: {"message": "[OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'.", "location": {"path": "spec-insert/spec/_fixtures/expected_output/param_tables.md", "range": {"start": {"line": 66, "column": 200}}}, "severity": "ERROR"}

Check failure on line 66 in spec-insert/spec/_fixtures/expected_output/param_tables.md

View workflow job for this annotation

GitHub Actions / style-job

[vale] reported by reviewdog 🐶 [OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'. Raw Output: {"message": "[OpenSearch.SubstitutionsError] Use 'indexes' instead of 'indices'.", "location": {"path": "spec-insert/spec/_fixtures/expected_output/param_tables.md", "range": {"start": {"line": 66, "column": 259}}}, "severity": "ERROR"}
| `pretty` | _optional_ | Boolean | Whether to pretty format the returned JSON response. | N/A |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
| `human` <br> _DEPRECATED_ | _optional_ | Boolean | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. | `true` |
Naarcha-AWS marked this conversation as resolved.
Show resolved Hide resolved
<!-- spec_insert_end -->
42 changes: 42 additions & 0 deletions spec-insert/spec/_fixtures/opensearch_spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ paths:
parameters:
- $ref: '#/components/parameters/_global___query.pretty'
- $ref: '#/components/parameters/_global___query.human'
- $ref: '#/components/parameters/cat.health___query.expand_wildcard'
/_search:
get:
operationId: search.0
Expand All @@ -32,6 +33,7 @@ paths:
parameters:
- $ref: '#/components/parameters/search___query.analyze_wildcard'
- $ref: '#/components/parameters/search___query.analyzer'
- $ref: '#/components/parameters/search___query.expand_wildcards'
/{index}/_search:
get:
operationId: search.2
Expand All @@ -44,6 +46,7 @@ paths:
- $ref: '#/components/parameters/search___path.index'
- $ref: '#/components/parameters/search___query.analyze_wildcard'
- $ref: '#/components/parameters/search___query.analyzer'
- $ref: '#/components/parameters/search___query.expand_wildcards'
post:
operationId: search.3
x-operation-group: search
Expand All @@ -55,6 +58,7 @@ paths:
- $ref: '#/components/parameters/search___path.index'
- $ref: '#/components/parameters/search___query.analyze_wildcard'
- $ref: '#/components/parameters/search___query.analyzer'
- $ref: '#/components/parameters/search___query.expand_wildcards'
components:

parameters:
Expand All @@ -80,6 +84,24 @@ components:
x-version-deprecated: '3.0'
x-deprecation-message: Use the `format` parameter instead.

cat.health___query.expand_wildcard:
in: query
required: true
name: expand_wildcard
description: |-
Whether to expand wildcard expression to concrete indices that are open, closed, or both.
schema:
oneOf:
- type: string
const: open
description: Expand wildcards to open indices only.
- type: string
const: closed
description: Expand wildcards to closed indices only.
- type: string
const: none
description: Do not expand wildcards.

search___path.index:
in: path
name: index
Expand Down Expand Up @@ -114,6 +136,18 @@ components:
type: string
style: form

search___query.expand_wildcards:
in: query
name: expand_wildcards
description: |-
Comma-separated list of expand wildcard options.
schema:
oneOf:
- $ref: '#/components/schemas/_common___ExpandWildcardsCompact'
- type: array
items:
$ref: '#/components/schemas/_common___ExpandWildcardsCompact'

schemas:

_common___Indices:
Expand All @@ -135,3 +169,11 @@ components:
const: _any
- type: string
const: _none

_common___ExpandWildcardsCompact:
type: string
enum:
- open
- closed
- none
- all
6 changes: 6 additions & 0 deletions spec-insert/spec/mock_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
param_table:
default_column:
empty_text: N/A
required_column:
true_text: "**Required**"
false_text: _Optional_
5 changes: 5 additions & 0 deletions spec-insert/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@
Kernel.srand config.seed

config.expose_dsl_globally = true

config.before(:each) do
mock_config = SpecHash.new(YAML.load_file('./spec/mock_config.yml')) # Replace with your desired mock value
stub_const('CONFIG', mock_config)
end
end

require 'active_support/all'
Expand Down
Loading