// Reproduces plan-time panic when the wrong type is interpolated in a list of // maps. // TODO: this should return a type error, rather than silently setting an empty // list func TestResource_dataSourceListMapPanic(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "val" required_map = {x = "y"} list_of_map = "${var.maplist}" } variable "maplist" { type = "list" default = [ {a = "b"} ] } `), ExpectError: nil, Check: func(s *terraform.State) error { return nil }, }, }, }) }
// Reproduces apply-time panic described in GH-7170 func TestResource_dataSourceListApplyPanic(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "ok" required_map = { key = "value" } } resource "test_resource" "bar" { required = "${test_resource.foo.computed_list}" required_map = { key = "value" } } `), ExpectError: regexp.MustCompile(`must be a single value, not a list`), Check: func(s *terraform.State) error { return nil }, }, }, }) }
func TestAccDnsCnameRecord_Basic(t *testing.T) { tests := []struct { DataSourceBlock string Expected string }{ { ` data "dns_cname_record" "foo" { host = "www.hashicorp.com" } `, "prod.k.ssl.global.fastly.net.", }, } for _, test := range tests { r.UnitTest(t, r.TestCase{ Providers: testAccProviders, Steps: []r.TestStep{ r.TestStep{ Config: test.DataSourceBlock, Check: r.ComposeTestCheckFunc( r.TestCheckResourceAttr("data.dns_cname_record.foo", "cname", test.Expected), ), }, }, }) } }
func TestAccDnsARecord_Basic(t *testing.T) { tests := []struct { DataSourceBlock string Expected []string }{ { ` data "dns_a_record" "foo" { host = "127.0.0.1.xip.io" } `, []string{ "127.0.0.1", }, }, } for _, test := range tests { r.UnitTest(t, r.TestCase{ Providers: testAccProviders, Steps: []r.TestStep{ r.TestStep{ Config: test.DataSourceBlock, Check: r.ComposeTestCheckFunc( testCheckAttrStringArray("data.dns_a_record.foo", "addrs", test.Expected), ), }, }, }) } }
func TestTemplateRendering(t *testing.T) { var cases = []struct { vars string template string want string }{ {`{}`, `ABC`, `ABC`}, {`{a="foo"}`, `$${a}`, `foo`}, {`{a="hello"}`, `$${replace(a, "ello", "i")}`, `hi`}, {`{}`, `${1+2+3}`, `6`}, } for _, tt := range cases { r.UnitTest(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ r.TestStep{ Config: testTemplateConfig(tt.template, tt.vars), Check: func(s *terraform.State) error { got := s.RootModule().Outputs["rendered"] if tt.want != got.Value { return fmt.Errorf("template:\n%s\nvars:\n%s\ngot:\n%s\nwant:\n%s\n", tt.template, tt.vars, got, tt.want) } return nil }, }, }, }) } }
func TestResource_dataSourceIndexMapList(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "val" required_map = { x = "y" } list_of_map = [ { a = "1" b = "2" }, { c = "3" d = "4" }, ] } output "map_from_list" { value = "${test_resource.foo.list_of_map[0]}" } output "value_from_map_from_list" { value = "${lookup(test_resource.foo.list_of_map[1], "d")}" } `), ExpectError: nil, Check: func(s *terraform.State) error { root := s.ModuleByPath(terraform.RootModulePath) mapOut := root.Outputs["map_from_list"].Value expectedMapOut := map[string]interface{}{ "a": "1", "b": "2", } valueOut := root.Outputs["value_from_map_from_list"].Value expectedValueOut := "4" if !reflect.DeepEqual(mapOut, expectedMapOut) { t.Fatalf("Expected: %#v\nGot: %#v", expectedMapOut, mapOut) } if !reflect.DeepEqual(valueOut, expectedValueOut) { t.Fatalf("Expected: %#v\nGot: %#v", valueOut, expectedValueOut) } return nil }, }, }, }) }
func TestResource_ignoreChangesDependent(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { count = 2 required = "yep" required_map { key = "value" } optional_force_new = "one" lifecycle { ignore_changes = ["optional_force_new"] } } resource "test_resource" "bar" { count = 2 required = "yep" required_map { key = "value" } optional = "${element(test_resource.foo.*.id, count.index)}" } `), Check: func(s *terraform.State) error { return nil }, }, resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { count = 2 required = "yep" required_map { key = "value" } optional_force_new = "two" lifecycle { ignore_changes = ["optional_force_new"] } } resource "test_resource" "bar" { count = 2 required = "yep" required_map { key = "value" } optional = "${element(test_resource.foo.*.id, count.index)}" } `), Check: func(s *terraform.State) error { return nil }, }, }, }) }
func TestState_basic(t *testing.T) { resource.UnitTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccState_basic, Check: resource.ComposeTestCheckFunc( testAccCheckStateValue( "terraform_remote_state.foo", "foo", "bar"), ), }, }, }) }
func TestResource_ignoreChangesMap(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" required_map = { key = "value" } optional_computed_map { foo = "bar" } lifecycle { ignore_changes = ["optional_computed_map"] } } `), Check: func(s *terraform.State) error { return nil }, }, resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" required_map = { key = "value" } optional_computed_map { foo = "bar" no = "update" } lifecycle { ignore_changes = ["optional_computed_map"] } } `), Check: func(s *terraform.State) error { return nil }, }, }, }) }
func TestDataSource_dataSourceCount(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: func(s *terraform.State) error { return nil }, Steps: []resource.TestStep{ { Config: strings.TrimSpace(` data "test_data_source" "test" { count = 3 input = "count-${count.index}" } resource "test_resource" "foo" { required = "yep" required_map = { key = "value" } list = ["${data.test_data_source.test.*.output}"] } `), Check: func(s *terraform.State) error { res, hasRes := s.RootModule().Resources["test_resource.foo"] if !hasRes { return errors.New("No test_resource.foo in state") } if res.Primary.Attributes["list.#"] != "3" { return errors.New("Wrong list.#, expected 3") } if res.Primary.Attributes["list.0"] != "count-0" { return errors.New("Wrong list.0, expected count-0") } if res.Primary.Attributes["list.1"] != "count-1" { return errors.New("Wrong list.0, expected count-1") } if res.Primary.Attributes["list.2"] != "count-2" { return errors.New("Wrong list.0, expected count-2") } return nil }, }, }, }) }
func TestDataSource_basic(t *testing.T) { programPath, err := buildDataSourceTestProgram() if err != nil { t.Fatal(err) return } resource.UnitTest(t, resource.TestCase{ Providers: testProviders, Steps: []resource.TestStep{ resource.TestStep{ Config: fmt.Sprintf(testDataSourceConfig_basic, programPath), Check: func(s *terraform.State) error { _, ok := s.RootModule().Resources["data.external.test"] if !ok { return fmt.Errorf("missing data resource") } outputs := s.RootModule().Outputs if outputs["argument"] == nil { return fmt.Errorf("missing 'argument' output") } if outputs["query_value"] == nil { return fmt.Errorf("missing 'query_value' output") } if outputs["argument"].Value != "cheese" { return fmt.Errorf( "'argument' output is %q; want 'cheese'", outputs["argument"].Value, ) } if outputs["query_value"].Value != "pizza" { return fmt.Errorf( "'query_value' output is %q; want 'pizza'", outputs["query_value"].Value, ) } return nil }, }, }, }) }
func TestDataSource_error(t *testing.T) { programPath, err := buildDataSourceTestProgram() if err != nil { t.Fatal(err) return } resource.UnitTest(t, resource.TestCase{ Providers: testProviders, Steps: []resource.TestStep{ resource.TestStep{ Config: fmt.Sprintf(testDataSourceConfig_error, programPath), ExpectError: regexp.MustCompile("I was asked to fail"), }, }, }) }
func TestState_complexOutputs(t *testing.T) { resource.UnitTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, Steps: []resource.TestStep{ { Config: testAccState_complexOutputs, Check: resource.ComposeTestCheckFunc( testAccCheckStateValue("terraform_remote_state.foo", "backend", "_local"), testAccCheckStateValue("terraform_remote_state.foo", "config.path", "./test-fixtures/complex_outputs.tfstate"), testAccCheckStateValue("terraform_remote_state.foo", "computed_set.#", "2"), testAccCheckStateValue("terraform_remote_state.foo", `map.%`, "2"), testAccCheckStateValue("terraform_remote_state.foo", `map.key`, "test"), ), }, }, }) }
func TestResource_basic(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" } `), Check: func(s *terraform.State) error { return nil }, }, }, }) }
// Covers specific scenario in #6005, handled by normalizing boolean strings in // helper/schema func TestResource_ignoreChangesForceNewBoolean(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" required_map = { key = "value" } optional_force_new = "one" optional_bool = true lifecycle { ignore_changes = ["optional_force_new"] } } `), Check: func(s *terraform.State) error { return nil }, }, resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" required_map = { key = "value" } optional_force_new = "two" optional_bool = true lifecycle { ignore_changes = ["optional_force_new"] } } `), Check: func(s *terraform.State) error { return nil }, }, }, }) }
// Targeted test in TestContext2Apply_ignoreChangesCreate func TestResource_ignoreChangesRequired(t *testing.T) { resource.UnitTest(t, resource.TestCase{ Providers: testAccProviders, CheckDestroy: testAccCheckResourceDestroy, Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` resource "test_resource" "foo" { required = "yep" lifecycle { ignore_changes = ["required"] } } `), Check: func(s *terraform.State) error { return nil }, }, }, }) }
func TestRender(t *testing.T) { testCases := []struct { ResourceBlock string Expected string }{ { `data "template_cloudinit_config" "foo" { gzip = false base64_encode = false part { content_type = "text/x-shellscript" content = "baz" } }`, "Content-Type: multipart/mixed; boundary=\"MIMEBOUNDARY\"\nMIME-Version: 1.0\r\n--MIMEBOUNDARY\r\nContent-Transfer-Encoding: 7bit\r\nContent-Type: text/x-shellscript\r\nMime-Version: 1.0\r\n\r\nbaz\r\n--MIMEBOUNDARY--\r\n", }, { `data "template_cloudinit_config" "foo" { gzip = false base64_encode = false part { content_type = "text/x-shellscript" content = "baz" filename = "foobar.sh" } }`, "Content-Type: multipart/mixed; boundary=\"MIMEBOUNDARY\"\nMIME-Version: 1.0\r\n--MIMEBOUNDARY\r\nContent-Disposition: attachment; filename=\"foobar.sh\"\r\nContent-Transfer-Encoding: 7bit\r\nContent-Type: text/x-shellscript\r\nMime-Version: 1.0\r\n\r\nbaz\r\n--MIMEBOUNDARY--\r\n", }, { `data "template_cloudinit_config" "foo" { gzip = false base64_encode = false part { content_type = "text/x-shellscript" content = "baz" } part { content_type = "text/x-shellscript" content = "ffbaz" } }`, "Content-Type: multipart/mixed; boundary=\"MIMEBOUNDARY\"\nMIME-Version: 1.0\r\n--MIMEBOUNDARY\r\nContent-Transfer-Encoding: 7bit\r\nContent-Type: text/x-shellscript\r\nMime-Version: 1.0\r\n\r\nbaz\r\n--MIMEBOUNDARY\r\nContent-Transfer-Encoding: 7bit\r\nContent-Type: text/x-shellscript\r\nMime-Version: 1.0\r\n\r\nffbaz\r\n--MIMEBOUNDARY--\r\n", }, } for _, tt := range testCases { r.UnitTest(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ r.TestStep{ Config: tt.ResourceBlock, Check: r.ComposeTestCheckFunc( r.TestCheckResourceAttr("data.template_cloudinit_config.foo", "rendered", tt.Expected), ), }, }, }) } }
func TestCertRequest(t *testing.T) { r.UnitTest(t, r.TestCase{ Providers: testProviders, Steps: []r.TestStep{ r.TestStep{ Config: fmt.Sprintf(` data "tls_cert_request" "test" { subject { common_name = "example.com" organization = "Example, Inc" organizational_unit = "Department of Terraform Testing" street_address = ["5879 Cotton Link"] locality = "Pirate Harbor" province = "CA" country = "US" postal_code = "95559-1227" serial_number = "2" } dns_names = [ "example.com", "example.net", ] ip_addresses = [ "127.0.0.1", "127.0.0.2", ] key_algorithm = "RSA" private_key_pem = <<EOT %s EOT } output "key_pem" { value = "${data.tls_cert_request.test.cert_request_pem}" } `, testPrivateKey), Check: func(s *terraform.State) error { gotUntyped := s.RootModule().Outputs["key_pem"].Value got, ok := gotUntyped.(string) if !ok { return fmt.Errorf("output for \"key_pem\" is not a string") } if !strings.HasPrefix(got, "-----BEGIN CERTIFICATE REQUEST----") { return fmt.Errorf("key is missing CSR PEM preamble") } block, _ := pem.Decode([]byte(got)) csr, err := x509.ParseCertificateRequest(block.Bytes) if err != nil { return fmt.Errorf("error parsing CSR: %s", err) } if expected, got := "2", csr.Subject.SerialNumber; got != expected { return fmt.Errorf("incorrect subject serial number: expected %v, got %v", expected, got) } if expected, got := "example.com", csr.Subject.CommonName; got != expected { return fmt.Errorf("incorrect subject common name: expected %v, got %v", expected, got) } if expected, got := "Example, Inc", csr.Subject.Organization[0]; got != expected { return fmt.Errorf("incorrect subject organization: expected %v, got %v", expected, got) } if expected, got := "Department of Terraform Testing", csr.Subject.OrganizationalUnit[0]; got != expected { return fmt.Errorf("incorrect subject organizational unit: expected %v, got %v", expected, got) } if expected, got := "5879 Cotton Link", csr.Subject.StreetAddress[0]; got != expected { return fmt.Errorf("incorrect subject street address: expected %v, got %v", expected, got) } if expected, got := "Pirate Harbor", csr.Subject.Locality[0]; got != expected { return fmt.Errorf("incorrect subject locality: expected %v, got %v", expected, got) } if expected, got := "CA", csr.Subject.Province[0]; got != expected { return fmt.Errorf("incorrect subject province: expected %v, got %v", expected, got) } if expected, got := "US", csr.Subject.Country[0]; got != expected { return fmt.Errorf("incorrect subject country: expected %v, got %v", expected, got) } if expected, got := "95559-1227", csr.Subject.PostalCode[0]; got != expected { return fmt.Errorf("incorrect subject postal code: expected %v, got %v", expected, got) } if expected, got := 2, len(csr.DNSNames); got != expected { return fmt.Errorf("incorrect number of DNS names: expected %v, got %v", expected, got) } if expected, got := "example.com", csr.DNSNames[0]; got != expected { return fmt.Errorf("incorrect DNS name 0: expected %v, got %v", expected, got) } if expected, got := "example.net", csr.DNSNames[1]; got != expected { return fmt.Errorf("incorrect DNS name 0: expected %v, got %v", expected, got) } if expected, got := 2, len(csr.IPAddresses); got != expected { return fmt.Errorf("incorrect number of IP addresses: expected %v, got %v", expected, got) } if expected, got := "127.0.0.1", csr.IPAddresses[0].String(); got != expected { return fmt.Errorf("incorrect IP address 0: expected %v, got %v", expected, got) } if expected, got := "127.0.0.2", csr.IPAddresses[1].String(); got != expected { return fmt.Errorf("incorrect IP address 0: expected %v, got %v", expected, got) } return nil }, }, }, }) }