Skip to content

Commit

Permalink
Small enhancement to doc generator to account for slices
Browse files Browse the repository at this point in the history
Signed-off-by: Anand Rajagopal <[email protected]>
  • Loading branch information
rajagopalanand committed Sep 11, 2023
1 parent 39be93d commit 1c9365d
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 24 deletions.
24 changes: 21 additions & 3 deletions docs/configuration/config-file-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2857,7 +2857,7 @@ The `limits_config` configures default and per-tenant limits imposed by Cortex s
# List of metric relabel configurations. Note that in most situations, it is
# more effective to use metrics relabeling directly in the Prometheus server,
# e.g. remote_write.write_relabel_configs.
[metric_relabel_configs: <relabel_config...> | default = ]
[metric_relabel_configs: <relabel_config...> | default = []]
# Enables support for exemplars in TSDB and sets the maximum number that will be
# stored. less than zero means disabled. If the value is set to zero, cortex
Expand Down Expand Up @@ -3099,7 +3099,7 @@ The `limits_config` configures default and per-tenant limits imposed by Cortex s
[alertmanager_max_alerts_size_bytes: <int> | default = 0]

# list of rule groups to disable
[disabled_rule_groups: <list of rule groups to disable> | default = ]
[disabled_rule_groups: <list of DisabledRuleGroup> | default = []]
```
### `memberlist_config`
Expand Down Expand Up @@ -3719,7 +3719,7 @@ The `ruler_config` configures the Cortex ruler.
[external_url: <url> | default = ]
# Labels to add to all alerts.
[external_labels: <map of string to string> | default = ]
[external_labels: <map of string to string> | default = []]
ruler_client:
# gRPC client max receive message size (bytes).
Expand Down Expand Up @@ -4932,3 +4932,21 @@ otel:
# CLI flag: -tracing.otel.tls.tls-insecure-skip-verify
[tls_insecure_skip_verify: <boolean> | default = false]
```
### `DisabledRuleGroup`

```yaml
# namespace in which the rule group belongs
[namespace: <string> | default = ""]
# name of the rule group
[name: <string> | default = ""]
```

### `Label`

```yaml
[name: <string> | default = ""]
[value: <string> | default = ""]
```
6 changes: 3 additions & 3 deletions pkg/util/validation/limits.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ func (e LimitError) Error() string {
}

type DisabledRuleGroup struct {
Namespace string `yaml:"namespace"`
Name string `yaml:"name"`
User string `yaml:"-"`
Namespace string `yaml:"namespace" doc:"nocli|description=namespace in which the rule group belongs"`
Name string `yaml:"name" doc:"nocli|description=name of the rule group"`
User string `yaml:"-" doc:"nocli"`
}

type DisabledRuleGroups []DisabledRuleGroup
Expand Down
5 changes: 5 additions & 0 deletions tools/doc-generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ const (
)

