From 6e8a50b0844de18718f3e1e355d555487e686ffe Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 6 May 2026 11:41:50 +0200 Subject: [PATCH 1/2] Replace remaining real-domain test hosts with .test Follow-up to #5125 ("Replace bar.com with bar.test in tests"), which only swept bar.com. The same footgun lived in many other test fixtures using real-resolving .com domains in `Config.Host`, `databricks.yml`'s `workspace.host`, and `.databrickscfg`: foo.com, test.com, test2.com, myhost.com, myworkspace.com, x.com, a.com, www.host[12].com, other.host.com. Why this surfaced now --------------------- The SDK well-known endpoint resolver (added during an earlier SDK bump) performs an HTTP fetch with a retry loop the first time `Config.EnsureResolved` runs. For non-resolving hosts (`.test`, `.invalid`, etc.) the resolver fails fast. For real domains it depends on the network: a quick TCP RST or 404 also returns fast; a slow handshake or silent drop triggers a 5-minute retry window. Timeline of `task test (linux, direct)` job duration: | Date | SHA | Duration | Notable | |--------|-----------|----------|-------------------------------| | Apr 16 | 490923836 | 497s | SDK 0.127.0 bump | | Apr 21 | f2443de9d | 466s | SDK 0.128.0 bump | | Apr 28 | 987c2d99e | 494s | last fast run | | Apr 29 | 4ad6ba334 | 1077s | #5125 (bar.com -> bar.test) | | Apr 30 | 22be781c1 | 1205s | +10min vs baseline | | May 6 | 9fc1f8db4 | 1178s | | The SDK bumps did not move the needle. The +10min jump appeared on Apr 29, which lines up with the GitHub Actions runner network changing behavior toward these external domains - most likely a firewall or egress-filtering change that stopped fast-failing the lookups, turning every test that set a real-domain `Config.Host` into a 5-minute stall. #5125 fixed the bar.com family and recovered most of the regression. foo.com lived in a separate file with a slightly different naming convention and missed that sweep, leaving `TestFilesToSync_Everything*` bleeding ~10min combined - the residual ~10min still visible in the table above. What this PR does ----------------- Mechanical `.com -> .test` swap across all remaining test fixtures that set a host. Same low-risk pattern as #5125. Includes the `cmd/root/bundle_test.go` set (x.com / a.com - both real domains), the schema testdata pass files (myworkspace.com), and the cmd/auth testdata fixture plus its consumers. Also adds a rule to AGENTS.md / CLAUDE.md so future test fixtures use a non-resolving TLD by default and we don't have to relearn this through a CI slowdown. Co-authored-by: Isaac --- AGENTS.md | 2 ++ bundle/config/validate/files_to_sync_test.go | 2 +- bundle/deploy/terraform/util_test.go | 2 +- bundle/internal/schema/testdata/pass/job.yml | 2 +- bundle/internal/schema/testdata/pass/ml.yml | 2 +- .../schema/testdata/pass/pipeline.yml | 2 +- bundle/run/pipeline_test.go | 2 +- cmd/auth/auth_test.go | 14 ++++---- cmd/auth/describe_test.go | 12 +++---- cmd/auth/login_test.go | 16 ++++----- cmd/auth/testdata/.databrickscfg | 6 ++-- cmd/root/bundle_test.go | 36 +++++++++---------- libs/auth/credentials_test.go | 8 ++--- libs/auth/env_test.go | 4 +-- libs/cmdctx/config_used_test.go | 8 ++--- libs/cmdctx/workspace_client_test.go | 4 +-- libs/template/helpers_test.go | 4 +-- libs/template/renderer_test.go | 2 +- libs/template/writer_test.go | 2 +- 19 files changed, 66 insertions(+), 64 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 85b27748a66..637e7192776 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -123,6 +123,8 @@ parentPath = "/Workspace" + parentPath **RULE: Do not add defensive `nil` checks for values the caller or framework is documented to always provide.** If a check exists "just in case", either remove it or attach a comment explaining why the invariant might be violated. Direct engine resource methods (`DoCreate`, `DoUpdate`, `RemapState`, etc.) never receive nil receivers or state from the framework, so extra nil-guards there are dead code. +**RULE: Use a non-resolving TLD (`.test`, `.example`, `.invalid`, `.localhost`) for any test fixture host — `Config.Host`, `databricks.yml`'s `workspace.host`, `.databrickscfg`.** Real domains hit the SDK well-known endpoint resolver and can stall tests for ~5 minutes per call when the runner network can't fast-fail the lookup. The repo convention is `.test`. See PR #5125 for prior history. + Where a panic is genuinely possible (e.g. `reflect.Type.Elem()` on a non-pointer, division by an empty slice's length), validate at the entry point and return an error. # Error Handling diff --git a/bundle/config/validate/files_to_sync_test.go b/bundle/config/validate/files_to_sync_test.go index 1ee11bf7bcd..71a1dfaf5a7 100644 --- a/bundle/config/validate/files_to_sync_test.go +++ b/bundle/config/validate/files_to_sync_test.go @@ -63,7 +63,7 @@ func setupBundleForFilesToSyncTest(t *testing.T) *bundle.Bundle { m := mocks.NewMockWorkspaceClient(t) m.WorkspaceClient.Config = &sdkconfig.Config{ - Host: "https://foo.com", + Host: "https://foo.test", } // The initialization logic in [sync.New] performs a check on the destination path. diff --git a/bundle/deploy/terraform/util_test.go b/bundle/deploy/terraform/util_test.go index 59b0f03635f..752d8063012 100644 --- a/bundle/deploy/terraform/util_test.go +++ b/bundle/deploy/terraform/util_test.go @@ -75,7 +75,7 @@ func TestParseResourcesStateWithExistingStateFile(t *testing.T) { "storage": "dbfs:/123456", "target": "test_dev", "timeouts": null, - "url": "https://test.com" + "url": "https://test.test" }, "sensitive_attributes": [] } diff --git a/bundle/internal/schema/testdata/pass/job.yml b/bundle/internal/schema/testdata/pass/job.yml index ec447ba39ae..cab0824b0a3 100644 --- a/bundle/internal/schema/testdata/pass/job.yml +++ b/bundle/internal/schema/testdata/pass/job.yml @@ -2,7 +2,7 @@ bundle: name: a job workspace: - host: "https://myworkspace.com" + host: "https://myworkspace.test" root_path: /abc presets: diff --git a/bundle/internal/schema/testdata/pass/ml.yml b/bundle/internal/schema/testdata/pass/ml.yml index d2885b6412f..58473e813db 100644 --- a/bundle/internal/schema/testdata/pass/ml.yml +++ b/bundle/internal/schema/testdata/pass/ml.yml @@ -2,7 +2,7 @@ bundle: name: ML workspace: - host: "https://myworkspace.com" + host: "https://myworkspace.test" root_path: /abc presets: diff --git a/bundle/internal/schema/testdata/pass/pipeline.yml b/bundle/internal/schema/testdata/pass/pipeline.yml index 1b2b1a10f0f..7114563c22c 100644 --- a/bundle/internal/schema/testdata/pass/pipeline.yml +++ b/bundle/internal/schema/testdata/pass/pipeline.yml @@ -2,7 +2,7 @@ bundle: name: a pipeline workspace: - host: "https://myworkspace.com" + host: "https://myworkspace.test" root_path: /abc presets: diff --git a/bundle/run/pipeline_test.go b/bundle/run/pipeline_test.go index 8febf62e4dc..56457218468 100644 --- a/bundle/run/pipeline_test.go +++ b/bundle/run/pipeline_test.go @@ -69,7 +69,7 @@ func TestPipelineRunnerRestart(t *testing.T) { m := mocks.NewMockWorkspaceClient(t) m.WorkspaceClient.Config = &sdk_config.Config{ - Host: "https://test.com", + Host: "https://test.test", } b.SetWorkpaceClient(m.WorkspaceClient) diff --git a/cmd/auth/auth_test.go b/cmd/auth/auth_test.go index c54d550f016..fc7e5d533d4 100644 --- a/cmd/auth/auth_test.go +++ b/cmd/auth/auth_test.go @@ -70,23 +70,23 @@ func TestValidateProfileHostConflict(t *testing.T) { // through Cobra's lifecycle (PreRunE on login) and that the root command's // PersistentPreRunE is NOT shadowed (it initializes logging, IO, user agent). func TestProfileHostConflictViaCobra(t *testing.T) { - // Point at a config file that has "profile-1" with host https://www.host1.com. + // Point at a config file that has "profile-1" with host https://www.host1.test. t.Setenv("DATABRICKS_CONFIG_FILE", "./testdata/.databrickscfg") ctx := cmdctx.GenerateExecId(t.Context()) cli := root.New(ctx) cli.AddCommand(New()) - // Set args: auth login --profile profile-1 --host https://other.host.com + // Set args: auth login --profile profile-1 --host https://other.host.test cli.SetArgs([]string{ "auth", "login", "--profile", "profile-1", - "--host", "https://other.host.com", + "--host", "https://other.host.test", }) _, err := cli.ExecuteContextC(ctx) require.Error(t, err) - assert.Contains(t, err.Error(), `--profile "profile-1" has host "https://www.host1.com", which conflicts with --host "https://other.host.com"`) + assert.Contains(t, err.Error(), `--profile "profile-1" has host "https://www.host1.test", which conflicts with --host "https://other.host.test"`) assert.Contains(t, err.Error(), "Use --profile only to select a profile") } @@ -101,12 +101,12 @@ func TestProfileHostConflictTokenViaCobra(t *testing.T) { cli.SetArgs([]string{ "auth", "token", "--profile", "profile-1", - "--host", "https://other.host.com", + "--host", "https://other.host.test", }) _, err := cli.ExecuteContextC(ctx) require.Error(t, err) - assert.Contains(t, err.Error(), `--profile "profile-1" has host "https://www.host1.com", which conflicts with --host "https://other.host.com"`) + assert.Contains(t, err.Error(), `--profile "profile-1" has host "https://www.host1.test", which conflicts with --host "https://other.host.test"`) } // TestProfileHostCompatibleViaCobra verifies that matching --profile and --host @@ -122,7 +122,7 @@ func TestProfileHostCompatibleViaCobra(t *testing.T) { cli.SetArgs([]string{ "auth", "login", "--profile", "profile-1", - "--host", "https://www.host1.com", + "--host", "https://www.host1.test", }) _, err := cli.ExecuteContextC(ctx) diff --git a/cmd/auth/describe_test.go b/cmd/auth/describe_test.go index 1ee8d5122d3..ef654aae3d2 100644 --- a/cmd/auth/describe_test.go +++ b/cmd/auth/describe_test.go @@ -44,7 +44,7 @@ func TestGetWorkspaceAuthStatus(t *testing.T) { status, err := getAuthStatus(cmd, []string{}, showSensitive, func(cmd *cobra.Command, args []string) (*config.Config, bool, error) { err := config.ConfigAttributes.ResolveFromStringMap(cfg, map[string]string{ - "host": "https://test.com", + "host": "https://test.test", "token": "test-token", "auth_type": "azure-cli", }) @@ -55,7 +55,7 @@ func TestGetWorkspaceAuthStatus(t *testing.T) { require.NotNil(t, status) require.Equal(t, "success", status.Status) require.Equal(t, "test-user", status.Username) - require.Equal(t, "https://test.com", status.Details.Host) + require.Equal(t, "https://test.test", status.Details.Host) require.Equal(t, "azure-cli", status.Details.AuthType) require.Equal(t, "azure-cli", status.Details.Configuration["auth_type"].Value) @@ -97,7 +97,7 @@ func TestGetWorkspaceAuthStatusError(t *testing.T) { status, err := getAuthStatus(cmd, []string{}, showSensitive, func(cmd *cobra.Command, args []string) (*config.Config, bool, error) { err = config.ConfigAttributes.ResolveFromStringMap(cfg, map[string]string{ - "host": "https://test.com", + "host": "https://test.test", "token": "test-token", "auth_type": "azure-cli", }) @@ -146,7 +146,7 @@ func TestGetWorkspaceAuthStatusSensitive(t *testing.T) { status, err := getAuthStatus(cmd, []string{}, showSensitive, func(cmd *cobra.Command, args []string) (*config.Config, bool, error) { err = config.ConfigAttributes.ResolveFromStringMap(cfg, map[string]string{ - "host": "https://test.com", + "host": "https://test.test", "token": "test-token", "auth_type": "azure-cli", }) @@ -196,7 +196,7 @@ func TestGetAccountAuthStatus(t *testing.T) { err = config.ConfigAttributes.ResolveFromStringMap(cfg, map[string]string{ "account_id": "test-account-id", "username": "test-user", - "host": "https://test.com", + "host": "https://test.test", "token": "test-token", "auth_type": "azure-cli", }) @@ -207,7 +207,7 @@ func TestGetAccountAuthStatus(t *testing.T) { require.Equal(t, "success", status.Status) require.Equal(t, "test-user", status.Username) - require.Equal(t, "https://test.com", status.Details.Host) + require.Equal(t, "https://test.test", status.Details.Host) require.Equal(t, "azure-cli", status.Details.AuthType) require.Equal(t, "test-account-id", status.AccountID) diff --git a/cmd/auth/login_test.go b/cmd/auth/login_test.go index e057c979c3b..d209c511154 100644 --- a/cmd/auth/login_test.go +++ b/cmd/auth/login_test.go @@ -145,10 +145,10 @@ func TestSetHost(t *testing.T) { assert.Equal(t, "val from --host", authArguments.Host) // Test setting host from flag with trailing slash is stripped - authArguments.Host = "https://www.host1.com/" + authArguments.Host = "https://www.host1.test/" err = setHostAndAccountId(ctx, profile1, &authArguments, []string{}) assert.NoError(t, err) - assert.Equal(t, "https://www.host1.com", authArguments.Host) + assert.Equal(t, "https://www.host1.test", authArguments.Host) // Test setting host from argument authArguments.Host = "" @@ -158,21 +158,21 @@ func TestSetHost(t *testing.T) { // Test setting host from argument with trailing slash is stripped authArguments.Host = "" - err = setHostAndAccountId(ctx, profile1, &authArguments, []string{"https://www.host1.com/"}) + err = setHostAndAccountId(ctx, profile1, &authArguments, []string{"https://www.host1.test/"}) assert.NoError(t, err) - assert.Equal(t, "https://www.host1.com", authArguments.Host) + assert.Equal(t, "https://www.host1.test", authArguments.Host) // Test setting host from profile authArguments.Host = "" err = setHostAndAccountId(ctx, profile1, &authArguments, []string{}) assert.NoError(t, err) - assert.Equal(t, "https://www.host1.com", authArguments.Host) + assert.Equal(t, "https://www.host1.test", authArguments.Host) // Test setting host from profile authArguments.Host = "" err = setHostAndAccountId(ctx, profile2, &authArguments, []string{}) assert.NoError(t, err) - assert.Equal(t, "https://www.host2.com", authArguments.Host) + assert.Equal(t, "https://www.host2.test", authArguments.Host) // Test host is not set. Should prompt. authArguments.Host = "" @@ -275,14 +275,14 @@ func TestLoadProfileByNameAndClusterID(t *testing.T) { name: "cluster profile", profile: "cluster-profile", configFileEnv: "./testdata/.databrickscfg", - expectedHost: "https://www.host2.com", + expectedHost: "https://www.host2.test", expectedClusterID: "cluster-from-config", }, { name: "profile from home directory (existing)", profile: "cluster-profile", homeDirOverride: "testdata", - expectedHost: "https://www.host2.com", + expectedHost: "https://www.host2.test", expectedClusterID: "cluster-from-config", }, { diff --git a/cmd/auth/testdata/.databrickscfg b/cmd/auth/testdata/.databrickscfg index fe836a53b4c..acd227d515e 100644 --- a/cmd/auth/testdata/.databrickscfg +++ b/cmd/auth/testdata/.databrickscfg @@ -1,15 +1,15 @@ [profile-1] -host = https://www.host1.com +host = https://www.host1.test [profile-2] -host = https://www.host2.com +host = https://www.host2.test [account-profile] host = https://accounts.cloud.databricks.com account_id = id-from-profile [cluster-profile] -host = https://www.host2.com +host = https://www.host2.test cluster_id = cluster-from-config [invalid-profile] diff --git a/cmd/root/bundle_test.go b/cmd/root/bundle_test.go index 87401150fb8..4ab2f1463e0 100644 --- a/cmd/root/bundle_test.go +++ b/cmd/root/bundle_test.go @@ -26,7 +26,7 @@ func setupDatabricksCfg(t *testing.T) { homeEnvVar = "USERPROFILE" } - cfg := []byte("[PROFILE-1]\nhost = https://a.com\ntoken = a\n[PROFILE-2]\nhost = https://a.com\ntoken = b\n") + cfg := []byte("[PROFILE-1]\nhost = https://a.test\ntoken = a\n[PROFILE-2]\nhost = https://a.test\ntoken = b\n") err := os.WriteFile(filepath.Join(tempHomeDir, ".databrickscfg"), cfg, 0o644) assert.NoError(t, err) @@ -95,17 +95,17 @@ func TestBundleConfigureDefault(t *testing.T) { } cmd := emptyCommand(t) - diags := setupWithHost(t, cmd, "https://x.com") + diags := setupWithHost(t, cmd, "https://x.test") require.Empty(t, diags) - assert.Equal(t, "https://x.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://x.test", cmdctx.ConfigUsed(cmd.Context()).Host) } func TestBundleConfigureWithMultipleMatches(t *testing.T) { testutil.CleanupEnvironment(t) cmd := emptyCommand(t) - diags := setupWithHost(t, cmd, "https://a.com") + diags := setupWithHost(t, cmd, "https://a.test") require.Len(t, diags, 1) assert.Contains(t, diags[0].Summary, "multiple profiles matched: PROFILE-1, PROFILE-2") assert.Contains(t, diags[0].Summary, "Matching workspace profiles: PROFILE-1, PROFILE-2") @@ -119,7 +119,7 @@ func TestBundleConfigureWithNonExistentProfileFlag(t *testing.T) { err := cmd.Flag("profile").Value.Set("NOEXIST") require.NoError(t, err) - diags := setupWithHost(t, cmd, "https://x.com") + diags := setupWithHost(t, cmd, "https://x.test") require.Len(t, diags, 1) assert.Contains(t, diags[0].Summary, "has no NOEXIST profile configured") } @@ -131,8 +131,8 @@ func TestBundleConfigureWithMismatchedProfile(t *testing.T) { err := cmd.Flag("profile").Value.Set("PROFILE-1") require.NoError(t, err) - diags := setupWithHost(t, cmd, "https://x.com") - assert.Equal(t, []diag.Diagnostic{{Summary: "cannot resolve bundle auth configuration: the host in the profile (https://a.com) doesn’t match the host configured in the bundle (https://x.com)"}}, diags) + diags := setupWithHost(t, cmd, "https://x.test") + assert.Equal(t, []diag.Diagnostic{{Summary: "cannot resolve bundle auth configuration: the host in the profile (https://a.test) doesn’t match the host configured in the bundle (https://x.test)"}}, diags) } func TestBundleConfigureWithCorrectProfile(t *testing.T) { @@ -141,10 +141,10 @@ func TestBundleConfigureWithCorrectProfile(t *testing.T) { cmd := emptyCommand(t) err := cmd.Flag("profile").Value.Set("PROFILE-1") require.NoError(t, err) - diags := setupWithHost(t, cmd, "https://a.com") + diags := setupWithHost(t, cmd, "https://a.test") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "PROFILE-1", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -154,8 +154,8 @@ func TestBundleConfigureWithMismatchedProfileEnvVariable(t *testing.T) { t.Setenv("DATABRICKS_CONFIG_PROFILE", "PROFILE-1") cmd := emptyCommand(t) - diags := setupWithHost(t, cmd, "https://x.com") - assert.Equal(t, []diag.Diagnostic{{Summary: "cannot resolve bundle auth configuration: the host in the profile (https://a.com) doesn’t match the host configured in the bundle (https://x.com)"}}, diags) + diags := setupWithHost(t, cmd, "https://x.test") + assert.Equal(t, []diag.Diagnostic{{Summary: "cannot resolve bundle auth configuration: the host in the profile (https://a.test) doesn’t match the host configured in the bundle (https://x.test)"}}, diags) } func TestBundleConfigureWithProfileFlagAndEnvVariable(t *testing.T) { @@ -166,9 +166,9 @@ func TestBundleConfigureWithProfileFlagAndEnvVariable(t *testing.T) { err := cmd.Flag("profile").Value.Set("PROFILE-1") require.NoError(t, err) - diags := setupWithHost(t, cmd, "https://a.com") + diags := setupWithHost(t, cmd, "https://a.test") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "PROFILE-1", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -180,7 +180,7 @@ func TestBundleConfigureProfileDefault(t *testing.T) { diags := setupWithProfile(t, cmd, "PROFILE-1") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "a", cmdctx.ConfigUsed(cmd.Context()).Token) assert.Equal(t, "PROFILE-1", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -195,7 +195,7 @@ func TestBundleConfigureProfileFlag(t *testing.T) { diags := setupWithProfile(t, cmd, "PROFILE-1") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "b", cmdctx.ConfigUsed(cmd.Context()).Token) assert.Equal(t, "PROFILE-2", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -209,7 +209,7 @@ func TestBundleConfigureProfileEnvVariable(t *testing.T) { diags := setupWithProfile(t, cmd, "PROFILE-1") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "b", cmdctx.ConfigUsed(cmd.Context()).Token) assert.Equal(t, "PROFILE-2", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -225,7 +225,7 @@ func TestBundleConfigureProfileFlagAndEnvVariable(t *testing.T) { diags := setupWithProfile(t, cmd, "PROFILE-1") require.Empty(t, diags) - assert.Equal(t, "https://a.com", cmdctx.ConfigUsed(cmd.Context()).Host) + assert.Equal(t, "https://a.test", cmdctx.ConfigUsed(cmd.Context()).Host) assert.Equal(t, "b", cmdctx.ConfigUsed(cmd.Context()).Token) assert.Equal(t, "PROFILE-2", cmdctx.ConfigUsed(cmd.Context()).Profile) } @@ -240,7 +240,7 @@ func TestBundleConfigureMultiMatchInteractivePromptFires(t *testing.T) { contents := ` workspace: - host: "https://a.com" + host: "https://a.test" ` err := os.WriteFile(filepath.Join(rootPath, "databricks.yml"), []byte(contents), 0o644) require.NoError(t, err) diff --git a/libs/auth/credentials_test.go b/libs/auth/credentials_test.go index 3ce2e4b0c4e..20c55e4d056 100644 --- a/libs/auth/credentials_test.go +++ b/libs/auth/credentials_test.go @@ -96,18 +96,18 @@ func TestAuthArgumentsFromConfig(t *testing.T) { { name: "all fields", cfg: &config.Config{ - Host: "https://myhost.com", + Host: "https://myhost.test", AccountID: "acc-123", WorkspaceID: "ws-456", Profile: "my-profile", - DiscoveryURL: "https://myhost.com/oidc/accounts/acc-123/.well-known/oauth-authorization-server", + DiscoveryURL: "https://myhost.test/oidc/accounts/acc-123/.well-known/oauth-authorization-server", }, want: AuthArguments{ - Host: "https://myhost.com", + Host: "https://myhost.test", AccountID: "acc-123", WorkspaceID: "ws-456", Profile: "my-profile", - DiscoveryURL: "https://myhost.com/oidc/accounts/acc-123/.well-known/oauth-authorization-server", + DiscoveryURL: "https://myhost.test/oidc/accounts/acc-123/.well-known/oauth-authorization-server", }, }, } diff --git a/libs/auth/env_test.go b/libs/auth/env_test.go index b1a41187f7d..4cb706c7795 100644 --- a/libs/auth/env_test.go +++ b/libs/auth/env_test.go @@ -10,7 +10,7 @@ import ( func TestAuthEnv(t *testing.T) { in := &config.Config{ Profile: "myprofile", - Host: "https://test.com", + Host: "https://test.test", Token: "test-token", Password: "test-password", MetadataServiceURL: "http://somurl.com", @@ -25,7 +25,7 @@ func TestAuthEnv(t *testing.T) { expected := map[string]string{ "DATABRICKS_CONFIG_PROFILE": "myprofile", - "DATABRICKS_HOST": "https://test.com", + "DATABRICKS_HOST": "https://test.test", "DATABRICKS_TOKEN": "test-token", "DATABRICKS_PASSWORD": "test-password", "DATABRICKS_METADATA_SERVICE_URL": "http://somurl.com", diff --git a/libs/cmdctx/config_used_test.go b/libs/cmdctx/config_used_test.go index 4a8ea02cbb0..f99febf8046 100644 --- a/libs/cmdctx/config_used_test.go +++ b/libs/cmdctx/config_used_test.go @@ -9,7 +9,7 @@ import ( func TestCommandConfigUsed(t *testing.T) { cfg := &config.Config{ - Host: "https://test.com", + Host: "https://test.test", } ctx := t.Context() @@ -25,12 +25,12 @@ func TestCommandConfigUsed(t *testing.T) { assert.Same(t, c, ConfigUsed(ctx)) // The config should have the correct configuration. - assert.Equal(t, "https://test.com", ConfigUsed(ctx).Host) + assert.Equal(t, "https://test.test", ConfigUsed(ctx).Host) // Second call should update the config used. cfg2 := &config.Config{ - Host: "https://test2.com", + Host: "https://test2.test", } ctx = SetConfigUsed(ctx, cfg2) - assert.Equal(t, "https://test2.com", ConfigUsed(ctx).Host) + assert.Equal(t, "https://test2.test", ConfigUsed(ctx).Host) } diff --git a/libs/cmdctx/workspace_client_test.go b/libs/cmdctx/workspace_client_test.go index 03ef9631862..cd3959602f5 100644 --- a/libs/cmdctx/workspace_client_test.go +++ b/libs/cmdctx/workspace_client_test.go @@ -13,7 +13,7 @@ func TestCommandWorkspaceClient(t *testing.T) { ctx := t.Context() client := &databricks.WorkspaceClient{ Config: &config.Config{ - Host: "https://test.com", + Host: "https://test.test", }, } @@ -29,7 +29,7 @@ func TestCommandWorkspaceClient(t *testing.T) { assert.Same(t, w, cmdctx.WorkspaceClient(ctx)) // The client should have the correct configuration. - assert.Equal(t, "https://test.com", cmdctx.WorkspaceClient(ctx).Config.Host) + assert.Equal(t, "https://test.test", cmdctx.WorkspaceClient(ctx).Config.Host) // Second call should panic. assert.Panics(t, func() { diff --git a/libs/template/helpers_test.go b/libs/template/helpers_test.go index fed3e336a5e..674dbe7bb34 100644 --- a/libs/template/helpers_test.go +++ b/libs/template/helpers_test.go @@ -141,7 +141,7 @@ func TestWorkspaceHost(t *testing.T) { w := &databricks.WorkspaceClient{ Config: &workspaceConfig.Config{ - Host: "https://myhost.com", + Host: "https://myhost.test", }, } ctx = cmdctx.SetWorkspaceClient(ctx, w) @@ -155,7 +155,7 @@ func TestWorkspaceHost(t *testing.T) { assert.NoError(t, err) assert.Len(t, r.files, 1) - assert.Contains(t, string(r.files[0].(*inMemoryFile).content), "https://myhost.com") + assert.Contains(t, string(r.files[0].(*inMemoryFile).content), "https://myhost.test") assert.Contains(t, string(r.files[0].(*inMemoryFile).content), "i3.xlarge") } diff --git a/libs/template/renderer_test.go b/libs/template/renderer_test.go index d73271c507a..bb839628627 100644 --- a/libs/template/renderer_test.go +++ b/libs/template/renderer_test.go @@ -34,7 +34,7 @@ func assertBuiltinTemplateValid(t *testing.T, template string, settings map[stri require.NoError(t, err) w := &databricks.WorkspaceClient{ - Config: &workspaceConfig.Config{Host: "https://myhost.com"}, + Config: &workspaceConfig.Config{Host: "https://myhost.test"}, } // Prepare helpers diff --git a/libs/template/writer_test.go b/libs/template/writer_test.go index 0fa2931f81f..33a3561cc0f 100644 --- a/libs/template/writer_test.go +++ b/libs/template/writer_test.go @@ -32,7 +32,7 @@ func TestDefaultWriterConfigureOnDBR(t *testing.T) { ctx := dbr.MockRuntime(t.Context(), dbr.Environment{IsDbr: true, Version: "15.4"}) ctx = cmdctx.SetWorkspaceClient(ctx, &databricks.WorkspaceClient{ - Config: &workspaceConfig.Config{Host: "https://myhost.com"}, + Config: &workspaceConfig.Config{Host: "https://myhost.test"}, }) w := &defaultWriter{} err := w.Configure(ctx, "/foo/bar", "/Workspace/out/abc") From 59f35070923fcf69f21e51296a2684bbc767ee7d Mon Sep 17 00:00:00 2001 From: Pieter Noordhuis Date: Wed, 6 May 2026 11:43:07 +0200 Subject: [PATCH 2/2] docs: cite RFC 2606 for the .test TLD rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the rule self-explaining: .test (and .example/.invalid/.localhost) are reserved by RFC 2606 §2 specifically so they don't resolve in real DNS, which is exactly the property we want for test fixture hosts. Co-authored-by: Isaac --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 637e7192776..3cdcc3406ad 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -123,7 +123,7 @@ parentPath = "/Workspace" + parentPath **RULE: Do not add defensive `nil` checks for values the caller or framework is documented to always provide.** If a check exists "just in case", either remove it or attach a comment explaining why the invariant might be violated. Direct engine resource methods (`DoCreate`, `DoUpdate`, `RemapState`, etc.) never receive nil receivers or state from the framework, so extra nil-guards there are dead code. -**RULE: Use a non-resolving TLD (`.test`, `.example`, `.invalid`, `.localhost`) for any test fixture host — `Config.Host`, `databricks.yml`'s `workspace.host`, `.databrickscfg`.** Real domains hit the SDK well-known endpoint resolver and can stall tests for ~5 minutes per call when the runner network can't fast-fail the lookup. The repo convention is `.test`. See PR #5125 for prior history. +**RULE: Use a non-resolving TLD reserved by [RFC 2606 §2](https://datatracker.ietf.org/doc/html/rfc2606#section-2) (`.test`, `.example`, `.invalid`, `.localhost`) for any test fixture host — `Config.Host`, `databricks.yml`'s `workspace.host`, `.databrickscfg`.** Real domains hit the SDK well-known endpoint resolver and can stall tests for ~5 minutes per call when the runner network can't fast-fail the lookup. The repo convention is `.test` (the TLD RFC 2606 specifically reserves "for use in testing"). See PR #5125 for prior history. Where a panic is genuinely possible (e.g. `reflect.Type.Elem()` on a non-pointer, division by an empty slice's length), validate at the entry point and return an error.