Skip to content

Commit 5a2da78

Browse files
[cmd/mdatagen] Add go_struct.ignore_default flag to suppress default value generation for config fields (#15198)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description This PR adds a `go_struct.ignore_default` flag to the mdatagen config schema system. When set to true on a config field, mdatagen omits that field from the generated `createDefaultConfig` function - emitting nil for pointer fields and `configoptional.None` for optional fields — instead of propagating defaults from the referenced schema. <!-- Issue number if applicable --> #### Link to tracking issue Fixes #15156 <!--Describe what testing was performed and which tests were added.--> #### Testing 1. Added and updated unit tests for default value parsing, JSON output, resolver behavior, null/default formatting, optional object defaults, and generated config helper behavior. 2. Exended `samplereceiver` example
1 parent 5ba1620 commit 5a2da78

11 files changed

Lines changed: 748 additions & 57 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. receiver/otlp)
7+
component: cmd/mdatagen
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Add `go_struct.ignore_default` flag to suppress default value generation for individual config fields.
11+
12+
# One or more tracking issues or pull requests related to the change
13+
issues: [15156]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext: |
19+
Setting `go_struct.ignore_default: true` on a config field causes mdatagen to omit that field's default
20+
from the generated `createDefaultConfig` function, emitting `nil` for pointer fields
21+
and `configoptional.None` for optional fields.
22+
23+
# Optional: The change log or logs in which this entry should be included.
24+
# e.g. '[user]' or '[user, api]'
25+
# Include 'user' if the change is relevant to end users.
26+
# Include 'api' if there is a change to a library API.
27+
# Default: '[user]'
28+
change_logs: [api]

