Skip to content
Closed
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
11 changes: 11 additions & 0 deletions bundle/direct/bundle_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,17 @@ func (b *DeploymentBundle) makePlan(ctx context.Context, configRoot *config.Root
pat,
func(p dyn.Path, v dyn.Value) (dyn.Value, error) {
s := p.String()
// Resource keys are used as identifiers in plan paths and looked up
// via dyn.NewPathFromString, which splits on '.'. A variable reference
// in a resource key (e.g. resources.schemas.${var.schema}) cannot be
// resolved at this stage and would be split into multiple path
// components, causing a nil dereference downstream in PrepareState.
// Reject early with an actionable error.
for _, c := range p {
if dynvar.ContainsVariableReference(c.Key()) {
return v, fmt.Errorf("resource key %q cannot contain variable references; use a literal key and parameterize fields like 'name' instead", s)
}
}
resourceType := config.GetResourceTypeFromKey(s)
if resourceType == "" {
return v, fmt.Errorf("cannot parse resource key: %q", s)
Expand Down
30 changes: 30 additions & 0 deletions bundle/direct/bundle_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ package direct
import (
"testing"

"github.com/databricks/cli/bundle/config"
"github.com/databricks/cli/bundle/config/resources"
"github.com/databricks/cli/bundle/direct/dresources"
"github.com/databricks/cli/bundle/direct/dstate"
"github.com/databricks/cli/libs/dyn"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestDynPathToStructPath(t *testing.T) {
Expand Down Expand Up @@ -35,3 +40,28 @@ func TestDynPathToStructPath(t *testing.T) {
assert.Equal(t, tc.expected, node.String())
}
}

// TestMakePlanRejectsVariableInResourceKey verifies that a variable reference
// in a resource map key (e.g. resources.schemas.${var.schema}) is rejected
// with a clear error rather than panicking with a nil pointer dereference
// inside PrepareState. Regression test for issue #5098.
func TestMakePlanRejectsVariableInResourceKey(t *testing.T) {
rootCfg := config.Root{
Resources: config.Resources{
Schemas: map[string]*resources.Schema{
"${var.schema}": {},
},
},
}
require.NoError(t, rootCfg.Mutate(func(v dyn.Value) (dyn.Value, error) { return v, nil }))

db := dstate.NewDatabase("", 0)
adapters, err := dresources.InitAll(nil)
require.NoError(t, err)
b := &DeploymentBundle{Adapters: adapters}

_, err = b.makePlan(t.Context(), &rootCfg, &db)
require.Error(t, err)
assert.Contains(t, err.Error(), "${var.schema}")
assert.Contains(t, err.Error(), "cannot contain variable references")
}