@@ -1564,6 +1564,7 @@ import {
15641564 t .Fatalf ("unexpected errors\n %s" , diags .Err ().Error ())
15651565 }
15661566}
1567+
15671568func TestContext2Plan_importDuringDestroy (t * testing.T ) {
15681569 m := testModuleInline (t , map [string ]string {
15691570 "main.tf" : `
@@ -1628,3 +1629,130 @@ func TestContext2Plan_importDuringDestroy(t *testing.T) {
16281629 t .Fatalf ("unexpected errors\n %s" , diags .Err ().Error ())
16291630 }
16301631}
1632+
1633+ func TestContext2Plan_importSelfReference (t * testing.T ) {
1634+ m := testModuleInline (t , map [string ]string {
1635+ "main.tf" : `
1636+ import {
1637+ to = test_object.a
1638+ id = test_object.a.test_string
1639+ }
1640+
1641+ resource "test_object" "a" {
1642+ test_string = "foo"
1643+ }
1644+ ` ,
1645+ })
1646+
1647+ p := simpleMockProvider ()
1648+ ctx := testContext2 (t , & ContextOpts {
1649+ Providers : map [addrs.Provider ]providers.Factory {
1650+ // The providers never actually going to get called here, we should
1651+ // catch the error long before anything happens.
1652+ addrs .NewDefaultProvider ("test" ): testProviderFuncFixed (p ),
1653+ },
1654+ })
1655+
1656+ _ , diags := ctx .Plan (m , states .NewState (), DefaultPlanOpts )
1657+
1658+ // We're expecting exactly one diag, which is the self-reference error.
1659+ if len (diags ) != 1 {
1660+ t .Fatalf ("expected one diag, got %d" , len (diags ))
1661+ }
1662+
1663+ got , want := diags .Err ().Error (), "Invalid import id argument: The import ID cannot reference the resource being imported."
1664+ if cmp .Diff (want , got ) != "" {
1665+ t .Fatalf ("unexpected error\n %s" , cmp .Diff (want , got ))
1666+ }
1667+ }
1668+
1669+ func TestContext2Plan_importSelfReferenceInst (t * testing.T ) {
1670+ m := testModuleInline (t , map [string ]string {
1671+ "main.tf" : `
1672+ import {
1673+ to = test_object.a[0]
1674+ id = test_object.a.test_string
1675+ }
1676+
1677+ resource "test_object" "a" {
1678+ count = 1
1679+ test_string = "foo"
1680+ }
1681+ ` ,
1682+ })
1683+
1684+ p := simpleMockProvider ()
1685+ ctx := testContext2 (t , & ContextOpts {
1686+ Providers : map [addrs.Provider ]providers.Factory {
1687+ // The providers never actually going to get called here, we should
1688+ // catch the error long before anything happens.
1689+ addrs .NewDefaultProvider ("test" ): testProviderFuncFixed (p ),
1690+ },
1691+ })
1692+
1693+ _ , diags := ctx .Plan (m , states .NewState (), DefaultPlanOpts )
1694+
1695+ // We're expecting exactly one diag, which is the self-reference error.
1696+ if len (diags ) != 1 {
1697+ t .Fatalf ("expected one diag, got %d: %s" , len (diags ), diags .ErrWithWarnings ())
1698+ }
1699+
1700+ got , want := diags .Err ().Error (), "Invalid import id argument: The import ID cannot reference the resource being imported."
1701+ if cmp .Diff (want , got ) != "" {
1702+ t .Fatalf ("unexpected error\n %s" , cmp .Diff (want , got ))
1703+ }
1704+ }
1705+
1706+ func TestContext2Plan_importSelfReferenceInModule (t * testing.T ) {
1707+ m := testModuleInline (t , map [string ]string {
1708+ "main.tf" : `
1709+ import {
1710+ to = module.mod.test_object.a
1711+ id = module.mod.foo
1712+ }
1713+
1714+ module "mod" {
1715+ source = "./mod"
1716+ }
1717+ ` ,
1718+ "mod/main.tf" : `
1719+ resource "test_object" "a" {
1720+ test_string = "foo"
1721+ }
1722+
1723+ output "foo" {
1724+ value = test_object.a.test_string
1725+ }
1726+ ` ,
1727+ })
1728+
1729+ p := simpleMockProvider ()
1730+ ctx := testContext2 (t , & ContextOpts {
1731+ Providers : map [addrs.Provider ]providers.Factory {
1732+ // The providers never actually going to get called here, we should
1733+ // catch the error long before anything happens.
1734+ addrs .NewDefaultProvider ("test" ): testProviderFuncFixed (p ),
1735+ },
1736+ })
1737+
1738+ _ , diags := ctx .Plan (m , states .NewState (), DefaultPlanOpts )
1739+
1740+ // We're expecting exactly one diag, which is the self-reference error.
1741+ if len (diags ) != 1 {
1742+ t .Fatalf ("expected one diag, got %d" , len (diags ))
1743+ }
1744+
1745+ // Terraform detects this case as a cycle, and the order of rendering the
1746+ // cycle if non-deterministic, so we can't do a straight string match.
1747+
1748+ got := diags .Err ().Error ()
1749+ if ! strings .Contains (got , "Cycle:" ) {
1750+ t .Errorf ("should have reported a cycle error, but got %s" , got )
1751+ }
1752+ if ! strings .Contains (got , "module.mod.output.foo (expand)" ) {
1753+ t .Errorf ("should have reported the cycle to contain the module output, but got %s" , got )
1754+ }
1755+ if ! strings .Contains (got , "module.mod.test_object.a (expand)" ) {
1756+ t .Errorf ("should have reported the cycle to contain the target resource, but got %s" , got )
1757+ }
1758+ }
0 commit comments