mirror of
https://github.com/hanzoai/telemetry.git
synced 2026-10-30 20:01:49 +00:00
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Previously, the schemagen loader used `config.schema.yaml` as the standalone file format for schema references. This PR changes the source of truth for cross-component schema references to `metadata.yaml` — the same file that already exists in every component directory. Instead of parsing a bare ConfigMetadata JSON-schema object, the loader now reads the config: section from a component's `metadata.yaml`, matching the structure that mdatagen already generates for every component. The generated output is likewise renamed to metadata.yaml (placed under internal/metadata/) and wrapped with the standard `metadata.yaml` envelope (type, status, config), so it is usable as a reference target by other components in the same way. <!-- Issue number if applicable --> #### Link to tracking issue Fixes #15259 <!--Describe what testing was performed and which tests were added.--> #### Testing Existing unit tests in `internal/schemagen` and `cmd/mdatagen/internal` were updated to reflect the new file name and Metadata wrapper format. The persistToFile test was strengthened to verify a full round-trip through loadFromFile. All tests pass.
418 lines
12 KiB
Go
418 lines
12 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package schemagen
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewRef(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
refPath string
|
|
expected *Ref
|
|
}{
|
|
{
|
|
name: "empty ref",
|
|
refPath: "",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "",
|
|
defName: "",
|
|
kind: Internal,
|
|
},
|
|
},
|
|
{
|
|
name: "internal ref",
|
|
refPath: "target_type",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "",
|
|
defName: "target_type",
|
|
kind: Internal,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref with absolute path",
|
|
refPath: "/config/configauth.config",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "/config/configauth",
|
|
defName: "config",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref with relative path (./)",
|
|
refPath: "./internal/metadata.config",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "./internal/metadata",
|
|
defName: "config",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref with relative path (../)",
|
|
refPath: "../other.config",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "../other",
|
|
defName: "config",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref without def name",
|
|
refPath: "/config/configauth",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "/config/configauth",
|
|
defName: "",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref empty",
|
|
refPath: "../",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "../",
|
|
defName: "",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "local ref empty short schemaId",
|
|
refPath: "../.test",
|
|
expected: &Ref{
|
|
namespace: "",
|
|
schemaID: "../",
|
|
defName: "test",
|
|
kind: Local,
|
|
},
|
|
},
|
|
{
|
|
name: "external ref without version",
|
|
refPath: "go.opentelemetry.io/collector/config/confighttp.client_config",
|
|
expected: &Ref{
|
|
namespace: "go.opentelemetry.io/collector",
|
|
schemaID: "config/confighttp",
|
|
defName: "client_config",
|
|
kind: External,
|
|
},
|
|
},
|
|
{
|
|
name: "external ref without def name",
|
|
refPath: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: &Ref{
|
|
namespace: "go.opentelemetry.io/collector",
|
|
schemaID: "config/confighttp",
|
|
defName: "",
|
|
kind: External,
|
|
},
|
|
},
|
|
{
|
|
name: "external ref without schema ID",
|
|
refPath: "go.opentelemetry.io/collector",
|
|
expected: &Ref{
|
|
namespace: "go.opentelemetry.io/collector",
|
|
schemaID: "",
|
|
defName: "",
|
|
kind: External,
|
|
},
|
|
},
|
|
{
|
|
name: "unknown namespace",
|
|
refPath: "com.github.example/custom.xyz",
|
|
expected: &Ref{
|
|
namespace: "com.github.example",
|
|
schemaID: "custom",
|
|
defName: "xyz",
|
|
kind: External,
|
|
},
|
|
},
|
|
{
|
|
name: "ref with wrong format",
|
|
refPath: "some/path.with.dots",
|
|
expected: &Ref{
|
|
namespace: "some",
|
|
schemaID: "path",
|
|
defName: "with.dots",
|
|
kind: External,
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := NewRef(tt.refPath)
|
|
require.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWithOrigin(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
refPath string
|
|
origin string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "absolute ref resolves against namespace",
|
|
refPath: "/config/configauth.config",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/configauth.config",
|
|
},
|
|
{
|
|
name: "absolute ref with empty origin unchanged",
|
|
refPath: "/config/configauth.config",
|
|
origin: "",
|
|
expected: "/config/configauth.config",
|
|
},
|
|
{
|
|
name: "relative ref resolves against module path",
|
|
refPath: "./internal/metadata.config",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/confighttp/internal/metadata.config",
|
|
},
|
|
{
|
|
name: "parent relative ref resolves against parent module",
|
|
refPath: "../configtls.tls_config",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/configtls.tls_config",
|
|
},
|
|
{
|
|
name: "external ref with same-namespace origin joins schema IDs",
|
|
refPath: "go.opentelemetry.io/collector/config/confighttp.client_config",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/confighttp/config/confighttp.client_config",
|
|
},
|
|
{
|
|
name: "internal ref with origin unchanged",
|
|
refPath: "target_type",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/confighttp.target_type",
|
|
},
|
|
{
|
|
name: "local relative ref with local absolute resolves to local absolute schema ID",
|
|
refPath: "./internal.timeout_config",
|
|
origin: "/config/confighttp",
|
|
expected: "/config/confighttp/internal.timeout_config",
|
|
},
|
|
{
|
|
name: "local relative ref with external origin resolves to external schema ID",
|
|
refPath: "./internal.timeout_config",
|
|
origin: "go.opentelemetry.io/collector/config/confighttp",
|
|
expected: "go.opentelemetry.io/collector/config/confighttp/internal.timeout_config",
|
|
},
|
|
{
|
|
name: "local absolute ref with local absolute origin keeps original schema ID",
|
|
refPath: "/config/confighttp.timeout_config",
|
|
origin: "/config/confignet.connection_config",
|
|
expected: "/config/confighttp.timeout_config",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ref := WithOrigin(tt.refPath, NewRef(tt.origin))
|
|
require.Equal(t, tt.expected, ref.CacheKey())
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRef_Validate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
refPath string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid collector reference",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid contrib reference",
|
|
refPath: "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver.config",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid internal reference",
|
|
refPath: "target_type",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid local absolute reference",
|
|
refPath: "/config/configauth.config",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "empty path",
|
|
refPath: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing def name",
|
|
refPath: "/config/configauth",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "missing schema ID with external ref",
|
|
refPath: "go.opentelemetry.io/collector",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ref := NewRef(tt.refPath)
|
|
err := ref.Validate()
|
|
if tt.wantErr {
|
|
require.Error(t, err)
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRef_URL(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
refPath string
|
|
version string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "collector reference",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v1.0.0",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/v1.0.0/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
{
|
|
name: "contrib reference",
|
|
refPath: "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver.config",
|
|
version: "v0.95.0",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector-contrib/v0.95.0/receiver/mysqlreceiver/metadata.yaml",
|
|
},
|
|
{
|
|
name: "main version",
|
|
refPath: "go.opentelemetry.io/collector/processor/batchprocessor.config",
|
|
version: "main",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/main/processor/batchprocessor/metadata.yaml",
|
|
},
|
|
{
|
|
name: "collector pseudo-version uses commit hash",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v0.147.1-0.20260317033252-665ab5d0143d",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/665ab5d0143d/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
{
|
|
name: "pseudo-version with incompatible suffix uses commit hash",
|
|
refPath: "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/mysqlreceiver.config",
|
|
version: "v0.95.1-0.20260317033252-665ab5d0143d+incompatible",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector-contrib/665ab5d0143d/receiver/mysqlreceiver/metadata.yaml",
|
|
},
|
|
{
|
|
name: "dirty version uses trimmed version string",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v1.0.0+dirty",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/v1.0.0/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
{
|
|
name: "unrecognized suffix uses raw version string",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v1.0.0-xxx-yyy+dirty",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/v1.0.0-xxx-yyy/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
{
|
|
name: "pre-release version passes through unchanged",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v1.0.0-rc.1",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/v1.0.0-rc.1/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
{
|
|
name: "pre-release tag that looks like a pseudo-version passes through unchanged",
|
|
refPath: "go.opentelemetry.io/collector/scraper/scraperhelper.controller_config",
|
|
version: "v1.0.0-beta-abc123abcdef",
|
|
expected: "https://raw.githubusercontent.com/open-telemetry/opentelemetry-collector/v1.0.0-beta-abc123abcdef/scraper/scraperhelper/metadata.yaml",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ref := NewRef(tt.refPath)
|
|
result, err := ref.URL(tt.version)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRef_String(t *testing.T) {
|
|
ref := NewRef("go.opentelemetry.io/collector/config/confighttp.client_config")
|
|
require.Equal(t, "go.opentelemetry.io/collector/config/confighttp.client_config", ref.String())
|
|
}
|
|
|
|
func TestRef_Module_EmptyNamespace(t *testing.T) {
|
|
ref := NewRef("target_type")
|
|
require.Empty(t, ref.Module())
|
|
}
|
|
|
|
func TestRef_URL_UnsupportedNamespace(t *testing.T) {
|
|
ref := NewRef("unsupported.example.com/pkg/sub.config")
|
|
_, err := ref.URL("v1.0.0")
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "unsupported namespace")
|
|
}
|
|
|
|
func TestRef_Validate_LocalRefMissingSchemaID(t *testing.T) {
|
|
ref := &Ref{schemaID: "", defName: "config", kind: Local}
|
|
err := ref.Validate()
|
|
require.Error(t, err)
|
|
require.Contains(t, err.Error(), "missing schema ID in local reference")
|
|
}
|
|
|
|
func TestNamespaceOf_FallbackLastSlash(t *testing.T) {
|
|
result := namespaceOf("com.example/some/path.type")
|
|
require.Equal(t, "com.example/some", result)
|
|
}
|
|
|
|
func TestNamespaceOf_NoSlash(t *testing.T) {
|
|
result := namespaceOf("noslash")
|
|
require.Empty(t, result)
|
|
}
|
|
|
|
func TestLocalizeRef(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
refPath string
|
|
importRootPath string
|
|
expected string
|
|
}{
|
|
{
|
|
name: "same root collector ref becomes local absolute",
|
|
refPath: "go.opentelemetry.io/collector/filter.config",
|
|
importRootPath: "go.opentelemetry.io/collector",
|
|
expected: "/filter.config",
|
|
},
|
|
{
|
|
name: "different root ref stays external",
|
|
refPath: "go.opentelemetry.io/collector/filter.config",
|
|
importRootPath: "github.com/open-telemetry/opentelemetry-collector-contrib",
|
|
expected: "go.opentelemetry.io/collector/filter.config",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
require.Equal(t, tt.expected, LocalizeRef(tt.refPath, tt.importRootPath))
|
|
})
|
|
}
|
|
}
|