Skip to content

Commit

Permalink
terraform: Add ephemeral resources to the graph, and validate refs
Browse files Browse the repository at this point in the history
This is not yet sufficient to actually open/renew/close ephemeral resource
instances, and so as of this commit a module including ephemeral resources
will misbehave. Further work in subsequent commits.
  • Loading branch information
apparentlymart committed Apr 30, 2024
1 parent cd2c886 commit aaa345f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 5 deletions.
3 changes: 3 additions & 0 deletions internal/providers/schemas.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ func (ss ProviderSchema) SchemaForResourceType(mode addrs.ResourceMode, typeName
case addrs.DataResourceMode:
// Data resources don't have schema versions right now, since state is discarded for each refresh
return ss.DataSources[typeName].Block, 0
case addrs.EphemeralResourceMode:
// Ephemeral resources don't have schema versions because their objects never outlive a single phase
return ss.EphemeralResourceTypes[typeName].Block, 0
default:
// Shouldn't happen, because the above cases are comprehensive.
return nil, 0
Expand Down
23 changes: 19 additions & 4 deletions internal/terraform/evaluate_valid.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,15 @@ func staticValidateResourceReference(modCfg *configs.Config, addr addrs.Resource
var diags tfdiags.Diagnostics

var modeAdjective string
modeArticleUpper := "A"
switch addr.Mode {
case addrs.ManagedResourceMode:
modeAdjective = "managed"
case addrs.DataResourceMode:
modeAdjective = "data"
case addrs.EphemeralResourceMode:
modeAdjective = "ephemeral"
modeArticleUpper = "An"
default:
// should never happen
modeAdjective = "<invalid-mode>"
Expand All @@ -223,8 +227,14 @@ func staticValidateResourceReference(modCfg *configs.Config, addr addrs.Resource
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: `Reference to undeclared resource`,
Detail: fmt.Sprintf(`A %s resource %q %q has not been declared in %s.%s`, modeAdjective, addr.Type, addr.Name, moduleConfigDisplayAddr(modCfg.Path), suggestion),
Subject: rng.ToHCL().Ptr(),
Detail: fmt.Sprintf(
`%s %s resource %q %q has not been declared in %s.%s`,
modeArticleUpper, modeAdjective,
addr.Type, addr.Name,
moduleConfigDisplayAddr(modCfg.Path),
suggestion,
),
Subject: rng.ToHCL().Ptr(),
})
return diags
}
Expand Down Expand Up @@ -259,8 +269,13 @@ func staticValidateResourceReference(modCfg *configs.Config, addr addrs.Resource
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: `Invalid resource type`,
Detail: fmt.Sprintf(`A %s resource type %q is not supported by provider %q.`, modeAdjective, addr.Type, providerFqn.String()),
Subject: rng.ToHCL().Ptr(),
Detail: fmt.Sprintf(
`%s %s resource type %q is not supported by provider %q.`,
modeArticleUpper, modeAdjective,
addr.Type,
providerFqn.String(),
),
Subject: rng.ToHCL().Ptr(),
})
return diags
}
Expand Down
13 changes: 13 additions & 0 deletions internal/terraform/evaluate_valid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ For example, to correlate with indices of a referring resource, use:
Ref: "data.boop_data.boop_nested",
WantErr: `Reference to scoped resource: The referenced data resource "boop_data" "boop_nested" is not available from this context.`,
},
{
Ref: "ephemeral.beep.boop",
WantErr: ``,
},
{
Ref: "ephemeral.beep.nonexistant",
WantErr: `Reference to undeclared resource: An ephemeral resource "beep" "nonexistant" has not been declared in the root module.`,
},
{
Ref: "data.boop_data.boop_nested",
WantErr: ``,
Expand Down Expand Up @@ -119,6 +127,11 @@ For example, to correlate with indices of a referring resource, use:
},
},
},
EphemeralResourceTypes: map[string]providers.Schema{
"beep": {
Block: &configschema.Block{},
},
},
},
}),
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ terraform {
source = "foobar/beep" # intentional mismatch between local name and type
}
}
# TODO: Remove this if ephemeral values / resources get stabilized. If this
# experiment is removed without stabilization, also remove the
# "ephemeral" block below and the test cases it's supporting.
experiments = [ephemeral_values]
}

resource "aws_instance" "no_count" {
Expand All @@ -22,6 +26,10 @@ resource "boop_whatever" "nope" {
data "beep" "boop" {
}

ephemeral "beep" "boop" {
provider = boop
}

check "foo" {
data "boop_data" "boop_nested" {}

Expand Down
5 changes: 4 additions & 1 deletion internal/terraform/transform_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,16 @@ func (t *ConfigTransformer) transformSingle(g *Graph, config *configs.Config) er
module := config.Module
log.Printf("[TRACE] ConfigTransformer: Starting for path: %v", path)

allResources := make([]*configs.Resource, 0, len(module.ManagedResources)+len(module.DataResources))
allResources := make([]*configs.Resource, 0, len(module.ManagedResources)+len(module.DataResources)+len(module.EphemeralResources))
for _, r := range module.ManagedResources {
allResources = append(allResources, r)
}
for _, r := range module.DataResources {
allResources = append(allResources, r)
}
for _, r := range module.EphemeralResources {
allResources = append(allResources, r)
}

// Take a copy of the import targets, so we can edit them as we go.
// Only include import targets that are targeting the current module.
Expand Down

0 comments on commit aaa345f

Please sign in to comment.