diff --git a/DEVELOPER_GUIDE.md b/DEVELOPER_GUIDE.md index 5f6678904c..13b172273a 100644 --- a/DEVELOPER_GUIDE.md +++ b/DEVELOPER_GUIDE.md @@ -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. diff --git a/spec-insert/config.yml b/spec-insert/config.yml new file mode 100644 index 0000000000..59f8a1af3d --- /dev/null +++ b/spec-insert/config.yml @@ -0,0 +1,6 @@ +param_table: + default_column: + empty_text: N/A + required_column: + true_text: "**Required**" + false_text: "_Optional_" diff --git a/spec-insert/lib/config.rb b/spec-insert/lib/config.rb new file mode 100644 index 0000000000..45f4799446 --- /dev/null +++ b/spec-insert/lib/config.rb @@ -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)) diff --git a/spec-insert/lib/insert_arguments.rb b/spec-insert/lib/insert_arguments.rb index 10e11de2b0..75d43fdda0 100644 --- a/spec-insert/lib/insert_arguments.rb +++ b/spec-insert/lib/insert_arguments.rb @@ -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] lines the lines between @@ -27,10 +25,7 @@ def component # @return [Array] 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] diff --git a/spec-insert/lib/renderers/parameter_table_renderer.rb b/spec-insert/lib/renderers/parameter_table_renderer.rb index 6df4090ac4..29c68ce46a 100644 --- a/spec-insert/lib/renderers/parameter_table_renderer.rb +++ b/spec-insert/lib/renderers/parameter_table_renderer.rb @@ -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] 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] @@ -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] 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}`#{'
_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? } + "
Valid values are: #{enums.map { |enum| "`#{enum[:value]}`" }.join(', ')}" + else + "
Valid values are:
#{enums.map { |enum| "- `#{enum[:value]}`: #{enum[:description]}" } + .join('
')}" + 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) diff --git a/spec-insert/lib/renderers/table_renderer.rb b/spec-insert/lib/renderers/table_renderer.rb index 1cabc435bd..afd2921c1d 100644 --- a/spec-insert/lib/renderers/table_renderer.rb +++ b/spec-insert/lib/renderers/table_renderer.rb @@ -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 diff --git a/spec-insert/lib/spec_hash.rb b/spec-insert/lib/spec_hash.rb index 4f34500a0a..000174d2e5 100644 --- a/spec-insert/lib/spec_hash.rb +++ b/spec-insert/lib/spec_hash.rb @@ -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 diff --git a/spec-insert/spec/_fixtures/expected_output/param_tables.md b/spec-insert/spec/_fixtures/expected_output/param_tables.md index 203ddf722c..910ea89e57 100644 --- a/spec-insert/spec/_fixtures/expected_output/param_tables.md +++ b/spec-insert/spec/_fixtures/expected_output/param_tables.md @@ -8,9 +8,9 @@ component: path_parameters 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`.
Valid values are: `_all`, `_any`, `_none` | Query Parameters Example with Global Parameters, Pretty Print, and Custom Columns @@ -26,12 +26,13 @@ columns: Data type, Parameter, Description, Required, Default 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`
_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 | +| List or String | `expand_wildcards` | Comma-separated list of expand wildcard options.
Valid values are: `open`, `closed`, `none`, `all` | _Optional_ | N/A | +| Boolean | `pretty` | Whether to pretty format the returned JSON response. | _Optional_ | N/A | +| Boolean | `human`
_DEPRECATED_ | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. | _Optional_ | `true` | Query Parameters Example with only Parameter and Description Columns @@ -42,10 +43,11 @@ component: query_parameters 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.
Valid values are: `open`, `closed`, `none`, `all` | Optional Params Text @@ -57,10 +59,11 @@ include_global: true --> ## 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`
_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.
Valid values are:
- `open`: Expand wildcards to open indices only.
- `closed`: Expand wildcards to closed indices only.
- `none`: Do not expand wildcards. | N/A | +| `pretty` | _Optional_ | Boolean | Whether to pretty format the returned JSON response. | N/A | +| `human`
_DEPRECATED_ | _Optional_ | Boolean | _(Deprecated since 3.0: Use the `format` parameter instead.)_ Whether to return human readable values for statistics. | `true` | diff --git a/spec-insert/spec/_fixtures/opensearch_spec.yaml b/spec-insert/spec/_fixtures/opensearch_spec.yaml index 3bafe57182..7c609e6fb8 100644 --- a/spec-insert/spec/_fixtures/opensearch_spec.yaml +++ b/spec-insert/spec/_fixtures/opensearch_spec.yaml @@ -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 @@ -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 @@ -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 @@ -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: @@ -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 @@ -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: @@ -135,3 +169,11 @@ components: const: _any - type: string const: _none + + _common___ExpandWildcardsCompact: + type: string + enum: + - open + - closed + - none + - all diff --git a/spec-insert/spec/mock_config.yml b/spec-insert/spec/mock_config.yml new file mode 100644 index 0000000000..f659f9d5cc --- /dev/null +++ b/spec-insert/spec/mock_config.yml @@ -0,0 +1,6 @@ +param_table: + default_column: + empty_text: N/A + required_column: + true_text: "**Required**" + false_text: _Optional_ \ No newline at end of file diff --git a/spec-insert/spec/spec_helper.rb b/spec-insert/spec/spec_helper.rb index 74d9dc9bb9..9c85ec48c9 100644 --- a/spec-insert/spec/spec_helper.rb +++ b/spec-insert/spec/spec_helper.rb @@ -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'