github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/transform_reference_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"reflect"
     5  	"sort"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/muratcelep/terraform/not-internal/addrs"
    10  	"github.com/muratcelep/terraform/not-internal/dag"
    11  )
    12  
    13  func TestReferenceTransformer_simple(t *testing.T) {
    14  	g := Graph{Path: addrs.RootModuleInstance}
    15  	g.Add(&graphNodeRefParentTest{
    16  		NameValue: "A",
    17  		Names:     []string{"A"},
    18  	})
    19  	g.Add(&graphNodeRefChildTest{
    20  		NameValue: "B",
    21  		Refs:      []string{"A"},
    22  	})
    23  
    24  	tf := &ReferenceTransformer{}
    25  	if err := tf.Transform(&g); err != nil {
    26  		t.Fatalf("err: %s", err)
    27  	}
    28  
    29  	actual := strings.TrimSpace(g.String())
    30  	expected := strings.TrimSpace(testTransformRefBasicStr)
    31  	if actual != expected {
    32  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
    33  	}
    34  }
    35  
    36  func TestReferenceTransformer_self(t *testing.T) {
    37  	g := Graph{Path: addrs.RootModuleInstance}
    38  	g.Add(&graphNodeRefParentTest{
    39  		NameValue: "A",
    40  		Names:     []string{"A"},
    41  	})
    42  	g.Add(&graphNodeRefChildTest{
    43  		NameValue: "B",
    44  		Refs:      []string{"A", "B"},
    45  	})
    46  
    47  	tf := &ReferenceTransformer{}
    48  	if err := tf.Transform(&g); err != nil {
    49  		t.Fatalf("err: %s", err)
    50  	}
    51  
    52  	actual := strings.TrimSpace(g.String())
    53  	expected := strings.TrimSpace(testTransformRefBasicStr)
    54  	if actual != expected {
    55  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
    56  	}
    57  }
    58  
    59  func TestReferenceTransformer_path(t *testing.T) {
    60  	g := Graph{Path: addrs.RootModuleInstance}
    61  	g.Add(&graphNodeRefParentTest{
    62  		NameValue: "A",
    63  		Names:     []string{"A"},
    64  	})
    65  	g.Add(&graphNodeRefChildTest{
    66  		NameValue: "B",
    67  		Refs:      []string{"A"},
    68  	})
    69  	g.Add(&graphNodeRefParentTest{
    70  		NameValue: "child.A",
    71  		PathValue: addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "child"}},
    72  		Names:     []string{"A"},
    73  	})
    74  	g.Add(&graphNodeRefChildTest{
    75  		NameValue: "child.B",
    76  		PathValue: addrs.ModuleInstance{addrs.ModuleInstanceStep{Name: "child"}},
    77  		Refs:      []string{"A"},
    78  	})
    79  
    80  	tf := &ReferenceTransformer{}
    81  	if err := tf.Transform(&g); err != nil {
    82  		t.Fatalf("err: %s", err)
    83  	}
    84  
    85  	actual := strings.TrimSpace(g.String())
    86  	expected := strings.TrimSpace(testTransformRefPathStr)
    87  	if actual != expected {
    88  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
    89  	}
    90  }
    91  
    92  func TestReferenceTransformer_resourceInstances(t *testing.T) {
    93  	// Our reference analyses are all done based on unexpanded addresses
    94  	// so that we can use this transformer both in the plan graph (where things
    95  	// are not expanded yet) and the apply graph (where resource instances are
    96  	// pre-expanded but nothing else is.)
    97  	// However, that would make the result too conservative about instances
    98  	// of the same resource in different instances of the same module, so we
    99  	// make an exception for that situation in particular, keeping references
   100  	// between resource instances segregated by their containing module
   101  	// instance.
   102  	g := Graph{Path: addrs.RootModuleInstance}
   103  	moduleInsts := []addrs.ModuleInstance{
   104  		{
   105  			{
   106  				Name: "foo", InstanceKey: addrs.IntKey(0),
   107  			},
   108  		},
   109  		{
   110  			{
   111  				Name: "foo", InstanceKey: addrs.IntKey(1),
   112  			},
   113  		},
   114  	}
   115  	resourceAs := make([]addrs.AbsResourceInstance, len(moduleInsts))
   116  	for i, moduleInst := range moduleInsts {
   117  		resourceAs[i] = addrs.Resource{
   118  			Mode: addrs.ManagedResourceMode,
   119  			Type: "thing",
   120  			Name: "a",
   121  		}.Instance(addrs.NoKey).Absolute(moduleInst)
   122  	}
   123  	resourceBs := make([]addrs.AbsResourceInstance, len(moduleInsts))
   124  	for i, moduleInst := range moduleInsts {
   125  		resourceBs[i] = addrs.Resource{
   126  			Mode: addrs.ManagedResourceMode,
   127  			Type: "thing",
   128  			Name: "b",
   129  		}.Instance(addrs.NoKey).Absolute(moduleInst)
   130  	}
   131  	g.Add(&graphNodeFakeResourceInstance{
   132  		Addr: resourceAs[0],
   133  	})
   134  	g.Add(&graphNodeFakeResourceInstance{
   135  		Addr: resourceBs[0],
   136  		Refs: []*addrs.Reference{
   137  			{
   138  				Subject: resourceAs[0].Resource,
   139  			},
   140  		},
   141  	})
   142  	g.Add(&graphNodeFakeResourceInstance{
   143  		Addr: resourceAs[1],
   144  	})
   145  	g.Add(&graphNodeFakeResourceInstance{
   146  		Addr: resourceBs[1],
   147  		Refs: []*addrs.Reference{
   148  			{
   149  				Subject: resourceAs[1].Resource,
   150  			},
   151  		},
   152  	})
   153  
   154  	tf := &ReferenceTransformer{}
   155  	if err := tf.Transform(&g); err != nil {
   156  		t.Fatalf("unexpected error: %s", err)
   157  	}
   158  
   159  	// Resource B should be connected to resource A in each module instance,
   160  	// but there should be no connections between the two module instances.
   161  	actual := strings.TrimSpace(g.String())
   162  	expected := strings.TrimSpace(`
   163  module.foo[0].thing.a
   164  module.foo[0].thing.b
   165    module.foo[0].thing.a
   166  module.foo[1].thing.a
   167  module.foo[1].thing.b
   168    module.foo[1].thing.a
   169  `)
   170  	if actual != expected {
   171  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   172  	}
   173  }
   174  
   175  func TestReferenceMapReferences(t *testing.T) {
   176  	cases := map[string]struct {
   177  		Nodes  []dag.Vertex
   178  		Check  dag.Vertex
   179  		Result []string
   180  	}{
   181  		"simple": {
   182  			Nodes: []dag.Vertex{
   183  				&graphNodeRefParentTest{
   184  					NameValue: "A",
   185  					Names:     []string{"A"},
   186  				},
   187  			},
   188  			Check: &graphNodeRefChildTest{
   189  				NameValue: "foo",
   190  				Refs:      []string{"A"},
   191  			},
   192  			Result: []string{"A"},
   193  		},
   194  	}
   195  
   196  	for tn, tc := range cases {
   197  		t.Run(tn, func(t *testing.T) {
   198  			rm := NewReferenceMap(tc.Nodes)
   199  			result := rm.References(tc.Check)
   200  
   201  			var resultStr []string
   202  			for _, v := range result {
   203  				resultStr = append(resultStr, dag.VertexName(v))
   204  			}
   205  
   206  			sort.Strings(resultStr)
   207  			sort.Strings(tc.Result)
   208  			if !reflect.DeepEqual(resultStr, tc.Result) {
   209  				t.Fatalf("bad: %#v", resultStr)
   210  			}
   211  		})
   212  	}
   213  }
   214  
   215  type graphNodeRefParentTest struct {
   216  	NameValue string
   217  	PathValue addrs.ModuleInstance
   218  	Names     []string
   219  }
   220  
   221  var _ GraphNodeReferenceable = (*graphNodeRefParentTest)(nil)
   222  
   223  func (n *graphNodeRefParentTest) Name() string {
   224  	return n.NameValue
   225  }
   226  
   227  func (n *graphNodeRefParentTest) ReferenceableAddrs() []addrs.Referenceable {
   228  	ret := make([]addrs.Referenceable, len(n.Names))
   229  	for i, name := range n.Names {
   230  		ret[i] = addrs.LocalValue{Name: name}
   231  	}
   232  	return ret
   233  }
   234  
   235  func (n *graphNodeRefParentTest) Path() addrs.ModuleInstance {
   236  	return n.PathValue
   237  }
   238  
   239  func (n *graphNodeRefParentTest) ModulePath() addrs.Module {
   240  	return n.PathValue.Module()
   241  }
   242  
   243  type graphNodeRefChildTest struct {
   244  	NameValue string
   245  	PathValue addrs.ModuleInstance
   246  	Refs      []string
   247  }
   248  
   249  var _ GraphNodeReferencer = (*graphNodeRefChildTest)(nil)
   250  
   251  func (n *graphNodeRefChildTest) Name() string {
   252  	return n.NameValue
   253  }
   254  
   255  func (n *graphNodeRefChildTest) References() []*addrs.Reference {
   256  	ret := make([]*addrs.Reference, len(n.Refs))
   257  	for i, name := range n.Refs {
   258  		ret[i] = &addrs.Reference{
   259  			Subject: addrs.LocalValue{Name: name},
   260  		}
   261  	}
   262  	return ret
   263  }
   264  
   265  func (n *graphNodeRefChildTest) Path() addrs.ModuleInstance {
   266  	return n.PathValue
   267  }
   268  
   269  func (n *graphNodeRefChildTest) ModulePath() addrs.Module {
   270  	return n.PathValue.Module()
   271  }
   272  
   273  type graphNodeFakeResourceInstance struct {
   274  	Addr addrs.AbsResourceInstance
   275  	Refs []*addrs.Reference
   276  }
   277  
   278  var _ GraphNodeResourceInstance = (*graphNodeFakeResourceInstance)(nil)
   279  var _ GraphNodeReferenceable = (*graphNodeFakeResourceInstance)(nil)
   280  var _ GraphNodeReferencer = (*graphNodeFakeResourceInstance)(nil)
   281  
   282  func (n *graphNodeFakeResourceInstance) ResourceInstanceAddr() addrs.AbsResourceInstance {
   283  	return n.Addr
   284  }
   285  
   286  func (n *graphNodeFakeResourceInstance) ModulePath() addrs.Module {
   287  	return n.Addr.Module.Module()
   288  }
   289  
   290  func (n *graphNodeFakeResourceInstance) ReferenceableAddrs() []addrs.Referenceable {
   291  	return []addrs.Referenceable{n.Addr.Resource}
   292  }
   293  
   294  func (n *graphNodeFakeResourceInstance) References() []*addrs.Reference {
   295  	return n.Refs
   296  }
   297  
   298  func (n *graphNodeFakeResourceInstance) StateDependencies() []addrs.ConfigResource {
   299  	return nil
   300  }
   301  
   302  func (n *graphNodeFakeResourceInstance) String() string {
   303  	return n.Addr.String()
   304  }
   305  
   306  const testTransformRefBasicStr = `
   307  A
   308  B
   309    A
   310  `
   311  
   312  const testTransformRefPathStr = `
   313  A
   314  B
   315    A
   316  child.A
   317  child.B
   318    child.A
   319  `