var (
typesToIgnoreCLI = map[string]bool{
"labels.Label": true,
"flagext.CIDR": true,
}

// Ordered list of root blocks. The order is the same order that will
// follow the markdown generation.
rootBlocks = []rootBlock{
Expand Down
73 changes: 55 additions & 18 deletions tools/doc-generator/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func parseConfig(block *configBlock, cfg interface{}, flags map[uintptr]*flag.Fl
}

// Skip field types which are non configurable
if field.Type.Kind() == reflect.Func {
if field.Type.Kind() == reflect.Func || field.Type.Kind() == reflect.Pointer {
continue
}

Expand All @@ -123,7 +123,7 @@ func parseConfig(block *configBlock, cfg interface{}, flags map[uintptr]*flag.Fl
}

// Handle custom fields in vendored libs upon which we have no control.
fieldEntry, err := getCustomFieldEntry(field, fieldValue, flags)
fieldEntry, err := getCustomFieldEntry(t, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -189,17 +189,45 @@ func parseConfig(block *configBlock, cfg interface{}, flags map[uintptr]*flag.Fl
return nil, errors.Wrapf(err, "config=%s.%s", t.PkgPath(), t.Name())
}

fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldDefault := ""
if field.Type.Kind() == reflect.Slice {
sliceElementType := field.Type.Elem()
if sliceElementType.Kind() == reflect.Struct {
rootBlocks = append(rootBlocks, rootBlock{
name: field.Type.Elem().Name(),
structType: field.Type.Elem(),
})
sliceElementBlock := &configBlock{
name: field.Type.Elem().Name(),
desc: "",
}
sliceElementCfg := reflect.New(sliceElementType).Interface()
otherBlocks, err := parseConfig(sliceElementBlock, sliceElementCfg, flags)

if err != nil {
return nil, err
}
if len(sliceElementBlock.entries) > 0 {
blocks = append(blocks, sliceElementBlock)
}

blocks = append(blocks, otherBlocks...)
}
fieldDefault = "[]"
}

fieldFlag, err := getFieldFlag(t, field, fieldValue, flags)
if err != nil {
return nil, errors.Wrapf(err, "config=%s.%s", t.PkgPath(), t.Name())
}
if fieldFlag == nil {
block.Add(&configEntry{
kind: "field",
name: fieldName,
required: isFieldRequired(field),
fieldDesc: getFieldDescription(field, ""),
fieldType: fieldType,
kind: "field",
name: fieldName,
required: isFieldRequired(field),
fieldDesc: getFieldDescription(field, ""),
fieldType: fieldType,
fieldDefault: fieldDefault,
})
continue
}
Expand All @@ -213,6 +241,7 @@ func parseConfig(block *configBlock, cfg interface{}, flags map[uintptr]*flag.Fl
fieldType: fieldType,
fieldDefault: fieldFlag.DefValue,
})

}

return blocks, nil
Expand Down Expand Up @@ -259,12 +288,12 @@ func getFieldType(t reflect.Type) (string, error) {
return "relabel_config...", nil
case "labels.Labels":
return "map of string to string", nil
case "validation.DisabledRuleGroups":
return "list of rule groups to disable", nil
}

// Fallback to auto-detection of built-in data types
switch t.Kind() {
case reflect.Struct:
return t.Name(), nil
case reflect.Bool:
return "boolean", nil

Expand Down Expand Up @@ -314,8 +343,9 @@ func getFieldType(t reflect.Type) (string, error) {
}
}

func getFieldFlag(field reflect.StructField, fieldValue reflect.Value, flags map[uintptr]*flag.Flag) (*flag.Flag, error) {
if isAbsentInCLI(field) {
func getFieldFlag(parent reflect.Type, field reflect.StructField, fieldValue reflect.Value, flags map[uintptr]*flag.Flag) (*flag.Flag, error) {

if isAbsentInCLI(field) || ignoreCLI(parent) {
return nil, nil
}
fieldPtr := fieldValue.Addr().Pointer()
Expand All @@ -327,9 +357,9 @@ func getFieldFlag(field reflect.StructField, fieldValue reflect.Value, flags map
return fieldFlag, nil
}

func getCustomFieldEntry(field reflect.StructField, fieldValue reflect.Value, flags map[uintptr]*flag.Flag) (*configEntry, error) {
func getCustomFieldEntry(parent reflect.Type, field reflect.StructField, fieldValue reflect.Value, flags map[uintptr]*flag.Flag) (*configEntry, error) {
if field.Type == reflect.TypeOf(logging.Level{}) || field.Type == reflect.TypeOf(logging.Format{}) {
fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldFlag, err := getFieldFlag(parent, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand All @@ -345,7 +375,7 @@ func getCustomFieldEntry(field reflect.StructField, fieldValue reflect.Value, fl
}, nil
}
if field.Type == reflect.TypeOf(flagext.URLValue{}) {
fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldFlag, err := getFieldFlag(parent, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand All @@ -361,7 +391,7 @@ func getCustomFieldEntry(field reflect.StructField, fieldValue reflect.Value, fl
}, nil
}
if field.Type == reflect.TypeOf(flagext.Secret{}) {
fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldFlag, err := getFieldFlag(parent, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand All @@ -377,7 +407,7 @@ func getCustomFieldEntry(field reflect.StructField, fieldValue reflect.Value, fl
}, nil
}
if field.Type == reflect.TypeOf(model.Duration(0)) {
fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldFlag, err := getFieldFlag(parent, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand All @@ -393,7 +423,7 @@ func getCustomFieldEntry(field reflect.StructField, fieldValue reflect.Value, fl
}, nil
}
if field.Type == reflect.TypeOf(flagext.Time{}) {
fieldFlag, err := getFieldFlag(field, fieldValue, flags)
fieldFlag, err := getFieldFlag(parent, field, fieldValue, flags)
if err != nil {
return nil, err
}
Expand All @@ -420,6 +450,13 @@ func isAbsentInCLI(f reflect.StructField) bool {
return getDocTagFlag(f, "nocli")
}

func ignoreCLI(f reflect.Type) bool {
if ignore, OK := typesToIgnoreCLI[f.String()]; OK && ignore {
return true
}
return false
}

func isFieldRequired(f reflect.StructField) bool {
return getDocTagFlag(f, "required")
}
Expand Down

0 comments on commit 1c9365d

Please sign in to comment.