github.com/articulate/terraform@v0.6.13-0.20160303003731-8d31c93862de/terraform/context_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"testing"
     7  	"time"
     8  )
     9  
    10  func testContext2(t *testing.T, opts *ContextOpts) *Context {
    11  	return NewContext(opts)
    12  }
    13  
    14  func testApplyFn(
    15  	info *InstanceInfo,
    16  	s *InstanceState,
    17  	d *InstanceDiff) (*InstanceState, error) {
    18  	if d.Destroy {
    19  		return nil, nil
    20  	}
    21  
    22  	id := "foo"
    23  	if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed {
    24  		id = idAttr.New
    25  	}
    26  
    27  	result := &InstanceState{
    28  		ID:         id,
    29  		Attributes: make(map[string]string),
    30  	}
    31  
    32  	// Copy all the prior attributes
    33  	for k, v := range s.Attributes {
    34  		result.Attributes[k] = v
    35  	}
    36  
    37  	if d != nil {
    38  		result = result.MergeDiff(d)
    39  	}
    40  	return result, nil
    41  }
    42  
    43  func testDiffFn(
    44  	info *InstanceInfo,
    45  	s *InstanceState,
    46  	c *ResourceConfig) (*InstanceDiff, error) {
    47  	var diff InstanceDiff
    48  	diff.Attributes = make(map[string]*ResourceAttrDiff)
    49  
    50  	for k, v := range c.Raw {
    51  		if _, ok := v.(string); !ok {
    52  			continue
    53  		}
    54  
    55  		// Ignore __-prefixed keys since they're used for magic
    56  		if k[0] == '_' && k[1] == '_' {
    57  			continue
    58  		}
    59  
    60  		if k == "nil" {
    61  			return nil, nil
    62  		}
    63  
    64  		// This key is used for other purposes
    65  		if k == "compute_value" {
    66  			continue
    67  		}
    68  
    69  		if k == "compute" {
    70  			attrDiff := &ResourceAttrDiff{
    71  				Old:         "",
    72  				New:         "",
    73  				NewComputed: true,
    74  			}
    75  
    76  			if cv, ok := c.Config["compute_value"]; ok {
    77  				if cv.(string) == "1" {
    78  					attrDiff.NewComputed = false
    79  					attrDiff.New = fmt.Sprintf("computed_%s", v.(string))
    80  				}
    81  			}
    82  
    83  			diff.Attributes[v.(string)] = attrDiff
    84  			continue
    85  		}
    86  
    87  		// If this key is not computed, then look it up in the
    88  		// cleaned config.
    89  		found := false
    90  		for _, ck := range c.ComputedKeys {
    91  			if ck == k {
    92  				found = true
    93  				break
    94  			}
    95  		}
    96  		if !found {
    97  			v = c.Config[k]
    98  		}
    99  
   100  		attrDiff := &ResourceAttrDiff{
   101  			Old: "",
   102  			New: v.(string),
   103  		}
   104  
   105  		if k == "require_new" {
   106  			attrDiff.RequiresNew = true
   107  		}
   108  		if _, ok := c.Raw["__"+k+"_requires_new"]; ok {
   109  			attrDiff.RequiresNew = true
   110  		}
   111  		diff.Attributes[k] = attrDiff
   112  	}
   113  
   114  	for _, k := range c.ComputedKeys {
   115  		diff.Attributes[k] = &ResourceAttrDiff{
   116  			Old:         "",
   117  			NewComputed: true,
   118  		}
   119  	}
   120  
   121  	for k, v := range diff.Attributes {
   122  		if v.NewComputed {
   123  			continue
   124  		}
   125  
   126  		old, ok := s.Attributes[k]
   127  		if !ok {
   128  			continue
   129  		}
   130  		if old == v.New {
   131  			delete(diff.Attributes, k)
   132  		}
   133  	}
   134  
   135  	if !diff.Empty() {
   136  		diff.Attributes["type"] = &ResourceAttrDiff{
   137  			Old: "",
   138  			New: info.Type,
   139  		}
   140  	}
   141  
   142  	return &diff, nil
   143  }
   144  
   145  func testProvider(prefix string) *MockResourceProvider {
   146  	p := new(MockResourceProvider)
   147  	p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) {
   148  		return s, nil
   149  	}
   150  	p.ResourcesReturn = []ResourceType{
   151  		ResourceType{
   152  			Name: fmt.Sprintf("%s_instance", prefix),
   153  		},
   154  	}
   155  
   156  	return p
   157  }
   158  
   159  func testProvisioner() *MockResourceProvisioner {
   160  	p := new(MockResourceProvisioner)
   161  	return p
   162  }
   163  
   164  func checkStateString(t *testing.T, state *State, expected string) {
   165  	actual := strings.TrimSpace(state.String())
   166  	expected = strings.TrimSpace(expected)
   167  
   168  	if actual != expected {
   169  		t.Fatalf("state does not match! actual:\n%s\n\nexpected:\n%s", actual, expected)
   170  	}
   171  }
   172  
   173  func resourceState(resourceType, resourceID string) *ResourceState {
   174  	return &ResourceState{
   175  		Type: resourceType,
   176  		Primary: &InstanceState{
   177  			ID: resourceID,
   178  		},
   179  	}
   180  }
   181  
   182  // Test helper that gives a function 3 seconds to finish, assumes deadlock and
   183  // fails test if it does not.
   184  func testCheckDeadlock(t *testing.T, f func()) {
   185  	timeout := make(chan bool, 1)
   186  	done := make(chan bool, 1)
   187  	go func() {
   188  		time.Sleep(3 * time.Second)
   189  		timeout <- true
   190  	}()
   191  	go func(f func(), done chan bool) {
   192  		defer func() { done <- true }()
   193  		f()
   194  	}(f, done)
   195  	select {
   196  	case <-timeout:
   197  		t.Fatalf("timed out! probably deadlock")
   198  	case <-done:
   199  		// ok
   200  	}
   201  }
   202  
   203  const testContextGraph = `
   204  root: root
   205  aws_instance.bar
   206    aws_instance.bar -> provider.aws
   207  aws_instance.foo
   208    aws_instance.foo -> provider.aws
   209  provider.aws
   210  root
   211    root -> aws_instance.bar
   212    root -> aws_instance.foo
   213  `
   214  
   215  const testContextRefreshModuleStr = `
   216  aws_instance.web: (1 tainted)
   217    ID = <not created>
   218    Tainted ID 1 = bar
   219  
   220  module.child:
   221    aws_instance.web:
   222      ID = new
   223  `
   224  
   225  const testContextRefreshOutputStr = `
   226  aws_instance.web:
   227    ID = foo
   228    foo = bar
   229  
   230  Outputs:
   231  
   232  foo = bar
   233  `
   234  
   235  const testContextRefreshOutputPartialStr = `
   236  <no state>
   237  `
   238  
   239  const testContextRefreshTaintedStr = `
   240  aws_instance.web: (1 tainted)
   241    ID = <not created>
   242    Tainted ID 1 = foo
   243  `