You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
terraform/internal/command/init_telemetry_test.go

193 lines
5.3 KiB

// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package command
import (
"testing"
"github.com/hashicorp/cli"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
"github.com/hashicorp/terraform/internal/telemetrytest"
)
// initTelemetryTest sets up telemetry capture for a test and re-obtains the
// package-level tracer so it points at the freshly-installed provider.
// This is necessary because OTel's global delegation is one-shot: the proxy
// tracer obtained during package init() is permanently wired to the first real
// provider set via SetTracerProvider. After that provider is shut down in a
// previous test's cleanup, we must replace the package-level tracer variable
// with one obtained directly from the new global provider.
func initTelemetryTest(t *testing.T) *tracetest.InMemoryExporter {
t.Helper()
origTracer := tracer
exp := telemetrytest.Init(t)
tracer = otel.GetTracerProvider().Tracer("github.com/hashicorp/terraform/internal/command")
t.Cleanup(func() { tracer = origTracer })
return exp
}
func TestInitCommand_telemetry_backend(t *testing.T) {
// Set up telemetry capture — must be before any command execution
telemetry := initTelemetryTest(t)
td := t.TempDir()
testCopyDir(t, testFixturePath("init-backend"), td)
t.Chdir(td)
ui := new(cli.MockUi)
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
View: view,
},
}
args := []string{}
if code := c.Run(args); code != 0 {
t.Fatalf("init failed: \n%s", done(t).All())
}
_ = done(t)
// Verify "initialize backend" span was emitted
telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
return s.Name == "initialize backend"
})
// Verify "install providers from config" span was emitted
telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
return s.Name == "install providers from config"
})
}
func TestInitCommand_telemetry_modules(t *testing.T) {
telemetry := initTelemetryTest(t)
td := t.TempDir()
testCopyDir(t, testFixturePath("init-get"), td)
t.Chdir(td)
ui := new(cli.MockUi)
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
View: view,
},
}
args := []string{}
if code := c.Run(args); code != 0 {
t.Fatalf("init failed: \n%s", done(t).All())
}
_ = done(t)
// Verify "install modules" span was emitted with upgrade=false.
// There are two "install modules" spans (one outer from getModules with
// the upgrade attribute, one inner from installModules without it), so
// we match on the presence of the upgrade attribute.
span := telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
if s.Name != "install modules" {
return false
}
for _, attr := range s.Attributes {
if string(attr.Key) == "upgrade" {
return true
}
}
return false
})
attrs := telemetrytest.AttributesMap(span.Attributes)
if got, want := attrs["upgrade"], false; got != want {
t.Errorf("wrong upgrade attribute\ngot: %v\nwant: %v", got, want)
}
}
func TestInitCommand_telemetry_modules_upgrade(t *testing.T) {
telemetry := initTelemetryTest(t)
td := t.TempDir()
testCopyDir(t, testFixturePath("init-get"), td)
t.Chdir(td)
ui := new(cli.MockUi)
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
View: view,
},
}
// Run with -upgrade flag
args := []string{"-upgrade"}
if code := c.Run(args); code != 0 {
t.Fatalf("init failed: \n%s", done(t).All())
}
_ = done(t)
// Verify "install modules" span was emitted with upgrade=true.
// Same as above, match on the span that carries the upgrade attribute.
span := telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
if s.Name != "install modules" {
return false
}
for _, attr := range s.Attributes {
if string(attr.Key) == "upgrade" {
return true
}
}
return false
})
attrs := telemetrytest.AttributesMap(span.Attributes)
if got, want := attrs["upgrade"], true; got != want {
t.Errorf("wrong upgrade attribute\ngot: %v\nwant: %v", got, want)
}
}
func TestInitCommand_telemetry_providers_from_state(t *testing.T) {
telemetry := initTelemetryTest(t)
td := t.TempDir()
testCopyDir(t, testFixturePath("init-provider-download/state-file-only"), td)
t.Chdir(td)
providerSource, close := newMockProviderSource(t, map[string][]string{
"hashicorp/random": {"1.0.0", "9.9.9"},
})
defer close()
ui := new(cli.MockUi)
view, done := testView(t)
c := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
View: view,
ProviderSource: providerSource,
},
}
args := []string{}
if code := c.Run(args); code != 0 {
t.Fatalf("init failed: \n%s", done(t).All())
}
_ = done(t)
// Verify "install providers from config" span was emitted
telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
return s.Name == "install providers from config"
})
// Verify "install providers from state" span was emitted
telemetrytest.FindSpan(t, telemetry, func(s tracetest.SpanStub) bool {
return s.Name == "install providers from state"
})
}