github.com/federicobaldo/terraform@v0.6.15-0.20160323222747-b20f680cbf05/terraform/graph_builder_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/dag"
     9  )
    10  
    11  func TestBasicGraphBuilder_impl(t *testing.T) {
    12  	var _ GraphBuilder = new(BasicGraphBuilder)
    13  }
    14  
    15  func TestBasicGraphBuilder(t *testing.T) {
    16  	b := &BasicGraphBuilder{
    17  		Steps: []GraphTransformer{
    18  			&testBasicGraphBuilderTransform{1},
    19  		},
    20  	}
    21  
    22  	g, err := b.Build(RootModulePath)
    23  	if err != nil {
    24  		t.Fatalf("err: %s", err)
    25  	}
    26  
    27  	if !reflect.DeepEqual(g.Path, RootModulePath) {
    28  		t.Fatalf("bad: %#v", g.Path)
    29  	}
    30  
    31  	actual := strings.TrimSpace(g.String())
    32  	expected := strings.TrimSpace(testBasicGraphBuilderStr)
    33  	if actual != expected {
    34  		t.Fatalf("bad: %s", actual)
    35  	}
    36  }
    37  
    38  func TestBasicGraphBuilder_validate(t *testing.T) {
    39  	b := &BasicGraphBuilder{
    40  		Steps: []GraphTransformer{
    41  			&testBasicGraphBuilderTransform{1},
    42  			&testBasicGraphBuilderTransform{2},
    43  		},
    44  		Validate: true,
    45  	}
    46  
    47  	_, err := b.Build(RootModulePath)
    48  	if err == nil {
    49  		t.Fatal("should error")
    50  	}
    51  }
    52  
    53  func TestBasicGraphBuilder_validateOff(t *testing.T) {
    54  	b := &BasicGraphBuilder{
    55  		Steps: []GraphTransformer{
    56  			&testBasicGraphBuilderTransform{1},
    57  			&testBasicGraphBuilderTransform{2},
    58  		},
    59  		Validate: false,
    60  	}
    61  
    62  	_, err := b.Build(RootModulePath)
    63  	if err != nil {
    64  		t.Fatalf("expected no error, got: %s", err)
    65  	}
    66  }
    67  
    68  func TestBuiltinGraphBuilder_impl(t *testing.T) {
    69  	var _ GraphBuilder = new(BuiltinGraphBuilder)
    70  }
    71  
    72  // This test is not meant to test all the transforms but rather just
    73  // to verify we get some basic sane graph out. Special tests to ensure
    74  // specific ordering of steps should be added in other tests.
    75  func TestBuiltinGraphBuilder(t *testing.T) {
    76  	b := &BuiltinGraphBuilder{
    77  		Root:     testModule(t, "graph-builder-basic"),
    78  		Validate: true,
    79  	}
    80  
    81  	g, err := b.Build(RootModulePath)
    82  	if err != nil {
    83  		t.Fatalf("err: %s", err)
    84  	}
    85  
    86  	actual := strings.TrimSpace(g.String())
    87  	expected := strings.TrimSpace(testBuiltinGraphBuilderBasicStr)
    88  	if actual != expected {
    89  		t.Fatalf("bad: %s", actual)
    90  	}
    91  }
    92  
    93  func TestBuiltinGraphBuilder_Verbose(t *testing.T) {
    94  	b := &BuiltinGraphBuilder{
    95  		Root:     testModule(t, "graph-builder-basic"),
    96  		Validate: true,
    97  		Verbose:  true,
    98  	}
    99  
   100  	g, err := b.Build(RootModulePath)
   101  	if err != nil {
   102  		t.Fatalf("err: %s", err)
   103  	}
   104  
   105  	actual := strings.TrimSpace(g.String())
   106  	expected := strings.TrimSpace(testBuiltinGraphBuilderVerboseStr)
   107  	if actual != expected {
   108  		t.Fatalf("bad: %s", actual)
   109  	}
   110  }
   111  
   112  // This tests that the CreateBeforeDestoryTransformer is not present when
   113  // we perform a "terraform destroy" operation. We don't actually do anything
   114  // else.
   115  func TestBuiltinGraphBuilder_CreateBeforeDestroy_Destroy_Bypass(t *testing.T) {
   116  	b := &BuiltinGraphBuilder{
   117  		Root:     testModule(t, "graph-builder-basic"),
   118  		Validate: true,
   119  		Destroy:  true,
   120  	}
   121  
   122  	steps := b.Steps([]string{})
   123  
   124  	actual := false
   125  	expected := false
   126  	for _, v := range steps {
   127  		switch v.(type) {
   128  		case *CreateBeforeDestroyTransformer:
   129  			actual = true
   130  		}
   131  	}
   132  
   133  	if actual != expected {
   134  		t.Fatalf("bad: CreateBeforeDestroyTransformer still in root path")
   135  	}
   136  }
   137  
   138  // This tests that the CreateBeforeDestoryTransformer *is* present
   139  // during a non-destroy operation (ie: Destroy not set).
   140  func TestBuiltinGraphBuilder_CreateBeforeDestroy_NonDestroy_Present(t *testing.T) {
   141  	b := &BuiltinGraphBuilder{
   142  		Root:     testModule(t, "graph-builder-basic"),
   143  		Validate: true,
   144  	}
   145  
   146  	steps := b.Steps([]string{})
   147  
   148  	actual := false
   149  	expected := true
   150  	for _, v := range steps {
   151  		switch v.(type) {
   152  		case *CreateBeforeDestroyTransformer:
   153  			actual = true
   154  		}
   155  	}
   156  
   157  	if actual != expected {
   158  		t.Fatalf("bad: CreateBeforeDestroyTransformer not in root path")
   159  	}
   160  }
   161  
   162  // This tests a cycle we got when a CBD resource depends on a non-CBD
   163  // resource. This cycle shouldn't happen in the general case anymore.
   164  func TestBuiltinGraphBuilder_cbdDepNonCbd(t *testing.T) {
   165  	b := &BuiltinGraphBuilder{
   166  		Root:     testModule(t, "graph-builder-cbd-non-cbd"),
   167  		Validate: true,
   168  	}
   169  
   170  	_, err := b.Build(RootModulePath)
   171  	if err != nil {
   172  		t.Fatalf("err: %s", err)
   173  	}
   174  }
   175  
   176  func TestBuiltinGraphBuilder_cbdDepNonCbd_errorsWhenVerbose(t *testing.T) {
   177  	b := &BuiltinGraphBuilder{
   178  		Root:     testModule(t, "graph-builder-cbd-non-cbd"),
   179  		Validate: true,
   180  		Verbose:  true,
   181  	}
   182  
   183  	_, err := b.Build(RootModulePath)
   184  	if err == nil {
   185  		t.Fatalf("expected err, got none")
   186  	}
   187  }
   188  
   189  func TestBuiltinGraphBuilder_multiLevelModule(t *testing.T) {
   190  	b := &BuiltinGraphBuilder{
   191  		Root:     testModule(t, "graph-builder-multi-level-module"),
   192  		Validate: true,
   193  	}
   194  
   195  	g, err := b.Build(RootModulePath)
   196  	if err != nil {
   197  		t.Fatalf("err: %s", err)
   198  	}
   199  
   200  	actual := strings.TrimSpace(g.String())
   201  	expected := strings.TrimSpace(testBuiltinGraphBuilderMultiLevelStr)
   202  	if actual != expected {
   203  		t.Fatalf("bad: %s", actual)
   204  	}
   205  }
   206  
   207  func TestBuiltinGraphBuilder_orphanDeps(t *testing.T) {
   208  	state := &State{
   209  		Modules: []*ModuleState{
   210  			&ModuleState{
   211  				Path: rootModulePath,
   212  				Resources: map[string]*ResourceState{
   213  					"aws_instance.foo": &ResourceState{
   214  						Type: "aws_instance",
   215  						Primary: &InstanceState{
   216  							ID: "foo",
   217  						},
   218  					},
   219  
   220  					"aws_instance.bar": &ResourceState{
   221  						Type:         "aws_instance",
   222  						Dependencies: []string{"aws_instance.foo"},
   223  						Primary: &InstanceState{
   224  							ID: "bar",
   225  						},
   226  					},
   227  				},
   228  			},
   229  		},
   230  	}
   231  
   232  	b := &BuiltinGraphBuilder{
   233  		Root:     testModule(t, "graph-builder-orphan-deps"),
   234  		State:    state,
   235  		Validate: true,
   236  	}
   237  
   238  	g, err := b.Build(RootModulePath)
   239  	if err != nil {
   240  		t.Fatalf("err: %s", err)
   241  	}
   242  
   243  	actual := strings.TrimSpace(g.String())
   244  	expected := strings.TrimSpace(testBuiltinGraphBuilderOrphanDepsStr)
   245  	if actual != expected {
   246  		t.Fatalf("bad: %s", actual)
   247  	}
   248  }
   249  
   250  /*
   251  TODO: This exposes a really bad bug we need to fix after we merge
   252  the f-ast-branch. This bug still exists in master.
   253  
   254  // This test tests that the graph builder properly expands modules.
   255  func TestBuiltinGraphBuilder_modules(t *testing.T) {
   256  	b := &BuiltinGraphBuilder{
   257  		Root: testModule(t, "graph-builder-modules"),
   258  	}
   259  
   260  	g, err := b.Build(RootModulePath)
   261  	if err != nil {
   262  		t.Fatalf("err: %s", err)
   263  	}
   264  
   265  	actual := strings.TrimSpace(g.String())
   266  	expected := strings.TrimSpace(testBuiltinGraphBuilderModuleStr)
   267  	if actual != expected {
   268  		t.Fatalf("bad: %s", actual)
   269  	}
   270  }
   271  */
   272  
   273  type testBasicGraphBuilderTransform struct {
   274  	V dag.Vertex
   275  }
   276  
   277  func (t *testBasicGraphBuilderTransform) Transform(g *Graph) error {
   278  	g.Add(t.V)
   279  	return nil
   280  }
   281  
   282  const testBasicGraphBuilderStr = `
   283  1
   284  `
   285  
   286  const testBuiltinGraphBuilderBasicStr = `
   287  aws_instance.db
   288    provider.aws
   289  aws_instance.web
   290    aws_instance.db
   291  provider.aws
   292  provider.aws (close)
   293    aws_instance.web
   294  `
   295  
   296  const testBuiltinGraphBuilderVerboseStr = `
   297  aws_instance.db
   298    aws_instance.db (destroy tainted)
   299    aws_instance.db (destroy)
   300  aws_instance.db (destroy tainted)
   301    aws_instance.web (destroy tainted)
   302  aws_instance.db (destroy)
   303    aws_instance.web (destroy)
   304  aws_instance.web
   305    aws_instance.db
   306  aws_instance.web (destroy tainted)
   307    provider.aws
   308  aws_instance.web (destroy)
   309    provider.aws
   310  provider.aws
   311  provider.aws (close)
   312    aws_instance.web
   313  `
   314  
   315  const testBuiltinGraphBuilderMultiLevelStr = `
   316  module.foo.module.bar.output.value
   317    module.foo.module.bar.var.bar
   318    module.foo.var.foo
   319  module.foo.module.bar.plan-destroy
   320  module.foo.module.bar.var.bar
   321    module.foo.var.foo
   322  module.foo.plan-destroy
   323  module.foo.var.foo
   324  root
   325    module.foo.module.bar.output.value
   326    module.foo.module.bar.plan-destroy
   327    module.foo.module.bar.var.bar
   328    module.foo.plan-destroy
   329    module.foo.var.foo
   330  `
   331  
   332  const testBuiltinGraphBuilderOrphanDepsStr = `
   333  aws_instance.bar (orphan)
   334    provider.aws
   335  aws_instance.foo (orphan)
   336    aws_instance.bar (orphan)
   337  provider.aws
   338  provider.aws (close)
   339    aws_instance.foo (orphan)
   340  `
   341  
   342  /*
   343  TODO: Commented out this const as it's likely this needs to
   344  be updated when the TestBuiltinGraphBuilder_modules test is
   345  enabled again.
   346  const testBuiltinGraphBuilderModuleStr = `
   347  aws_instance.web
   348    aws_instance.web (destroy)
   349  aws_instance.web (destroy)
   350    aws_security_group.firewall
   351    module.consul (expanded)
   352    provider.aws
   353  aws_security_group.firewall
   354    aws_security_group.firewall (destroy)
   355  aws_security_group.firewall (destroy)
   356    provider.aws
   357  module.consul (expanded)
   358    aws_security_group.firewall
   359    provider.aws
   360  provider.aws
   361  `
   362  */