providers/test: Add count resource <-> data source dep count scale tests
These tests cover the new refresh behaviour and would fail with "index out of range" if the refresh graph is not expanded to take new resources into account as well (scale out), or if it does not with expanded count orphans in a way that makes sure they don't get interpolated when walked (scale in).
This commit is contained in:
parent
7b1618efde
commit
f63ad1dbd1
|
@ -0,0 +1,224 @@
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestResourceDataDep_alignedCountScaleOut tests to make sure interpolation
|
||||||
|
// works (namely without index errors) when a data source and a resource share
|
||||||
|
// the same count variable during scale-out with an existing state.
|
||||||
|
func TestResourceDataDep_alignedCountScaleOut(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testResourceDataDepConfig(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testResourceDataDepConfig(4),
|
||||||
|
Check: resource.TestCheckOutput("out", "value_from_api,value_from_api,value_from_api,value_from_api"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestResourceDataDep_alignedCountScaleIn tests to make sure interpolation
|
||||||
|
// works (namely without index errors) when a data source and a resource share
|
||||||
|
// the same count variable during scale-in with an existing state.
|
||||||
|
func TestResourceDataDep_alignedCountScaleIn(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testResourceDataDepConfig(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testResourceDataDepConfig(2),
|
||||||
|
Check: resource.TestCheckOutput("out", "value_from_api,value_from_api"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDataResourceDep_alignedCountScaleOut functions like
|
||||||
|
// TestResourceDataDep_alignedCountScaleOut, but with the dependencies swapped
|
||||||
|
// (resource now depends on data source, a pretty regular use case, but
|
||||||
|
// included here to check for regressions).
|
||||||
|
func TestDataResourceDep_alignedCountScaleOut(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testDataResourceDepConfig(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testDataResourceDepConfig(4),
|
||||||
|
Check: resource.TestCheckOutput("out", "test,test,test,test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDataResourceDep_alignedCountScaleIn functions like
|
||||||
|
// TestResourceDataDep_alignedCountScaleIn, but with the dependencies swapped
|
||||||
|
// (resource now depends on data source, a pretty regular use case, but
|
||||||
|
// included here to check for regressions).
|
||||||
|
func TestDataResourceDep_alignedCountScaleIn(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testDataResourceDepConfig(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testDataResourceDepConfig(2),
|
||||||
|
Check: resource.TestCheckOutput("out", "test,test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestResourceResourceDep_alignedCountScaleOut functions like
|
||||||
|
// TestResourceDataDep_alignedCountScaleOut, but with a resource-to-resource
|
||||||
|
// dependency instead, a pretty regular use case, but included here to check
|
||||||
|
// for regressions.
|
||||||
|
func TestResourceResourceDep_alignedCountScaleOut(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testResourceResourceDepConfig(2),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testResourceResourceDepConfig(4),
|
||||||
|
Check: resource.TestCheckOutput("out", "test,test,test,test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestResourceResourceDep_alignedCountScaleIn functions like
|
||||||
|
// TestResourceDataDep_alignedCountScaleIn, but with a resource-to-resource
|
||||||
|
// dependency instead, a pretty regular use case, but included here to check
|
||||||
|
// for regressions.
|
||||||
|
func TestResourceResourceDep_alignedCountScaleIn(t *testing.T) {
|
||||||
|
resource.UnitTest(t, resource.TestCase{
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: func(s *terraform.State) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testResourceResourceDepConfig(4),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Config: testResourceResourceDepConfig(2),
|
||||||
|
Check: resource.TestCheckOutput("out", "test,test"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testResourceDataDepConfig(count int) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
variable count {
|
||||||
|
default = "%d"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "foo" {
|
||||||
|
count = "${var.count}"
|
||||||
|
required = "yes"
|
||||||
|
|
||||||
|
required_map = {
|
||||||
|
"foo" = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "test_data_source" "bar" {
|
||||||
|
count = "${var.count}"
|
||||||
|
input = "${test_resource.foo.*.computed_read_only[count.index]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "out" {
|
||||||
|
value = "${join(",", data.test_data_source.bar.*.output)}"
|
||||||
|
}
|
||||||
|
`, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testDataResourceDepConfig(count int) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
variable count {
|
||||||
|
default = "%d"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "test_data_source" "foo" {
|
||||||
|
count = "${var.count}"
|
||||||
|
input = "test"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "bar" {
|
||||||
|
count = "${var.count}"
|
||||||
|
required = "yes"
|
||||||
|
optional = "${data.test_data_source.foo.*.output[count.index]}"
|
||||||
|
|
||||||
|
required_map = {
|
||||||
|
"foo" = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "out" {
|
||||||
|
value = "${join(",", test_resource.bar.*.optional)}"
|
||||||
|
}
|
||||||
|
`, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testResourceResourceDepConfig(count int) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
variable count {
|
||||||
|
default = "%d"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "foo" {
|
||||||
|
count = "${var.count}"
|
||||||
|
required = "yes"
|
||||||
|
optional = "test"
|
||||||
|
|
||||||
|
required_map = {
|
||||||
|
"foo" = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "test_resource" "bar" {
|
||||||
|
count = "${var.count}"
|
||||||
|
required = "yes"
|
||||||
|
optional = "${test_resource.foo.*.optional[count.index]}"
|
||||||
|
|
||||||
|
required_map = {
|
||||||
|
"foo" = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "out" {
|
||||||
|
value = "${join(",", test_resource.bar.*.optional)}"
|
||||||
|
}
|
||||||
|
`, count)
|
||||||
|
}
|
Loading…
Reference in New Issue