@redpanda-data/docs-extensions-and-macros 4.8.0 → 4.9.0
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 +236 -54
- package/package.json +1 -1
- package/tools/property-extractor/Makefile +68 -50
- package/tools/property-extractor/cloud_config.py +594 -0
- package/tools/property-extractor/compare-properties.js +378 -0
- package/tools/property-extractor/generate-handlebars-docs.js +444 -0
- package/tools/property-extractor/helpers/and.js +10 -0
- package/tools/property-extractor/helpers/eq.js +9 -0
- package/tools/property-extractor/helpers/formatPropertyValue.js +128 -0
- package/tools/property-extractor/helpers/formatUnits.js +26 -0
- package/tools/property-extractor/helpers/index.js +13 -0
- package/tools/property-extractor/helpers/join.js +18 -0
- package/tools/property-extractor/helpers/ne.js +9 -0
- package/tools/property-extractor/helpers/not.js +8 -0
- package/tools/property-extractor/helpers/or.js +10 -0
- package/tools/property-extractor/helpers/renderPropertyExample.js +42 -0
- package/tools/property-extractor/package-lock.json +77 -0
- package/tools/property-extractor/package.json +6 -0
- package/tools/property-extractor/parser.py +27 -1
- package/tools/property-extractor/property_extractor.py +1428 -49
- package/tools/property-extractor/requirements.txt +2 -0
- package/tools/property-extractor/templates/deprecated-properties.hbs +25 -0
- package/tools/property-extractor/templates/deprecated-property.hbs +7 -0
- package/tools/property-extractor/templates/property-cloud.hbs +105 -0
- package/tools/property-extractor/templates/property-page.hbs +22 -0
- package/tools/property-extractor/templates/property.hbs +85 -0
- package/tools/property-extractor/templates/topic-property-cloud.hbs +97 -0
- package/tools/property-extractor/templates/topic-property.hbs +73 -0
- package/tools/property-extractor/transformers.py +178 -6
- package/tools/property-extractor/json-to-asciidoc/generate_docs.py +0 -491
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{{#if deprecated}}
|
|
2
|
+
= Deprecated Configuration Properties
|
|
3
|
+
:description: This is an exhaustive list of all the deprecated properties.
|
|
4
|
+
|
|
5
|
+
This is an exhaustive list of all the deprecated properties.
|
|
6
|
+
|
|
7
|
+
{{#if brokerProperties}}
|
|
8
|
+
== Broker properties
|
|
9
|
+
|
|
10
|
+
{{#each brokerProperties}}
|
|
11
|
+
{{> deprecated-property}}
|
|
12
|
+
|
|
13
|
+
{{/each}}
|
|
14
|
+
{{/if}}
|
|
15
|
+
|
|
16
|
+
{{#if clusterProperties}}
|
|
17
|
+
== Cluster properties
|
|
18
|
+
|
|
19
|
+
{{#each clusterProperties}}
|
|
20
|
+
{{> deprecated-property}}
|
|
21
|
+
|
|
22
|
+
{{/each}}
|
|
23
|
+
{{/if}}
|
|
24
|
+
|
|
25
|
+
{{/if}}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{{#if cloud_supported}}
|
|
2
|
+
// tag::redpanda-cloud[]
|
|
3
|
+
{{/if}}
|
|
4
|
+
=== {{name}}
|
|
5
|
+
{{#if version}}
|
|
6
|
+
|
|
7
|
+
*Introduced in {{version}}*
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if description}}
|
|
10
|
+
|
|
11
|
+
{{{description}}}
|
|
12
|
+
{{else}}
|
|
13
|
+
|
|
14
|
+
No description available.
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if is_enterprise}}
|
|
17
|
+
|
|
18
|
+
ifndef::env-cloud[]
|
|
19
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
20
|
+
endif::[]
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if cloud_byoc_only}}
|
|
23
|
+
|
|
24
|
+
NOTE: This property is available only in Redpanda Cloud BYOC deployments.
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if units}}
|
|
27
|
+
|
|
28
|
+
*Unit:* {{units}}
|
|
29
|
+
{{else}}
|
|
30
|
+
{{#if (formatUnits name)}}
|
|
31
|
+
|
|
32
|
+
*Unit:* {{formatUnits name}}
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{/if}}
|
|
35
|
+
{{#if (ne defined_in "src/v/config/node_config.cc")}}
|
|
36
|
+
{{#if (ne needs_restart undefined)}}
|
|
37
|
+
|
|
38
|
+
*Requires restart:* {{#if needs_restart}}Yes{{else}}No{{/if}}
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{/if}}
|
|
41
|
+
{{#if visibility}}
|
|
42
|
+
|
|
43
|
+
// tag::self-managed-only[]
|
|
44
|
+
*Visibility:* `{{visibility}}`
|
|
45
|
+
// end::self-managed-only[]
|
|
46
|
+
{{/if}}
|
|
47
|
+
{{#if type}}
|
|
48
|
+
|
|
49
|
+
*Type:* {{type}}
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (and minimum maximum)}}
|
|
52
|
+
|
|
53
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
54
|
+
{{else}}
|
|
55
|
+
{{#if minimum}}
|
|
56
|
+
|
|
57
|
+
*Minimum value:* `{{minimum}}`
|
|
58
|
+
{{/if}}
|
|
59
|
+
{{#if maximum}}
|
|
60
|
+
|
|
61
|
+
*Maximum value:* `{{maximum}}`
|
|
62
|
+
{{/if}}
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{#if (ne default undefined)}}
|
|
65
|
+
|
|
66
|
+
ifdef::env-cloud[]
|
|
67
|
+
*Default:* Available in the Redpanda Cloud Console
|
|
68
|
+
endif::[]
|
|
69
|
+
ifndef::env-cloud[]
|
|
70
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
71
|
+
endif::[]
|
|
72
|
+
{{/if}}
|
|
73
|
+
|
|
74
|
+
// tag::self-managed-only[]
|
|
75
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
76
|
+
// end::self-managed-only[]
|
|
77
|
+
{{#if example}}
|
|
78
|
+
|
|
79
|
+
{{{renderPropertyExample this}}}
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if related_topics}}
|
|
82
|
+
|
|
83
|
+
*Related topics:*
|
|
84
|
+
|
|
85
|
+
{{#each related_topics}}
|
|
86
|
+
* {{{this}}}
|
|
87
|
+
{{/each}}
|
|
88
|
+
{{/if}}
|
|
89
|
+
{{#if aliases}}
|
|
90
|
+
|
|
91
|
+
// tag::self-managed-only[]
|
|
92
|
+
*Aliases:* {{join aliases ", "}}
|
|
93
|
+
// end::self-managed-only[]
|
|
94
|
+
{{/if}}
|
|
95
|
+
{{#if is_deprecated}}
|
|
96
|
+
|
|
97
|
+
[WARNING]
|
|
98
|
+
====
|
|
99
|
+
This property is deprecated.
|
|
100
|
+
====
|
|
101
|
+
{{/if}}
|
|
102
|
+
---
|
|
103
|
+
{{#if cloud_supported}}
|
|
104
|
+
// end::redpanda-cloud[]
|
|
105
|
+
{{/if}}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
{{#each groups}}
|
|
18
|
+
{{#each this.properties}}
|
|
19
|
+
{{> (lookup ../this "template")}}
|
|
20
|
+
|
|
21
|
+
{{/each}}
|
|
22
|
+
{{/each}}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
=== {{name}}
|
|
2
|
+
|
|
3
|
+
{{#if version}}
|
|
4
|
+
*Introduced in {{version}}*
|
|
5
|
+
{{/if}}
|
|
6
|
+
|
|
7
|
+
{{#if description}}
|
|
8
|
+
{{{description}}}
|
|
9
|
+
{{else}}
|
|
10
|
+
No description available.
|
|
11
|
+
{{/if}}
|
|
12
|
+
|
|
13
|
+
{{#if is_enterprise}}
|
|
14
|
+
ifndef::env-cloud[]
|
|
15
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
16
|
+
endif::[]
|
|
17
|
+
|
|
18
|
+
{{/if}}
|
|
19
|
+
|
|
20
|
+
{{#if units}}
|
|
21
|
+
*Unit:* {{units}}
|
|
22
|
+
|
|
23
|
+
{{else}}
|
|
24
|
+
{{#if (formatUnits name)}}
|
|
25
|
+
*Unit:* {{formatUnits name}}
|
|
26
|
+
|
|
27
|
+
{{/if}}
|
|
28
|
+
{{/if}}
|
|
29
|
+
{{#if (ne defined_in "src/v/config/node_config.cc")}}
|
|
30
|
+
{{#if (ne needs_restart undefined)}}
|
|
31
|
+
*Requires restart:* {{#if needs_restart}}Yes{{else}}No{{/if}}
|
|
32
|
+
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{/if}}
|
|
35
|
+
{{#if visibility}}
|
|
36
|
+
*Visibility:* `{{visibility}}`
|
|
37
|
+
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{#if type}}
|
|
40
|
+
*Type:* {{type}}
|
|
41
|
+
|
|
42
|
+
{{/if}}
|
|
43
|
+
{{#if (and minimum maximum)}}
|
|
44
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
45
|
+
|
|
46
|
+
{{else}}
|
|
47
|
+
{{#if minimum}}
|
|
48
|
+
*Minimum value:* `{{minimum}}`
|
|
49
|
+
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if maximum}}
|
|
52
|
+
*Maximum value:* `{{maximum}}`
|
|
53
|
+
|
|
54
|
+
{{/if}}
|
|
55
|
+
{{/if}}
|
|
56
|
+
{{#if (ne default undefined)}}
|
|
57
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
58
|
+
|
|
59
|
+
{{/if}}
|
|
60
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
61
|
+
|
|
62
|
+
{{#if example}}
|
|
63
|
+
{{{renderPropertyExample this}}}
|
|
64
|
+
{{/if}}
|
|
65
|
+
|
|
66
|
+
{{#if related_topics}}
|
|
67
|
+
*Related topics:*
|
|
68
|
+
|
|
69
|
+
{{#each related_topics}}
|
|
70
|
+
* {{{this}}}
|
|
71
|
+
{{/each}}
|
|
72
|
+
{{/if}}
|
|
73
|
+
|
|
74
|
+
{{#if aliases}}
|
|
75
|
+
*Aliases:* {{join aliases ", "}}
|
|
76
|
+
|
|
77
|
+
{{/if}}
|
|
78
|
+
{{#if is_deprecated}}
|
|
79
|
+
[WARNING]
|
|
80
|
+
====
|
|
81
|
+
This property is deprecated.
|
|
82
|
+
====
|
|
83
|
+
|
|
84
|
+
{{/if}}
|
|
85
|
+
---
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{{#if cloud_supported}}
|
|
2
|
+
// tag::redpanda-cloud[]
|
|
3
|
+
{{/if}}
|
|
4
|
+
=== {{name}}
|
|
5
|
+
{{#if version}}
|
|
6
|
+
|
|
7
|
+
*Introduced in {{version}}*
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if description}}
|
|
10
|
+
|
|
11
|
+
{{{description}}}
|
|
12
|
+
{{else}}
|
|
13
|
+
|
|
14
|
+
No description available.
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if is_enterprise}}
|
|
17
|
+
|
|
18
|
+
ifndef::env-cloud[]
|
|
19
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
20
|
+
endif::[]
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if cloud_byoc_only}}
|
|
23
|
+
|
|
24
|
+
NOTE: This property is only available in Redpanda Cloud BYOC deployments.
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if type}}
|
|
27
|
+
|
|
28
|
+
*Type:* {{type}}
|
|
29
|
+
{{/if}}
|
|
30
|
+
{{#if acceptable_values}}
|
|
31
|
+
|
|
32
|
+
*Accepted values:* {{{acceptable_values}}}
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{#if corresponding_cluster_property}}
|
|
35
|
+
|
|
36
|
+
*Related cluster property:* xref:reference:cluster-properties.adoc#{{corresponding_cluster_property}}[{{corresponding_cluster_property}}]
|
|
37
|
+
{{/if}}
|
|
38
|
+
{{#if (and minimum maximum)}}
|
|
39
|
+
|
|
40
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
41
|
+
{{else}}
|
|
42
|
+
{{#if minimum}}
|
|
43
|
+
|
|
44
|
+
*Minimum value:* `{{minimum}}`
|
|
45
|
+
{{/if}}
|
|
46
|
+
{{#if maximum}}
|
|
47
|
+
|
|
48
|
+
*Maximum value:* `{{maximum}}`
|
|
49
|
+
{{/if}}
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (ne default undefined)}}
|
|
52
|
+
{{#if cloud_supported}}
|
|
53
|
+
|
|
54
|
+
ifdef::env-cloud[]
|
|
55
|
+
*Default:* Available in the Redpanda Cloud Console
|
|
56
|
+
endif::[]
|
|
57
|
+
ifndef::env-cloud[]
|
|
58
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
59
|
+
endif::[]
|
|
60
|
+
{{else}}
|
|
61
|
+
|
|
62
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{/if}}
|
|
65
|
+
|
|
66
|
+
// tag::self-managed-only[]
|
|
67
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
68
|
+
// end::self-managed-only[]
|
|
69
|
+
{{#if example}}
|
|
70
|
+
|
|
71
|
+
{{{renderPropertyExample this}}}
|
|
72
|
+
{{/if}}
|
|
73
|
+
{{#if related_topics}}
|
|
74
|
+
|
|
75
|
+
*Related topics:*
|
|
76
|
+
|
|
77
|
+
{{#each related_topics}}
|
|
78
|
+
* {{{this}}}
|
|
79
|
+
{{/each}}
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if aliases}}
|
|
82
|
+
|
|
83
|
+
// tag::self-managed-only[]
|
|
84
|
+
*Aliases:* {{join aliases ", "}}
|
|
85
|
+
// end::self-managed-only[]
|
|
86
|
+
{{/if}}
|
|
87
|
+
{{#if is_deprecated}}
|
|
88
|
+
|
|
89
|
+
[WARNING]
|
|
90
|
+
====
|
|
91
|
+
This property is deprecated.
|
|
92
|
+
====
|
|
93
|
+
{{/if}}
|
|
94
|
+
---
|
|
95
|
+
{{#if cloud_supported}}
|
|
96
|
+
// end::redpanda-cloud[]
|
|
97
|
+
{{/if}}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
=== {{name}}
|
|
2
|
+
{{#if version}}
|
|
3
|
+
|
|
4
|
+
*Introduced in {{version}}*
|
|
5
|
+
{{/if}}
|
|
6
|
+
{{#if description}}
|
|
7
|
+
|
|
8
|
+
{{{description}}}
|
|
9
|
+
{{else}}
|
|
10
|
+
|
|
11
|
+
No description available.
|
|
12
|
+
{{/if}}
|
|
13
|
+
{{#if is_enterprise}}
|
|
14
|
+
|
|
15
|
+
ifndef::env-cloud[]
|
|
16
|
+
*Enterprise license required*: `{{enterprise_value}}` (for license details, see xref:get-started:licensing/index.adoc[Redpanda Licensing])
|
|
17
|
+
endif::[]
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{#if type}}
|
|
20
|
+
|
|
21
|
+
*Type:* {{type}}
|
|
22
|
+
{{/if}}
|
|
23
|
+
{{#if acceptable_values}}
|
|
24
|
+
|
|
25
|
+
*Accepted values:* {{{acceptable_values}}}
|
|
26
|
+
{{/if}}
|
|
27
|
+
{{#if corresponding_cluster_property}}
|
|
28
|
+
|
|
29
|
+
*Related cluster property:* xref:reference:cluster-properties.adoc#{{corresponding_cluster_property}}[{{corresponding_cluster_property}}]
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if (and minimum maximum)}}
|
|
32
|
+
|
|
33
|
+
*Accepted values:* [`{{minimum}}`, `{{maximum}}`]
|
|
34
|
+
{{else}}
|
|
35
|
+
{{#if minimum}}
|
|
36
|
+
|
|
37
|
+
*Minimum value:* `{{minimum}}`
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{#if maximum}}
|
|
40
|
+
|
|
41
|
+
*Maximum value:* `{{maximum}}`
|
|
42
|
+
{{/if}}
|
|
43
|
+
{{/if}}
|
|
44
|
+
{{#if (ne default undefined)}}
|
|
45
|
+
|
|
46
|
+
*Default:* `{{formatPropertyValue default type}}`
|
|
47
|
+
{{/if}}
|
|
48
|
+
|
|
49
|
+
*Nullable:* {{#if nullable}}Yes{{else}}No{{/if}}
|
|
50
|
+
{{#if example}}
|
|
51
|
+
|
|
52
|
+
{{{renderPropertyExample this}}}
|
|
53
|
+
{{/if}}
|
|
54
|
+
{{#if related_topics}}
|
|
55
|
+
|
|
56
|
+
*Related topics:*
|
|
57
|
+
|
|
58
|
+
{{#each related_topics}}
|
|
59
|
+
* {{{this}}}
|
|
60
|
+
{{/each}}
|
|
61
|
+
{{/if}}
|
|
62
|
+
{{#if aliases}}
|
|
63
|
+
|
|
64
|
+
*Aliases:* {{join aliases ", "}}
|
|
65
|
+
{{/if}}
|
|
66
|
+
{{#if is_deprecated}}
|
|
67
|
+
|
|
68
|
+
[WARNING]
|
|
69
|
+
====
|
|
70
|
+
This property is deprecated.
|
|
71
|
+
====
|
|
72
|
+
{{/if}}
|
|
73
|
+
---
|
|
@@ -1,13 +1,50 @@
|
|
|
1
1
|
import re
|
|
2
|
+
import logging
|
|
2
3
|
from property_bag import PropertyBag
|
|
3
4
|
from parser import normalize_string
|
|
4
5
|
|
|
6
|
+
# Get logger for this module
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
# Import the process_enterprise_value function from property_extractor
|
|
10
|
+
# Note: We import at function level to avoid circular imports since property_extractor
|
|
11
|
+
# imports transformers.py. This pattern allows the EnterpriseTransformer to access
|
|
12
|
+
# the centralized enterprise value processing logic without creating import cycles.
|
|
13
|
+
def get_process_enterprise_value():
|
|
14
|
+
"""
|
|
15
|
+
Lazily import and return the centralized `process_enterprise_value` function from `property_extractor`.
|
|
16
|
+
|
|
17
|
+
Attempts to import `process_enterprise_value` and return it to avoid circular-import issues. If the import fails an error message is printed and None is returned.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Callable or None: The `process_enterprise_value` callable when available, otherwise `None`.
|
|
21
|
+
"""
|
|
22
|
+
try:
|
|
23
|
+
from property_extractor import process_enterprise_value
|
|
24
|
+
return process_enterprise_value
|
|
25
|
+
except ImportError as e:
|
|
26
|
+
logger.error("Cannot import process_enterprise_value from property_extractor: %s", e)
|
|
27
|
+
return None
|
|
28
|
+
|
|
5
29
|
|
|
6
30
|
class BasicInfoTransformer:
|
|
7
31
|
def accepts(self, info, file_pair):
|
|
32
|
+
"""
|
|
33
|
+
Always accepts the provided info and file_pair.
|
|
34
|
+
|
|
35
|
+
Parameters:
|
|
36
|
+
info (dict): Parsed metadata for a property (annotation/params/declaration).
|
|
37
|
+
file_pair (object): Pair of source/implementation file metadata used by transformers.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
bool: Always returns True, indicating this transformer should be applied.
|
|
41
|
+
"""
|
|
8
42
|
return True
|
|
9
43
|
|
|
10
44
|
def parse(self, property, info, file_pair):
|
|
45
|
+
if not info.get("params") or len(info["params"]) == 0:
|
|
46
|
+
return property
|
|
47
|
+
|
|
11
48
|
property["name"] = info["params"][0]["value"]
|
|
12
49
|
property["defined_in"] = re.sub(
|
|
13
50
|
r"^.*src/", "src/", str(file_pair.implementation)
|
|
@@ -36,13 +73,52 @@ class IsNullableTransformer:
|
|
|
36
73
|
|
|
37
74
|
|
|
38
75
|
class IsArrayTransformer:
|
|
76
|
+
"""
|
|
77
|
+
Detects properties that should be treated as arrays based on their C++ type declarations.
|
|
78
|
+
|
|
79
|
+
This transformer identifies two types of array properties:
|
|
80
|
+
1. std::vector<T> - Standard C++ vectors
|
|
81
|
+
2. one_or_many_property<T> - Redpanda's custom type that accepts either a single value or an array
|
|
82
|
+
|
|
83
|
+
The one_or_many_property type is used in Redpanda configuration for properties like 'admin'
|
|
84
|
+
and 'admin_api_tls' where users can specify either:
|
|
85
|
+
- A single object: admin: {address: "127.0.0.1", port: 9644}
|
|
86
|
+
- An array of objects: admin: [{address: "127.0.0.1", port: 9644}, {address: "0.0.0.0", port: 9645}]
|
|
87
|
+
|
|
88
|
+
When detected, these properties are marked with:
|
|
89
|
+
- type: "array"
|
|
90
|
+
- items: {type: <inner_type>} where <inner_type> is extracted from T
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# Class-level constants for array type patterns
|
|
94
|
+
ARRAY_PATTERN_STD_VECTOR = "std::vector"
|
|
95
|
+
ARRAY_PATTERN_ONE_OR_MANY = "one_or_many_property"
|
|
96
|
+
|
|
39
97
|
def __init__(self, type_transformer):
|
|
40
98
|
self.type_transformer = type_transformer
|
|
41
99
|
|
|
42
100
|
def accepts(self, info, file_pair):
|
|
43
|
-
|
|
101
|
+
"""
|
|
102
|
+
Check if this property declaration represents an array type.
|
|
103
|
+
|
|
104
|
+
Returns True for:
|
|
105
|
+
- std::vector<T> declarations (standard C++ vectors)
|
|
106
|
+
- one_or_many_property<T> declarations (Redpanda's flexible array type)
|
|
107
|
+
"""
|
|
108
|
+
return (self.ARRAY_PATTERN_STD_VECTOR in info["declaration"] or
|
|
109
|
+
self.ARRAY_PATTERN_ONE_OR_MANY in info["declaration"])
|
|
44
110
|
|
|
45
111
|
def parse(self, property, info, file_pair):
|
|
112
|
+
"""
|
|
113
|
+
Transform the property to indicate it's an array type.
|
|
114
|
+
|
|
115
|
+
Sets:
|
|
116
|
+
- property["type"] = "array"
|
|
117
|
+
- property["items"]["type"] = <extracted_inner_type>
|
|
118
|
+
|
|
119
|
+
The inner type is extracted by the type_transformer, which handles
|
|
120
|
+
removing the wrapper (std::vector<> or one_or_many_property<>) to get T.
|
|
121
|
+
"""
|
|
46
122
|
property["type"] = "array"
|
|
47
123
|
property["items"] = PropertyBag()
|
|
48
124
|
property["items"]["type"] = self.type_transformer.get_type_from_declaration(
|
|
@@ -94,10 +170,35 @@ class VisibilityTransformer:
|
|
|
94
170
|
|
|
95
171
|
|
|
96
172
|
class TypeTransformer:
|
|
173
|
+
|
|
174
|
+
# Class-level constants for type pattern matching
|
|
175
|
+
# Shared with IsArrayTransformer for consistency
|
|
176
|
+
ARRAY_PATTERN_STD_VECTOR = "std::vector"
|
|
177
|
+
ARRAY_PATTERN_ONE_OR_MANY = "one_or_many_property"
|
|
178
|
+
OPTIONAL_PATTERN = "std::optional"
|
|
179
|
+
|
|
97
180
|
def accepts(self, info, file_pair):
|
|
98
181
|
return True
|
|
99
182
|
|
|
100
183
|
def get_cpp_type_from_declaration(self, declaration):
|
|
184
|
+
"""
|
|
185
|
+
Extract the inner type from C++ property declarations.
|
|
186
|
+
|
|
187
|
+
This method handles various C++ template types and extracts the core type T from:
|
|
188
|
+
- property<T> -> T
|
|
189
|
+
- std::optional<T> -> T
|
|
190
|
+
- std::vector<T> -> T
|
|
191
|
+
- one_or_many_property<T> -> T (Redpanda's flexible array type)
|
|
192
|
+
|
|
193
|
+
For one_or_many_property, this is crucial because it allows the same property
|
|
194
|
+
to accept either a single value or an array of values in the configuration.
|
|
195
|
+
Examples:
|
|
196
|
+
- one_or_many_property<model::broker_endpoint> -> model::broker_endpoint
|
|
197
|
+
- one_or_many_property<endpoint_tls_config> -> endpoint_tls_config
|
|
198
|
+
|
|
199
|
+
The extracted type is then used to determine the JSON schema type and
|
|
200
|
+
for resolving default values from the definitions.
|
|
201
|
+
"""
|
|
101
202
|
one_line_declaration = declaration.replace("\n", "").strip()
|
|
102
203
|
raw_type = (
|
|
103
204
|
re.sub(r"^.*property<(.+)>.*", "\\1", one_line_declaration)
|
|
@@ -105,11 +206,19 @@ class TypeTransformer:
|
|
|
105
206
|
.replace(",", "")
|
|
106
207
|
)
|
|
107
208
|
|
|
108
|
-
if
|
|
209
|
+
if self.OPTIONAL_PATTERN in raw_type:
|
|
109
210
|
raw_type = re.sub(".*std::optional<(.+)>.*", "\\1", raw_type)
|
|
110
211
|
|
|
111
|
-
if
|
|
212
|
+
if self.ARRAY_PATTERN_STD_VECTOR in raw_type:
|
|
112
213
|
raw_type = re.sub(".*std::vector<(.+)>.*", "\\1", raw_type)
|
|
214
|
+
|
|
215
|
+
# Handle one_or_many_property<T> - extract the inner type T
|
|
216
|
+
# This is essential for Redpanda's flexible configuration properties
|
|
217
|
+
# that can accept either single values or arrays
|
|
218
|
+
# Check and extract from raw_type for consistency with other type extractors
|
|
219
|
+
if self.ARRAY_PATTERN_ONE_OR_MANY in raw_type:
|
|
220
|
+
raw_type = re.sub(".*one_or_many_property<(.+)>.*", "\\1", raw_type)
|
|
221
|
+
raw_type = raw_type.split()[0].replace(",", "")
|
|
113
222
|
|
|
114
223
|
return raw_type
|
|
115
224
|
|
|
@@ -282,6 +391,10 @@ class FriendlyDefaultTransformer:
|
|
|
282
391
|
- std::chrono::milliseconds(10)
|
|
283
392
|
- std::nullopt
|
|
284
393
|
"""
|
|
394
|
+
|
|
395
|
+
# Class-level constants for pattern matching in default values
|
|
396
|
+
ARRAY_PATTERN_STD_VECTOR = "std::vector"
|
|
397
|
+
|
|
285
398
|
def accepts(self, info, file_pair):
|
|
286
399
|
return info.get("params") and len(info["params"]) > 3
|
|
287
400
|
|
|
@@ -308,7 +421,7 @@ class FriendlyDefaultTransformer:
|
|
|
308
421
|
return property
|
|
309
422
|
|
|
310
423
|
# Transform std::vector defaults.
|
|
311
|
-
if
|
|
424
|
+
if self.ARRAY_PATTERN_STD_VECTOR in default:
|
|
312
425
|
m = re.search(r'\{([^}]+)\}', default)
|
|
313
426
|
if m:
|
|
314
427
|
contents = m.group(1).strip()
|
|
@@ -351,13 +464,65 @@ class AliasTransformer:
|
|
|
351
464
|
|
|
352
465
|
|
|
353
466
|
class EnterpriseTransformer:
|
|
467
|
+
"""
|
|
468
|
+
Transforms enterprise property values from C++ expressions to user-friendly JSON.
|
|
469
|
+
|
|
470
|
+
This transformer processes enterprise values by delegating to the
|
|
471
|
+
centralized process_enterprise_value function which handles the full range of
|
|
472
|
+
C++ expression types found in enterprise property definitions.
|
|
473
|
+
"""
|
|
354
474
|
def accepts(self, info, file_pair):
|
|
475
|
+
"""
|
|
476
|
+
Return True if the provided info indicates an enterprise-only property.
|
|
477
|
+
|
|
478
|
+
Parameters:
|
|
479
|
+
info (dict): The metadata dictionary for a property. This function checks for a 'type' key whose string contains 'enterprise'.
|
|
480
|
+
file_pair: Unused; present for transformer interface compatibility.
|
|
481
|
+
|
|
482
|
+
Returns:
|
|
483
|
+
bool: True when info contains a 'type' that includes 'enterprise', otherwise False.
|
|
484
|
+
"""
|
|
355
485
|
return bool(info.get('type') and 'enterprise' in info['type'])
|
|
356
486
|
|
|
357
487
|
def parse(self, property, info, file_pair):
|
|
488
|
+
"""
|
|
489
|
+
Mark a property as enterprise-only and attach its enterprise value.
|
|
490
|
+
|
|
491
|
+
If an enterprise value is present in info['params'][0]['value'], this method attempts to process it using the shared
|
|
492
|
+
process_enterprise_value helper (loaded via get_process_enterprise_value()). If the processor is unavailable or raises
|
|
493
|
+
an exception, the raw enterprise value is used.
|
|
494
|
+
|
|
495
|
+
Side effects:
|
|
496
|
+
- Sets property["enterprise_value"] to the processed or raw value.
|
|
497
|
+
- Sets property["is_enterprise"] = True.
|
|
498
|
+
- Removes the first element from info['params'].
|
|
499
|
+
|
|
500
|
+
Parameters:
|
|
501
|
+
property (dict): Property bag to modify and return.
|
|
502
|
+
info (dict): Parsed metadata; must have a non-None 'params' list for processing.
|
|
503
|
+
file_pair: Unused here but accepted for transformer API compatibility.
|
|
504
|
+
|
|
505
|
+
Returns:
|
|
506
|
+
dict: The updated property bag.
|
|
507
|
+
"""
|
|
358
508
|
if info['params'] is not None:
|
|
359
509
|
enterpriseValue = info['params'][0]['value']
|
|
360
|
-
|
|
510
|
+
|
|
511
|
+
# Get the processing function
|
|
512
|
+
process_enterprise_value = get_process_enterprise_value()
|
|
513
|
+
if process_enterprise_value is None:
|
|
514
|
+
property["enterprise_value"] = enterpriseValue
|
|
515
|
+
property['is_enterprise'] = True
|
|
516
|
+
del info['params'][0]
|
|
517
|
+
return property
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
processed_value = process_enterprise_value(enterpriseValue)
|
|
521
|
+
property["enterprise_value"] = processed_value
|
|
522
|
+
except Exception:
|
|
523
|
+
# Fallback to raw value if processing fails
|
|
524
|
+
property["enterprise_value"] = enterpriseValue
|
|
525
|
+
|
|
361
526
|
property['is_enterprise'] = True
|
|
362
527
|
del info['params'][0]
|
|
363
528
|
return property
|
|
@@ -386,7 +551,14 @@ class MetaParamTransformer:
|
|
|
386
551
|
iterable_params = info['params']
|
|
387
552
|
for param in iterable_params:
|
|
388
553
|
if isinstance(param['value'], str) and param['value'].startswith("meta{"):
|
|
389
|
-
|
|
554
|
+
# Extract content between meta{ and } using explicit slicing
|
|
555
|
+
param_value = param['value']
|
|
556
|
+
if param_value.endswith('}'):
|
|
557
|
+
meta_content = param_value[5:-1].strip() # Remove "meta{" and "}"
|
|
558
|
+
else:
|
|
559
|
+
# Handle malformed meta{ without closing }
|
|
560
|
+
meta_content = param_value[5:].strip() # Remove "meta{" only
|
|
561
|
+
|
|
390
562
|
meta_dict = {}
|
|
391
563
|
for item in meta_content.split(','):
|
|
392
564
|
item = item.strip()
|