@redpanda-data/docs-extensions-and-macros 4.10.0 → 4.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/doc-tools.js +23 -3
- package/package.json +1 -1
- package/tools/property-extractor/Makefile +3 -2
- package/tools/property-extractor/generate-handlebars-docs.js +255 -74
- package/tools/property-extractor/property_extractor.py +285 -40
- package/tools/property-extractor/templates/property-cloud.hbs +2 -3
- package/tools/property-extractor/templates/property-page-with-includes.hbs +17 -0
- package/tools/property-extractor/templates/property.hbs +4 -5
- package/tools/property-extractor/transformers.py +240 -36
|
@@ -117,6 +117,24 @@ def process_enterprise_value(enterprise_str):
|
|
|
117
117
|
"""
|
|
118
118
|
enterprise_str = enterprise_str.strip()
|
|
119
119
|
|
|
120
|
+
# Handle special SASL mechanism function names
|
|
121
|
+
if enterprise_str == "is_enterprise_sasl_mechanism":
|
|
122
|
+
# Dynamically look up enterprise SASL mechanisms from source
|
|
123
|
+
enterprise_mechanisms = get_enterprise_sasl_mechanisms()
|
|
124
|
+
if enterprise_mechanisms:
|
|
125
|
+
return enterprise_mechanisms
|
|
126
|
+
else:
|
|
127
|
+
# Fallback to known values if lookup fails
|
|
128
|
+
return ["GSSAPI", "OAUTHBEARER"]
|
|
129
|
+
elif enterprise_str == "is_enterprise_sasl_mechanisms_override":
|
|
130
|
+
# Get the enterprise mechanisms dynamically for a more accurate description
|
|
131
|
+
enterprise_mechanisms = get_enterprise_sasl_mechanisms()
|
|
132
|
+
if enterprise_mechanisms:
|
|
133
|
+
mechanism_list = ", ".join(enterprise_mechanisms)
|
|
134
|
+
return f"Any override containing enterprise mechanisms ({mechanism_list})."
|
|
135
|
+
else:
|
|
136
|
+
return "Any override containing enterprise mechanisms."
|
|
137
|
+
|
|
120
138
|
# FIRST: Handle std::vector initialization patterns (highest priority)
|
|
121
139
|
# This must come before enum processing because vectors can contain enums
|
|
122
140
|
# Tolerate optional whitespace around braces
|
|
@@ -196,19 +214,15 @@ def process_enterprise_value(enterprise_str):
|
|
|
196
214
|
|
|
197
215
|
def resolve_cpp_function_call(function_name):
|
|
198
216
|
"""
|
|
199
|
-
Resolve
|
|
217
|
+
Resolve a small set of known zero-argument C++ functions to their literal string return values by scanning a local Redpanda source tree.
|
|
200
218
|
|
|
201
|
-
|
|
219
|
+
Searches predefined files and regex patterns for the specified fully-qualified function name (e.g., "model::kafka_audit_logging_topic") and returns the captured string if found; returns None when no match or when the Redpanda source tree cannot be located.
|
|
202
220
|
|
|
203
221
|
Parameters:
|
|
204
|
-
function_name (str): Fully-qualified C++ function name to resolve
|
|
222
|
+
function_name (str): Fully-qualified C++ function name to resolve.
|
|
205
223
|
|
|
206
224
|
Returns:
|
|
207
|
-
str or None: The
|
|
208
|
-
|
|
209
|
-
Notes:
|
|
210
|
-
- The function performs filesystem I/O and regex-based source searching; it does not raise on read errors but logs and continues.
|
|
211
|
-
- Only a small, hard-coded set of function names/patterns is supported; unknown names immediately return None.
|
|
225
|
+
str or None: The literal string returned by the C++ function when resolved, or `None` if unresolved.
|
|
212
226
|
"""
|
|
213
227
|
# Map function names to likely search patterns and file locations
|
|
214
228
|
search_patterns = {
|
|
@@ -322,7 +336,174 @@ def resolve_cpp_function_call(function_name):
|
|
|
322
336
|
return None
|
|
323
337
|
|
|
324
338
|
|
|
339
|
+
def resolve_constexpr_identifier(identifier):
|
|
340
|
+
"""
|
|
341
|
+
Resolve a constexpr identifier from Redpanda source code to its literal string value.
|
|
342
|
+
|
|
343
|
+
Searches common Redpanda source locations for constexpr string or string_view definitions matching the given identifier and returns the literal if found.
|
|
344
|
+
|
|
345
|
+
Parameters:
|
|
346
|
+
identifier (str): The identifier name to resolve (e.g., "scram").
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
str or None: The resolved literal string value if found, otherwise `None`.
|
|
350
|
+
"""
|
|
351
|
+
# Try to find the Redpanda source directory
|
|
352
|
+
redpanda_source_paths = [
|
|
353
|
+
'tmp/redpanda', # Current directory
|
|
354
|
+
'../tmp/redpanda', # Parent directory
|
|
355
|
+
'tools/property-extractor/tmp/redpanda', # From project root
|
|
356
|
+
os.path.join(os.getcwd(), 'tools', 'property-extractor', 'tmp', 'redpanda')
|
|
357
|
+
]
|
|
358
|
+
|
|
359
|
+
redpanda_source = None
|
|
360
|
+
for path in redpanda_source_paths:
|
|
361
|
+
if os.path.exists(path):
|
|
362
|
+
redpanda_source = path
|
|
363
|
+
break
|
|
364
|
+
|
|
365
|
+
if not redpanda_source:
|
|
366
|
+
logger.debug(f"Could not find Redpanda source directory to resolve identifier: {identifier}")
|
|
367
|
+
return None
|
|
368
|
+
|
|
369
|
+
# Pattern to match constexpr string_view definitions
|
|
370
|
+
# Matches: inline constexpr std::string_view scram{"SCRAM"};
|
|
371
|
+
patterns = [
|
|
372
|
+
rf'inline\s+constexpr\s+std::string_view\s+{re.escape(identifier)}\s*\{{\s*"([^"]+)"\s*\}}',
|
|
373
|
+
rf'constexpr\s+std::string_view\s+{re.escape(identifier)}\s*\{{\s*"([^"]+)"\s*\}}',
|
|
374
|
+
rf'inline\s+constexpr\s+auto\s+{re.escape(identifier)}\s*=\s*"([^"]+)"',
|
|
375
|
+
rf'constexpr\s+auto\s+{re.escape(identifier)}\s*=\s*"([^"]+)"',
|
|
376
|
+
rf'static\s+constexpr\s+std::string_view\s+{re.escape(identifier)}\s*\{{\s*"([^"]+)"\s*\}}',
|
|
377
|
+
rf'static\s+inline\s+constexpr\s+std::string_view\s+{re.escape(identifier)}\s*\{{\s*"([^"]+)"\s*\}}',
|
|
378
|
+
]
|
|
379
|
+
|
|
380
|
+
# Search recursively through the config directory and other common locations
|
|
381
|
+
search_dirs = [
|
|
382
|
+
os.path.join(redpanda_source, 'src', 'v', 'config'),
|
|
383
|
+
os.path.join(redpanda_source, 'src', 'v', 'kafka'),
|
|
384
|
+
os.path.join(redpanda_source, 'src', 'v', 'security'),
|
|
385
|
+
os.path.join(redpanda_source, 'src', 'v', 'pandaproxy'),
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
for search_dir in search_dirs:
|
|
389
|
+
if not os.path.exists(search_dir):
|
|
390
|
+
continue
|
|
391
|
+
|
|
392
|
+
# Walk through the directory recursively
|
|
393
|
+
for root, dirs, files in os.walk(search_dir):
|
|
394
|
+
for file in files:
|
|
395
|
+
# Check both .h and .cc files since definitions can be in either
|
|
396
|
+
if file.endswith(('.h', '.cc', '.hpp', '.cpp')):
|
|
397
|
+
file_path = os.path.join(root, file)
|
|
398
|
+
try:
|
|
399
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
400
|
+
content = f.read()
|
|
401
|
+
|
|
402
|
+
# Try each pattern
|
|
403
|
+
for pattern in patterns:
|
|
404
|
+
match = re.search(pattern, content, re.MULTILINE)
|
|
405
|
+
if match:
|
|
406
|
+
resolved_value = match.group(1)
|
|
407
|
+
logger.debug(f"Resolved identifier '{identifier}' -> '{resolved_value}' from {file_path}")
|
|
408
|
+
return resolved_value
|
|
409
|
+
|
|
410
|
+
except (FileNotFoundError, PermissionError, OSError, UnicodeDecodeError) as e:
|
|
411
|
+
logger.debug(f"Error reading {file_path}: {e}")
|
|
412
|
+
continue
|
|
413
|
+
|
|
414
|
+
logger.debug(f"Could not resolve identifier: {identifier}")
|
|
415
|
+
return None
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def get_enterprise_sasl_mechanisms():
|
|
419
|
+
"""
|
|
420
|
+
Locate and resolve enterprise SASL mechanisms declared in Redpanda's sasl_mechanisms.h.
|
|
421
|
+
|
|
422
|
+
Searches known Redpanda source locations for an inline constexpr definition of enterprise_sasl_mechanisms,
|
|
423
|
+
extracts the identifiers, and resolves each identifier to its literal string value where possible; unresolved
|
|
424
|
+
identifiers are converted to an uppercase fallback.
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
list or None: List of enterprise SASL mechanism strings (e.g., ["GSSAPI", "OAUTHBEARER"]),
|
|
428
|
+
or `None` if the lookup fails.
|
|
429
|
+
"""
|
|
430
|
+
# Try to find the Redpanda source directory
|
|
431
|
+
redpanda_source_paths = [
|
|
432
|
+
'tmp/redpanda', # Current directory
|
|
433
|
+
'../tmp/redpanda', # Parent directory
|
|
434
|
+
'tools/property-extractor/tmp/redpanda', # From project root
|
|
435
|
+
os.path.join(os.getcwd(), 'tools', 'property-extractor', 'tmp', 'redpanda')
|
|
436
|
+
]
|
|
437
|
+
|
|
438
|
+
redpanda_source = None
|
|
439
|
+
for path in redpanda_source_paths:
|
|
440
|
+
if os.path.exists(path):
|
|
441
|
+
redpanda_source = path
|
|
442
|
+
break
|
|
443
|
+
|
|
444
|
+
if not redpanda_source:
|
|
445
|
+
logger.debug("Could not find Redpanda source directory to resolve enterprise SASL mechanisms")
|
|
446
|
+
return None
|
|
447
|
+
|
|
448
|
+
# Look for the enterprise_sasl_mechanisms definition in sasl_mechanisms.h
|
|
449
|
+
sasl_mechanisms_file = os.path.join(redpanda_source, 'src', 'v', 'config', 'sasl_mechanisms.h')
|
|
450
|
+
|
|
451
|
+
if not os.path.exists(sasl_mechanisms_file):
|
|
452
|
+
logger.debug(f"sasl_mechanisms.h not found at {sasl_mechanisms_file}")
|
|
453
|
+
return None
|
|
454
|
+
|
|
455
|
+
try:
|
|
456
|
+
with open(sasl_mechanisms_file, 'r', encoding='utf-8') as f:
|
|
457
|
+
content = f.read()
|
|
458
|
+
|
|
459
|
+
# Pattern to match the enterprise_sasl_mechanisms array definition
|
|
460
|
+
# inline constexpr auto enterprise_sasl_mechanisms = std::to_array<std::string_view>({gssapi, oauthbearer});
|
|
461
|
+
pattern = r'inline\s+constexpr\s+auto\s+enterprise_sasl_mechanisms\s*=\s*std::to_array<[^>]+>\s*\(\s*\{\s*([^}]+)\s*\}\s*\)'
|
|
462
|
+
|
|
463
|
+
match = re.search(pattern, content, re.MULTILINE | re.DOTALL)
|
|
464
|
+
if match:
|
|
465
|
+
# Extract the identifiers from the array (e.g., "gssapi, oauthbearer")
|
|
466
|
+
identifiers_str = match.group(1).strip()
|
|
467
|
+
|
|
468
|
+
# Split by comma and clean up whitespace
|
|
469
|
+
identifiers = [id.strip() for id in identifiers_str.split(',') if id.strip()]
|
|
470
|
+
|
|
471
|
+
# Resolve each identifier to its actual string value
|
|
472
|
+
mechanisms = []
|
|
473
|
+
for identifier in identifiers:
|
|
474
|
+
resolved_value = resolve_constexpr_identifier(identifier)
|
|
475
|
+
if resolved_value:
|
|
476
|
+
mechanisms.append(resolved_value)
|
|
477
|
+
else:
|
|
478
|
+
logger.debug(f"Could not resolve SASL mechanism identifier: {identifier}")
|
|
479
|
+
# Fallback: use the identifier name in uppercase
|
|
480
|
+
mechanisms.append(identifier.upper())
|
|
481
|
+
|
|
482
|
+
if mechanisms:
|
|
483
|
+
logger.debug(f"Resolved enterprise SASL mechanisms: {mechanisms}")
|
|
484
|
+
return mechanisms
|
|
485
|
+
else:
|
|
486
|
+
logger.debug("Could not find enterprise_sasl_mechanisms definition in sasl_mechanisms.h")
|
|
487
|
+
return None
|
|
488
|
+
|
|
489
|
+
except (OSError, UnicodeDecodeError, re.error) as e:
|
|
490
|
+
logger.debug(f"Error reading {sasl_mechanisms_file}: {e}")
|
|
491
|
+
return None
|
|
492
|
+
|
|
493
|
+
|
|
325
494
|
def validate_paths(options):
|
|
495
|
+
"""
|
|
496
|
+
Validate that required file-system paths referenced by `options` exist and exit the process on failure.
|
|
497
|
+
|
|
498
|
+
Checks:
|
|
499
|
+
- Verifies `options.path` exists; logs an error and exits with status code 1 if it does not.
|
|
500
|
+
- If `options.definitions` is provided, verifies that file exists; logs an error and exits with status code 1 if it does not.
|
|
501
|
+
|
|
502
|
+
Parameters:
|
|
503
|
+
options: An object with at least the attributes:
|
|
504
|
+
- path (str): Path to the input source directory or file.
|
|
505
|
+
- definitions (Optional[str]): Path to the type definitions file (may be None or empty).
|
|
506
|
+
"""
|
|
326
507
|
path = options.path
|
|
327
508
|
|
|
328
509
|
if not os.path.exists(path):
|
|
@@ -713,21 +894,16 @@ def add_config_scope(properties):
|
|
|
713
894
|
|
|
714
895
|
def resolve_type_and_default(properties, definitions):
|
|
715
896
|
"""
|
|
716
|
-
|
|
897
|
+
Normalize property types and expand C++-style default values into JSON-compatible Python structures.
|
|
717
898
|
|
|
718
|
-
This function
|
|
719
|
-
- Resolves type references found in `properties` against `definitions` (supports "$ref" and direct type names) and normalizes property "type" to a JSON Schema primitive ("object", "string", "integer", "boolean", "array", "number") with sensible fallbacks.
|
|
720
|
-
- Expands C++ constructor/initializer syntax and common C++ patterns appearing in default values into JSON-compatible Python values (e.g., nested constructor calls -> dicts, initializer lists -> lists, `std::nullopt` -> None, enum-like tokens -> strings).
|
|
721
|
-
- Ensures array-typed properties (including one_or_many_property cases) have array defaults: single-object defaults are wrapped into a one-element list and "{}" string defaults become [].
|
|
722
|
-
- Updates array item type information when item types reference definitions.
|
|
723
|
-
- Applies a final pass to convert any remaining C++-patterned defaults and to transform any `enterprise_value` strings via process_enterprise_value.
|
|
899
|
+
This function resolves type references in each property against the provided definitions (supports "$ref" and direct type names), normalizes property "type" to a JSON Schema primitive when possible, expands C++ constructor/initializer and common C++ literal patterns found in "default" values into Python primitives/objects/lists, ensures array-typed properties have array defaults (including handling one_or_many_property cases), updates array item type information when item types reference definitions, and converts any `enterprise_value` strings via process_enterprise_value.
|
|
724
900
|
|
|
725
901
|
Parameters:
|
|
726
|
-
properties (dict): Mapping of property names to
|
|
727
|
-
definitions (dict): Mapping of
|
|
902
|
+
properties (dict): Mapping of property names to metadata dictionaries. Relevant keys that may be modified include "type", "default", "items", and "enterprise_value".
|
|
903
|
+
definitions (dict): Mapping of definition names to JSON Schema definition dictionaries used to resolve $ref targets and to infer shapes for expanding constructor-style defaults.
|
|
728
904
|
|
|
729
905
|
Returns:
|
|
730
|
-
dict: The same `properties` mapping after in-place normalization and expansion of types and
|
|
906
|
+
dict: The same `properties` mapping after in-place normalization and expansion of types, defaults, item types, and enterprise values.
|
|
731
907
|
"""
|
|
732
908
|
import ast
|
|
733
909
|
import re
|
|
@@ -742,20 +918,42 @@ def resolve_type_and_default(properties, definitions):
|
|
|
742
918
|
return defn
|
|
743
919
|
|
|
744
920
|
def parse_constructor(s):
|
|
745
|
-
"""
|
|
921
|
+
"""
|
|
922
|
+
Parse a C++-style constructor or initializer expression into its type name and argument list.
|
|
923
|
+
|
|
924
|
+
Parses input forms such as `Type(arg1, arg2)`, `Type{arg1, arg2}`, or plain literals/enum-like tokens. For string literals the returned argument is a Python string value; for integer literals the returned argument is an int. Nested constructors and nested brace/paren groups are preserved as argument tokens.
|
|
925
|
+
|
|
926
|
+
Parameters:
|
|
927
|
+
s (str): The C++ expression to parse.
|
|
928
|
+
|
|
929
|
+
Returns:
|
|
930
|
+
tuple:
|
|
931
|
+
- type_name (str|None): The parsed type name for constructor forms, or `None` when `s` is a primitive literal or enum-like token.
|
|
932
|
+
- args (list): A list of argument tokens; tokens are raw strings for complex/nested arguments, Python `str` for quoted string literals, or `int` for integer literals.
|
|
933
|
+
"""
|
|
746
934
|
s = s.strip()
|
|
935
|
+
original_s = s
|
|
747
936
|
if s.startswith("{") and s.endswith("}"):
|
|
748
937
|
s = s[1:-1].strip()
|
|
938
|
+
|
|
939
|
+
# Try parentheses syntax first: type_name(args)
|
|
749
940
|
match = re.match(r'([a-zA-Z0-9_:]+)\((.*)\)', s)
|
|
750
|
-
if
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
941
|
+
if match:
|
|
942
|
+
type_name, arg_str = match.groups()
|
|
943
|
+
else:
|
|
944
|
+
# Try curly brace syntax: type_name{args}
|
|
945
|
+
match = re.match(r'([a-zA-Z0-9_:]+)\{(.*)\}', s)
|
|
946
|
+
if match:
|
|
947
|
+
type_name, arg_str = match.groups()
|
|
948
|
+
else:
|
|
949
|
+
# Primitive or enum
|
|
950
|
+
if s.startswith('"') and s.endswith('"'):
|
|
951
|
+
return None, [ast.literal_eval(s)]
|
|
952
|
+
try:
|
|
953
|
+
return None, [int(s)]
|
|
954
|
+
except ValueError:
|
|
955
|
+
return None, [s]
|
|
956
|
+
|
|
759
957
|
args = []
|
|
760
958
|
depth = 0
|
|
761
959
|
current = ''
|
|
@@ -768,9 +966,9 @@ def resolve_type_and_default(properties, definitions):
|
|
|
768
966
|
args.append(current.strip())
|
|
769
967
|
current = ''
|
|
770
968
|
else:
|
|
771
|
-
if c
|
|
969
|
+
if c in '({' and not in_string:
|
|
772
970
|
depth += 1
|
|
773
|
-
elif c
|
|
971
|
+
elif c in ')}' and not in_string:
|
|
774
972
|
depth -= 1
|
|
775
973
|
current += c
|
|
776
974
|
if current.strip():
|
|
@@ -779,13 +977,18 @@ def resolve_type_and_default(properties, definitions):
|
|
|
779
977
|
|
|
780
978
|
def process_cpp_patterns(arg_str):
|
|
781
979
|
"""
|
|
782
|
-
|
|
980
|
+
Convert a C++-style expression string into a JSON-friendly literal representation.
|
|
783
981
|
|
|
784
|
-
|
|
785
|
-
- net::unresolved_address("127.0.0.1", 9092) -> expands based on type definition
|
|
982
|
+
This function recognises common C++ patterns produced by the extractor and maps them to values suitable for JSON schema defaults and examples. Handled cases include:
|
|
786
983
|
- std::nullopt -> null
|
|
787
|
-
-
|
|
788
|
-
-
|
|
984
|
+
- zero-argument functions (e.g., model::kafka_audit_logging_topic()) resolved from source when possible
|
|
985
|
+
- enum tokens (e.g., fips_mode_flag::disabled -> "disabled")
|
|
986
|
+
- constexpr identifiers and simple string constructors resolved to their literal strings when available
|
|
987
|
+
- known default constructors and truncated type names mapped to sensible defaults (e.g., duration -> 0, path -> "")
|
|
988
|
+
- simple heuristics for unknown constructors and concatenated expressions
|
|
989
|
+
|
|
990
|
+
Returns:
|
|
991
|
+
processed (str): A string representing the JSON-ready value (for example: '"value"', 'null', '0', or the original input when no mapping applied).
|
|
789
992
|
"""
|
|
790
993
|
arg_str = arg_str.strip()
|
|
791
994
|
|
|
@@ -808,6 +1011,24 @@ def resolve_type_and_default(properties, definitions):
|
|
|
808
1011
|
enum_value = enum_match.group(1)
|
|
809
1012
|
return f'"{enum_value}"'
|
|
810
1013
|
|
|
1014
|
+
# Handle constexpr identifier resolution (such as scram -> "SCRAM")
|
|
1015
|
+
# Check if this is a simple identifier that might be a constexpr variable
|
|
1016
|
+
if re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', arg_str):
|
|
1017
|
+
resolved_value = resolve_constexpr_identifier(arg_str)
|
|
1018
|
+
if resolved_value is not None:
|
|
1019
|
+
return f'"{resolved_value}"'
|
|
1020
|
+
|
|
1021
|
+
# Handle string constructor patterns like ss::sstring{identifier}
|
|
1022
|
+
sstring_match = re.match(r'ss::sstring\{([a-zA-Z_][a-zA-Z0-9_]*)\}', arg_str)
|
|
1023
|
+
if sstring_match:
|
|
1024
|
+
identifier = sstring_match.group(1)
|
|
1025
|
+
resolved_value = resolve_constexpr_identifier(identifier)
|
|
1026
|
+
if resolved_value is not None:
|
|
1027
|
+
return f'"{resolved_value}"'
|
|
1028
|
+
else:
|
|
1029
|
+
# Fallback to the identifier itself
|
|
1030
|
+
return f'"{identifier}"'
|
|
1031
|
+
|
|
811
1032
|
# Handle default constructors and their default values
|
|
812
1033
|
# This handles cases where C++ default constructors are used but should map to specific values
|
|
813
1034
|
|
|
@@ -861,12 +1082,23 @@ def resolve_type_and_default(properties, definitions):
|
|
|
861
1082
|
|
|
862
1083
|
def expand_default(type_name, default_str):
|
|
863
1084
|
"""
|
|
864
|
-
|
|
1085
|
+
Convert a C++-style default initializer into a JSON-serializable Python value.
|
|
865
1086
|
|
|
866
|
-
|
|
867
|
-
|
|
1087
|
+
This expands C++ constructor and initializer-list syntax into Python primitives, dictionaries, and lists suitable for JSON output. Supported transformations include:
|
|
1088
|
+
- String constructors and quoted literals → Python str.
|
|
1089
|
+
- Integer and boolean literals → Python int and bool.
|
|
1090
|
+
- Object constructors (Type(arg1, arg2) or Type{...}) → dict mapping constructor arguments to the object's properties when a corresponding type definition exists.
|
|
1091
|
+
- Nested constructors → nested dicts with their fields expanded.
|
|
1092
|
+
- Array initializer lists (e.g., {Type(...), Type(...)}) → Python list with each element expanded.
|
|
1093
|
+
- Special-case mappings for known type patterns (for example, an address-type constructor expanded into {"address", "port"} when the target type expects that shape).
|
|
1094
|
+
If a default cannot be resolved or the type is an enum, the original input is returned unchanged; the string "null" is converted to None. If default_str is not a string, it is returned as-is.
|
|
868
1095
|
|
|
869
|
-
|
|
1096
|
+
Parameters:
|
|
1097
|
+
type_name (str): The resolved type name for the default value (e.g., "model::broker_endpoint" or a primitive type like "string").
|
|
1098
|
+
default_str (str | any): The C++ default expression to expand, or a non-string value already decoded.
|
|
1099
|
+
|
|
1100
|
+
Returns:
|
|
1101
|
+
The expanded Python representation of the default: a dict for objects, a list for arrays, a primitive (str/int/bool), None for null, or the original value/string when expansion is not possible.
|
|
870
1102
|
"""
|
|
871
1103
|
# Handle non-string defaults
|
|
872
1104
|
if not isinstance(default_str, str):
|
|
@@ -883,6 +1115,19 @@ def resolve_type_and_default(properties, definitions):
|
|
|
883
1115
|
return ast.literal_eval(processed)
|
|
884
1116
|
else:
|
|
885
1117
|
return processed
|
|
1118
|
+
|
|
1119
|
+
# Handle string type with constructor syntax (e.g., ss::sstring{scram})
|
|
1120
|
+
if type_name == "string" and ("{" in default_str or "(" in default_str):
|
|
1121
|
+
tname, args = parse_constructor(default_str)
|
|
1122
|
+
if tname and args:
|
|
1123
|
+
# For string constructors, resolve the first argument and return it as the string value
|
|
1124
|
+
first_arg = args[0] if args else ""
|
|
1125
|
+
# Apply C++ pattern processing to resolve identifiers
|
|
1126
|
+
processed_arg = process_cpp_patterns(first_arg)
|
|
1127
|
+
if processed_arg.startswith('"') and processed_arg.endswith('"'):
|
|
1128
|
+
return ast.literal_eval(processed_arg) # Remove quotes
|
|
1129
|
+
else:
|
|
1130
|
+
return processed_arg
|
|
886
1131
|
|
|
887
1132
|
type_def = resolve_definition_type(definitions.get(type_name, {}))
|
|
888
1133
|
if "enum" in type_def:
|
|
@@ -1619,4 +1864,4 @@ def main():
|
|
|
1619
1864
|
sys.exit(1)
|
|
1620
1865
|
|
|
1621
1866
|
if __name__ == "__main__":
|
|
1622
|
-
main()
|
|
1867
|
+
main()
|
|
@@ -20,8 +20,9 @@ ifndef::env-cloud[]
|
|
|
20
20
|
endif::[]
|
|
21
21
|
{{/if}}
|
|
22
22
|
{{#if cloud_byoc_only}}
|
|
23
|
-
|
|
23
|
+
ifdef::env-cloud[]
|
|
24
24
|
NOTE: This property is available only in Redpanda Cloud BYOC deployments.
|
|
25
|
+
endif::[]
|
|
25
26
|
{{/if}}
|
|
26
27
|
{{#if units}}
|
|
27
28
|
|
|
@@ -71,9 +72,7 @@ ifndef::env-cloud[]
|
|
|
71
72
|
endif::[]
|
|
72
73
|
{{/if}}
|
|
73
74
|
|
|
74
|
-
// tag::self-managed-only[]
|
|
75
75
|
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
76
|
-
// end::self-managed-only[]
|
|
77
76
|
{{#if example}}
|
|
78
77
|
|
|
79
78
|
{{{renderPropertyExample this}}}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
= {{pageTitle}}
|
|
2
|
+
{{#if pageAliases}}
|
|
3
|
+
:page-aliases: {{join pageAliases ", "}}
|
|
4
|
+
{{/if}}
|
|
5
|
+
:description: {{description}}
|
|
6
|
+
|
|
7
|
+
{{{intro}}}
|
|
8
|
+
|
|
9
|
+
{{#if sectionTitle}}
|
|
10
|
+
== {{sectionTitle}}
|
|
11
|
+
{{/if}}
|
|
12
|
+
|
|
13
|
+
{{#if sectionIntro}}
|
|
14
|
+
{{{sectionIntro}}}
|
|
15
|
+
{{/if}}
|
|
16
|
+
|
|
17
|
+
include::reference:partial$properties/{{filename}}.adoc[]
|
|
@@ -58,28 +58,27 @@ endif::[]
|
|
|
58
58
|
|
|
59
59
|
{{/if}}
|
|
60
60
|
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
61
|
-
|
|
62
61
|
{{#if example}}
|
|
62
|
+
|
|
63
63
|
{{{renderPropertyExample this}}}
|
|
64
64
|
{{/if}}
|
|
65
|
-
|
|
66
65
|
{{#if related_topics}}
|
|
66
|
+
|
|
67
67
|
*Related topics:*
|
|
68
68
|
|
|
69
69
|
{{#each related_topics}}
|
|
70
70
|
* {{{this}}}
|
|
71
71
|
{{/each}}
|
|
72
72
|
{{/if}}
|
|
73
|
-
|
|
74
73
|
{{#if aliases}}
|
|
75
|
-
*Aliases:* {{join aliases ", "}}
|
|
76
74
|
|
|
75
|
+
*Aliases:* {{join aliases ", "}}
|
|
77
76
|
{{/if}}
|
|
78
77
|
{{#if is_deprecated}}
|
|
78
|
+
|
|
79
79
|
[WARNING]
|
|
80
80
|
====
|
|
81
81
|
This property is deprecated.
|
|
82
82
|
====
|
|
83
|
-
|
|
84
83
|
{{/if}}
|
|
85
84
|
---
|