terraform: add Dependencies to ResourceState

This commit is contained in:
Mitchell Hashimoto 2014-06-30 17:40:56 -07:00
parent b3de33cc69
commit 521b432728
4 changed files with 73 additions and 7 deletions

View File

@ -16,8 +16,7 @@ import (
// can use to keep track of what real world resources it is actually // can use to keep track of what real world resources it is actually
// managing. // managing.
type State struct { type State struct {
Dependencies map[string][][]string Resources map[string]*ResourceState
Resources map[string]*ResourceState
once sync.Once once sync.Once
} }
@ -75,6 +74,13 @@ func (s *State) String() string {
for ak, av := range rs.Attributes { for ak, av := range rs.Attributes {
buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av)) buf.WriteString(fmt.Sprintf(" %s = %s\n", ak, av))
} }
if len(rs.Dependencies) > 0 {
buf.WriteString(fmt.Sprintf("\n Dependencies:\n"))
for _, dep := range rs.Dependencies {
buf.WriteString(fmt.Sprintf(" %s\n", dep.ID))
}
}
} }
return buf.String() return buf.String()
@ -135,10 +141,43 @@ func WriteState(d *State, dst io.Writer) error {
// Extra is just extra data that a provider can return that we store // Extra is just extra data that a provider can return that we store
// for later, but is not exposed in any way to the user. // for later, but is not exposed in any way to the user.
type ResourceState struct { type ResourceState struct {
ID string // This is filled in and managed by Terraform, and is the resource
Type string // type itself such as "mycloud_instance". If a resource provider sets
// this value, it won't be persisted.
Type string
// The attributes below are all meant to be filled in by the
// resource providers themselves. Documentation for each are above
// each element.
// A unique ID for this resource. This is opaque to Terraform
// and is only meant as a lookup mechanism for the providers.
ID string
// Attributes are basic information about the resource. Any keys here
// are accessible in variable format within Terraform configurations:
// ${resourcetype.name.attribute}.
Attributes map[string]string Attributes map[string]string
Extra map[string]interface{}
// Extra information that the provider can store about a resource.
// This data is opaque, never shown to the user, and is sent back to
// the provider as-is for whatever purpose appropriate.
Extra map[string]interface{}
// Dependencies are a list of things that this resource relies on
// existing to remain intact. For example: an AWS instance might
// depend on a subnet (which itself might depend on a VPC, and so
// on).
//
// Terraform uses this information to build valid destruction
// orders and to warn the user if they're destroying a resource that
// another resource depends on.
//
// Things can be put into this list that may not be managed by
// Terraform. If Terraform doesn't find a matching ID in the
// overall state, then it assumes it isn't managed and doesn't
// worry about it.
Dependencies []ResourceDependency
} }
// MergeDiff takes a ResourceDiff and merges the attributes into // MergeDiff takes a ResourceDiff and merges the attributes into
@ -174,3 +213,11 @@ func (s *ResourceState) MergeDiff(d *ResourceDiff) *ResourceState {
return &result return &result
} }
// ResourceDependency maps a resource to another resource that it
// depends on to remain intact and uncorrupted.
type ResourceDependency struct {
// ID of the resource that we depend on. This ID should map
// directly to another ResourceState's ID.
ID string
}

View File

@ -104,6 +104,10 @@ func (t *Terraform) apply(
p *Plan) (*State, error) { p *Plan) (*State, error) {
s := new(State) s := new(State)
err := g.Walk(t.applyWalkFn(s, p)) err := g.Walk(t.applyWalkFn(s, p))
// Now that we've built the state and have the graph, re-calculate
// the dependencies for our state based on what we did.
return s, err return s, err
} }

View File

@ -492,15 +492,27 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
return nil, nil return nil, nil
} }
id := "foo"
if idAttr, ok := d.Attributes["id"]; ok {
id = idAttr.New
}
result := &ResourceState{ result := &ResourceState{
ID: "foo", ID: id,
Attributes: make(map[string]string),
} }
if d != nil { if d != nil {
result = result.MergeDiff(d) result = result.MergeDiff(d)
} }
if depAttr, ok := d.Attributes["dep"]; ok {
result.Dependencies = []ResourceDependency{
ResourceDependency{
ID: depAttr.New,
},
}
}
return result, nil return result, nil
} }

View File

@ -1,7 +1,10 @@
resource "aws_instance" "foo" { resource "aws_instance" "foo" {
id = "foo"
num = "2" num = "2"
} }
resource "aws_instance" "bar" { resource "aws_instance" "bar" {
id = "bar"
foo = "{aws_instance.foo.num}" foo = "{aws_instance.foo.num}"
dep = "foo"
} }