config: depgraph can contain provider configuratoins

This commit is contained in:
Mitchell Hashimoto 2014-06-05 12:47:28 -07:00
parent e2fa7094bd
commit 3ccfd4d08c
4 changed files with 72 additions and 18 deletions

View File

@ -118,6 +118,7 @@ func (r *Resource) ReplaceVariables(vs map[string]string) *Resource {
// ResourceGraph returns a dependency graph of the resources from this
// Terraform configuration.
func (c *Config) ResourceGraph() *depgraph.Graph {
// This tracks all the resource nouns
nouns := make(map[string]*depgraph.Noun)
for _, r := range c.Resources {
noun := &depgraph.Noun{
@ -127,9 +128,30 @@ func (c *Config) ResourceGraph() *depgraph.Graph {
nouns[noun.Name] = noun
}
for _, noun := range nouns {
r := noun.Meta.(*Resource)
for _, v := range r.Variables {
// Build the list of nouns that we iterate over
nounsList := make([]*depgraph.Noun, 0, len(nouns))
for _, n := range nouns {
nounsList = append(nounsList, n)
}
// This tracks the provider configs that are nouns in our dep graph
pcNouns := make(map[string]*depgraph.Noun)
i := 0
for i < len(nounsList) {
noun := nounsList[i]
i += 1
// Determine depenencies based on variables. Both resources
// and provider configurations have dependencies in this case.
var vars map[string]InterpolatedVariable
switch n := noun.Meta.(type) {
case *Resource:
vars = n.Variables
case *ProviderConfig:
vars = n.Variables
}
for _, v := range vars {
// Only resource variables impose dependencies
rv, ok := v.(*ResourceVariable)
if !ok {
@ -145,12 +167,32 @@ func (c *Config) ResourceGraph() *depgraph.Graph {
noun.Deps = append(noun.Deps, dep)
}
// If this is a Resource, then check if we have to also
// depend on a provider configuration.
if r, ok := noun.Meta.(*Resource); ok {
// If there is a provider config that matches this resource
// then we add that as a dependency.
if pcName := r.ProviderConfigName(c.ProviderConfigs); pcName != "" {
pcNoun, ok := pcNouns[pcName]
if !ok {
pcNoun = &depgraph.Noun{
Name: fmt.Sprintf("provider.%s", pcName),
Meta: c.ProviderConfigs[pcName],
}
pcNouns[pcName] = pcNoun
nounsList = append(nounsList, pcNoun)
}
// Create the list of nouns that the depgraph.Graph struct expects
nounsList := make([]*depgraph.Noun, 0, len(nouns))
for _, n := range nouns {
nounsList = append(nounsList, n)
dep := &depgraph.Dependency{
Name: pcName,
Source: noun,
Target: pcNoun,
}
noun.Deps = append(noun.Deps, dep)
}
}
}
// Create a root that just depends on everything else finishing.
@ -170,6 +212,14 @@ func (c *Config) ResourceGraph() *depgraph.Graph {
}
}
// Validate does some basic semantic checking of the configuration.
func (c *Config) Validate() error {
// TODO(mitchellh): make sure all referenced variables exist
// TODO(mitchellh): make sure types/names have valid values (characters)
return nil
}
// Required tests whether a variable is required or not.
func (v *Variable) Required() bool {
return !v.defaultSet

View File

@ -128,16 +128,21 @@ func TestResourceReplaceVariables(t *testing.T) {
const resourceGraphValue = `
root: root
root -> aws_security_group.firewall
root -> aws_instance.web
root -> aws_load_balancer.weblb
openstack_floating_ip.random
aws_security_group.firewall
aws_security_group.firewall -> provider.aws
aws_instance.web
aws_instance.web -> aws_security_group.firewall
aws_instance.web -> provider.aws
aws_load_balancer.weblb
aws_load_balancer.weblb -> aws_instance.web
aws_load_balancer.weblb -> provider.aws
provider.aws
provider.aws -> openstack_floating_ip.random
root
root -> openstack_floating_ip.random
root -> aws_security_group.firewall
root -> aws_instance.web
root -> aws_load_balancer.weblb
root -> provider.aws
`

View File

@ -3,6 +3,12 @@ variable "foo" {
description = "bar";
}
provider "aws" {
foo = "${openstack_floating_ip.random.value}"
}
resource "openstack_floating_ip" "random" {}
resource "aws_security_group" "firewall" {}
resource "aws_instance" "web" {

View File

@ -114,13 +114,6 @@ func (g *Graph) String() string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("root: %s\n", g.Root.Name))
for _, dep := range g.Root.Deps {
buf.WriteString(fmt.Sprintf(
" %s -> %s\n",
dep.Source,
dep.Target))
}
for _, n := range g.Nouns {
buf.WriteString(fmt.Sprintf("%s\n", n.Name))
for _, dep := range n.Deps {