github.com/handlerbot/terraform@v0.10.0-beta1.0.20180726153736-26b68d98f9cb/builtin/providers/test/resource_test.go (about)

     1  package test
     2  
     3  import (
     4  	"reflect"
     5  	"regexp"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/terraform"
    11  )
    12  
    13  func TestResource_basic(t *testing.T) {
    14  	resource.UnitTest(t, resource.TestCase{
    15  		Providers:    testAccProviders,
    16  		CheckDestroy: testAccCheckResourceDestroy,
    17  		Steps: []resource.TestStep{
    18  			resource.TestStep{
    19  				Config: strings.TrimSpace(`
    20  resource "test_resource" "foo" {
    21  	required = "yep"
    22  	required_map = {
    23  	    key = "value"
    24  	}
    25  }
    26  				`),
    27  				Check: func(s *terraform.State) error {
    28  					return nil
    29  				},
    30  			},
    31  		},
    32  	})
    33  }
    34  
    35  // Targeted test in TestContext2Apply_ignoreChangesCreate
    36  func TestResource_ignoreChangesRequired(t *testing.T) {
    37  	resource.UnitTest(t, resource.TestCase{
    38  		Providers:    testAccProviders,
    39  		CheckDestroy: testAccCheckResourceDestroy,
    40  		Steps: []resource.TestStep{
    41  			resource.TestStep{
    42  				Config: strings.TrimSpace(`
    43  resource "test_resource" "foo" {
    44          required = "yep"
    45  	required_map = {
    46  	    key = "value"
    47  	}
    48          lifecycle {
    49                  ignore_changes = ["required"]
    50          }
    51  }
    52                                 `),
    53  				Check: func(s *terraform.State) error {
    54  					return nil
    55  				},
    56  			},
    57  		},
    58  	})
    59  }
    60  
    61  func TestResource_ignoreChangesEmpty(t *testing.T) {
    62  	resource.UnitTest(t, resource.TestCase{
    63  		Providers:    testAccProviders,
    64  		CheckDestroy: testAccCheckResourceDestroy,
    65  		Steps: []resource.TestStep{
    66  			resource.TestStep{
    67  				Config: strings.TrimSpace(`
    68  resource "test_resource" "foo" {
    69  	required           = "yep"
    70  	required_map = {
    71  	    key = "value"
    72  	}
    73  	optional_force_new = "one"
    74  	lifecycle {
    75  		ignore_changes = []
    76  	}
    77  }
    78  				`),
    79  				Check: func(s *terraform.State) error {
    80  					return nil
    81  				},
    82  			},
    83  			resource.TestStep{
    84  				Config: strings.TrimSpace(`
    85  resource "test_resource" "foo" {
    86  	required           = "yep"
    87  	required_map {
    88  	    key = "value"
    89  	}
    90  	optional_force_new = "two"
    91  	lifecycle {
    92  		ignore_changes = []
    93  	}
    94  }
    95  				`),
    96  				Check: func(s *terraform.State) error {
    97  					return nil
    98  				},
    99  			},
   100  		},
   101  	})
   102  }
   103  
   104  func TestResource_ignoreChangesForceNew(t *testing.T) {
   105  	resource.UnitTest(t, resource.TestCase{
   106  		Providers:    testAccProviders,
   107  		CheckDestroy: testAccCheckResourceDestroy,
   108  		Steps: []resource.TestStep{
   109  			resource.TestStep{
   110  				Config: strings.TrimSpace(`
   111  resource "test_resource" "foo" {
   112  	required           = "yep"
   113  	required_map {
   114  	    key = "value"
   115  	}
   116  	optional_force_new = "one"
   117  	lifecycle {
   118  		ignore_changes = ["optional_force_new"]
   119  	}
   120  }
   121  				`),
   122  				Check: func(s *terraform.State) error {
   123  					return nil
   124  				},
   125  			},
   126  			resource.TestStep{
   127  				Config: strings.TrimSpace(`
   128  resource "test_resource" "foo" {
   129  	required           = "yep"
   130  	required_map = {
   131  	    key = "value"
   132  	}
   133  	optional_force_new = "two"
   134  	lifecycle {
   135  		ignore_changes = ["optional_force_new"]
   136  	}
   137  }
   138  				`),
   139  				Check: func(s *terraform.State) error {
   140  					return nil
   141  				},
   142  			},
   143  		},
   144  	})
   145  }
   146  
   147  // Covers specific scenario in #6005, handled by normalizing boolean strings in
   148  // helper/schema
   149  func TestResource_ignoreChangesForceNewBoolean(t *testing.T) {
   150  	resource.UnitTest(t, resource.TestCase{
   151  		Providers:    testAccProviders,
   152  		CheckDestroy: testAccCheckResourceDestroy,
   153  		Steps: []resource.TestStep{
   154  			resource.TestStep{
   155  				Config: strings.TrimSpace(`
   156  resource "test_resource" "foo" {
   157    required           = "yep"
   158    required_map = {
   159      key = "value"
   160    }
   161    optional_force_new = "one"
   162    optional_bool      = true
   163    lifecycle {
   164      ignore_changes = ["optional_force_new"]
   165    }
   166  }
   167  				`),
   168  				Check: func(s *terraform.State) error {
   169  					return nil
   170  				},
   171  			},
   172  			resource.TestStep{
   173  				Config: strings.TrimSpace(`
   174  resource "test_resource" "foo" {
   175    required           = "yep"
   176    required_map = {
   177      key = "value"
   178    }
   179    optional_force_new = "two"
   180    optional_bool      = true
   181    lifecycle {
   182      ignore_changes = ["optional_force_new"]
   183    }
   184  }
   185  				`),
   186  				Check: func(s *terraform.State) error {
   187  					return nil
   188  				},
   189  			},
   190  		},
   191  	})
   192  }
   193  
   194  // Reproduces plan-time panic described in GH-7170
   195  func TestResource_dataSourceListPlanPanic(t *testing.T) {
   196  	resource.UnitTest(t, resource.TestCase{
   197  		Providers:    testAccProviders,
   198  		CheckDestroy: testAccCheckResourceDestroy,
   199  		Steps: []resource.TestStep{
   200  			resource.TestStep{
   201  				Config: strings.TrimSpace(`
   202  data "test_data_source" "foo" {}
   203  resource "test_resource" "foo" {
   204    required = "${data.test_data_source.foo.list}"
   205    required_map = {
   206      key = "value"
   207    }
   208  }
   209  				`),
   210  				ExpectError: regexp.MustCompile(`must be a single value, not a list`),
   211  				Check: func(s *terraform.State) error {
   212  					return nil
   213  				},
   214  			},
   215  		},
   216  	})
   217  }
   218  
   219  // Reproduces apply-time panic described in GH-7170
   220  func TestResource_dataSourceListApplyPanic(t *testing.T) {
   221  	resource.UnitTest(t, resource.TestCase{
   222  		Providers:    testAccProviders,
   223  		CheckDestroy: testAccCheckResourceDestroy,
   224  		Steps: []resource.TestStep{
   225  			resource.TestStep{
   226  				Config: strings.TrimSpace(`
   227  resource "test_resource" "foo" {
   228    required = "ok"
   229    required_map = {
   230      key = "value"
   231    }
   232  }
   233  resource "test_resource" "bar" {
   234    required = "${test_resource.foo.computed_list}"
   235    required_map = {
   236      key = "value"
   237    }
   238  }
   239  				`),
   240  				ExpectError: regexp.MustCompile(`must be a single value, not a list`),
   241  				Check: func(s *terraform.State) error {
   242  					return nil
   243  				},
   244  			},
   245  		},
   246  	})
   247  }
   248  
   249  func TestResource_ignoreChangesMap(t *testing.T) {
   250  	resource.UnitTest(t, resource.TestCase{
   251  		Providers:    testAccProviders,
   252  		CheckDestroy: testAccCheckResourceDestroy,
   253  		Steps: []resource.TestStep{
   254  			resource.TestStep{
   255  				Config: strings.TrimSpace(`
   256  resource "test_resource" "foo" {
   257  	required           = "yep"
   258  	required_map = {
   259  	  key = "value"
   260  	}
   261  	optional_computed_map {
   262  		foo = "bar"
   263  	}
   264  	lifecycle {
   265  		ignore_changes = ["optional_computed_map"]
   266  	}
   267  }
   268  				`),
   269  				Check: func(s *terraform.State) error {
   270  					return nil
   271  				},
   272  			},
   273  			resource.TestStep{
   274  				Config: strings.TrimSpace(`
   275  resource "test_resource" "foo" {
   276  	required           = "yep"
   277  	required_map = {
   278  	  key = "value"
   279  	}
   280  	optional_computed_map {
   281  		foo = "bar"
   282  		no  = "update"
   283  	}
   284  	lifecycle {
   285  		ignore_changes = ["optional_computed_map"]
   286  	}
   287  }
   288  				`),
   289  				Check: func(s *terraform.State) error {
   290  					return nil
   291  				},
   292  			},
   293  		},
   294  	})
   295  }
   296  
   297  func TestResource_ignoreChangesDependent(t *testing.T) {
   298  	resource.UnitTest(t, resource.TestCase{
   299  		Providers:    testAccProviders,
   300  		CheckDestroy: testAccCheckResourceDestroy,
   301  		Steps: []resource.TestStep{
   302  			resource.TestStep{
   303  				Config: strings.TrimSpace(`
   304  resource "test_resource" "foo" {
   305  	count = 2
   306  	required = "yep"
   307  	required_map { key = "value" }
   308  
   309  	optional_force_new = "one"
   310  	lifecycle {
   311  		ignore_changes = ["optional_force_new"]
   312  	}
   313  }
   314  resource "test_resource" "bar" {
   315  	count = 2
   316  	required = "yep"
   317  	required_map { key = "value" }
   318  	optional = "${element(test_resource.foo.*.id, count.index)}"
   319  }
   320  				`),
   321  				Check: func(s *terraform.State) error {
   322  					return nil
   323  				},
   324  			},
   325  			resource.TestStep{
   326  				Config: strings.TrimSpace(`
   327  resource "test_resource" "foo" {
   328  	count = 2
   329  	required = "yep"
   330  	required_map { key = "value" }
   331  
   332  	optional_force_new = "two"
   333  	lifecycle {
   334  		ignore_changes = ["optional_force_new"]
   335  	}
   336  }
   337  resource "test_resource" "bar" {
   338  	count = 2
   339  	required = "yep"
   340  	required_map { key = "value" }
   341  	optional = "${element(test_resource.foo.*.id, count.index)}"
   342  }
   343  				`),
   344  				Check: func(s *terraform.State) error {
   345  					return nil
   346  				},
   347  			},
   348  		},
   349  	})
   350  }
   351  
   352  func TestResource_ignoreChangesStillReplaced(t *testing.T) {
   353  	resource.UnitTest(t, resource.TestCase{
   354  		Providers:    testAccProviders,
   355  		CheckDestroy: testAccCheckResourceDestroy,
   356  		Steps: []resource.TestStep{
   357  			resource.TestStep{
   358  				Config: strings.TrimSpace(`
   359  resource "test_resource" "foo" {
   360    required     = "yep"
   361    required_map = {
   362      key = "value"
   363    }
   364    optional_force_new = "one"
   365    optional_bool      = true
   366    lifecycle {
   367      ignore_changes = ["optional_bool"]
   368    }
   369  }
   370  				`),
   371  				Check: func(s *terraform.State) error {
   372  					return nil
   373  				},
   374  			},
   375  			resource.TestStep{
   376  				Config: strings.TrimSpace(`
   377  resource "test_resource" "foo" {
   378    required     = "yep"
   379    required_map = {
   380      key = "value"
   381    }
   382    optional_force_new = "two"
   383    optional_bool      = false
   384    lifecycle {
   385      ignore_changes = ["optional_bool"]
   386    }
   387  }
   388  				`),
   389  				Check: func(s *terraform.State) error {
   390  					return nil
   391  				},
   392  			},
   393  		},
   394  	})
   395  }
   396  
   397  // Reproduces plan-time panic when the wrong type is interpolated in a list of
   398  // maps.
   399  // TODO: this should return a type error, rather than silently setting an empty
   400  //       list
   401  func TestResource_dataSourceListMapPanic(t *testing.T) {
   402  	resource.UnitTest(t, resource.TestCase{
   403  		Providers:    testAccProviders,
   404  		CheckDestroy: testAccCheckResourceDestroy,
   405  		Steps: []resource.TestStep{
   406  			resource.TestStep{
   407  				Config: strings.TrimSpace(`
   408  resource "test_resource" "foo" {
   409    required = "val"
   410    required_map = {x = "y"}
   411    list_of_map = "${var.maplist}"
   412  }
   413  
   414  variable "maplist" {
   415    type = "list"
   416  
   417    default = [
   418      {a = "b"}
   419    ]
   420  }
   421  				`),
   422  				ExpectError: nil,
   423  				Check: func(s *terraform.State) error {
   424  					return nil
   425  				},
   426  			},
   427  		},
   428  	})
   429  }
   430  
   431  func TestResource_dataSourceIndexMapList(t *testing.T) {
   432  	resource.UnitTest(t, resource.TestCase{
   433  		Providers:    testAccProviders,
   434  		CheckDestroy: testAccCheckResourceDestroy,
   435  		Steps: []resource.TestStep{
   436  			resource.TestStep{
   437  				Config: strings.TrimSpace(`
   438  resource "test_resource" "foo" {
   439    required = "val"
   440  
   441    required_map = {
   442      x = "y"
   443    }
   444  
   445    list_of_map = [
   446      {
   447        a = "1"
   448        b = "2"
   449      },
   450      {
   451        c = "3"
   452        d = "4"
   453      },
   454    ]
   455  }
   456  
   457  output "map_from_list" {
   458    value = "${test_resource.foo.list_of_map[0]}"
   459  }
   460  
   461  output "value_from_map_from_list" {
   462    value = "${lookup(test_resource.foo.list_of_map[1], "d")}"
   463  }
   464  				`),
   465  				ExpectError: nil,
   466  				Check: func(s *terraform.State) error {
   467  					root := s.ModuleByPath(terraform.RootModulePath)
   468  					mapOut := root.Outputs["map_from_list"].Value
   469  					expectedMapOut := map[string]interface{}{
   470  						"a": "1",
   471  						"b": "2",
   472  					}
   473  
   474  					valueOut := root.Outputs["value_from_map_from_list"].Value
   475  					expectedValueOut := "4"
   476  
   477  					if !reflect.DeepEqual(mapOut, expectedMapOut) {
   478  						t.Fatalf("Expected: %#v\nGot: %#v", expectedMapOut, mapOut)
   479  					}
   480  					if !reflect.DeepEqual(valueOut, expectedValueOut) {
   481  						t.Fatalf("Expected: %#v\nGot: %#v", valueOut, expectedValueOut)
   482  					}
   483  					return nil
   484  				},
   485  			},
   486  		},
   487  	})
   488  }
   489  
   490  func testAccCheckResourceDestroy(s *terraform.State) error {
   491  	return nil
   492  }