Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .chloggen/fix-mdatagen-enum-panic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
change_type: bug_fix

component: cmd/mdatagen

note: Fix panic when handling single-element or empty enum attributes in cmd/mdatagen

issues: [15644]

change_logs: [user]
10 changes: 8 additions & 2 deletions cmd/mdatagen/internal/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ func (md *Metadata) validateResourceAttributes() error {
if attr.EnabledPtr == nil {
errs = errors.Join(errs, fmt.Errorf("enabled field is required for resource attribute: %v", name))
}
if attr.Enum != nil && len(attr.Enum) < 2 {
errs = errors.Join(errs, fmt.Errorf("enum for resource attribute %v must have at least two values", name))
}
}
return errs
}
Expand Down Expand Up @@ -316,6 +319,9 @@ func (md *Metadata) validateAttributes(usedAttrs map[AttributeName]bool) error {
if attr.EnabledPtr != nil {
errs = errors.Join(errs, fmt.Errorf("enabled field is not allowed for regular attribute: %v", attrName))
}
if attr.Enum != nil && len(attr.Enum) < 2 {
errs = errors.Join(errs, fmt.Errorf("enum for attribute %v must have at least two values", attrName))
}
if !usedAttrs[attrName] {
unusedAttrs = append(unusedAttrs, attrName)
}
Expand Down Expand Up @@ -699,7 +705,7 @@ func (a Attribute) Name() AttributeName {
}

func (a Attribute) TestValue() string {
if a.Enum != nil {
if len(a.Enum) > 0 {
return fmt.Sprintf(`%q`, a.Enum[0])
}
switch a.Type.ValueType {
Expand All @@ -724,7 +730,7 @@ func (a Attribute) TestValue() string {
}

func (a Attribute) TestValueTwo() string {
if a.Enum != nil {
if len(a.Enum) > 1 {
return fmt.Sprintf(`%q`, a.Enum[1])
}
switch a.Type.ValueType {
Expand Down
73 changes: 73 additions & 0 deletions cmd/mdatagen/internal/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go.opentelemetry.io/collector/cmd/mdatagen/internal/cfggen"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/internal/schemagen"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
)

Expand Down Expand Up @@ -130,6 +131,22 @@ func TestValidate(t *testing.T) {
name: "testdata/no_type_attr.yaml",
wantErr: "empty type for attribute: used_attr",
},
{
name: "testdata/empty_enum_attr.yaml",
wantErr: "enum for attribute string_attr must have at least two values",
},
{
name: "testdata/single_enum_attr.yaml",
wantErr: "enum for attribute string_attr must have at least two values",
},
{
name: "testdata/empty_enum_rattr.yaml",
wantErr: "enum for resource attribute string.resource.attr must have at least two values",
},
{
name: "testdata/single_enum_rattr.yaml",
wantErr: "enum for resource attribute string.resource.attr must have at least two values",
},
{
name: "testdata/entity_undefined_id_attribute.yaml",
wantErr: `entity "host": identity refers to undefined resource attribute: host.missing`,
Expand Down Expand Up @@ -324,6 +341,62 @@ func TestCodeCovID(t *testing.T) {
}
}

func TestAttributeTestValueAndTestValueTwo(t *testing.T) {
tests := []struct {
name string
attr Attribute
wantTestVal string
wantTestVal2 string
}{
{
name: "multi element enum",
attr: Attribute{
FullName: AttributeName("mode"),
Type: ValueType{ValueType: pcommon.ValueTypeStr},
Enum: []string{"first", "second", "third"},
},
wantTestVal: `"first"`,
wantTestVal2: `"second"`,
},
{
name: "single element enum",
attr: Attribute{
FullName: AttributeName("mode"),
Type: ValueType{ValueType: pcommon.ValueTypeStr},
Enum: []string{"default"},
},
wantTestVal: `"default"`,
wantTestVal2: `"mode-val-2"`,
},
{
name: "empty enum slice",
attr: Attribute{
FullName: AttributeName("mode"),
Type: ValueType{ValueType: pcommon.ValueTypeStr},
Enum: []string{},
},
wantTestVal: `"mode-val"`,
wantTestVal2: `"mode-val-2"`,
},
{
name: "non-enum string attribute",
attr: Attribute{
FullName: AttributeName("mode"),
Type: ValueType{ValueType: pcommon.ValueTypeStr},
},
wantTestVal: `"mode-val"`,
wantTestVal2: `"mode-val-2"`,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.wantTestVal, tt.attr.TestValue())
assert.Equal(t, tt.wantTestVal2, tt.attr.TestValueTwo())
})
}
}

func TestAttributeRequirementLevel(t *testing.T) {
tests := []struct {
name string
Expand Down
4 changes: 2 additions & 2 deletions cmd/mdatagen/internal/templates/helper.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
{{- end -}}

{{- define "getAttributeValue" -}}
{{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ (index (attributeInfo .).Enum 0) | publicVar }}{{ else }}{{ (attributeInfo .).TestValue }}{{ end }}
{{ if gt (len (attributeInfo .).Enum) 0 }}Attribute{{ .Render }}{{ (index (attributeInfo .).Enum 0) | publicVar }}{{ else }}{{ (attributeInfo .).TestValue }}{{ end }}
{{- end -}}

{{- define "getAttributeValueTwo" -}}
{{ if (attributeInfo .).Enum }}Attribute{{ .Render }}{{ if gt (len (attributeInfo .).Enum) 1}}{{ (index (attributeInfo .).Enum 1) | publicVar}}{{ else }}{{ (index (attributeInfo .).Enum 0) | publicVar}}{{ end }}{{ else }}{{ (attributeInfo .).TestValueTwo }}{{ end }}
{{ if gt (len (attributeInfo .).Enum) 0 }}Attribute{{ .Render }}{{ if gt (len (attributeInfo .).Enum) 1}}{{ (index (attributeInfo .).Enum 1) | publicVar}}{{ else }}{{ (index (attributeInfo .).Enum 0) | publicVar}}{{ end }}{{ else }}{{ (attributeInfo .).TestValueTwo }}{{ end }}
{{- end -}}

{{- define "assertResourceAttributeValue" -}}
Expand Down
24 changes: 24 additions & 0 deletions cmd/mdatagen/internal/testdata/empty_enum_attr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type: file

status:
class: receiver
stability:
beta: [metrics]

attributes:
string_attr:
description: string attribute description
type: string
enum: []

metrics:
default.metric:
enabled: true
description: Monotonic cumulative sum int metric enabled by default.
stability: development
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
attributes: [string_attr]
13 changes: 13 additions & 0 deletions cmd/mdatagen/internal/testdata/empty_enum_rattr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: file

status:
class: receiver
stability:
beta: [metrics]

resource_attributes:
string.resource.attr:
description: string resource attribute
type: string
enabled: true
enum: []
24 changes: 24 additions & 0 deletions cmd/mdatagen/internal/testdata/single_enum_attr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type: file

status:
class: receiver
stability:
beta: [metrics]

attributes:
string_attr:
description: string attribute description
type: string
enum: ["default"]

metrics:
default.metric:
enabled: true
description: Monotonic cumulative sum int metric enabled by default.
stability: development
unit: s
sum:
value_type: int
monotonic: true
aggregation_temporality: cumulative
attributes: [string_attr]
13 changes: 13 additions & 0 deletions cmd/mdatagen/internal/testdata/single_enum_rattr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
type: file

status:
class: receiver
stability:
beta: [metrics]

resource_attributes:
string.resource.attr:
description: string resource attribute
type: string
enabled: true
enum: ["default"]