github.com/mehmetalisavas/terraform@v0.7.10/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 // This now returns no errors due to a general fix while building the graph 177 func TestBuiltinGraphBuilder_cbdDepNonCbd_errorsWhenVerbose(t *testing.T) { 178 b := &BuiltinGraphBuilder{ 179 Root: testModule(t, "graph-builder-cbd-non-cbd"), 180 Validate: true, 181 Verbose: true, 182 } 183 184 _, err := b.Build(RootModulePath) 185 if err != nil { 186 t.Fatalf("err: %s", err) 187 } 188 } 189 190 func TestBuiltinGraphBuilder_multiLevelModule(t *testing.T) { 191 b := &BuiltinGraphBuilder{ 192 Root: testModule(t, "graph-builder-multi-level-module"), 193 Validate: true, 194 } 195 196 g, err := b.Build(RootModulePath) 197 if err != nil { 198 t.Fatalf("err: %s", err) 199 } 200 201 actual := strings.TrimSpace(g.String()) 202 expected := strings.TrimSpace(testBuiltinGraphBuilderMultiLevelStr) 203 if actual != expected { 204 t.Fatalf("bad: %s", actual) 205 } 206 } 207 208 func TestBuiltinGraphBuilder_orphanDeps(t *testing.T) { 209 state := &State{ 210 Modules: []*ModuleState{ 211 &ModuleState{ 212 Path: rootModulePath, 213 Resources: map[string]*ResourceState{ 214 "aws_instance.foo": &ResourceState{ 215 Type: "aws_instance", 216 Primary: &InstanceState{ 217 ID: "foo", 218 }, 219 }, 220 221 "aws_instance.bar": &ResourceState{ 222 Type: "aws_instance", 223 Dependencies: []string{"aws_instance.foo"}, 224 Primary: &InstanceState{ 225 ID: "bar", 226 }, 227 }, 228 }, 229 }, 230 }, 231 } 232 233 b := &BuiltinGraphBuilder{ 234 Root: testModule(t, "graph-builder-orphan-deps"), 235 State: state, 236 Validate: true, 237 } 238 239 g, err := b.Build(RootModulePath) 240 if err != nil { 241 t.Fatalf("err: %s", err) 242 } 243 244 actual := strings.TrimSpace(g.String()) 245 expected := strings.TrimSpace(testBuiltinGraphBuilderOrphanDepsStr) 246 if actual != expected { 247 t.Fatalf("bad: %s", actual) 248 } 249 } 250 251 /* 252 TODO: This exposes a really bad bug we need to fix after we merge 253 the f-ast-branch. This bug still exists in master. 254 255 // This test tests that the graph builder properly expands modules. 256 func TestBuiltinGraphBuilder_modules(t *testing.T) { 257 b := &BuiltinGraphBuilder{ 258 Root: testModule(t, "graph-builder-modules"), 259 } 260 261 g, err := b.Build(RootModulePath) 262 if err != nil { 263 t.Fatalf("err: %s", err) 264 } 265 266 actual := strings.TrimSpace(g.String()) 267 expected := strings.TrimSpace(testBuiltinGraphBuilderModuleStr) 268 if actual != expected { 269 t.Fatalf("bad: %s", actual) 270 } 271 } 272 */ 273 274 type testBasicGraphBuilderTransform struct { 275 V dag.Vertex 276 } 277 278 func (t *testBasicGraphBuilderTransform) Transform(g *Graph) error { 279 g.Add(t.V) 280 return nil 281 } 282 283 const testBasicGraphBuilderStr = ` 284 1 285 ` 286 287 const testBuiltinGraphBuilderBasicStr = ` 288 aws_instance.db 289 provider.aws 290 aws_instance.web 291 aws_instance.db 292 provider.aws 293 provider.aws (close) 294 aws_instance.web 295 ` 296 297 const testBuiltinGraphBuilderVerboseStr = ` 298 aws_instance.db 299 aws_instance.db (destroy) 300 aws_instance.db (destroy) 301 aws_instance.web (destroy) 302 aws_instance.web 303 aws_instance.db 304 aws_instance.web (destroy) 305 provider.aws 306 provider.aws 307 provider.aws (close) 308 aws_instance.web 309 ` 310 311 const testBuiltinGraphBuilderMultiLevelStr = ` 312 module.foo.module.bar.output.value 313 module.foo.module.bar.var.bar 314 module.foo.var.foo 315 module.foo.module.bar.plan-destroy 316 module.foo.module.bar.var.bar 317 module.foo.var.foo 318 module.foo.plan-destroy 319 module.foo.var.foo 320 root 321 module.foo.module.bar.output.value 322 module.foo.module.bar.plan-destroy 323 module.foo.module.bar.var.bar 324 module.foo.plan-destroy 325 module.foo.var.foo 326 ` 327 328 const testBuiltinGraphBuilderOrphanDepsStr = ` 329 aws_instance.bar (orphan) 330 provider.aws 331 aws_instance.foo (orphan) 332 aws_instance.bar (orphan) 333 provider.aws 334 provider.aws (close) 335 aws_instance.foo (orphan) 336 ` 337 338 /* 339 TODO: Commented out this const as it's likely this needs to 340 be updated when the TestBuiltinGraphBuilder_modules test is 341 enabled again. 342 const testBuiltinGraphBuilderModuleStr = ` 343 aws_instance.web 344 aws_instance.web (destroy) 345 aws_instance.web (destroy) 346 aws_security_group.firewall 347 module.consul (expanded) 348 provider.aws 349 aws_security_group.firewall 350 aws_security_group.firewall (destroy) 351 aws_security_group.firewall (destroy) 352 provider.aws 353 module.consul (expanded) 354 aws_security_group.firewall 355 provider.aws 356 provider.aws 357 ` 358 */