config: "ResourceMode" concept for resources
Previously resources were assumed to always support the full set of create, read, update and delete operations, and Terraform's resource management lifecycle. Data sources introduce a new kind of resource that only supports the "read" operation. To support this, a new "Mode" field is added to the Resource concept within the config layer, which can be set to ManagedResourceMode (to indicate the only mode previously possible) or DataResourceMode (to indicate that only "read" is supported). To support both managed and data resources in the tests, the stringification of resources in config_string.go is adjusted slightly to use the Id() method rather than the unusual type[name] serialization from before, causing a simple mechanical adjustment to the loader tests' expected result strings.
This commit is contained in:
parent
f331240601
commit
fc4fa10981
|
@ -67,9 +67,11 @@ type ProviderConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A resource represents a single Terraform resource in the configuration.
|
// A resource represents a single Terraform resource in the configuration.
|
||||||
// A Terraform resource is something that represents some component that
|
// A Terraform resource is something that supports some or all of the
|
||||||
// can be created and managed, and has some properties associated with it.
|
// usual "create, read, update, delete" operations, depending on
|
||||||
|
// the given Mode.
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
|
Mode ResourceMode // which operations the resource supports
|
||||||
Name string
|
Name string
|
||||||
Type string
|
Type string
|
||||||
RawCount *RawConfig
|
RawCount *RawConfig
|
||||||
|
@ -85,6 +87,7 @@ type Resource struct {
|
||||||
// interpolation.
|
// interpolation.
|
||||||
func (r *Resource) Copy() *Resource {
|
func (r *Resource) Copy() *Resource {
|
||||||
n := &Resource{
|
n := &Resource{
|
||||||
|
Mode: r.Mode,
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
Type: r.Type,
|
Type: r.Type,
|
||||||
RawCount: r.RawCount.Copy(),
|
RawCount: r.RawCount.Copy(),
|
||||||
|
@ -210,7 +213,14 @@ func (r *Resource) Count() (int, error) {
|
||||||
|
|
||||||
// A unique identifier for this resource.
|
// A unique identifier for this resource.
|
||||||
func (r *Resource) Id() string {
|
func (r *Resource) Id() string {
|
||||||
|
switch r.Mode {
|
||||||
|
case ManagedResourceMode:
|
||||||
return fmt.Sprintf("%s.%s", r.Type, r.Name)
|
return fmt.Sprintf("%s.%s", r.Type, r.Name)
|
||||||
|
case DataResourceMode:
|
||||||
|
return fmt.Sprintf("data.%s.%s", r.Type, r.Name)
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("unknown resource mode %s", r.Mode))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate does some basic semantic checking of the configuration.
|
// Validate does some basic semantic checking of the configuration.
|
||||||
|
@ -804,13 +814,14 @@ func (c *ProviderConfig) mergerMerge(m merger) merger {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) mergerName() string {
|
func (r *Resource) mergerName() string {
|
||||||
return fmt.Sprintf("%s.%s", r.Type, r.Name)
|
return r.Id()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Resource) mergerMerge(m merger) merger {
|
func (r *Resource) mergerMerge(m merger) merger {
|
||||||
r2 := m.(*Resource)
|
r2 := m.(*Resource)
|
||||||
|
|
||||||
result := *r
|
result := *r
|
||||||
|
result.Mode = r2.Mode
|
||||||
result.Name = r2.Name
|
result.Name = r2.Name
|
||||||
result.Type = r2.Type
|
result.Type = r2.Type
|
||||||
result.RawConfig = result.RawConfig.merge(r2.RawConfig)
|
result.RawConfig = result.RawConfig.merge(r2.RawConfig)
|
||||||
|
|
|
@ -178,7 +178,7 @@ func resourcesStr(rs []*Resource) string {
|
||||||
ks := make([]string, 0, len(rs))
|
ks := make([]string, 0, len(rs))
|
||||||
mapping := make(map[string]int)
|
mapping := make(map[string]int)
|
||||||
for i, r := range rs {
|
for i, r := range rs {
|
||||||
k := fmt.Sprintf("%s[%s]", r.Type, r.Name)
|
k := r.Id()
|
||||||
ks = append(ks, k)
|
ks = append(ks, k)
|
||||||
mapping[k] = i
|
mapping[k] = i
|
||||||
}
|
}
|
||||||
|
@ -190,9 +190,8 @@ func resourcesStr(rs []*Resource) string {
|
||||||
for _, i := range order {
|
for _, i := range order {
|
||||||
r := rs[i]
|
r := rs[i]
|
||||||
result += fmt.Sprintf(
|
result += fmt.Sprintf(
|
||||||
"%s[%s] (x%s)\n",
|
"%s (x%s)\n",
|
||||||
r.Type,
|
r.Id(),
|
||||||
r.Name,
|
|
||||||
r.RawCount.Value())
|
r.RawCount.Value())
|
||||||
|
|
||||||
ks := make([]string, 0, len(r.RawConfig.Raw))
|
ks := make([]string, 0, len(r.RawConfig.Raw))
|
||||||
|
|
|
@ -566,6 +566,7 @@ func loadResourcesHcl(list *ast.ObjectList) ([]*Resource, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
result = append(result, &Resource{
|
result = append(result, &Resource{
|
||||||
|
Mode: ManagedResourceMode,
|
||||||
Name: k,
|
Name: k,
|
||||||
Type: t,
|
Type: t,
|
||||||
RawCount: countConfig,
|
RawCount: countConfig,
|
||||||
|
|
|
@ -742,13 +742,13 @@ func TestLoad_jsonAttributes(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const jsonAttributeStr = `
|
const jsonAttributeStr = `
|
||||||
cloudstack_firewall[test] (x1)
|
cloudstack_firewall.test (x1)
|
||||||
ipaddress
|
ipaddress
|
||||||
rule
|
rule
|
||||||
`
|
`
|
||||||
|
|
||||||
const windowsHeredocResourcesStr = `
|
const windowsHeredocResourcesStr = `
|
||||||
aws_instance[test] (x1)
|
aws_instance.test (x1)
|
||||||
user_data
|
user_data
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -759,17 +759,17 @@ aws
|
||||||
`
|
`
|
||||||
|
|
||||||
const heredocResourcesStr = `
|
const heredocResourcesStr = `
|
||||||
aws_iam_policy[policy] (x1)
|
aws_iam_policy.policy (x1)
|
||||||
description
|
description
|
||||||
name
|
name
|
||||||
path
|
path
|
||||||
policy
|
policy
|
||||||
aws_instance[heredocwithnumbers] (x1)
|
aws_instance.heredocwithnumbers (x1)
|
||||||
ami
|
ami
|
||||||
provisioners
|
provisioners
|
||||||
local-exec
|
local-exec
|
||||||
command
|
command
|
||||||
aws_instance[test] (x1)
|
aws_instance.test (x1)
|
||||||
ami
|
ami
|
||||||
provisioners
|
provisioners
|
||||||
remote-exec
|
remote-exec
|
||||||
|
@ -777,7 +777,7 @@ aws_instance[test] (x1)
|
||||||
`
|
`
|
||||||
|
|
||||||
const escapedquotesResourcesStr = `
|
const escapedquotesResourcesStr = `
|
||||||
aws_instance[quotes] (x1)
|
aws_instance.quotes (x1)
|
||||||
ami
|
ami
|
||||||
vars
|
vars
|
||||||
user: var.ami
|
user: var.ami
|
||||||
|
@ -800,7 +800,7 @@ do
|
||||||
`
|
`
|
||||||
|
|
||||||
const basicResourcesStr = `
|
const basicResourcesStr = `
|
||||||
aws_instance[db] (x1)
|
aws_instance.db (x1)
|
||||||
VPC
|
VPC
|
||||||
security_groups
|
security_groups
|
||||||
provisioners
|
provisioners
|
||||||
|
@ -811,7 +811,7 @@ aws_instance[db] (x1)
|
||||||
aws_instance.web
|
aws_instance.web
|
||||||
vars
|
vars
|
||||||
resource: aws_security_group.firewall.*.id
|
resource: aws_security_group.firewall.*.id
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
network_interface
|
network_interface
|
||||||
security_groups
|
security_groups
|
||||||
|
@ -822,7 +822,7 @@ aws_instance[web] (x1)
|
||||||
vars
|
vars
|
||||||
resource: aws_security_group.firewall.foo
|
resource: aws_security_group.firewall.foo
|
||||||
user: var.foo
|
user: var.foo
|
||||||
aws_security_group[firewall] (x5)
|
aws_security_group.firewall (x5)
|
||||||
`
|
`
|
||||||
|
|
||||||
const basicVariablesStr = `
|
const basicVariablesStr = `
|
||||||
|
@ -854,18 +854,18 @@ do
|
||||||
`
|
`
|
||||||
|
|
||||||
const dirBasicResourcesStr = `
|
const dirBasicResourcesStr = `
|
||||||
aws_instance[db] (x1)
|
aws_instance.db (x1)
|
||||||
security_groups
|
security_groups
|
||||||
vars
|
vars
|
||||||
resource: aws_security_group.firewall.*.id
|
resource: aws_security_group.firewall.*.id
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
network_interface
|
network_interface
|
||||||
security_groups
|
security_groups
|
||||||
vars
|
vars
|
||||||
resource: aws_security_group.firewall.foo
|
resource: aws_security_group.firewall.foo
|
||||||
user: var.foo
|
user: var.foo
|
||||||
aws_security_group[firewall] (x5)
|
aws_security_group.firewall (x5)
|
||||||
`
|
`
|
||||||
|
|
||||||
const dirBasicVariablesStr = `
|
const dirBasicVariablesStr = `
|
||||||
|
@ -891,10 +891,10 @@ do
|
||||||
`
|
`
|
||||||
|
|
||||||
const dirOverrideResourcesStr = `
|
const dirOverrideResourcesStr = `
|
||||||
aws_instance[db] (x1)
|
aws_instance.db (x1)
|
||||||
ami
|
ami
|
||||||
security_groups
|
security_groups
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
foo
|
foo
|
||||||
network_interface
|
network_interface
|
||||||
|
@ -902,7 +902,7 @@ aws_instance[web] (x1)
|
||||||
vars
|
vars
|
||||||
resource: aws_security_group.firewall.foo
|
resource: aws_security_group.firewall.foo
|
||||||
user: var.foo
|
user: var.foo
|
||||||
aws_security_group[firewall] (x5)
|
aws_security_group.firewall (x5)
|
||||||
`
|
`
|
||||||
|
|
||||||
const dirOverrideVariablesStr = `
|
const dirOverrideVariablesStr = `
|
||||||
|
@ -918,8 +918,8 @@ aws
|
||||||
`
|
`
|
||||||
|
|
||||||
const importResourcesStr = `
|
const importResourcesStr = `
|
||||||
aws_security_group[db] (x1)
|
aws_security_group.db (x1)
|
||||||
aws_security_group[web] (x1)
|
aws_security_group.web (x1)
|
||||||
`
|
`
|
||||||
|
|
||||||
const importVariablesStr = `
|
const importVariablesStr = `
|
||||||
|
@ -938,7 +938,7 @@ bar
|
||||||
`
|
`
|
||||||
|
|
||||||
const provisionerResourcesStr = `
|
const provisionerResourcesStr = `
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
security_groups
|
security_groups
|
||||||
provisioners
|
provisioners
|
||||||
|
@ -950,7 +950,7 @@ aws_instance[web] (x1)
|
||||||
`
|
`
|
||||||
|
|
||||||
const connectionResourcesStr = `
|
const connectionResourcesStr = `
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
security_groups
|
security_groups
|
||||||
provisioners
|
provisioners
|
||||||
|
@ -976,17 +976,17 @@ foo (required)
|
||||||
`
|
`
|
||||||
|
|
||||||
const createBeforeDestroyResourcesStr = `
|
const createBeforeDestroyResourcesStr = `
|
||||||
aws_instance[bar] (x1)
|
aws_instance.bar (x1)
|
||||||
ami
|
ami
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
`
|
`
|
||||||
|
|
||||||
const ignoreChangesResourcesStr = `
|
const ignoreChangesResourcesStr = `
|
||||||
aws_instance[bar] (x1)
|
aws_instance.bar (x1)
|
||||||
ami
|
ami
|
||||||
aws_instance[baz] (x1)
|
aws_instance.baz (x1)
|
||||||
ami
|
ami
|
||||||
aws_instance[web] (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
//go:generate stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go
|
||||||
|
type ResourceMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ManagedResourceMode ResourceMode = iota
|
||||||
|
DataResourceMode
|
||||||
|
)
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Code generated by "stringer -type=ResourceMode -output=resource_mode_string.go resource_mode.go"; DO NOT EDIT
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const _ResourceMode_name = "ManagedResourceModeDataResourceMode"
|
||||||
|
|
||||||
|
var _ResourceMode_index = [...]uint8{0, 19, 35}
|
||||||
|
|
||||||
|
func (i ResourceMode) String() string {
|
||||||
|
if i < 0 || i >= ResourceMode(len(_ResourceMode_index)-1) {
|
||||||
|
return fmt.Sprintf("ResourceMode(%d)", i)
|
||||||
|
}
|
||||||
|
return _ResourceMode_name[_ResourceMode_index[i]:_ResourceMode_index[i+1]]
|
||||||
|
}
|
Loading…
Reference in New Issue