cmd/mdatagen/internal/cfggen/generation.go

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func NewCfgFns(rootPackage, componentPackage string) map[string]any {
2525
}
2626
imports, err := ExtractImports(cfg, rootPackage, componentPackage)
2727
if err != nil {
28-
return []string{}
28+
panic(err)
2929
}
3030
return imports
3131
},
@@ -202,7 +202,10 @@ func collectImports(md *ConfigMetadata, imports map[string]bool, rootPackage, co
202202

203203
if md.GoType != "" {
204204
ref, err := ResolveGoTypeRef(md.GoType, rootPackage, componentPackage)
205-
if err == nil && ref.ImportPath != "" {
205+
if err != nil {
206+
return fmt.Errorf("failed to resolve import for custom type %q: %w", md.GoType, err)
207+
}
208+
if ref.ImportPath != "" {
206209
imports[ref.ImportPath] = true
207210
}
208211
}
@@ -217,11 +220,17 @@ func collectImports(md *ConfigMetadata, imports map[string]bool, rootPackage, co
217220

218221
if md.ResolvedFrom != "" {
219222
ref, err := ResolveGoTypeRef(md.ResolvedFrom, rootPackage, componentPackage)
220-
if err == nil && ref.ImportPath != "" {
223+
if err != nil {
224+
return fmt.Errorf("failed to resolve import for reference %q: %w", md.ResolvedFrom, err)
225+
}
226+
if ref.ImportPath != "" {
221227
imports[ref.ImportPath] = true
222228
}
223229
refDesc := NewRef(md.ResolvedFrom)
224230
if !refDesc.isInternal() {
231+
if err := collectCustomDefaultImports(md, md.Default, imports, rootPackage, componentPackage); err != nil {
232+
return err
233+
}
225234
return nil
226235
}
227236
}
@@ -267,6 +276,42 @@ func collectImports(md *ConfigMetadata, imports map[string]bool, rootPackage, co
267276
return nil
268277
}
269278

279+
func collectCustomDefaultImports(md *ConfigMetadata, defaultValue any, imports map[string]bool, rootPackage, componentPackage string) error {
280+
if md == nil || md.GoStruct.IgnoreDefault {
281+
return nil
282+
}
283+
284+
switch typedValue := defaultValue.(type) {
285+
case map[string]any:
286+
if md.AdditionalProperties != nil {
287+
return nil
288+
}
289+
for key, value := range typedValue {
290+
prop := md.Properties[key]
291+
if prop == nil {
292+
continue
293+
}
294+
if err := collectImports(prop, imports, rootPackage, componentPackage); err != nil {
295+
return err
296+
}
297+
if err := collectCustomDefaultImports(prop, value, imports, rootPackage, componentPackage); err != nil {
298+
return err
299+
}
300+
}
301+
case []any:
302+
if md.Items == nil || md.Items.Type != "object" {
303+
return nil
304+
}
305+
for _, item := range typedValue {
306+
if err := collectCustomDefaultImports(md.Items, item, imports, rootPackage, componentPackage); err != nil {
307+
return err
308+
}
309+
}
310+
}
311+
312+
return nil
313+
}
314+
270315
// FormatTypeName resolves a reference string to a Go type expression using GoTypeRef.
271316
func FormatTypeName(ref, rootPackage, componentPackage string) (string, error) {
272317
tr, err := ResolveGoTypeRef(ref, rootPackage, componentPackage)
@@ -448,8 +493,10 @@ func generateValidatorName(propName string, desc *CustomValidatorConfig) string
448493
}
449494

450495
func MapCustomDefaults(schema *ConfigMetadata, defaultValue any, rootPackage, componentPackage string) []string {
496+
if schema.GoStruct.IgnoreDefault {
497+
return nil
498+
}
451499
exps := make([]string, 0)
452-
453500
switch typedValue := defaultValue.(type) {
454501
case map[string]any:
455502
// is nested struct
@@ -483,12 +530,25 @@ func MapCustomDefaults(schema *ConfigMetadata, defaultValue any, rootPackage, co
483530
}
484531

485532
func FormatDefaultValue(md *ConfigMetadata, name string, defaultValue any, rootPackage, componentPackage string) string {
533+
if md.GoStruct.IgnoreDefault || (defaultValue == nil && !hasDefaultValue(md)) {
534+
if md.IsPointer {
535+
return "nil"
536+
}
537+
if md.IsOptional {
538+
t, _ := resolveGoType(md, name, rootPackage, componentPackage)
539+
return fmt.Sprintf("configoptional.None[%s]()", t)
540+
}
541+
return ""
542+
}
486543
exp := formatSimpleValue(md, name, defaultValue, rootPackage, componentPackage)
487544
if md.IsPointer {
488-
exp = "&" + exp
545+
return "&" + exp
489546
}
490547
if md.IsOptional {
491-
exp = fmt.Sprintf("configoptional.Some(%s)", exp)
548+
if md.Type == "object" && md.Properties != nil {
549+
return fmt.Sprintf("configoptional.Default(%s)", exp)
550+
}
551+
return fmt.Sprintf("configoptional.Some(%s)", exp)
492552
}
493553
return exp
494554
}
@@ -504,16 +564,19 @@ func FormatBaseValue(md *ConfigMetadata, name string, defaultValue any, rootPack
504564
func WrapDefaultValue(md *ConfigMetadata, varName string) string {
505565
exp := varName
506566
if md.IsPointer {
507-
exp = "&" + exp
567+
return "&" + exp
508568
}
509569
if md.IsOptional {
510-
exp = fmt.Sprintf("configoptional.Some(%s)", exp)
570+
if md.Type == "object" && md.Properties != nil {
571+
return fmt.Sprintf("configoptional.Default(%s)", exp)
572+
}
573+
return fmt.Sprintf("configoptional.Some(%s)", exp)
511574
}
512575
return exp
513576
}
514577

515578
func hasDefaultValue(md *ConfigMetadata) bool {
516-
if md.Default != nil {
579+
if !md.GoStruct.IgnoreDefault && md.Default != nil {
517580
return true
518581
}
519582
for _, prop := range md.Properties {
@@ -559,8 +622,8 @@ func formatSimpleValue(md *ConfigMetadata, name string, defaultValue any, rootPa
559622
return ""
560623
}
561624

562-
// do not process further if "default" attribute not defined
563-
if defaultValue == nil {
625+
// do not process further if "ignore_default" attribute set
626+
if md.GoStruct.IgnoreDefault {
564627
return ""
565628
}
566629

0 commit comments

Comments
 (0)