github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/context_apply_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"log"
     9  	"reflect"
    10  	"runtime"
    11  	"sort"
    12  	"strings"
    13  	"sync"
    14  	"sync/atomic"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/davecgh/go-spew/spew"
    19  	"github.com/go-test/deep"
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
    22  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs"
    23  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/configschema"
    24  	"github.com/hashicorp/terraform-plugin-sdk/internal/configs/hcl2shim"
    25  	"github.com/hashicorp/terraform-plugin-sdk/internal/plans"
    26  	"github.com/hashicorp/terraform-plugin-sdk/internal/providers"
    27  	"github.com/hashicorp/terraform-plugin-sdk/internal/provisioners"
    28  	"github.com/hashicorp/terraform-plugin-sdk/internal/states"
    29  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
    30  	"github.com/zclconf/go-cty/cty"
    31  )
    32  
    33  func TestContext2Apply_basic(t *testing.T) {
    34  	m := testModule(t, "apply-good")
    35  	p := testProvider("aws")
    36  	p.ApplyFn = testApplyFn
    37  	p.DiffFn = testDiffFn
    38  	ctx := testContext2(t, &ContextOpts{
    39  		Config: m,
    40  		ProviderResolver: providers.ResolverFixed(
    41  			map[string]providers.Factory{
    42  				"aws": testProviderFuncFixed(p),
    43  			},
    44  		),
    45  	})
    46  
    47  	if _, diags := ctx.Plan(); diags.HasErrors() {
    48  		t.Fatalf("plan errors: %s", diags.Err())
    49  	}
    50  
    51  	state, diags := ctx.Apply()
    52  	if diags.HasErrors() {
    53  		t.Fatalf("diags: %s", diags.Err())
    54  	}
    55  
    56  	mod := state.RootModule()
    57  	if len(mod.Resources) < 2 {
    58  		t.Fatalf("bad: %#v", mod.Resources)
    59  	}
    60  
    61  	actual := strings.TrimSpace(state.String())
    62  	expected := strings.TrimSpace(testTerraformApplyStr)
    63  	if actual != expected {
    64  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
    65  	}
    66  }
    67  
    68  func TestContext2Apply_unstable(t *testing.T) {
    69  	// This tests behavior when the configuration contains an unstable value,
    70  	// such as the result of uuid() or timestamp(), where each call produces
    71  	// a different result.
    72  	//
    73  	// This is an important case to test because we need to ensure that
    74  	// we don't re-call the function during the apply phase: the value should
    75  	// be fixed during plan
    76  
    77  	m := testModule(t, "apply-unstable")
    78  	p := testProvider("test")
    79  	p.ApplyFn = testApplyFn
    80  	p.DiffFn = testDiffFn
    81  	ctx := testContext2(t, &ContextOpts{
    82  		Config: m,
    83  		ProviderResolver: providers.ResolverFixed(
    84  			map[string]providers.Factory{
    85  				"test": testProviderFuncFixed(p),
    86  			},
    87  		),
    88  	})
    89  
    90  	plan, diags := ctx.Plan()
    91  	if diags.HasErrors() {
    92  		t.Fatalf("unexpected error during Plan: %s", diags.Err())
    93  	}
    94  
    95  	addr := addrs.Resource{
    96  		Mode: addrs.ManagedResourceMode,
    97  		Type: "test_resource",
    98  		Name: "foo",
    99  	}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance)
   100  	schema := p.GetSchemaReturn.ResourceTypes["test_resource"] // automatically available in mock
   101  	rds := plan.Changes.ResourceInstance(addr)
   102  	rd, err := rds.Decode(schema.ImpliedType())
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	if rd.After.GetAttr("random").IsKnown() {
   107  		t.Fatalf("Attribute 'random' has known value %#v; should be unknown in plan", rd.After.GetAttr("random"))
   108  	}
   109  
   110  	state, diags := ctx.Apply()
   111  	if diags.HasErrors() {
   112  		t.Fatalf("unexpected error during Apply: %s", diags.Err())
   113  	}
   114  
   115  	mod := state.Module(addr.Module)
   116  	rss := state.ResourceInstance(addr)
   117  
   118  	if len(mod.Resources) != 1 {
   119  		t.Fatalf("wrong number of resources %d; want 1", len(mod.Resources))
   120  	}
   121  
   122  	rs, err := rss.Current.Decode(schema.ImpliedType())
   123  	got := rs.Value.GetAttr("random")
   124  	if !got.IsKnown() {
   125  		t.Fatalf("random is still unknown after apply")
   126  	}
   127  	if got, want := len(got.AsString()), 36; got != want {
   128  		t.Fatalf("random string has wrong length %d; want %d", got, want)
   129  	}
   130  }
   131  
   132  func TestContext2Apply_escape(t *testing.T) {
   133  	m := testModule(t, "apply-escape")
   134  	p := testProvider("aws")
   135  	p.ApplyFn = testApplyFn
   136  	p.DiffFn = testDiffFn
   137  	ctx := testContext2(t, &ContextOpts{
   138  		Config: m,
   139  		ProviderResolver: providers.ResolverFixed(
   140  			map[string]providers.Factory{
   141  				"aws": testProviderFuncFixed(p),
   142  			},
   143  		),
   144  	})
   145  
   146  	if _, diags := ctx.Plan(); diags.HasErrors() {
   147  		t.Fatalf("plan errors: %s", diags.Err())
   148  	}
   149  
   150  	state, diags := ctx.Apply()
   151  	if diags.HasErrors() {
   152  		t.Fatalf("diags: %s", diags.Err())
   153  	}
   154  
   155  	checkStateString(t, state, `
   156  aws_instance.bar:
   157    ID = foo
   158    provider = provider.aws
   159    foo = "bar"
   160    type = aws_instance
   161  `)
   162  }
   163  
   164  func TestContext2Apply_resourceCountOneList(t *testing.T) {
   165  	m := testModule(t, "apply-resource-count-one-list")
   166  	p := testProvider("null")
   167  	p.ApplyFn = testApplyFn
   168  	p.DiffFn = testDiffFn
   169  	ctx := testContext2(t, &ContextOpts{
   170  		Config: m,
   171  		ProviderResolver: providers.ResolverFixed(
   172  			map[string]providers.Factory{
   173  				"null": testProviderFuncFixed(p),
   174  			},
   175  		),
   176  	})
   177  
   178  	if _, diags := ctx.Plan(); diags.HasErrors() {
   179  		t.Fatalf("plan errors: %s", diags.Err())
   180  	}
   181  
   182  	state, diags := ctx.Apply()
   183  	assertNoDiagnostics(t, diags)
   184  
   185  	got := strings.TrimSpace(state.String())
   186  	want := strings.TrimSpace(`null_resource.foo.0:
   187    ID = foo
   188    provider = provider.null
   189  
   190  Outputs:
   191  
   192  test = [foo]`)
   193  	if got != want {
   194  		t.Fatalf("got:\n%s\n\nwant:\n%s\n", got, want)
   195  	}
   196  }
   197  func TestContext2Apply_resourceCountZeroList(t *testing.T) {
   198  	m := testModule(t, "apply-resource-count-zero-list")
   199  	p := testProvider("null")
   200  	p.ApplyFn = testApplyFn
   201  	p.DiffFn = testDiffFn
   202  	ctx := testContext2(t, &ContextOpts{
   203  		Config: m,
   204  		ProviderResolver: providers.ResolverFixed(
   205  			map[string]providers.Factory{
   206  				"null": testProviderFuncFixed(p),
   207  			},
   208  		),
   209  	})
   210  
   211  	if _, diags := ctx.Plan(); diags.HasErrors() {
   212  		t.Fatalf("plan errors: %s", diags.Err())
   213  	}
   214  
   215  	state, diags := ctx.Apply()
   216  	if diags.HasErrors() {
   217  		t.Fatalf("diags: %s", diags.Err())
   218  	}
   219  
   220  	got := strings.TrimSpace(state.String())
   221  	want := strings.TrimSpace(`Outputs:
   222  
   223  test = []`)
   224  	if got != want {
   225  		t.Fatalf("wrong state\n\ngot:\n%s\n\nwant:\n%s\n", got, want)
   226  	}
   227  }
   228  
   229  func TestContext2Apply_resourceDependsOnModule(t *testing.T) {
   230  	m := testModule(t, "apply-resource-depends-on-module")
   231  	p := testProvider("aws")
   232  	p.DiffFn = testDiffFn
   233  
   234  	// verify the apply happens in the correct order
   235  	var mu sync.Mutex
   236  	var order []string
   237  
   238  	p.ApplyFn = func(
   239  		info *InstanceInfo,
   240  		is *InstanceState,
   241  		id *InstanceDiff) (*InstanceState, error) {
   242  
   243  		if id.Attributes["ami"].New == "child" {
   244  
   245  			// make the child slower than the parent
   246  			time.Sleep(50 * time.Millisecond)
   247  
   248  			mu.Lock()
   249  			order = append(order, "child")
   250  			mu.Unlock()
   251  		} else {
   252  			mu.Lock()
   253  			order = append(order, "parent")
   254  			mu.Unlock()
   255  		}
   256  
   257  		return testApplyFn(info, is, id)
   258  	}
   259  
   260  	ctx := testContext2(t, &ContextOpts{
   261  		Config: m,
   262  		ProviderResolver: providers.ResolverFixed(
   263  			map[string]providers.Factory{
   264  				"aws": testProviderFuncFixed(p),
   265  			},
   266  		),
   267  	})
   268  
   269  	if _, diags := ctx.Plan(); diags.HasErrors() {
   270  		t.Fatalf("plan errors: %s", diags.Err())
   271  	}
   272  
   273  	state, diags := ctx.Apply()
   274  	if diags.HasErrors() {
   275  		t.Fatalf("diags: %s", diags.Err())
   276  	}
   277  
   278  	if !reflect.DeepEqual(order, []string{"child", "parent"}) {
   279  		t.Fatal("resources applied out of order")
   280  	}
   281  
   282  	checkStateString(t, state, testTerraformApplyResourceDependsOnModuleStr)
   283  }
   284  
   285  // Test that without a config, the Dependencies in the state are enough
   286  // to maintain proper ordering.
   287  func TestContext2Apply_resourceDependsOnModuleStateOnly(t *testing.T) {
   288  	m := testModule(t, "apply-resource-depends-on-module-empty")
   289  	p := testProvider("aws")
   290  	p.DiffFn = testDiffFn
   291  
   292  	state := MustShimLegacyState(&State{
   293  		Modules: []*ModuleState{
   294  			{
   295  				Path: rootModulePath,
   296  				Resources: map[string]*ResourceState{
   297  					"aws_instance.a": {
   298  						Type: "aws_instance",
   299  						Primary: &InstanceState{
   300  							ID: "parent",
   301  						},
   302  						Dependencies: []string{"module.child"},
   303  						Provider:     "provider.aws",
   304  					},
   305  				},
   306  			},
   307  			{
   308  				Path: []string{"root", "child"},
   309  				Resources: map[string]*ResourceState{
   310  					"aws_instance.child": {
   311  						Type: "aws_instance",
   312  						Primary: &InstanceState{
   313  							ID: "child",
   314  						},
   315  						Provider: "provider.aws",
   316  					},
   317  				},
   318  			},
   319  		},
   320  	})
   321  
   322  	{
   323  		// verify the apply happens in the correct order
   324  		var mu sync.Mutex
   325  		var order []string
   326  
   327  		p.ApplyFn = func(
   328  			info *InstanceInfo,
   329  			is *InstanceState,
   330  			id *InstanceDiff) (*InstanceState, error) {
   331  
   332  			if is.ID == "parent" {
   333  				// make the dep slower than the parent
   334  				time.Sleep(50 * time.Millisecond)
   335  
   336  				mu.Lock()
   337  				order = append(order, "child")
   338  				mu.Unlock()
   339  			} else {
   340  				mu.Lock()
   341  				order = append(order, "parent")
   342  				mu.Unlock()
   343  			}
   344  
   345  			return testApplyFn(info, is, id)
   346  		}
   347  
   348  		ctx := testContext2(t, &ContextOpts{
   349  			Config: m,
   350  			ProviderResolver: providers.ResolverFixed(
   351  				map[string]providers.Factory{
   352  					"aws": testProviderFuncFixed(p),
   353  				},
   354  			),
   355  			State: state,
   356  		})
   357  
   358  		if _, diags := ctx.Plan(); diags.HasErrors() {
   359  			t.Fatalf("diags: %s", diags.Err())
   360  		}
   361  
   362  		state, diags := ctx.Apply()
   363  		assertNoErrors(t, diags)
   364  
   365  		if !reflect.DeepEqual(order, []string{"child", "parent"}) {
   366  			t.Fatal("resources applied out of order")
   367  		}
   368  
   369  		checkStateString(t, state, "<no state>")
   370  	}
   371  }
   372  
   373  func TestContext2Apply_resourceDependsOnModuleDestroy(t *testing.T) {
   374  	m := testModule(t, "apply-resource-depends-on-module")
   375  	p := testProvider("aws")
   376  	p.DiffFn = testDiffFn
   377  
   378  	var globalState *states.State
   379  	{
   380  		p.ApplyFn = testApplyFn
   381  		ctx := testContext2(t, &ContextOpts{
   382  			Config: m,
   383  			ProviderResolver: providers.ResolverFixed(
   384  				map[string]providers.Factory{
   385  					"aws": testProviderFuncFixed(p),
   386  				},
   387  			),
   388  		})
   389  
   390  		if _, diags := ctx.Plan(); diags.HasErrors() {
   391  			t.Fatalf("diags: %s", diags.Err())
   392  		}
   393  
   394  		state, diags := ctx.Apply()
   395  		if diags.HasErrors() {
   396  			t.Fatalf("diags: %s", diags.Err())
   397  		}
   398  
   399  		globalState = state
   400  	}
   401  
   402  	{
   403  		// Wait for the dependency, sleep, and verify the graph never
   404  		// called a child.
   405  		var called int32
   406  		var checked bool
   407  		p.ApplyFn = func(
   408  			info *InstanceInfo,
   409  			is *InstanceState,
   410  			id *InstanceDiff) (*InstanceState, error) {
   411  
   412  			if is.Attributes["ami"] == "parent" {
   413  				checked = true
   414  
   415  				// Sleep to allow parallel execution
   416  				time.Sleep(50 * time.Millisecond)
   417  
   418  				// Verify that called is 0 (dep not called)
   419  				if atomic.LoadInt32(&called) != 0 {
   420  					return nil, fmt.Errorf("module child should not be called")
   421  				}
   422  			}
   423  
   424  			atomic.AddInt32(&called, 1)
   425  			return testApplyFn(info, is, id)
   426  		}
   427  
   428  		ctx := testContext2(t, &ContextOpts{
   429  			Config: m,
   430  			ProviderResolver: providers.ResolverFixed(
   431  				map[string]providers.Factory{
   432  					"aws": testProviderFuncFixed(p),
   433  				},
   434  			),
   435  			State:   globalState,
   436  			Destroy: true,
   437  		})
   438  
   439  		if _, diags := ctx.Plan(); diags.HasErrors() {
   440  			t.Fatalf("diags: %s", diags.Err())
   441  		}
   442  
   443  		state, diags := ctx.Apply()
   444  		if diags.HasErrors() {
   445  			t.Fatalf("diags: %s", diags.Err())
   446  		}
   447  
   448  		if !checked {
   449  			t.Fatal("should check")
   450  		}
   451  
   452  		checkStateString(t, state, `<no state>`)
   453  	}
   454  }
   455  
   456  func TestContext2Apply_resourceDependsOnModuleGrandchild(t *testing.T) {
   457  	m := testModule(t, "apply-resource-depends-on-module-deep")
   458  	p := testProvider("aws")
   459  	p.DiffFn = testDiffFn
   460  
   461  	{
   462  		// Wait for the dependency, sleep, and verify the graph never
   463  		// called a child.
   464  		var called int32
   465  		var checked bool
   466  		p.ApplyFn = func(
   467  			info *InstanceInfo,
   468  			is *InstanceState,
   469  			id *InstanceDiff) (*InstanceState, error) {
   470  
   471  			if id.Attributes["ami"].New == "grandchild" {
   472  				checked = true
   473  
   474  				// Sleep to allow parallel execution
   475  				time.Sleep(50 * time.Millisecond)
   476  
   477  				// Verify that called is 0 (dep not called)
   478  				if atomic.LoadInt32(&called) != 0 {
   479  					return nil, fmt.Errorf("aws_instance.a should not be called")
   480  				}
   481  			}
   482  
   483  			atomic.AddInt32(&called, 1)
   484  			return testApplyFn(info, is, id)
   485  		}
   486  
   487  		ctx := testContext2(t, &ContextOpts{
   488  			Config: m,
   489  			ProviderResolver: providers.ResolverFixed(
   490  				map[string]providers.Factory{
   491  					"aws": testProviderFuncFixed(p),
   492  				},
   493  			),
   494  		})
   495  
   496  		if _, diags := ctx.Plan(); diags.HasErrors() {
   497  			t.Fatalf("diags: %s", diags.Err())
   498  		}
   499  
   500  		state, diags := ctx.Apply()
   501  		if diags.HasErrors() {
   502  			t.Fatalf("diags: %s", diags.Err())
   503  		}
   504  
   505  		if !checked {
   506  			t.Fatal("should check")
   507  		}
   508  
   509  		checkStateString(t, state, testTerraformApplyResourceDependsOnModuleDeepStr)
   510  	}
   511  }
   512  
   513  func TestContext2Apply_resourceDependsOnModuleInModule(t *testing.T) {
   514  	m := testModule(t, "apply-resource-depends-on-module-in-module")
   515  	p := testProvider("aws")
   516  	p.DiffFn = testDiffFn
   517  
   518  	{
   519  		// Wait for the dependency, sleep, and verify the graph never
   520  		// called a child.
   521  		var called int32
   522  		var checked bool
   523  		p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
   524  			if id.Attributes["ami"].New == "grandchild" {
   525  				checked = true
   526  
   527  				// Sleep to allow parallel execution
   528  				time.Sleep(50 * time.Millisecond)
   529  
   530  				// Verify that called is 0 (dep not called)
   531  				if atomic.LoadInt32(&called) != 0 {
   532  					return nil, fmt.Errorf("something else was applied before grandchild; grandchild should be first")
   533  				}
   534  			}
   535  
   536  			atomic.AddInt32(&called, 1)
   537  			return testApplyFn(info, is, id)
   538  		}
   539  
   540  		ctx := testContext2(t, &ContextOpts{
   541  			Config: m,
   542  			ProviderResolver: providers.ResolverFixed(
   543  				map[string]providers.Factory{
   544  					"aws": testProviderFuncFixed(p),
   545  				},
   546  			),
   547  		})
   548  
   549  		if _, diags := ctx.Plan(); diags.HasErrors() {
   550  			t.Fatalf("diags: %s", diags.Err())
   551  		}
   552  
   553  		state, diags := ctx.Apply()
   554  		if diags.HasErrors() {
   555  			t.Fatalf("diags: %s", diags.Err())
   556  		}
   557  
   558  		if !checked {
   559  			t.Fatal("should check")
   560  		}
   561  
   562  		checkStateString(t, state, testTerraformApplyResourceDependsOnModuleInModuleStr)
   563  	}
   564  }
   565  
   566  func TestContext2Apply_mapVarBetweenModules(t *testing.T) {
   567  	m := testModule(t, "apply-map-var-through-module")
   568  	p := testProvider("null")
   569  	p.ApplyFn = testApplyFn
   570  	p.DiffFn = testDiffFn
   571  	ctx := testContext2(t, &ContextOpts{
   572  		Config: m,
   573  		ProviderResolver: providers.ResolverFixed(
   574  			map[string]providers.Factory{
   575  				"null": testProviderFuncFixed(p),
   576  			},
   577  		),
   578  	})
   579  
   580  	if _, diags := ctx.Plan(); diags.HasErrors() {
   581  		t.Fatalf("plan errors: %s", diags.Err())
   582  	}
   583  
   584  	state, diags := ctx.Apply()
   585  	if diags.HasErrors() {
   586  		t.Fatalf("diags: %s", diags.Err())
   587  	}
   588  
   589  	actual := strings.TrimSpace(state.String())
   590  	expected := strings.TrimSpace(`<no state>
   591  Outputs:
   592  
   593  amis_from_module = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 }
   594  
   595  module.test:
   596    null_resource.noop:
   597      ID = foo
   598      provider = provider.null
   599  
   600    Outputs:
   601  
   602    amis_out = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 }`)
   603  	if actual != expected {
   604  		t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual)
   605  	}
   606  }
   607  
   608  func TestContext2Apply_refCount(t *testing.T) {
   609  	m := testModule(t, "apply-ref-count")
   610  	p := testProvider("aws")
   611  	p.ApplyFn = testApplyFn
   612  	p.DiffFn = testDiffFn
   613  	ctx := testContext2(t, &ContextOpts{
   614  		Config: m,
   615  		ProviderResolver: providers.ResolverFixed(
   616  			map[string]providers.Factory{
   617  				"aws": testProviderFuncFixed(p),
   618  			},
   619  		),
   620  	})
   621  
   622  	if _, diags := ctx.Plan(); diags.HasErrors() {
   623  		t.Fatalf("plan errors: %s", diags.Err())
   624  	}
   625  
   626  	state, diags := ctx.Apply()
   627  	if diags.HasErrors() {
   628  		t.Fatalf("diags: %s", diags.Err())
   629  	}
   630  
   631  	mod := state.RootModule()
   632  	if len(mod.Resources) < 2 {
   633  		t.Fatalf("bad: %#v", mod.Resources)
   634  	}
   635  
   636  	actual := strings.TrimSpace(state.String())
   637  	expected := strings.TrimSpace(testTerraformApplyRefCountStr)
   638  	if actual != expected {
   639  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   640  	}
   641  }
   642  
   643  func TestContext2Apply_providerAlias(t *testing.T) {
   644  	m := testModule(t, "apply-provider-alias")
   645  	p := testProvider("aws")
   646  	p.ApplyFn = testApplyFn
   647  	p.DiffFn = testDiffFn
   648  	ctx := testContext2(t, &ContextOpts{
   649  		Config: m,
   650  		ProviderResolver: providers.ResolverFixed(
   651  			map[string]providers.Factory{
   652  				"aws": testProviderFuncFixed(p),
   653  			},
   654  		),
   655  	})
   656  
   657  	if _, diags := ctx.Plan(); diags.HasErrors() {
   658  		t.Fatalf("plan errors: %s", diags.Err())
   659  	}
   660  
   661  	state, diags := ctx.Apply()
   662  	if diags.HasErrors() {
   663  		t.Fatalf("diags: %s", diags.Err())
   664  	}
   665  
   666  	mod := state.RootModule()
   667  	if len(mod.Resources) < 2 {
   668  		t.Fatalf("bad: %#v", mod.Resources)
   669  	}
   670  
   671  	actual := strings.TrimSpace(state.String())
   672  	expected := strings.TrimSpace(testTerraformApplyProviderAliasStr)
   673  	if actual != expected {
   674  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   675  	}
   676  }
   677  
   678  // Two providers that are configured should both be configured prior to apply
   679  func TestContext2Apply_providerAliasConfigure(t *testing.T) {
   680  	m := testModule(t, "apply-provider-alias-configure")
   681  
   682  	p2 := testProvider("another")
   683  	p2.ApplyFn = testApplyFn
   684  	p2.DiffFn = testDiffFn
   685  
   686  	ctx := testContext2(t, &ContextOpts{
   687  		Config: m,
   688  		ProviderResolver: providers.ResolverFixed(
   689  			map[string]providers.Factory{
   690  				"another": testProviderFuncFixed(p2),
   691  			},
   692  		),
   693  	})
   694  
   695  	if p, diags := ctx.Plan(); diags.HasErrors() {
   696  		t.Fatalf("diags: %s", diags.Err())
   697  	} else {
   698  		t.Logf(legacyDiffComparisonString(p.Changes))
   699  	}
   700  
   701  	// Configure to record calls AFTER Plan above
   702  	var configCount int32
   703  	p2.ConfigureFn = func(c *ResourceConfig) error {
   704  		atomic.AddInt32(&configCount, 1)
   705  
   706  		foo, ok := c.Get("foo")
   707  		if !ok {
   708  			return fmt.Errorf("foo is not found")
   709  		}
   710  
   711  		if foo != "bar" {
   712  			return fmt.Errorf("foo: %#v", foo)
   713  		}
   714  
   715  		return nil
   716  	}
   717  
   718  	state, diags := ctx.Apply()
   719  	if diags.HasErrors() {
   720  		t.Fatalf("diags: %s", diags.Err())
   721  	}
   722  
   723  	if configCount != 2 {
   724  		t.Fatalf("provider config expected 2 calls, got: %d", configCount)
   725  	}
   726  
   727  	actual := strings.TrimSpace(state.String())
   728  	expected := strings.TrimSpace(testTerraformApplyProviderAliasConfigStr)
   729  	if actual != expected {
   730  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   731  	}
   732  }
   733  
   734  // GH-2870
   735  func TestContext2Apply_providerWarning(t *testing.T) {
   736  	m := testModule(t, "apply-provider-warning")
   737  	p := testProvider("aws")
   738  	p.ApplyFn = testApplyFn
   739  	p.DiffFn = testDiffFn
   740  	p.ValidateFn = func(c *ResourceConfig) (ws []string, es []error) {
   741  		ws = append(ws, "Just a warning")
   742  		return
   743  	}
   744  	ctx := testContext2(t, &ContextOpts{
   745  		Config: m,
   746  		ProviderResolver: providers.ResolverFixed(
   747  			map[string]providers.Factory{
   748  				"aws": testProviderFuncFixed(p),
   749  			},
   750  		),
   751  	})
   752  
   753  	if _, diags := ctx.Plan(); diags.HasErrors() {
   754  		t.Fatalf("plan errors: %s", diags.Err())
   755  	}
   756  
   757  	state, diags := ctx.Apply()
   758  	if diags.HasErrors() {
   759  		t.Fatalf("diags: %s", diags.Err())
   760  	}
   761  
   762  	actual := strings.TrimSpace(state.String())
   763  	expected := strings.TrimSpace(`
   764  aws_instance.foo:
   765    ID = foo
   766    provider = provider.aws
   767  	`)
   768  	if actual != expected {
   769  		t.Fatalf("got: \n%s\n\nexpected:\n%s", actual, expected)
   770  	}
   771  
   772  	if !p.ConfigureCalled {
   773  		t.Fatalf("provider Configure() was never called!")
   774  	}
   775  }
   776  
   777  func TestContext2Apply_emptyModule(t *testing.T) {
   778  	m := testModule(t, "apply-empty-module")
   779  	p := testProvider("aws")
   780  	p.ApplyFn = testApplyFn
   781  	p.DiffFn = testDiffFn
   782  	ctx := testContext2(t, &ContextOpts{
   783  		Config: m,
   784  		ProviderResolver: providers.ResolverFixed(
   785  			map[string]providers.Factory{
   786  				"aws": testProviderFuncFixed(p),
   787  			},
   788  		),
   789  	})
   790  
   791  	if _, diags := ctx.Plan(); diags.HasErrors() {
   792  		t.Fatalf("plan errors: %s", diags.Err())
   793  	}
   794  
   795  	state, diags := ctx.Apply()
   796  	if diags.HasErrors() {
   797  		t.Fatalf("diags: %s", diags.Err())
   798  	}
   799  
   800  	actual := strings.TrimSpace(state.String())
   801  	actual = strings.Replace(actual, "  ", "", -1)
   802  	expected := strings.TrimSpace(testTerraformApplyEmptyModuleStr)
   803  	if actual != expected {
   804  		t.Fatalf("bad: \n%s\nexpect:\n%s", actual, expected)
   805  	}
   806  }
   807  
   808  func TestContext2Apply_createBeforeDestroy(t *testing.T) {
   809  	m := testModule(t, "apply-good-create-before")
   810  	p := testProvider("aws")
   811  	p.ApplyFn = testApplyFn
   812  	p.DiffFn = testDiffFn
   813  	state := MustShimLegacyState(&State{
   814  		Modules: []*ModuleState{
   815  			{
   816  				Path: rootModulePath,
   817  				Resources: map[string]*ResourceState{
   818  					"aws_instance.bar": {
   819  						Type: "aws_instance",
   820  						Primary: &InstanceState{
   821  							ID: "bar",
   822  							Attributes: map[string]string{
   823  								"require_new": "abc",
   824  							},
   825  						},
   826  					},
   827  				},
   828  			},
   829  		},
   830  	})
   831  	ctx := testContext2(t, &ContextOpts{
   832  		Config: m,
   833  		ProviderResolver: providers.ResolverFixed(
   834  			map[string]providers.Factory{
   835  				"aws": testProviderFuncFixed(p),
   836  			},
   837  		),
   838  		State: state,
   839  	})
   840  
   841  	if p, diags := ctx.Plan(); diags.HasErrors() {
   842  		t.Fatalf("diags: %s", diags.Err())
   843  	} else {
   844  		t.Logf(legacyDiffComparisonString(p.Changes))
   845  	}
   846  
   847  	state, diags := ctx.Apply()
   848  	if diags.HasErrors() {
   849  		t.Fatalf("diags: %s", diags.Err())
   850  	}
   851  
   852  	mod := state.RootModule()
   853  	if got, want := len(mod.Resources), 1; got != want {
   854  		t.Logf("state:\n%s", state)
   855  		t.Fatalf("wrong number of resources %d; want %d", got, want)
   856  	}
   857  
   858  	actual := strings.TrimSpace(state.String())
   859  	expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr)
   860  	if actual != expected {
   861  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
   862  	}
   863  }
   864  
   865  func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) {
   866  	m := testModule(t, "apply-good-create-before-update")
   867  	p := testProvider("aws")
   868  	p.ApplyFn = testApplyFn
   869  	p.DiffFn = testDiffFn
   870  	state := MustShimLegacyState(&State{
   871  		Modules: []*ModuleState{
   872  			{
   873  				Path: rootModulePath,
   874  				Resources: map[string]*ResourceState{
   875  					"aws_instance.bar": {
   876  						Type: "aws_instance",
   877  						Primary: &InstanceState{
   878  							ID: "bar",
   879  							Attributes: map[string]string{
   880  								"foo": "bar",
   881  							},
   882  						},
   883  					},
   884  				},
   885  			},
   886  		},
   887  	})
   888  	ctx := testContext2(t, &ContextOpts{
   889  		Config: m,
   890  		ProviderResolver: providers.ResolverFixed(
   891  			map[string]providers.Factory{
   892  				"aws": testProviderFuncFixed(p),
   893  			},
   894  		),
   895  		State: state,
   896  	})
   897  
   898  	if p, diags := ctx.Plan(); diags.HasErrors() {
   899  		t.Fatalf("diags: %s", diags.Err())
   900  	} else {
   901  		t.Logf(legacyDiffComparisonString(p.Changes))
   902  	}
   903  
   904  	state, diags := ctx.Apply()
   905  	if diags.HasErrors() {
   906  		t.Fatalf("diags: %s", diags.Err())
   907  	}
   908  
   909  	mod := state.RootModule()
   910  	if len(mod.Resources) != 1 {
   911  		t.Fatalf("bad: %s", state)
   912  	}
   913  
   914  	actual := strings.TrimSpace(state.String())
   915  	expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr)
   916  	if actual != expected {
   917  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
   918  	}
   919  }
   920  
   921  // This tests that when a CBD resource depends on a non-CBD resource,
   922  // we can still properly apply changes that require new for both.
   923  func TestContext2Apply_createBeforeDestroy_dependsNonCBD(t *testing.T) {
   924  	m := testModule(t, "apply-cbd-depends-non-cbd")
   925  	p := testProvider("aws")
   926  	p.ApplyFn = testApplyFn
   927  	p.DiffFn = testDiffFn
   928  	state := MustShimLegacyState(&State{
   929  		Modules: []*ModuleState{
   930  			{
   931  				Path: rootModulePath,
   932  				Resources: map[string]*ResourceState{
   933  					"aws_instance.bar": {
   934  						Type: "aws_instance",
   935  						Primary: &InstanceState{
   936  							ID: "bar",
   937  							Attributes: map[string]string{
   938  								"require_new": "abc",
   939  							},
   940  						},
   941  					},
   942  
   943  					"aws_instance.foo": {
   944  						Type: "aws_instance",
   945  						Primary: &InstanceState{
   946  							ID: "foo",
   947  							Attributes: map[string]string{
   948  								"require_new": "abc",
   949  							},
   950  						},
   951  					},
   952  				},
   953  			},
   954  		},
   955  	})
   956  	ctx := testContext2(t, &ContextOpts{
   957  		Config: m,
   958  		ProviderResolver: providers.ResolverFixed(
   959  			map[string]providers.Factory{
   960  				"aws": testProviderFuncFixed(p),
   961  			},
   962  		),
   963  		State: state,
   964  	})
   965  
   966  	if p, diags := ctx.Plan(); diags.HasErrors() {
   967  		t.Fatalf("diags: %s", diags.Err())
   968  	} else {
   969  		t.Logf(legacyDiffComparisonString(p.Changes))
   970  	}
   971  
   972  	state, diags := ctx.Apply()
   973  	if diags.HasErrors() {
   974  		t.Fatalf("diags: %s", diags.Err())
   975  	}
   976  
   977  	checkStateString(t, state, `
   978  aws_instance.bar:
   979    ID = foo
   980    provider = provider.aws
   981    require_new = yes
   982    type = aws_instance
   983    value = foo
   984  
   985    Dependencies:
   986      aws_instance.foo
   987  aws_instance.foo:
   988    ID = foo
   989    provider = provider.aws
   990    require_new = yes
   991    type = aws_instance
   992  	`)
   993  }
   994  
   995  func TestContext2Apply_createBeforeDestroy_hook(t *testing.T) {
   996  	h := new(MockHook)
   997  	m := testModule(t, "apply-good-create-before")
   998  	p := testProvider("aws")
   999  	p.ApplyFn = testApplyFn
  1000  	p.DiffFn = testDiffFn
  1001  	state := MustShimLegacyState(&State{
  1002  		Modules: []*ModuleState{
  1003  			{
  1004  				Path: rootModulePath,
  1005  				Resources: map[string]*ResourceState{
  1006  					"aws_instance.bar": {
  1007  						Type: "aws_instance",
  1008  						Primary: &InstanceState{
  1009  							ID: "bar",
  1010  							Attributes: map[string]string{
  1011  								"require_new": "abc",
  1012  							},
  1013  						},
  1014  						Provider: "provider.aws",
  1015  					},
  1016  				},
  1017  			},
  1018  		},
  1019  	})
  1020  
  1021  	var actual []cty.Value
  1022  	var actualLock sync.Mutex
  1023  	h.PostApplyFn = func(addr addrs.AbsResourceInstance, gen states.Generation, sv cty.Value, e error) (HookAction, error) {
  1024  		actualLock.Lock()
  1025  
  1026  		defer actualLock.Unlock()
  1027  		actual = append(actual, sv)
  1028  		return HookActionContinue, nil
  1029  	}
  1030  
  1031  	ctx := testContext2(t, &ContextOpts{
  1032  		Config: m,
  1033  		Hooks:  []Hook{h},
  1034  		ProviderResolver: providers.ResolverFixed(
  1035  			map[string]providers.Factory{
  1036  				"aws": testProviderFuncFixed(p),
  1037  			},
  1038  		),
  1039  		State: state,
  1040  	})
  1041  
  1042  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1043  		t.Fatalf("diags: %s", diags.Err())
  1044  	} else {
  1045  		t.Logf(legacyDiffComparisonString(p.Changes))
  1046  	}
  1047  
  1048  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1049  		t.Fatalf("apply errors: %s", diags.Err())
  1050  	}
  1051  
  1052  	expected := []cty.Value{
  1053  		cty.ObjectVal(map[string]cty.Value{
  1054  			"id":          cty.StringVal("foo"),
  1055  			"require_new": cty.StringVal("xyz"),
  1056  			"type":        cty.StringVal("aws_instance"),
  1057  		}),
  1058  		cty.NullVal(cty.DynamicPseudoType),
  1059  	}
  1060  
  1061  	cmpOpt := cmp.Transformer("ctyshim", hcl2shim.ConfigValueFromHCL2)
  1062  	if !cmp.Equal(actual, expected, cmpOpt) {
  1063  		t.Fatalf("wrong state snapshot sequence\n%s", cmp.Diff(expected, actual, cmpOpt))
  1064  	}
  1065  }
  1066  
  1067  // Test that we can perform an apply with CBD in a count with deposed instances.
  1068  func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) {
  1069  	m := testModule(t, "apply-cbd-count")
  1070  	p := testProvider("aws")
  1071  	p.ApplyFn = testApplyFn
  1072  	p.DiffFn = testDiffFn
  1073  
  1074  	state := MustShimLegacyState(&State{
  1075  		Modules: []*ModuleState{
  1076  			{
  1077  				Path: rootModulePath,
  1078  				Resources: map[string]*ResourceState{
  1079  					"aws_instance.bar.0": {
  1080  						Type: "aws_instance",
  1081  						Primary: &InstanceState{
  1082  							ID:      "bar",
  1083  							Tainted: true,
  1084  						},
  1085  
  1086  						Deposed: []*InstanceState{
  1087  							{
  1088  								ID: "foo",
  1089  							},
  1090  						},
  1091  					},
  1092  					"aws_instance.bar.1": {
  1093  						Type: "aws_instance",
  1094  						Primary: &InstanceState{
  1095  							ID:      "bar",
  1096  							Tainted: true,
  1097  						},
  1098  
  1099  						Deposed: []*InstanceState{
  1100  							{
  1101  								ID: "bar",
  1102  							},
  1103  						},
  1104  					},
  1105  				},
  1106  			},
  1107  		},
  1108  	})
  1109  
  1110  	ctx := testContext2(t, &ContextOpts{
  1111  		Config: m,
  1112  		ProviderResolver: providers.ResolverFixed(
  1113  			map[string]providers.Factory{
  1114  				"aws": testProviderFuncFixed(p),
  1115  			},
  1116  		),
  1117  		State: state,
  1118  	})
  1119  
  1120  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1121  		t.Fatalf("diags: %s", diags.Err())
  1122  	} else {
  1123  		t.Logf(legacyDiffComparisonString(p.Changes))
  1124  	}
  1125  
  1126  	state, diags := ctx.Apply()
  1127  	if diags.HasErrors() {
  1128  		t.Fatalf("diags: %s", diags.Err())
  1129  	}
  1130  
  1131  	checkStateString(t, state, `
  1132  aws_instance.bar.0:
  1133    ID = foo
  1134    provider = provider.aws
  1135    foo = bar
  1136    type = aws_instance
  1137  aws_instance.bar.1:
  1138    ID = foo
  1139    provider = provider.aws
  1140    foo = bar
  1141    type = aws_instance
  1142  	`)
  1143  }
  1144  
  1145  // Test that when we have a deposed instance but a good primary, we still
  1146  // destroy the deposed instance.
  1147  func TestContext2Apply_createBeforeDestroy_deposedOnly(t *testing.T) {
  1148  	m := testModule(t, "apply-cbd-deposed-only")
  1149  	p := testProvider("aws")
  1150  	p.ApplyFn = testApplyFn
  1151  	p.DiffFn = testDiffFn
  1152  
  1153  	state := MustShimLegacyState(&State{
  1154  		Modules: []*ModuleState{
  1155  			{
  1156  				Path: rootModulePath,
  1157  				Resources: map[string]*ResourceState{
  1158  					"aws_instance.bar": {
  1159  						Type: "aws_instance",
  1160  						Primary: &InstanceState{
  1161  							ID: "bar",
  1162  						},
  1163  
  1164  						Deposed: []*InstanceState{
  1165  							{
  1166  								ID: "foo",
  1167  							},
  1168  						},
  1169  						Provider: "provider.aws",
  1170  					},
  1171  				},
  1172  			},
  1173  		},
  1174  	})
  1175  
  1176  	ctx := testContext2(t, &ContextOpts{
  1177  		Config: m,
  1178  		ProviderResolver: providers.ResolverFixed(
  1179  			map[string]providers.Factory{
  1180  				"aws": testProviderFuncFixed(p),
  1181  			},
  1182  		),
  1183  		State: state,
  1184  	})
  1185  
  1186  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1187  		t.Fatalf("diags: %s", diags.Err())
  1188  	} else {
  1189  		t.Logf(legacyDiffComparisonString(p.Changes))
  1190  	}
  1191  
  1192  	state, diags := ctx.Apply()
  1193  	if diags.HasErrors() {
  1194  		t.Fatalf("diags: %s", diags.Err())
  1195  	}
  1196  
  1197  	checkStateString(t, state, `
  1198  aws_instance.bar:
  1199    ID = bar
  1200    provider = provider.aws
  1201  	`)
  1202  }
  1203  
  1204  func TestContext2Apply_destroyComputed(t *testing.T) {
  1205  	m := testModule(t, "apply-destroy-computed")
  1206  	p := testProvider("aws")
  1207  	p.ApplyFn = testApplyFn
  1208  	p.DiffFn = testDiffFn
  1209  	state := MustShimLegacyState(&State{
  1210  		Modules: []*ModuleState{
  1211  			{
  1212  				Path: rootModulePath,
  1213  				Resources: map[string]*ResourceState{
  1214  					"aws_instance.foo": {
  1215  						Type: "aws_instance",
  1216  						Primary: &InstanceState{
  1217  							ID: "foo",
  1218  							Attributes: map[string]string{
  1219  								"output": "value",
  1220  							},
  1221  						},
  1222  						Provider: "provider.aws",
  1223  					},
  1224  				},
  1225  			},
  1226  		},
  1227  	})
  1228  	ctx := testContext2(t, &ContextOpts{
  1229  		Config: m,
  1230  		ProviderResolver: providers.ResolverFixed(
  1231  			map[string]providers.Factory{
  1232  				"aws": testProviderFuncFixed(p),
  1233  			},
  1234  		),
  1235  		State:   state,
  1236  		Destroy: true,
  1237  	})
  1238  
  1239  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1240  		logDiagnostics(t, diags)
  1241  		t.Fatal("plan failed")
  1242  	} else {
  1243  		t.Logf("plan:\n\n%s", legacyDiffComparisonString(p.Changes))
  1244  	}
  1245  
  1246  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1247  		logDiagnostics(t, diags)
  1248  		t.Fatal("apply failed")
  1249  	}
  1250  }
  1251  
  1252  // Test that the destroy operation uses depends_on as a source of ordering.
  1253  func TestContext2Apply_destroyDependsOn(t *testing.T) {
  1254  	// It is possible for this to be racy, so we loop a number of times
  1255  	// just to check.
  1256  	for i := 0; i < 10; i++ {
  1257  		testContext2Apply_destroyDependsOn(t)
  1258  	}
  1259  }
  1260  
  1261  func testContext2Apply_destroyDependsOn(t *testing.T) {
  1262  	m := testModule(t, "apply-destroy-depends-on")
  1263  	p := testProvider("aws")
  1264  	p.ApplyFn = testApplyFn
  1265  	p.DiffFn = testDiffFn
  1266  	state := MustShimLegacyState(&State{
  1267  		Modules: []*ModuleState{
  1268  			{
  1269  				Path: rootModulePath,
  1270  				Resources: map[string]*ResourceState{
  1271  					"aws_instance.foo": {
  1272  						Type: "aws_instance",
  1273  						Primary: &InstanceState{
  1274  							ID:         "foo",
  1275  							Attributes: map[string]string{},
  1276  						},
  1277  					},
  1278  
  1279  					"aws_instance.bar": {
  1280  						Type: "aws_instance",
  1281  						Primary: &InstanceState{
  1282  							ID:         "bar",
  1283  							Attributes: map[string]string{},
  1284  						},
  1285  					},
  1286  				},
  1287  			},
  1288  		},
  1289  	})
  1290  
  1291  	// Record the order we see Apply
  1292  	var actual []string
  1293  	var actualLock sync.Mutex
  1294  	p.ApplyFn = func(
  1295  		_ *InstanceInfo, is *InstanceState, _ *InstanceDiff) (*InstanceState, error) {
  1296  		actualLock.Lock()
  1297  		defer actualLock.Unlock()
  1298  		actual = append(actual, is.ID)
  1299  		return nil, nil
  1300  	}
  1301  
  1302  	ctx := testContext2(t, &ContextOpts{
  1303  		Config: m,
  1304  		ProviderResolver: providers.ResolverFixed(
  1305  			map[string]providers.Factory{
  1306  				"aws": testProviderFuncFixed(p),
  1307  			},
  1308  		),
  1309  		State:       state,
  1310  		Destroy:     true,
  1311  		Parallelism: 1, // To check ordering
  1312  	})
  1313  
  1314  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1315  		t.Fatalf("plan errors: %s", diags.Err())
  1316  	}
  1317  
  1318  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1319  		t.Fatalf("apply errors: %s", diags.Err())
  1320  	}
  1321  
  1322  	expected := []string{"foo", "bar"}
  1323  	if !reflect.DeepEqual(actual, expected) {
  1324  		t.Fatalf("wrong order\ngot:  %#v\nwant: %#v", actual, expected)
  1325  	}
  1326  }
  1327  
  1328  // Test that destroy ordering is correct with dependencies only
  1329  // in the state.
  1330  func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
  1331  	// It is possible for this to be racy, so we loop a number of times
  1332  	// just to check.
  1333  	for i := 0; i < 10; i++ {
  1334  		testContext2Apply_destroyDependsOnStateOnly(t)
  1335  	}
  1336  }
  1337  
  1338  func testContext2Apply_destroyDependsOnStateOnly(t *testing.T) {
  1339  	m := testModule(t, "empty")
  1340  	p := testProvider("aws")
  1341  	p.ApplyFn = testApplyFn
  1342  	p.DiffFn = testDiffFn
  1343  	state := MustShimLegacyState(&State{
  1344  		Modules: []*ModuleState{
  1345  			{
  1346  				Path: rootModulePath,
  1347  				Resources: map[string]*ResourceState{
  1348  					"aws_instance.foo": {
  1349  						Type: "aws_instance",
  1350  						Primary: &InstanceState{
  1351  							ID:         "foo",
  1352  							Attributes: map[string]string{},
  1353  						},
  1354  						Provider: "provider.aws",
  1355  					},
  1356  
  1357  					"aws_instance.bar": {
  1358  						Type: "aws_instance",
  1359  						Primary: &InstanceState{
  1360  							ID:         "bar",
  1361  							Attributes: map[string]string{},
  1362  						},
  1363  						Dependencies: []string{"aws_instance.foo"},
  1364  						Provider:     "provider.aws",
  1365  					},
  1366  				},
  1367  			},
  1368  		},
  1369  	})
  1370  
  1371  	// Record the order we see Apply
  1372  	var actual []string
  1373  	var actualLock sync.Mutex
  1374  	p.ApplyFn = func(
  1375  		_ *InstanceInfo, is *InstanceState, _ *InstanceDiff) (*InstanceState, error) {
  1376  		actualLock.Lock()
  1377  		defer actualLock.Unlock()
  1378  		actual = append(actual, is.ID)
  1379  		return nil, nil
  1380  	}
  1381  
  1382  	ctx := testContext2(t, &ContextOpts{
  1383  		Config: m,
  1384  		ProviderResolver: providers.ResolverFixed(
  1385  			map[string]providers.Factory{
  1386  				"aws": testProviderFuncFixed(p),
  1387  			},
  1388  		),
  1389  		State:       state,
  1390  		Destroy:     true,
  1391  		Parallelism: 1, // To check ordering
  1392  	})
  1393  
  1394  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1395  		t.Fatalf("plan errors: %s", diags.Err())
  1396  	}
  1397  
  1398  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1399  		t.Fatalf("apply errors: %s", diags.Err())
  1400  	}
  1401  
  1402  	expected := []string{"bar", "foo"}
  1403  	if !reflect.DeepEqual(actual, expected) {
  1404  		t.Fatalf("wrong order\ngot:  %#v\nwant: %#v", actual, expected)
  1405  	}
  1406  }
  1407  
  1408  // Test that destroy ordering is correct with dependencies only
  1409  // in the state within a module (GH-11749)
  1410  func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
  1411  	// It is possible for this to be racy, so we loop a number of times
  1412  	// just to check.
  1413  	for i := 0; i < 10; i++ {
  1414  		testContext2Apply_destroyDependsOnStateOnlyModule(t)
  1415  	}
  1416  }
  1417  
  1418  func testContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) {
  1419  	m := testModule(t, "empty")
  1420  	p := testProvider("aws")
  1421  	p.ApplyFn = testApplyFn
  1422  	p.DiffFn = testDiffFn
  1423  	state := MustShimLegacyState(&State{
  1424  		Modules: []*ModuleState{
  1425  			{
  1426  				Path: []string{"root", "child"},
  1427  				Resources: map[string]*ResourceState{
  1428  					"aws_instance.foo": {
  1429  						Type: "aws_instance",
  1430  						Primary: &InstanceState{
  1431  							ID:         "foo",
  1432  							Attributes: map[string]string{},
  1433  						},
  1434  						Provider: "provider.aws",
  1435  					},
  1436  
  1437  					"aws_instance.bar": {
  1438  						Type: "aws_instance",
  1439  						Primary: &InstanceState{
  1440  							ID:         "bar",
  1441  							Attributes: map[string]string{},
  1442  						},
  1443  						Dependencies: []string{"aws_instance.foo"},
  1444  						Provider:     "provider.aws",
  1445  					},
  1446  				},
  1447  			},
  1448  		},
  1449  	})
  1450  
  1451  	// Record the order we see Apply
  1452  	var actual []string
  1453  	var actualLock sync.Mutex
  1454  	p.ApplyFn = func(
  1455  		_ *InstanceInfo, is *InstanceState, _ *InstanceDiff) (*InstanceState, error) {
  1456  		actualLock.Lock()
  1457  		defer actualLock.Unlock()
  1458  		actual = append(actual, is.ID)
  1459  		return nil, nil
  1460  	}
  1461  
  1462  	ctx := testContext2(t, &ContextOpts{
  1463  		Config: m,
  1464  		ProviderResolver: providers.ResolverFixed(
  1465  			map[string]providers.Factory{
  1466  				"aws": testProviderFuncFixed(p),
  1467  			},
  1468  		),
  1469  		State:       state,
  1470  		Destroy:     true,
  1471  		Parallelism: 1, // To check ordering
  1472  	})
  1473  
  1474  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1475  		t.Fatalf("plan errors: %s", diags.Err())
  1476  	}
  1477  
  1478  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1479  		t.Fatalf("apply errors: %s", diags.Err())
  1480  	}
  1481  
  1482  	expected := []string{"bar", "foo"}
  1483  	if !reflect.DeepEqual(actual, expected) {
  1484  		t.Fatalf("wrong order\ngot:  %#v\nwant: %#v", actual, expected)
  1485  	}
  1486  }
  1487  
  1488  func TestContext2Apply_dataBasic(t *testing.T) {
  1489  	m := testModule(t, "apply-data-basic")
  1490  	p := testProvider("null")
  1491  	p.ApplyFn = testApplyFn
  1492  	p.DiffFn = testDiffFn
  1493  	p.ReadDataSourceResponse = providers.ReadDataSourceResponse{
  1494  		State: cty.ObjectVal(map[string]cty.Value{
  1495  			"id":  cty.StringVal("yo"),
  1496  			"foo": cty.NullVal(cty.String),
  1497  		}),
  1498  	}
  1499  
  1500  	ctx := testContext2(t, &ContextOpts{
  1501  		Config: m,
  1502  		ProviderResolver: providers.ResolverFixed(
  1503  			map[string]providers.Factory{
  1504  				"null": testProviderFuncFixed(p),
  1505  			},
  1506  		),
  1507  	})
  1508  
  1509  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1510  		t.Fatalf("diags: %s", diags.Err())
  1511  	} else {
  1512  		t.Logf(legacyDiffComparisonString(p.Changes))
  1513  	}
  1514  
  1515  	state, diags := ctx.Apply()
  1516  	assertNoErrors(t, diags)
  1517  
  1518  	actual := strings.TrimSpace(state.String())
  1519  	expected := strings.TrimSpace(testTerraformApplyDataBasicStr)
  1520  	if actual != expected {
  1521  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  1522  	}
  1523  }
  1524  
  1525  func TestContext2Apply_destroyData(t *testing.T) {
  1526  	m := testModule(t, "apply-destroy-data-resource")
  1527  	p := testProvider("null")
  1528  	p.ApplyFn = testApplyFn
  1529  	p.DiffFn = testDiffFn
  1530  	state := MustShimLegacyState(&State{
  1531  		Modules: []*ModuleState{
  1532  			{
  1533  				Path: rootModulePath,
  1534  				Resources: map[string]*ResourceState{
  1535  					"data.null_data_source.testing": {
  1536  						Type: "null_data_source",
  1537  						Primary: &InstanceState{
  1538  							ID: "-",
  1539  							Attributes: map[string]string{
  1540  								"inputs.#":    "1",
  1541  								"inputs.test": "yes",
  1542  							},
  1543  						},
  1544  					},
  1545  				},
  1546  			},
  1547  		},
  1548  	})
  1549  	hook := &testHook{}
  1550  	ctx := testContext2(t, &ContextOpts{
  1551  		Config: m,
  1552  		ProviderResolver: providers.ResolverFixed(
  1553  			map[string]providers.Factory{
  1554  				"null": testProviderFuncFixed(p),
  1555  			},
  1556  		),
  1557  		State:   state,
  1558  		Destroy: true,
  1559  		Hooks:   []Hook{hook},
  1560  	})
  1561  
  1562  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1563  		t.Fatalf("diags: %s", diags.Err())
  1564  	} else {
  1565  		t.Logf(legacyDiffComparisonString(p.Changes))
  1566  	}
  1567  
  1568  	newState, diags := ctx.Apply()
  1569  	if diags.HasErrors() {
  1570  		t.Fatalf("diags: %s", diags.Err())
  1571  	}
  1572  
  1573  	if got := len(newState.Modules); got != 1 {
  1574  		t.Fatalf("state has %d modules after destroy; want 1", got)
  1575  	}
  1576  
  1577  	if got := len(newState.RootModule().Resources); got != 0 {
  1578  		t.Fatalf("state has %d resources after destroy; want 0", got)
  1579  	}
  1580  
  1581  	wantHookCalls := []*testHookCall{
  1582  		{"PreDiff", "data.null_data_source.testing"},
  1583  		{"PostDiff", "data.null_data_source.testing"},
  1584  		{"PostStateUpdate", ""},
  1585  	}
  1586  	if !reflect.DeepEqual(hook.Calls, wantHookCalls) {
  1587  		t.Errorf("wrong hook calls\ngot: %swant: %s", spew.Sdump(hook.Calls), spew.Sdump(wantHookCalls))
  1588  	}
  1589  }
  1590  
  1591  // https://github.com/hashicorp/terraform-plugin-sdk/pull/5096
  1592  func TestContext2Apply_destroySkipsCBD(t *testing.T) {
  1593  	// Config contains CBD resource depending on non-CBD resource, which triggers
  1594  	// a cycle if they are both replaced, but should _not_ trigger a cycle when
  1595  	// just doing a `terraform destroy`.
  1596  	m := testModule(t, "apply-destroy-cbd")
  1597  	p := testProvider("aws")
  1598  	p.ApplyFn = testApplyFn
  1599  	p.DiffFn = testDiffFn
  1600  	state := MustShimLegacyState(&State{
  1601  		Modules: []*ModuleState{
  1602  			{
  1603  				Path: rootModulePath,
  1604  				Resources: map[string]*ResourceState{
  1605  					"aws_instance.foo": {
  1606  						Type: "aws_instance",
  1607  						Primary: &InstanceState{
  1608  							ID: "foo",
  1609  						},
  1610  					},
  1611  					"aws_instance.bar": {
  1612  						Type: "aws_instance",
  1613  						Primary: &InstanceState{
  1614  							ID: "foo",
  1615  						},
  1616  					},
  1617  				},
  1618  			},
  1619  		},
  1620  	})
  1621  	ctx := testContext2(t, &ContextOpts{
  1622  		Config: m,
  1623  		ProviderResolver: providers.ResolverFixed(
  1624  			map[string]providers.Factory{
  1625  				"aws": testProviderFuncFixed(p),
  1626  			},
  1627  		),
  1628  		State:   state,
  1629  		Destroy: true,
  1630  	})
  1631  
  1632  	if p, diags := ctx.Plan(); diags.HasErrors() {
  1633  		t.Fatalf("diags: %s", diags.Err())
  1634  	} else {
  1635  		t.Logf(legacyDiffComparisonString(p.Changes))
  1636  	}
  1637  
  1638  	if _, diags := ctx.Apply(); diags.HasErrors() {
  1639  		t.Fatalf("apply errors: %s", diags.Err())
  1640  	}
  1641  }
  1642  
  1643  func TestContext2Apply_destroyModuleVarProviderConfig(t *testing.T) {
  1644  	m := testModule(t, "apply-destroy-mod-var-provider-config")
  1645  	p := testProvider("aws")
  1646  	p.ApplyFn = testApplyFn
  1647  	p.DiffFn = testDiffFn
  1648  	state := MustShimLegacyState(&State{
  1649  		Modules: []*ModuleState{
  1650  			{
  1651  				Path: []string{"root", "child"},
  1652  				Resources: map[string]*ResourceState{
  1653  					"aws_instance.foo": {
  1654  						Type: "aws_instance",
  1655  						Primary: &InstanceState{
  1656  							ID: "foo",
  1657  						},
  1658  					},
  1659  				},
  1660  			},
  1661  		},
  1662  	})
  1663  	ctx := testContext2(t, &ContextOpts{
  1664  		Config: m,
  1665  		ProviderResolver: providers.ResolverFixed(
  1666  			map[string]providers.Factory{
  1667  				"aws": testProviderFuncFixed(p),
  1668  			},
  1669  		),
  1670  		State:   state,
  1671  		Destroy: true,
  1672  	})
  1673  
  1674  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1675  		t.Fatalf("plan errors: %s", diags.Err())
  1676  	}
  1677  
  1678  	_, diags := ctx.Apply()
  1679  	if diags.HasErrors() {
  1680  		t.Fatalf("diags: %s", diags.Err())
  1681  	}
  1682  }
  1683  
  1684  // https://github.com/hashicorp/terraform-plugin-sdk/issues/2892
  1685  func TestContext2Apply_destroyCrossProviders(t *testing.T) {
  1686  	m := testModule(t, "apply-destroy-cross-providers")
  1687  
  1688  	p_aws := testProvider("aws")
  1689  	p_aws.ApplyFn = testApplyFn
  1690  	p_aws.DiffFn = testDiffFn
  1691  	p_aws.GetSchemaReturn = &ProviderSchema{
  1692  		ResourceTypes: map[string]*configschema.Block{
  1693  			"aws_instance": {
  1694  				Attributes: map[string]*configschema.Attribute{
  1695  					"id": {
  1696  						Type:     cty.String,
  1697  						Computed: true,
  1698  					},
  1699  				},
  1700  			},
  1701  			"aws_vpc": {
  1702  				Attributes: map[string]*configschema.Attribute{
  1703  					"value": {
  1704  						Type:     cty.String,
  1705  						Optional: true,
  1706  					},
  1707  				},
  1708  			},
  1709  		},
  1710  	}
  1711  
  1712  	providers := map[string]providers.Factory{
  1713  		"aws": testProviderFuncFixed(p_aws),
  1714  	}
  1715  
  1716  	// Bug only appears from time to time,
  1717  	// so we run this test multiple times
  1718  	// to check for the race-condition
  1719  
  1720  	// FIXME: this test flaps now, so run it more times
  1721  	for i := 0; i <= 100; i++ {
  1722  		ctx := getContextForApply_destroyCrossProviders(t, m, providers)
  1723  
  1724  		if _, diags := ctx.Plan(); diags.HasErrors() {
  1725  			logDiagnostics(t, diags)
  1726  			t.Fatal("plan failed")
  1727  		}
  1728  
  1729  		if _, diags := ctx.Apply(); diags.HasErrors() {
  1730  			logDiagnostics(t, diags)
  1731  			t.Fatal("apply failed")
  1732  		}
  1733  	}
  1734  }
  1735  
  1736  func getContextForApply_destroyCrossProviders(t *testing.T, m *configs.Config, providerFactories map[string]providers.Factory) *Context {
  1737  	state := MustShimLegacyState(&State{
  1738  		Modules: []*ModuleState{
  1739  			{
  1740  				Path: rootModulePath,
  1741  				Resources: map[string]*ResourceState{
  1742  					"aws_instance.shared": {
  1743  						Type: "aws_instance",
  1744  						Primary: &InstanceState{
  1745  							ID: "remote-2652591293",
  1746  							Attributes: map[string]string{
  1747  								"id": "test",
  1748  							},
  1749  						},
  1750  						Provider: "provider.aws",
  1751  					},
  1752  				},
  1753  			},
  1754  			{
  1755  				Path: []string{"root", "child"},
  1756  				Resources: map[string]*ResourceState{
  1757  					"aws_vpc.bar": {
  1758  						Type: "aws_vpc",
  1759  						Primary: &InstanceState{
  1760  							ID: "vpc-aaabbb12",
  1761  							Attributes: map[string]string{
  1762  								"value": "test",
  1763  							},
  1764  						},
  1765  						Provider: "provider.aws",
  1766  					},
  1767  				},
  1768  			},
  1769  		},
  1770  	})
  1771  	ctx := testContext2(t, &ContextOpts{
  1772  		Config:           m,
  1773  		ProviderResolver: providers.ResolverFixed(providerFactories),
  1774  		State:            state,
  1775  		Destroy:          true,
  1776  	})
  1777  
  1778  	return ctx
  1779  }
  1780  
  1781  func TestContext2Apply_minimal(t *testing.T) {
  1782  	m := testModule(t, "apply-minimal")
  1783  	p := testProvider("aws")
  1784  	p.ApplyFn = testApplyFn
  1785  	p.DiffFn = testDiffFn
  1786  	ctx := testContext2(t, &ContextOpts{
  1787  		Config: m,
  1788  		ProviderResolver: providers.ResolverFixed(
  1789  			map[string]providers.Factory{
  1790  				"aws": testProviderFuncFixed(p),
  1791  			},
  1792  		),
  1793  	})
  1794  
  1795  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1796  		t.Fatalf("plan errors: %s", diags.Err())
  1797  	}
  1798  
  1799  	state, diags := ctx.Apply()
  1800  	if diags.HasErrors() {
  1801  		t.Fatalf("diags: %s", diags.Err())
  1802  	}
  1803  
  1804  	actual := strings.TrimSpace(state.String())
  1805  	expected := strings.TrimSpace(testTerraformApplyMinimalStr)
  1806  	if actual != expected {
  1807  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  1808  	}
  1809  }
  1810  
  1811  func TestContext2Apply_badDiff(t *testing.T) {
  1812  	m := testModule(t, "apply-good")
  1813  	p := testProvider("aws")
  1814  	p.ApplyFn = testApplyFn
  1815  	p.DiffFn = testDiffFn
  1816  	ctx := testContext2(t, &ContextOpts{
  1817  		Config: m,
  1818  		ProviderResolver: providers.ResolverFixed(
  1819  			map[string]providers.Factory{
  1820  				"aws": testProviderFuncFixed(p),
  1821  			},
  1822  		),
  1823  	})
  1824  
  1825  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1826  		t.Fatalf("plan errors: %s", diags.Err())
  1827  	}
  1828  
  1829  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  1830  		return &InstanceDiff{
  1831  			Attributes: map[string]*ResourceAttrDiff{
  1832  				"newp": {
  1833  					Old:         "",
  1834  					New:         "",
  1835  					NewComputed: true,
  1836  				},
  1837  			},
  1838  		}, nil
  1839  	}
  1840  
  1841  	if _, diags := ctx.Apply(); diags == nil {
  1842  		t.Fatal("should error")
  1843  	}
  1844  }
  1845  
  1846  func TestContext2Apply_cancel(t *testing.T) {
  1847  	stopped := false
  1848  
  1849  	m := testModule(t, "apply-cancel")
  1850  	p := testProvider("aws")
  1851  	ctx := testContext2(t, &ContextOpts{
  1852  		Config: m,
  1853  		ProviderResolver: providers.ResolverFixed(
  1854  			map[string]providers.Factory{
  1855  				"aws": testProviderFuncFixed(p),
  1856  			},
  1857  		),
  1858  	})
  1859  
  1860  	p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) {
  1861  		if !stopped {
  1862  			stopped = true
  1863  			go ctx.Stop()
  1864  
  1865  			for {
  1866  				if ctx.sh.Stopped() {
  1867  					break
  1868  				}
  1869  				time.Sleep(10 * time.Millisecond)
  1870  			}
  1871  		}
  1872  
  1873  		return &InstanceState{
  1874  			ID: "foo",
  1875  			Attributes: map[string]string{
  1876  				"value": "2",
  1877  			},
  1878  		}, nil
  1879  	}
  1880  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  1881  		d := &InstanceDiff{
  1882  			Attributes: map[string]*ResourceAttrDiff{},
  1883  		}
  1884  		if new, ok := rc.Get("value"); ok {
  1885  			d.Attributes["value"] = &ResourceAttrDiff{
  1886  				New: new.(string),
  1887  			}
  1888  		}
  1889  		if new, ok := rc.Get("foo"); ok {
  1890  			d.Attributes["foo"] = &ResourceAttrDiff{
  1891  				New: new.(string),
  1892  			}
  1893  		}
  1894  		return d, nil
  1895  	}
  1896  
  1897  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1898  		t.Fatalf("plan errors: %s", diags.Err())
  1899  	}
  1900  
  1901  	// Start the Apply in a goroutine
  1902  	var applyDiags tfdiags.Diagnostics
  1903  	stateCh := make(chan *states.State)
  1904  	go func() {
  1905  		state, diags := ctx.Apply()
  1906  		applyDiags = diags
  1907  
  1908  		stateCh <- state
  1909  	}()
  1910  
  1911  	state := <-stateCh
  1912  	if applyDiags.HasErrors() {
  1913  		t.Fatalf("unexpected errors: %s", applyDiags.Err())
  1914  	}
  1915  
  1916  	actual := strings.TrimSpace(state.String())
  1917  	expected := strings.TrimSpace(testTerraformApplyCancelStr)
  1918  	if actual != expected {
  1919  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  1920  	}
  1921  
  1922  	if !p.StopCalled {
  1923  		t.Fatal("stop should be called")
  1924  	}
  1925  }
  1926  
  1927  func TestContext2Apply_cancelBlock(t *testing.T) {
  1928  	m := testModule(t, "apply-cancel-block")
  1929  	p := testProvider("aws")
  1930  	ctx := testContext2(t, &ContextOpts{
  1931  		Config: m,
  1932  		ProviderResolver: providers.ResolverFixed(
  1933  			map[string]providers.Factory{
  1934  				"aws": testProviderFuncFixed(p),
  1935  			},
  1936  		),
  1937  	})
  1938  
  1939  	applyCh := make(chan struct{})
  1940  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  1941  		return &InstanceDiff{
  1942  			Attributes: map[string]*ResourceAttrDiff{
  1943  				"id": {
  1944  					New: "foo",
  1945  				},
  1946  				"num": {
  1947  					New: "2",
  1948  				},
  1949  			},
  1950  		}, nil
  1951  	}
  1952  	p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) {
  1953  		close(applyCh)
  1954  
  1955  		for !ctx.sh.Stopped() {
  1956  			// Wait for stop to be called. We call Gosched here so that
  1957  			// the other goroutines can always be scheduled to set Stopped.
  1958  			runtime.Gosched()
  1959  		}
  1960  
  1961  		// Sleep
  1962  		time.Sleep(100 * time.Millisecond)
  1963  
  1964  		return &InstanceState{
  1965  			ID: "foo",
  1966  			Attributes: map[string]string{
  1967  				"num": "2",
  1968  			},
  1969  		}, nil
  1970  	}
  1971  
  1972  	if _, diags := ctx.Plan(); diags.HasErrors() {
  1973  		t.Fatalf("plan errors: %s", diags.Err())
  1974  	}
  1975  
  1976  	// Start the Apply in a goroutine
  1977  	var applyDiags tfdiags.Diagnostics
  1978  	stateCh := make(chan *states.State)
  1979  	go func() {
  1980  		state, diags := ctx.Apply()
  1981  		applyDiags = diags
  1982  
  1983  		stateCh <- state
  1984  	}()
  1985  
  1986  	stopDone := make(chan struct{})
  1987  	go func() {
  1988  		defer close(stopDone)
  1989  		<-applyCh
  1990  		ctx.Stop()
  1991  	}()
  1992  
  1993  	// Make sure that stop blocks
  1994  	select {
  1995  	case <-stopDone:
  1996  		t.Fatal("stop should block")
  1997  	case <-time.After(10 * time.Millisecond):
  1998  	}
  1999  
  2000  	// Wait for stop
  2001  	select {
  2002  	case <-stopDone:
  2003  	case <-time.After(500 * time.Millisecond):
  2004  		t.Fatal("stop should be done")
  2005  	}
  2006  
  2007  	// Wait for apply to complete
  2008  	state := <-stateCh
  2009  	if applyDiags.HasErrors() {
  2010  		t.Fatalf("unexpected error: %s", applyDiags.Err())
  2011  	}
  2012  
  2013  	checkStateString(t, state, `
  2014  aws_instance.foo:
  2015    ID = foo
  2016    provider = provider.aws
  2017    num = 2
  2018  	`)
  2019  }
  2020  
  2021  func TestContext2Apply_cancelProvisioner(t *testing.T) {
  2022  	m := testModule(t, "apply-cancel-provisioner")
  2023  	p := testProvider("aws")
  2024  	p.ApplyFn = testApplyFn
  2025  	p.DiffFn = testDiffFn
  2026  
  2027  	pr := testProvisioner()
  2028  	pr.GetSchemaResponse = provisioners.GetSchemaResponse{
  2029  		Provisioner: &configschema.Block{
  2030  			Attributes: map[string]*configschema.Attribute{
  2031  				"foo": {
  2032  					Type:     cty.String,
  2033  					Optional: true,
  2034  				},
  2035  			},
  2036  		},
  2037  	}
  2038  
  2039  	ctx := testContext2(t, &ContextOpts{
  2040  		Config: m,
  2041  		ProviderResolver: providers.ResolverFixed(
  2042  			map[string]providers.Factory{
  2043  				"aws": testProviderFuncFixed(p),
  2044  			},
  2045  		),
  2046  		Provisioners: map[string]ProvisionerFactory{
  2047  			"shell": testProvisionerFuncFixed(pr),
  2048  		},
  2049  	})
  2050  
  2051  	prStopped := make(chan struct{})
  2052  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  2053  		// Start the stop process
  2054  		go ctx.Stop()
  2055  
  2056  		<-prStopped
  2057  		return nil
  2058  	}
  2059  	pr.StopFn = func() error {
  2060  		close(prStopped)
  2061  		return nil
  2062  	}
  2063  
  2064  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2065  		t.Fatalf("plan errors: %s", diags.Err())
  2066  	}
  2067  
  2068  	// Start the Apply in a goroutine
  2069  	var applyDiags tfdiags.Diagnostics
  2070  	stateCh := make(chan *states.State)
  2071  	go func() {
  2072  		state, diags := ctx.Apply()
  2073  		applyDiags = diags
  2074  
  2075  		stateCh <- state
  2076  	}()
  2077  
  2078  	// Wait for completion
  2079  	state := <-stateCh
  2080  	assertNoErrors(t, applyDiags)
  2081  
  2082  	checkStateString(t, state, `
  2083  aws_instance.foo: (tainted)
  2084    ID = foo
  2085    provider = provider.aws
  2086    num = 2
  2087    type = aws_instance
  2088  	`)
  2089  
  2090  	if !pr.StopCalled {
  2091  		t.Fatal("stop should be called")
  2092  	}
  2093  }
  2094  
  2095  func TestContext2Apply_compute(t *testing.T) {
  2096  	m := testModule(t, "apply-compute")
  2097  	p := testProvider("aws")
  2098  	p.ApplyFn = testApplyFn
  2099  	p.DiffFn = testDiffFn
  2100  	p.GetSchemaReturn = &ProviderSchema{
  2101  		ResourceTypes: map[string]*configschema.Block{
  2102  			"aws_instance": {
  2103  				Attributes: map[string]*configschema.Attribute{
  2104  					"num": {
  2105  						Type:     cty.Number,
  2106  						Optional: true,
  2107  					},
  2108  					"compute": {
  2109  						Type:     cty.String,
  2110  						Optional: true,
  2111  					},
  2112  					"compute_value": {
  2113  						Type:     cty.String,
  2114  						Optional: true,
  2115  					},
  2116  					"foo": {
  2117  						Type:     cty.String,
  2118  						Optional: true,
  2119  					},
  2120  					"id": {
  2121  						Type:     cty.String,
  2122  						Computed: true,
  2123  					},
  2124  					"type": {
  2125  						Type:     cty.String,
  2126  						Computed: true,
  2127  					},
  2128  					"value": { // Populated from compute_value because compute = "value" in the config fixture
  2129  						Type:     cty.String,
  2130  						Computed: true,
  2131  					},
  2132  				},
  2133  			},
  2134  		},
  2135  	}
  2136  
  2137  	ctx := testContext2(t, &ContextOpts{
  2138  		Config: m,
  2139  		ProviderResolver: providers.ResolverFixed(
  2140  			map[string]providers.Factory{
  2141  				"aws": testProviderFuncFixed(p),
  2142  			},
  2143  		),
  2144  	})
  2145  
  2146  	ctx.variables = InputValues{
  2147  		"value": &InputValue{
  2148  			Value:      cty.NumberIntVal(1),
  2149  			SourceType: ValueFromCaller,
  2150  		},
  2151  	}
  2152  
  2153  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2154  		t.Fatalf("plan errors: %s", diags.Err())
  2155  	}
  2156  
  2157  	state, diags := ctx.Apply()
  2158  	if diags.HasErrors() {
  2159  		t.Fatalf("unexpected errors: %s", diags.Err())
  2160  	}
  2161  
  2162  	actual := strings.TrimSpace(state.String())
  2163  	expected := strings.TrimSpace(testTerraformApplyComputeStr)
  2164  	if actual != expected {
  2165  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2166  	}
  2167  }
  2168  
  2169  func TestContext2Apply_countDecrease(t *testing.T) {
  2170  	m := testModule(t, "apply-count-dec")
  2171  	p := testProvider("aws")
  2172  	p.DiffFn = testDiffFn
  2173  	p.ApplyFn = testApplyFn
  2174  	s := MustShimLegacyState(&State{
  2175  		Modules: []*ModuleState{
  2176  			{
  2177  				Path: rootModulePath,
  2178  				Resources: map[string]*ResourceState{
  2179  					"aws_instance.foo.0": {
  2180  						Type: "aws_instance",
  2181  						Primary: &InstanceState{
  2182  							ID: "bar",
  2183  							Attributes: map[string]string{
  2184  								"foo":  "foo",
  2185  								"type": "aws_instance",
  2186  							},
  2187  						},
  2188  					},
  2189  					"aws_instance.foo.1": {
  2190  						Type: "aws_instance",
  2191  						Primary: &InstanceState{
  2192  							ID: "bar",
  2193  							Attributes: map[string]string{
  2194  								"foo":  "foo",
  2195  								"type": "aws_instance",
  2196  							},
  2197  						},
  2198  					},
  2199  					"aws_instance.foo.2": {
  2200  						Type: "aws_instance",
  2201  						Primary: &InstanceState{
  2202  							ID: "bar",
  2203  							Attributes: map[string]string{
  2204  								"foo":  "foo",
  2205  								"type": "aws_instance",
  2206  							},
  2207  						},
  2208  					},
  2209  				},
  2210  			},
  2211  		},
  2212  	})
  2213  	ctx := testContext2(t, &ContextOpts{
  2214  		Config: m,
  2215  		ProviderResolver: providers.ResolverFixed(
  2216  			map[string]providers.Factory{
  2217  				"aws": testProviderFuncFixed(p),
  2218  			},
  2219  		),
  2220  		State: s,
  2221  	})
  2222  
  2223  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2224  		logDiagnostics(t, diags)
  2225  		t.Fatal("plan failed")
  2226  	}
  2227  
  2228  	state, diags := ctx.Apply()
  2229  	assertNoErrors(t, diags)
  2230  
  2231  	actual := strings.TrimSpace(state.String())
  2232  	expected := strings.TrimSpace(testTerraformApplyCountDecStr)
  2233  	if actual != expected {
  2234  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2235  	}
  2236  }
  2237  
  2238  func TestContext2Apply_countDecreaseToOneX(t *testing.T) {
  2239  	m := testModule(t, "apply-count-dec-one")
  2240  	p := testProvider("aws")
  2241  	p.ApplyFn = testApplyFn
  2242  	p.DiffFn = testDiffFn
  2243  	s := MustShimLegacyState(&State{
  2244  		Modules: []*ModuleState{
  2245  			{
  2246  				Path: rootModulePath,
  2247  				Resources: map[string]*ResourceState{
  2248  					"aws_instance.foo.0": {
  2249  						Type: "aws_instance",
  2250  						Primary: &InstanceState{
  2251  							ID: "bar",
  2252  							Attributes: map[string]string{
  2253  								"foo":  "foo",
  2254  								"type": "aws_instance",
  2255  							},
  2256  						},
  2257  					},
  2258  					"aws_instance.foo.1": {
  2259  						Type: "aws_instance",
  2260  						Primary: &InstanceState{
  2261  							ID: "bar",
  2262  						},
  2263  					},
  2264  					"aws_instance.foo.2": {
  2265  						Type: "aws_instance",
  2266  						Primary: &InstanceState{
  2267  							ID: "bar",
  2268  						},
  2269  					},
  2270  				},
  2271  			},
  2272  		},
  2273  	})
  2274  	ctx := testContext2(t, &ContextOpts{
  2275  		Config: m,
  2276  		ProviderResolver: providers.ResolverFixed(
  2277  			map[string]providers.Factory{
  2278  				"aws": testProviderFuncFixed(p),
  2279  			},
  2280  		),
  2281  		State: s,
  2282  	})
  2283  
  2284  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2285  		t.Fatalf("plan errors: %s", diags.Err())
  2286  	}
  2287  
  2288  	state, diags := ctx.Apply()
  2289  	if diags.HasErrors() {
  2290  		t.Fatalf("diags: %s", diags.Err())
  2291  	}
  2292  
  2293  	actual := strings.TrimSpace(state.String())
  2294  	expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr)
  2295  	if actual != expected {
  2296  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2297  	}
  2298  }
  2299  
  2300  // https://github.com/PeoplePerHour/terraform/pull/11
  2301  //
  2302  // This tests a case where both a "resource" and "resource.0" are in
  2303  // the state file, which apparently is a reasonable backwards compatibility
  2304  // concern found in the above 3rd party repo.
  2305  func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) {
  2306  	m := testModule(t, "apply-count-dec-one")
  2307  	p := testProvider("aws")
  2308  	p.ApplyFn = testApplyFn
  2309  	p.DiffFn = testDiffFn
  2310  	s := MustShimLegacyState(&State{
  2311  		Modules: []*ModuleState{
  2312  			{
  2313  				Path: rootModulePath,
  2314  				Resources: map[string]*ResourceState{
  2315  					"aws_instance.foo": {
  2316  						Type: "aws_instance",
  2317  						Primary: &InstanceState{
  2318  							ID: "bar",
  2319  							Attributes: map[string]string{
  2320  								"foo":  "foo",
  2321  								"type": "aws_instance",
  2322  							},
  2323  						},
  2324  					},
  2325  					"aws_instance.foo.0": {
  2326  						Type: "aws_instance",
  2327  						Primary: &InstanceState{
  2328  							ID: "baz",
  2329  							Attributes: map[string]string{
  2330  								"type": "aws_instance",
  2331  							},
  2332  						},
  2333  					},
  2334  				},
  2335  			},
  2336  		},
  2337  	})
  2338  	ctx := testContext2(t, &ContextOpts{
  2339  		Config: m,
  2340  		ProviderResolver: providers.ResolverFixed(
  2341  			map[string]providers.Factory{
  2342  				"aws": testProviderFuncFixed(p),
  2343  			},
  2344  		),
  2345  		State: s,
  2346  	})
  2347  
  2348  	if p, diags := ctx.Plan(); diags.HasErrors() {
  2349  		t.Fatalf("diags: %s", diags.Err())
  2350  	} else {
  2351  		got := strings.TrimSpace(legacyPlanComparisonString(ctx.State(), p.Changes))
  2352  		want := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedPlanStr)
  2353  		if got != want {
  2354  			t.Fatalf("wrong plan result\ngot:\n%s\nwant:\n%s", got, want)
  2355  		}
  2356  	}
  2357  
  2358  	state, diags := ctx.Apply()
  2359  	if diags.HasErrors() {
  2360  		t.Fatalf("diags: %s", diags.Err())
  2361  	}
  2362  
  2363  	actual := strings.TrimSpace(state.String())
  2364  	expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr)
  2365  	if actual != expected {
  2366  		t.Fatalf("wrong final state\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2367  	}
  2368  }
  2369  
  2370  func TestContext2Apply_countTainted(t *testing.T) {
  2371  	m := testModule(t, "apply-count-tainted")
  2372  	p := testProvider("aws")
  2373  	p.DiffFn = testDiffFn
  2374  	p.ApplyFn = testApplyFn
  2375  	s := MustShimLegacyState(&State{
  2376  		Modules: []*ModuleState{
  2377  			{
  2378  				Path: rootModulePath,
  2379  				Resources: map[string]*ResourceState{
  2380  					"aws_instance.foo.0": {
  2381  						Type: "aws_instance",
  2382  						Primary: &InstanceState{
  2383  							ID: "bar",
  2384  							Attributes: map[string]string{
  2385  								"foo":  "foo",
  2386  								"type": "aws_instance",
  2387  							},
  2388  							Tainted: true,
  2389  						},
  2390  					},
  2391  				},
  2392  			},
  2393  		},
  2394  	})
  2395  	ctx := testContext2(t, &ContextOpts{
  2396  		Config: m,
  2397  		ProviderResolver: providers.ResolverFixed(
  2398  			map[string]providers.Factory{
  2399  				"aws": testProviderFuncFixed(p),
  2400  			},
  2401  		),
  2402  		State: s,
  2403  	})
  2404  
  2405  	{
  2406  		plan, diags := ctx.Plan()
  2407  		assertNoErrors(t, diags)
  2408  		got := strings.TrimSpace(legacyDiffComparisonString(plan.Changes))
  2409  		want := strings.TrimSpace(`
  2410  DESTROY/CREATE: aws_instance.foo[0]
  2411    foo:  "foo" => "foo"
  2412    id:   "bar" => "<computed>"
  2413    type: "aws_instance" => "aws_instance"
  2414  CREATE: aws_instance.foo[1]
  2415    foo:  "" => "foo"
  2416    id:   "" => "<computed>"
  2417    type: "" => "aws_instance"
  2418  `)
  2419  		if got != want {
  2420  			t.Fatalf("wrong plan\n\ngot:\n%s\n\nwant:\n%s", got, want)
  2421  		}
  2422  	}
  2423  
  2424  	state, diags := ctx.Apply()
  2425  	assertNoErrors(t, diags)
  2426  
  2427  	got := strings.TrimSpace(state.String())
  2428  	want := strings.TrimSpace(`
  2429  aws_instance.foo.0:
  2430    ID = foo
  2431    provider = provider.aws
  2432    foo = foo
  2433    type = aws_instance
  2434  aws_instance.foo.1:
  2435    ID = foo
  2436    provider = provider.aws
  2437    foo = foo
  2438    type = aws_instance
  2439  `)
  2440  	if got != want {
  2441  		t.Fatalf("wrong final state\n\ngot:\n%s\n\nwant:\n%s", got, want)
  2442  	}
  2443  }
  2444  
  2445  func TestContext2Apply_countVariable(t *testing.T) {
  2446  	m := testModule(t, "apply-count-variable")
  2447  	p := testProvider("aws")
  2448  	p.ApplyFn = testApplyFn
  2449  	p.DiffFn = testDiffFn
  2450  	ctx := testContext2(t, &ContextOpts{
  2451  		Config: m,
  2452  		ProviderResolver: providers.ResolverFixed(
  2453  			map[string]providers.Factory{
  2454  				"aws": testProviderFuncFixed(p),
  2455  			},
  2456  		),
  2457  	})
  2458  
  2459  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2460  		t.Fatalf("plan errors: %s", diags.Err())
  2461  	}
  2462  
  2463  	state, diags := ctx.Apply()
  2464  	if diags.HasErrors() {
  2465  		t.Fatalf("diags: %s", diags.Err())
  2466  	}
  2467  
  2468  	actual := strings.TrimSpace(state.String())
  2469  	expected := strings.TrimSpace(testTerraformApplyCountVariableStr)
  2470  	if actual != expected {
  2471  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2472  	}
  2473  }
  2474  
  2475  func TestContext2Apply_countVariableRef(t *testing.T) {
  2476  	m := testModule(t, "apply-count-variable-ref")
  2477  	p := testProvider("aws")
  2478  	p.ApplyFn = testApplyFn
  2479  	p.DiffFn = testDiffFn
  2480  	ctx := testContext2(t, &ContextOpts{
  2481  		Config: m,
  2482  		ProviderResolver: providers.ResolverFixed(
  2483  			map[string]providers.Factory{
  2484  				"aws": testProviderFuncFixed(p),
  2485  			},
  2486  		),
  2487  	})
  2488  
  2489  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2490  		t.Fatalf("plan errors: %s", diags.Err())
  2491  	}
  2492  
  2493  	state, diags := ctx.Apply()
  2494  	if diags.HasErrors() {
  2495  		t.Fatalf("diags: %s", diags.Err())
  2496  	}
  2497  
  2498  	actual := strings.TrimSpace(state.String())
  2499  	expected := strings.TrimSpace(testTerraformApplyCountVariableRefStr)
  2500  	if actual != expected {
  2501  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2502  	}
  2503  }
  2504  
  2505  func TestContext2Apply_provisionerInterpCount(t *testing.T) {
  2506  	// This test ensures that a provisioner can interpolate a resource count
  2507  	// even though the provisioner expression is evaluated during the plan
  2508  	// walk. https://github.com/hashicorp/terraform-plugin-sdk/issues/16840
  2509  
  2510  	m, snap := testModuleWithSnapshot(t, "apply-provisioner-interp-count")
  2511  
  2512  	p := testProvider("aws")
  2513  	p.ApplyFn = testApplyFn
  2514  	p.DiffFn = testDiffFn
  2515  
  2516  	pr := testProvisioner()
  2517  
  2518  	providerResolver := providers.ResolverFixed(
  2519  		map[string]providers.Factory{
  2520  			"aws": testProviderFuncFixed(p),
  2521  		},
  2522  	)
  2523  	provisioners := map[string]ProvisionerFactory{
  2524  		"local-exec": testProvisionerFuncFixed(pr),
  2525  	}
  2526  	ctx := testContext2(t, &ContextOpts{
  2527  		Config:           m,
  2528  		ProviderResolver: providerResolver,
  2529  		Provisioners:     provisioners,
  2530  	})
  2531  
  2532  	plan, diags := ctx.Plan()
  2533  	if diags.HasErrors() {
  2534  		t.Fatalf("plan failed unexpectedly: %s", diags.Err())
  2535  	}
  2536  
  2537  	state := ctx.State()
  2538  
  2539  	// We'll marshal and unmarshal the plan here, to ensure that we have
  2540  	// a clean new context as would be created if we separately ran
  2541  	// terraform plan -out=tfplan && terraform apply tfplan
  2542  	ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  2543  	if err != nil {
  2544  		t.Fatal(err)
  2545  	}
  2546  	ctxOpts.ProviderResolver = providerResolver
  2547  	ctxOpts.Provisioners = provisioners
  2548  	ctx, diags = NewContext(ctxOpts)
  2549  	if diags.HasErrors() {
  2550  		t.Fatalf("failed to create context for plan: %s", diags.Err())
  2551  	}
  2552  
  2553  	// Applying the plan should now succeed
  2554  	_, diags = ctx.Apply()
  2555  	if diags.HasErrors() {
  2556  		t.Fatalf("apply failed unexpectedly: %s", diags.Err())
  2557  	}
  2558  
  2559  	// Verify apply was invoked
  2560  	if !pr.ProvisionResourceCalled {
  2561  		t.Fatalf("provisioner was not called")
  2562  	}
  2563  }
  2564  
  2565  func TestContext2Apply_foreachVariable(t *testing.T) {
  2566  	m := testModule(t, "plan-for-each-unknown-value")
  2567  	p := testProvider("aws")
  2568  	p.ApplyFn = testApplyFn
  2569  	p.DiffFn = testDiffFn
  2570  	ctx := testContext2(t, &ContextOpts{
  2571  		Config: m,
  2572  		ProviderResolver: providers.ResolverFixed(
  2573  			map[string]providers.Factory{
  2574  				"aws": testProviderFuncFixed(p),
  2575  			},
  2576  		),
  2577  		Variables: InputValues{
  2578  			"foo": &InputValue{
  2579  				Value: cty.StringVal("hello"),
  2580  			},
  2581  		},
  2582  	})
  2583  
  2584  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2585  		t.Fatalf("plan errors: %s", diags.Err())
  2586  	}
  2587  
  2588  	state, diags := ctx.Apply()
  2589  	if diags.HasErrors() {
  2590  		t.Fatalf("diags: %s", diags.Err())
  2591  	}
  2592  
  2593  	actual := strings.TrimSpace(state.String())
  2594  	expected := strings.TrimSpace(testTerraformApplyForEachVariableStr)
  2595  	if actual != expected {
  2596  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2597  	}
  2598  }
  2599  
  2600  func TestContext2Apply_moduleBasic(t *testing.T) {
  2601  	m := testModule(t, "apply-module")
  2602  	p := testProvider("aws")
  2603  	p.ApplyFn = testApplyFn
  2604  	p.DiffFn = testDiffFn
  2605  	ctx := testContext2(t, &ContextOpts{
  2606  		Config: m,
  2607  		ProviderResolver: providers.ResolverFixed(
  2608  			map[string]providers.Factory{
  2609  				"aws": testProviderFuncFixed(p),
  2610  			},
  2611  		),
  2612  	})
  2613  
  2614  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2615  		t.Fatalf("plan errors: %s", diags.Err())
  2616  	}
  2617  
  2618  	state, diags := ctx.Apply()
  2619  	if diags.HasErrors() {
  2620  		t.Fatalf("diags: %s", diags.Err())
  2621  	}
  2622  
  2623  	actual := strings.TrimSpace(state.String())
  2624  	expected := strings.TrimSpace(testTerraformApplyModuleStr)
  2625  	if actual != expected {
  2626  		t.Fatalf("bad, expected:\n%s\n\nactual:\n%s", expected, actual)
  2627  	}
  2628  }
  2629  
  2630  func TestContext2Apply_moduleDestroyOrder(t *testing.T) {
  2631  	m := testModule(t, "apply-module-destroy-order")
  2632  	p := testProvider("aws")
  2633  	p.DiffFn = testDiffFn
  2634  
  2635  	// Create a custom apply function to track the order they were destroyed
  2636  	var order []string
  2637  	var orderLock sync.Mutex
  2638  	p.ApplyFn = func(
  2639  		info *InstanceInfo,
  2640  		is *InstanceState,
  2641  		id *InstanceDiff) (*InstanceState, error) {
  2642  
  2643  		if is.ID == "b" {
  2644  			// Pause briefly to make any race conditions more visible, since
  2645  			// missing edges here can cause undeterministic ordering.
  2646  			time.Sleep(100 * time.Millisecond)
  2647  		}
  2648  
  2649  		orderLock.Lock()
  2650  		defer orderLock.Unlock()
  2651  
  2652  		order = append(order, is.ID)
  2653  		return nil, nil
  2654  	}
  2655  
  2656  	p.GetSchemaReturn = &ProviderSchema{
  2657  		ResourceTypes: map[string]*configschema.Block{
  2658  			"aws_instance": {
  2659  				Attributes: map[string]*configschema.Attribute{
  2660  					"id":    {Type: cty.String, Required: true},
  2661  					"blah":  {Type: cty.String, Optional: true},
  2662  					"value": {Type: cty.String, Optional: true},
  2663  				},
  2664  			},
  2665  		},
  2666  	}
  2667  
  2668  	state := MustShimLegacyState(&State{
  2669  		Modules: []*ModuleState{
  2670  			{
  2671  				Path: rootModulePath,
  2672  				Resources: map[string]*ResourceState{
  2673  					"aws_instance.b": resourceState("aws_instance", "b"),
  2674  				},
  2675  			},
  2676  
  2677  			{
  2678  				Path: []string{"root", "child"},
  2679  				Resources: map[string]*ResourceState{
  2680  					"aws_instance.a": resourceState("aws_instance", "a"),
  2681  				},
  2682  				Outputs: map[string]*OutputState{
  2683  					"a_output": {
  2684  						Type:      "string",
  2685  						Sensitive: false,
  2686  						Value:     "a",
  2687  					},
  2688  				},
  2689  			},
  2690  		},
  2691  	})
  2692  
  2693  	ctx := testContext2(t, &ContextOpts{
  2694  		Config: m,
  2695  		ProviderResolver: providers.ResolverFixed(
  2696  			map[string]providers.Factory{
  2697  				"aws": testProviderFuncFixed(p),
  2698  			},
  2699  		),
  2700  		State:   state,
  2701  		Destroy: true,
  2702  	})
  2703  
  2704  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2705  		t.Fatalf("plan errors: %s", diags.Err())
  2706  	}
  2707  
  2708  	state, diags := ctx.Apply()
  2709  	if diags.HasErrors() {
  2710  		t.Fatalf("diags: %s", diags.Err())
  2711  	}
  2712  
  2713  	expected := []string{"b", "a"}
  2714  	if !reflect.DeepEqual(order, expected) {
  2715  		t.Errorf("wrong order\ngot: %#v\nwant: %#v", order, expected)
  2716  	}
  2717  
  2718  	{
  2719  		actual := strings.TrimSpace(state.String())
  2720  		expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr)
  2721  		if actual != expected {
  2722  			t.Errorf("wrong final state\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  2723  		}
  2724  	}
  2725  }
  2726  
  2727  func TestContext2Apply_moduleInheritAlias(t *testing.T) {
  2728  	m := testModule(t, "apply-module-provider-inherit-alias")
  2729  	p := testProvider("aws")
  2730  	p.ApplyFn = testApplyFn
  2731  	p.DiffFn = testDiffFn
  2732  
  2733  	p.ConfigureFn = func(c *ResourceConfig) error {
  2734  		if _, ok := c.Get("value"); !ok {
  2735  			return nil
  2736  		}
  2737  
  2738  		if _, ok := c.Get("root"); ok {
  2739  			return fmt.Errorf("child should not get root")
  2740  		}
  2741  
  2742  		return nil
  2743  	}
  2744  
  2745  	ctx := testContext2(t, &ContextOpts{
  2746  		Config: m,
  2747  		ProviderResolver: providers.ResolverFixed(
  2748  			map[string]providers.Factory{
  2749  				"aws": testProviderFuncFixed(p),
  2750  			},
  2751  		),
  2752  	})
  2753  
  2754  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2755  		t.Fatalf("plan errors: %s", diags.Err())
  2756  	}
  2757  
  2758  	state, diags := ctx.Apply()
  2759  	if diags.HasErrors() {
  2760  		t.Fatalf("diags: %s", diags.Err())
  2761  	}
  2762  
  2763  	checkStateString(t, state, `
  2764  <no state>
  2765  module.child:
  2766    aws_instance.foo:
  2767      ID = foo
  2768      provider = provider.aws.eu
  2769  	`)
  2770  }
  2771  
  2772  func TestContext2Apply_orphanResource(t *testing.T) {
  2773  	// This is a two-step test:
  2774  	// 1. Apply a configuration with resources that have count set.
  2775  	//    This should place the empty resource object in the state to record
  2776  	//    that each exists, and record any instances.
  2777  	// 2. Apply an empty configuration against the same state, which should
  2778  	//    then clean up both the instances and the containing resource objects.
  2779  	p := testProvider("test")
  2780  	p.ApplyFn = testApplyFn
  2781  	p.DiffFn = testDiffFn
  2782  	p.GetSchemaReturn = &ProviderSchema{
  2783  		ResourceTypes: map[string]*configschema.Block{
  2784  			"test_thing": {},
  2785  		},
  2786  	}
  2787  
  2788  	// Step 1: create the resources and instances
  2789  	m := testModule(t, "apply-orphan-resource")
  2790  	ctx := testContext2(t, &ContextOpts{
  2791  		Config: m,
  2792  		ProviderResolver: providers.ResolverFixed(
  2793  			map[string]providers.Factory{
  2794  				"test": testProviderFuncFixed(p),
  2795  			},
  2796  		),
  2797  	})
  2798  	_, diags := ctx.Plan()
  2799  	assertNoErrors(t, diags)
  2800  	state, diags := ctx.Apply()
  2801  	assertNoErrors(t, diags)
  2802  
  2803  	// At this point both resources should be recorded in the state, along
  2804  	// with the single instance associated with test_thing.one.
  2805  	want := states.BuildState(func(s *states.SyncState) {
  2806  		providerAddr := addrs.ProviderConfig{
  2807  			Type: "test",
  2808  		}.Absolute(addrs.RootModuleInstance)
  2809  		zeroAddr := addrs.Resource{
  2810  			Mode: addrs.ManagedResourceMode,
  2811  			Type: "test_thing",
  2812  			Name: "zero",
  2813  		}.Absolute(addrs.RootModuleInstance)
  2814  		oneAddr := addrs.Resource{
  2815  			Mode: addrs.ManagedResourceMode,
  2816  			Type: "test_thing",
  2817  			Name: "one",
  2818  		}.Absolute(addrs.RootModuleInstance)
  2819  		s.SetResourceMeta(zeroAddr, states.EachList, providerAddr)
  2820  		s.SetResourceMeta(oneAddr, states.EachList, providerAddr)
  2821  		s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.IntKey(0)), &states.ResourceInstanceObjectSrc{
  2822  			Status:    states.ObjectReady,
  2823  			AttrsJSON: []byte(`{}`),
  2824  		}, providerAddr)
  2825  	})
  2826  	if !cmp.Equal(state, want) {
  2827  		t.Fatalf("wrong state after step 1\n%s", cmp.Diff(want, state))
  2828  	}
  2829  
  2830  	// Step 2: update with an empty config, to destroy everything
  2831  	m = testModule(t, "empty")
  2832  	ctx = testContext2(t, &ContextOpts{
  2833  		Config: m,
  2834  		State:  state,
  2835  		ProviderResolver: providers.ResolverFixed(
  2836  			map[string]providers.Factory{
  2837  				"test": testProviderFuncFixed(p),
  2838  			},
  2839  		),
  2840  	})
  2841  	_, diags = ctx.Plan()
  2842  	assertNoErrors(t, diags)
  2843  	state, diags = ctx.Apply()
  2844  	assertNoErrors(t, diags)
  2845  
  2846  	// The state should now be _totally_ empty, with just an empty root module
  2847  	// (since that always exists) and no resources at all.
  2848  	want = states.NewState()
  2849  	if !cmp.Equal(state, want) {
  2850  		t.Fatalf("wrong state after step 2\ngot: %swant: %s", spew.Sdump(state), spew.Sdump(want))
  2851  	}
  2852  
  2853  }
  2854  
  2855  func TestContext2Apply_moduleOrphanInheritAlias(t *testing.T) {
  2856  	m := testModule(t, "apply-module-provider-inherit-alias-orphan")
  2857  	p := testProvider("aws")
  2858  	p.ApplyFn = testApplyFn
  2859  	p.DiffFn = testDiffFn
  2860  
  2861  	called := false
  2862  	p.ConfigureFn = func(c *ResourceConfig) error {
  2863  		called = true
  2864  
  2865  		if _, ok := c.Get("child"); !ok {
  2866  			return nil
  2867  		}
  2868  
  2869  		if _, ok := c.Get("root"); ok {
  2870  			return fmt.Errorf("child should not get root")
  2871  		}
  2872  
  2873  		return nil
  2874  	}
  2875  
  2876  	// Create a state with an orphan module
  2877  	state := MustShimLegacyState(&State{
  2878  		Modules: []*ModuleState{
  2879  			{
  2880  				Path: []string{"root", "child"},
  2881  				Resources: map[string]*ResourceState{
  2882  					"aws_instance.bar": {
  2883  						Type: "aws_instance",
  2884  						Primary: &InstanceState{
  2885  							ID: "bar",
  2886  						},
  2887  						Provider: "provider.aws.eu",
  2888  					},
  2889  				},
  2890  			},
  2891  		},
  2892  	})
  2893  
  2894  	ctx := testContext2(t, &ContextOpts{
  2895  		Config: m,
  2896  		State:  state,
  2897  		ProviderResolver: providers.ResolverFixed(
  2898  			map[string]providers.Factory{
  2899  				"aws": testProviderFuncFixed(p),
  2900  			},
  2901  		),
  2902  	})
  2903  
  2904  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2905  		t.Fatalf("plan errors: %s", diags.Err())
  2906  	}
  2907  
  2908  	state, diags := ctx.Apply()
  2909  	if diags.HasErrors() {
  2910  		t.Fatalf("diags: %s", diags.Err())
  2911  	}
  2912  
  2913  	if !called {
  2914  		t.Fatal("must call configure")
  2915  	}
  2916  
  2917  	checkStateString(t, state, "<no state>")
  2918  }
  2919  
  2920  func TestContext2Apply_moduleOrphanProvider(t *testing.T) {
  2921  	m := testModule(t, "apply-module-orphan-provider-inherit")
  2922  	p := testProvider("aws")
  2923  	p.ApplyFn = testApplyFn
  2924  	p.DiffFn = testDiffFn
  2925  
  2926  	p.ConfigureFn = func(c *ResourceConfig) error {
  2927  		if _, ok := c.Get("value"); !ok {
  2928  			return fmt.Errorf("value is not found")
  2929  		}
  2930  
  2931  		return nil
  2932  	}
  2933  
  2934  	// Create a state with an orphan module
  2935  	state := MustShimLegacyState(&State{
  2936  		Modules: []*ModuleState{
  2937  			{
  2938  				Path: []string{"root", "child"},
  2939  				Resources: map[string]*ResourceState{
  2940  					"aws_instance.bar": {
  2941  						Type: "aws_instance",
  2942  						Primary: &InstanceState{
  2943  							ID: "bar",
  2944  						},
  2945  						Provider: "provider.aws",
  2946  					},
  2947  				},
  2948  			},
  2949  		},
  2950  	})
  2951  
  2952  	ctx := testContext2(t, &ContextOpts{
  2953  		Config: m,
  2954  		State:  state,
  2955  		ProviderResolver: providers.ResolverFixed(
  2956  			map[string]providers.Factory{
  2957  				"aws": testProviderFuncFixed(p),
  2958  			},
  2959  		),
  2960  	})
  2961  
  2962  	if _, diags := ctx.Plan(); diags.HasErrors() {
  2963  		t.Fatalf("plan errors: %s", diags.Err())
  2964  	}
  2965  
  2966  	if _, diags := ctx.Apply(); diags.HasErrors() {
  2967  		t.Fatalf("apply errors: %s", diags.Err())
  2968  	}
  2969  }
  2970  
  2971  func TestContext2Apply_moduleOrphanGrandchildProvider(t *testing.T) {
  2972  	m := testModule(t, "apply-module-orphan-provider-inherit")
  2973  	p := testProvider("aws")
  2974  	p.ApplyFn = testApplyFn
  2975  	p.DiffFn = testDiffFn
  2976  
  2977  	p.ConfigureFn = func(c *ResourceConfig) error {
  2978  		if _, ok := c.Get("value"); !ok {
  2979  			return fmt.Errorf("value is not found")
  2980  		}
  2981  
  2982  		return nil
  2983  	}
  2984  
  2985  	// Create a state with an orphan module that is nested (grandchild)
  2986  	state := MustShimLegacyState(&State{
  2987  		Modules: []*ModuleState{
  2988  			{
  2989  				Path: []string{"root", "parent", "child"},
  2990  				Resources: map[string]*ResourceState{
  2991  					"aws_instance.bar": {
  2992  						Type: "aws_instance",
  2993  						Primary: &InstanceState{
  2994  							ID: "bar",
  2995  						},
  2996  						Provider: "provider.aws",
  2997  					},
  2998  				},
  2999  			},
  3000  		},
  3001  	})
  3002  
  3003  	ctx := testContext2(t, &ContextOpts{
  3004  		Config: m,
  3005  		State:  state,
  3006  		ProviderResolver: providers.ResolverFixed(
  3007  			map[string]providers.Factory{
  3008  				"aws": testProviderFuncFixed(p),
  3009  			},
  3010  		),
  3011  	})
  3012  
  3013  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3014  		t.Fatalf("plan errors: %s", diags.Err())
  3015  	}
  3016  
  3017  	if _, diags := ctx.Apply(); diags.HasErrors() {
  3018  		t.Fatalf("apply errors: %s", diags.Err())
  3019  	}
  3020  }
  3021  
  3022  func TestContext2Apply_moduleGrandchildProvider(t *testing.T) {
  3023  	m := testModule(t, "apply-module-grandchild-provider-inherit")
  3024  	p := testProvider("aws")
  3025  	p.ApplyFn = testApplyFn
  3026  	p.DiffFn = testDiffFn
  3027  
  3028  	var callLock sync.Mutex
  3029  	called := false
  3030  	p.ConfigureFn = func(c *ResourceConfig) error {
  3031  		if _, ok := c.Get("value"); !ok {
  3032  			return fmt.Errorf("value is not found")
  3033  		}
  3034  		callLock.Lock()
  3035  		called = true
  3036  		callLock.Unlock()
  3037  
  3038  		return nil
  3039  	}
  3040  
  3041  	ctx := testContext2(t, &ContextOpts{
  3042  		Config: m,
  3043  		ProviderResolver: providers.ResolverFixed(
  3044  			map[string]providers.Factory{
  3045  				"aws": testProviderFuncFixed(p),
  3046  			},
  3047  		),
  3048  	})
  3049  
  3050  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3051  		t.Fatalf("plan errors: %s", diags.Err())
  3052  	}
  3053  
  3054  	if _, diags := ctx.Apply(); diags.HasErrors() {
  3055  		t.Fatalf("apply errors: %s", diags.Err())
  3056  	}
  3057  
  3058  	callLock.Lock()
  3059  	defer callLock.Unlock()
  3060  	if called != true {
  3061  		t.Fatalf("err: configure never called")
  3062  	}
  3063  }
  3064  
  3065  // This tests an issue where all the providers in a module but not
  3066  // in the root weren't being added to the root properly. In this test
  3067  // case: aws is explicitly added to root, but "test" should be added to.
  3068  // With the bug, it wasn't.
  3069  func TestContext2Apply_moduleOnlyProvider(t *testing.T) {
  3070  	m := testModule(t, "apply-module-only-provider")
  3071  	p := testProvider("aws")
  3072  	p.ApplyFn = testApplyFn
  3073  	p.DiffFn = testDiffFn
  3074  	pTest := testProvider("test")
  3075  	pTest.ApplyFn = testApplyFn
  3076  	pTest.DiffFn = testDiffFn
  3077  
  3078  	ctx := testContext2(t, &ContextOpts{
  3079  		Config: m,
  3080  		ProviderResolver: providers.ResolverFixed(
  3081  			map[string]providers.Factory{
  3082  				"aws":  testProviderFuncFixed(p),
  3083  				"test": testProviderFuncFixed(pTest),
  3084  			},
  3085  		),
  3086  	})
  3087  
  3088  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3089  		t.Fatalf("plan errors: %s", diags.Err())
  3090  	}
  3091  
  3092  	state, diags := ctx.Apply()
  3093  	if diags.HasErrors() {
  3094  		t.Fatalf("diags: %s", diags.Err())
  3095  	}
  3096  
  3097  	actual := strings.TrimSpace(state.String())
  3098  	expected := strings.TrimSpace(testTerraformApplyModuleOnlyProviderStr)
  3099  	if actual != expected {
  3100  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3101  	}
  3102  }
  3103  
  3104  func TestContext2Apply_moduleProviderAlias(t *testing.T) {
  3105  	m := testModule(t, "apply-module-provider-alias")
  3106  	p := testProvider("aws")
  3107  	p.ApplyFn = testApplyFn
  3108  	p.DiffFn = testDiffFn
  3109  	ctx := testContext2(t, &ContextOpts{
  3110  		Config: m,
  3111  		ProviderResolver: providers.ResolverFixed(
  3112  			map[string]providers.Factory{
  3113  				"aws": testProviderFuncFixed(p),
  3114  			},
  3115  		),
  3116  	})
  3117  
  3118  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3119  		t.Fatalf("plan errors: %s", diags.Err())
  3120  	}
  3121  
  3122  	state, diags := ctx.Apply()
  3123  	if diags.HasErrors() {
  3124  		t.Fatalf("diags: %s", diags.Err())
  3125  	}
  3126  
  3127  	actual := strings.TrimSpace(state.String())
  3128  	expected := strings.TrimSpace(testTerraformApplyModuleProviderAliasStr)
  3129  	if actual != expected {
  3130  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3131  	}
  3132  }
  3133  
  3134  func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) {
  3135  	m := testModule(t, "apply-module-provider-alias")
  3136  	p := testProvider("aws")
  3137  	p.ApplyFn = testApplyFn
  3138  	p.DiffFn = testDiffFn
  3139  	ctx := testContext2(t, &ContextOpts{
  3140  		Config: m,
  3141  		ProviderResolver: providers.ResolverFixed(
  3142  			map[string]providers.Factory{
  3143  				"aws": testProviderFuncFixed(p),
  3144  			},
  3145  		),
  3146  		Targets: []addrs.Targetable{
  3147  			addrs.AbsResource{
  3148  				Module: addrs.RootModuleInstance,
  3149  				Resource: addrs.Resource{
  3150  					Mode: addrs.ManagedResourceMode,
  3151  					Type: "nonexistent",
  3152  					Name: "thing",
  3153  				},
  3154  			},
  3155  		},
  3156  	})
  3157  
  3158  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3159  		t.Fatalf("plan errors: %s", diags.Err())
  3160  	}
  3161  
  3162  	state, diags := ctx.Apply()
  3163  	if diags.HasErrors() {
  3164  		t.Fatalf("diags: %s", diags.Err())
  3165  	}
  3166  
  3167  	actual := strings.TrimSpace(state.String())
  3168  	expected := strings.TrimSpace(`
  3169  <no state>
  3170  	`)
  3171  	if actual != expected {
  3172  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3173  	}
  3174  }
  3175  
  3176  func TestContext2Apply_moduleProviderCloseNested(t *testing.T) {
  3177  	m := testModule(t, "apply-module-provider-close-nested")
  3178  	p := testProvider("aws")
  3179  	p.ApplyFn = testApplyFn
  3180  	p.DiffFn = testDiffFn
  3181  	ctx := testContext2(t, &ContextOpts{
  3182  		Config: m,
  3183  		ProviderResolver: providers.ResolverFixed(
  3184  			map[string]providers.Factory{
  3185  				"aws": testProviderFuncFixed(p),
  3186  			},
  3187  		),
  3188  		State: MustShimLegacyState(&State{
  3189  			Modules: []*ModuleState{
  3190  				{
  3191  					Path: []string{"root", "child", "subchild"},
  3192  					Resources: map[string]*ResourceState{
  3193  						"aws_instance.foo": {
  3194  							Type: "aws_instance",
  3195  							Primary: &InstanceState{
  3196  								ID: "bar",
  3197  							},
  3198  						},
  3199  					},
  3200  				},
  3201  			},
  3202  		}),
  3203  		Destroy: true,
  3204  	})
  3205  
  3206  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3207  		t.Fatalf("plan errors: %s", diags.Err())
  3208  	}
  3209  
  3210  	if _, diags := ctx.Apply(); diags.HasErrors() {
  3211  		t.Fatalf("apply errors: %s", diags.Err())
  3212  	}
  3213  }
  3214  
  3215  // Tests that variables used as module vars that reference data that
  3216  // already exists in the state and requires no diff works properly. This
  3217  // fixes an issue faced where module variables were pruned because they were
  3218  // accessing "non-existent" resources (they existed, just not in the graph
  3219  // cause they weren't in the diff).
  3220  func TestContext2Apply_moduleVarRefExisting(t *testing.T) {
  3221  	m := testModule(t, "apply-ref-existing")
  3222  	p := testProvider("aws")
  3223  	p.ApplyFn = testApplyFn
  3224  	p.DiffFn = testDiffFn
  3225  
  3226  	state := MustShimLegacyState(&State{
  3227  		Modules: []*ModuleState{
  3228  			{
  3229  				Path: rootModulePath,
  3230  				Resources: map[string]*ResourceState{
  3231  					"aws_instance.foo": {
  3232  						Type: "aws_instance",
  3233  						Primary: &InstanceState{
  3234  							ID: "foo",
  3235  							Attributes: map[string]string{
  3236  								"foo": "bar",
  3237  							},
  3238  						},
  3239  						Provider: "provider.aws",
  3240  					},
  3241  				},
  3242  			},
  3243  		},
  3244  	})
  3245  
  3246  	ctx := testContext2(t, &ContextOpts{
  3247  		Config: m,
  3248  		ProviderResolver: providers.ResolverFixed(
  3249  			map[string]providers.Factory{
  3250  				"aws": testProviderFuncFixed(p),
  3251  			},
  3252  		),
  3253  		State: state,
  3254  	})
  3255  
  3256  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3257  		t.Fatalf("plan errors: %s", diags.Err())
  3258  	}
  3259  
  3260  	state, diags := ctx.Apply()
  3261  	if diags.HasErrors() {
  3262  		t.Fatalf("diags: %s", diags.Err())
  3263  	}
  3264  
  3265  	actual := strings.TrimSpace(state.String())
  3266  	expected := strings.TrimSpace(testTerraformApplyModuleVarRefExistingStr)
  3267  	if actual != expected {
  3268  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3269  	}
  3270  }
  3271  
  3272  func TestContext2Apply_moduleVarResourceCount(t *testing.T) {
  3273  	m := testModule(t, "apply-module-var-resource-count")
  3274  	p := testProvider("aws")
  3275  	p.ApplyFn = testApplyFn
  3276  	p.DiffFn = testDiffFn
  3277  	ctx := testContext2(t, &ContextOpts{
  3278  		Config: m,
  3279  		ProviderResolver: providers.ResolverFixed(
  3280  			map[string]providers.Factory{
  3281  				"aws": testProviderFuncFixed(p),
  3282  			},
  3283  		),
  3284  		Variables: InputValues{
  3285  			"num": &InputValue{
  3286  				Value:      cty.NumberIntVal(2),
  3287  				SourceType: ValueFromCaller,
  3288  			},
  3289  		},
  3290  		Destroy: true,
  3291  	})
  3292  
  3293  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3294  		t.Fatalf("plan errors: %s", diags.Err())
  3295  	}
  3296  
  3297  	if _, diags := ctx.Apply(); diags.HasErrors() {
  3298  		t.Fatalf("apply errors: %s", diags.Err())
  3299  	}
  3300  
  3301  	ctx = testContext2(t, &ContextOpts{
  3302  		Config: m,
  3303  		ProviderResolver: providers.ResolverFixed(
  3304  			map[string]providers.Factory{
  3305  				"aws": testProviderFuncFixed(p),
  3306  			},
  3307  		),
  3308  		Variables: InputValues{
  3309  			"num": &InputValue{
  3310  				Value:      cty.NumberIntVal(5),
  3311  				SourceType: ValueFromCaller,
  3312  			},
  3313  		},
  3314  	})
  3315  
  3316  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3317  		t.Fatalf("plan errors: %s", diags.Err())
  3318  	}
  3319  
  3320  	if _, diags := ctx.Apply(); diags.HasErrors() {
  3321  		t.Fatalf("apply errors: %s", diags.Err())
  3322  	}
  3323  }
  3324  
  3325  // GH-819
  3326  func TestContext2Apply_moduleBool(t *testing.T) {
  3327  	m := testModule(t, "apply-module-bool")
  3328  	p := testProvider("aws")
  3329  	p.ApplyFn = testApplyFn
  3330  	p.DiffFn = testDiffFn
  3331  	ctx := testContext2(t, &ContextOpts{
  3332  		Config: m,
  3333  		ProviderResolver: providers.ResolverFixed(
  3334  			map[string]providers.Factory{
  3335  				"aws": testProviderFuncFixed(p),
  3336  			},
  3337  		),
  3338  	})
  3339  
  3340  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3341  		t.Fatalf("plan errors: %s", diags.Err())
  3342  	}
  3343  
  3344  	state, diags := ctx.Apply()
  3345  	if diags.HasErrors() {
  3346  		t.Fatalf("diags: %s", diags.Err())
  3347  	}
  3348  
  3349  	actual := strings.TrimSpace(state.String())
  3350  	expected := strings.TrimSpace(testTerraformApplyModuleBoolStr)
  3351  	if actual != expected {
  3352  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3353  	}
  3354  }
  3355  
  3356  // Tests that a module can be targeted and everything is properly created.
  3357  // This adds to the plan test to also just verify that apply works.
  3358  func TestContext2Apply_moduleTarget(t *testing.T) {
  3359  	m := testModule(t, "plan-targeted-cross-module")
  3360  	p := testProvider("aws")
  3361  	p.ApplyFn = testApplyFn
  3362  	p.DiffFn = testDiffFn
  3363  	ctx := testContext2(t, &ContextOpts{
  3364  		Config: m,
  3365  		ProviderResolver: providers.ResolverFixed(
  3366  			map[string]providers.Factory{
  3367  				"aws": testProviderFuncFixed(p),
  3368  			},
  3369  		),
  3370  		Targets: []addrs.Targetable{
  3371  			addrs.RootModuleInstance.Child("B", addrs.NoKey),
  3372  		},
  3373  	})
  3374  
  3375  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3376  		t.Fatalf("plan errors: %s", diags.Err())
  3377  	}
  3378  
  3379  	state, diags := ctx.Apply()
  3380  	if diags.HasErrors() {
  3381  		t.Fatalf("diags: %s", diags.Err())
  3382  	}
  3383  
  3384  	checkStateString(t, state, `
  3385  <no state>
  3386  module.A:
  3387    aws_instance.foo:
  3388      ID = foo
  3389      provider = provider.aws
  3390      foo = bar
  3391      type = aws_instance
  3392  
  3393    Outputs:
  3394  
  3395    value = foo
  3396  module.B:
  3397    aws_instance.bar:
  3398      ID = foo
  3399      provider = provider.aws
  3400      foo = foo
  3401      type = aws_instance
  3402  	`)
  3403  }
  3404  
  3405  func TestContext2Apply_multiProvider(t *testing.T) {
  3406  	m := testModule(t, "apply-multi-provider")
  3407  	p := testProvider("aws")
  3408  	p.ApplyFn = testApplyFn
  3409  	p.DiffFn = testDiffFn
  3410  
  3411  	pDO := testProvider("do")
  3412  	pDO.ApplyFn = testApplyFn
  3413  	pDO.DiffFn = testDiffFn
  3414  
  3415  	ctx := testContext2(t, &ContextOpts{
  3416  		Config: m,
  3417  		ProviderResolver: providers.ResolverFixed(
  3418  			map[string]providers.Factory{
  3419  				"aws": testProviderFuncFixed(p),
  3420  				"do":  testProviderFuncFixed(pDO),
  3421  			},
  3422  		),
  3423  	})
  3424  
  3425  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3426  		t.Fatalf("plan errors: %s", diags.Err())
  3427  	}
  3428  
  3429  	state, diags := ctx.Apply()
  3430  	if diags.HasErrors() {
  3431  		t.Fatalf("diags: %s", diags.Err())
  3432  	}
  3433  
  3434  	mod := state.RootModule()
  3435  	if len(mod.Resources) < 2 {
  3436  		t.Fatalf("bad: %#v", mod.Resources)
  3437  	}
  3438  
  3439  	actual := strings.TrimSpace(state.String())
  3440  	expected := strings.TrimSpace(testTerraformApplyMultiProviderStr)
  3441  	if actual != expected {
  3442  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  3443  	}
  3444  }
  3445  
  3446  func TestContext2Apply_multiProviderDestroy(t *testing.T) {
  3447  	m := testModule(t, "apply-multi-provider-destroy")
  3448  	p := testProvider("aws")
  3449  	p.ApplyFn = testApplyFn
  3450  	p.DiffFn = testDiffFn
  3451  	p.GetSchemaReturn = &ProviderSchema{
  3452  		Provider: &configschema.Block{
  3453  			Attributes: map[string]*configschema.Attribute{
  3454  				"addr": {Type: cty.String, Optional: true},
  3455  			},
  3456  		},
  3457  		ResourceTypes: map[string]*configschema.Block{
  3458  			"aws_instance": {
  3459  				Attributes: map[string]*configschema.Attribute{
  3460  					"foo": {Type: cty.String, Optional: true},
  3461  				},
  3462  			},
  3463  		},
  3464  	}
  3465  
  3466  	p2 := testProvider("vault")
  3467  	p2.ApplyFn = testApplyFn
  3468  	p2.DiffFn = testDiffFn
  3469  	p2.GetSchemaReturn = &ProviderSchema{
  3470  		ResourceTypes: map[string]*configschema.Block{
  3471  			"vault_instance": {
  3472  				Attributes: map[string]*configschema.Attribute{
  3473  					"id": {Type: cty.String, Computed: true},
  3474  				},
  3475  			},
  3476  		},
  3477  	}
  3478  
  3479  	var state *states.State
  3480  
  3481  	// First, create the instances
  3482  	{
  3483  		ctx := testContext2(t, &ContextOpts{
  3484  			Config: m,
  3485  			ProviderResolver: providers.ResolverFixed(
  3486  				map[string]providers.Factory{
  3487  					"aws":   testProviderFuncFixed(p),
  3488  					"vault": testProviderFuncFixed(p2),
  3489  				},
  3490  			),
  3491  		})
  3492  
  3493  		if _, diags := ctx.Plan(); diags.HasErrors() {
  3494  			t.Fatalf("errors during create plan: %s", diags.Err())
  3495  		}
  3496  
  3497  		s, diags := ctx.Apply()
  3498  		if diags.HasErrors() {
  3499  			t.Fatalf("errors during create apply: %s", diags.Err())
  3500  		}
  3501  
  3502  		state = s
  3503  	}
  3504  
  3505  	// Destroy them
  3506  	{
  3507  		// Verify that aws_instance.bar is destroyed first
  3508  		var checked bool
  3509  		var called int32
  3510  		var lock sync.Mutex
  3511  		applyFn := func(
  3512  			info *InstanceInfo,
  3513  			is *InstanceState,
  3514  			id *InstanceDiff) (*InstanceState, error) {
  3515  			lock.Lock()
  3516  			defer lock.Unlock()
  3517  
  3518  			if info.Type == "aws_instance" {
  3519  				checked = true
  3520  
  3521  				// Sleep to allow parallel execution
  3522  				time.Sleep(50 * time.Millisecond)
  3523  
  3524  				// Verify that called is 0 (dep not called)
  3525  				if atomic.LoadInt32(&called) != 0 {
  3526  					return nil, fmt.Errorf("nothing else should be called")
  3527  				}
  3528  			}
  3529  
  3530  			atomic.AddInt32(&called, 1)
  3531  			return testApplyFn(info, is, id)
  3532  		}
  3533  
  3534  		// Set the apply functions
  3535  		p.ApplyFn = applyFn
  3536  		p2.ApplyFn = applyFn
  3537  
  3538  		ctx := testContext2(t, &ContextOpts{
  3539  			Destroy: true,
  3540  			State:   state,
  3541  			Config:  m,
  3542  			ProviderResolver: providers.ResolverFixed(
  3543  				map[string]providers.Factory{
  3544  					"aws":   testProviderFuncFixed(p),
  3545  					"vault": testProviderFuncFixed(p2),
  3546  				},
  3547  			),
  3548  		})
  3549  
  3550  		if _, diags := ctx.Plan(); diags.HasErrors() {
  3551  			t.Fatalf("errors during destroy plan: %s", diags.Err())
  3552  		}
  3553  
  3554  		s, diags := ctx.Apply()
  3555  		if diags.HasErrors() {
  3556  			t.Fatalf("errors during destroy apply: %s", diags.Err())
  3557  		}
  3558  
  3559  		if !checked {
  3560  			t.Fatal("should be checked")
  3561  		}
  3562  
  3563  		state = s
  3564  	}
  3565  
  3566  	checkStateString(t, state, `<no state>`)
  3567  }
  3568  
  3569  // This is like the multiProviderDestroy test except it tests that
  3570  // dependent resources within a child module that inherit provider
  3571  // configuration are still destroyed first.
  3572  func TestContext2Apply_multiProviderDestroyChild(t *testing.T) {
  3573  	m := testModule(t, "apply-multi-provider-destroy-child")
  3574  	p := testProvider("aws")
  3575  	p.ApplyFn = testApplyFn
  3576  	p.DiffFn = testDiffFn
  3577  	p.GetSchemaReturn = &ProviderSchema{
  3578  		Provider: &configschema.Block{
  3579  			Attributes: map[string]*configschema.Attribute{
  3580  				"value": {Type: cty.String, Optional: true},
  3581  			},
  3582  		},
  3583  		ResourceTypes: map[string]*configschema.Block{
  3584  			"aws_instance": {
  3585  				Attributes: map[string]*configschema.Attribute{
  3586  					"foo": {Type: cty.String, Optional: true},
  3587  				},
  3588  			},
  3589  		},
  3590  	}
  3591  
  3592  	p2 := testProvider("vault")
  3593  	p2.ApplyFn = testApplyFn
  3594  	p2.DiffFn = testDiffFn
  3595  	p2.GetSchemaReturn = &ProviderSchema{
  3596  		Provider: &configschema.Block{},
  3597  		ResourceTypes: map[string]*configschema.Block{
  3598  			"vault_instance": {
  3599  				Attributes: map[string]*configschema.Attribute{
  3600  					"id": {Type: cty.String, Computed: true},
  3601  				},
  3602  			},
  3603  		},
  3604  	}
  3605  
  3606  	var state *states.State
  3607  
  3608  	// First, create the instances
  3609  	{
  3610  		ctx := testContext2(t, &ContextOpts{
  3611  			Config: m,
  3612  			ProviderResolver: providers.ResolverFixed(
  3613  				map[string]providers.Factory{
  3614  					"aws":   testProviderFuncFixed(p),
  3615  					"vault": testProviderFuncFixed(p2),
  3616  				},
  3617  			),
  3618  		})
  3619  
  3620  		if _, diags := ctx.Plan(); diags.HasErrors() {
  3621  			t.Fatalf("diags: %s", diags.Err())
  3622  		}
  3623  
  3624  		s, diags := ctx.Apply()
  3625  		if diags.HasErrors() {
  3626  			t.Fatalf("diags: %s", diags.Err())
  3627  		}
  3628  
  3629  		state = s
  3630  	}
  3631  
  3632  	// Destroy them
  3633  	{
  3634  		// Verify that aws_instance.bar is destroyed first
  3635  		var checked bool
  3636  		var called int32
  3637  		var lock sync.Mutex
  3638  		applyFn := func(
  3639  			info *InstanceInfo,
  3640  			is *InstanceState,
  3641  			id *InstanceDiff) (*InstanceState, error) {
  3642  			lock.Lock()
  3643  			defer lock.Unlock()
  3644  
  3645  			if info.Type == "aws_instance" {
  3646  				checked = true
  3647  
  3648  				// Sleep to allow parallel execution
  3649  				time.Sleep(50 * time.Millisecond)
  3650  
  3651  				// Verify that called is 0 (dep not called)
  3652  				if atomic.LoadInt32(&called) != 0 {
  3653  					return nil, fmt.Errorf("nothing else should be called")
  3654  				}
  3655  			}
  3656  
  3657  			atomic.AddInt32(&called, 1)
  3658  			return testApplyFn(info, is, id)
  3659  		}
  3660  
  3661  		// Set the apply functions
  3662  		p.ApplyFn = applyFn
  3663  		p2.ApplyFn = applyFn
  3664  
  3665  		ctx := testContext2(t, &ContextOpts{
  3666  			Destroy: true,
  3667  			State:   state,
  3668  			Config:  m,
  3669  			ProviderResolver: providers.ResolverFixed(
  3670  				map[string]providers.Factory{
  3671  					"aws":   testProviderFuncFixed(p),
  3672  					"vault": testProviderFuncFixed(p2),
  3673  				},
  3674  			),
  3675  		})
  3676  
  3677  		if _, diags := ctx.Plan(); diags.HasErrors() {
  3678  			t.Fatalf("diags: %s", diags.Err())
  3679  		}
  3680  
  3681  		s, diags := ctx.Apply()
  3682  		if diags.HasErrors() {
  3683  			t.Fatalf("diags: %s", diags.Err())
  3684  		}
  3685  
  3686  		if !checked {
  3687  			t.Fatal("should be checked")
  3688  		}
  3689  
  3690  		state = s
  3691  	}
  3692  
  3693  	checkStateString(t, state, `
  3694  <no state>
  3695  `)
  3696  }
  3697  
  3698  func TestContext2Apply_multiVar(t *testing.T) {
  3699  	m := testModule(t, "apply-multi-var")
  3700  	p := testProvider("aws")
  3701  	p.ApplyFn = testApplyFn
  3702  	p.DiffFn = testDiffFn
  3703  
  3704  	// First, apply with a count of 3
  3705  	ctx := testContext2(t, &ContextOpts{
  3706  		Config: m,
  3707  		ProviderResolver: providers.ResolverFixed(
  3708  			map[string]providers.Factory{
  3709  				"aws": testProviderFuncFixed(p),
  3710  			},
  3711  		),
  3712  		Variables: InputValues{
  3713  			"num": &InputValue{
  3714  				Value:      cty.NumberIntVal(3),
  3715  				SourceType: ValueFromCaller,
  3716  			},
  3717  		},
  3718  	})
  3719  
  3720  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3721  		t.Fatalf("plan errors: %s", diags.Err())
  3722  	}
  3723  
  3724  	state, diags := ctx.Apply()
  3725  	if diags.HasErrors() {
  3726  		t.Fatalf("diags: %s", diags.Err())
  3727  	}
  3728  
  3729  	actual := state.RootModule().OutputValues["output"]
  3730  	expected := cty.StringVal("bar0,bar1,bar2")
  3731  	if actual == nil || actual.Value != expected {
  3732  		t.Fatalf("wrong value\ngot:  %#v\nwant: %#v", actual.Value, expected)
  3733  	}
  3734  
  3735  	t.Logf("Initial state: %s", state.String())
  3736  
  3737  	// Apply again, reduce the count to 1
  3738  	{
  3739  		ctx := testContext2(t, &ContextOpts{
  3740  			Config: m,
  3741  			State:  state,
  3742  			ProviderResolver: providers.ResolverFixed(
  3743  				map[string]providers.Factory{
  3744  					"aws": testProviderFuncFixed(p),
  3745  				},
  3746  			),
  3747  			Variables: InputValues{
  3748  				"num": &InputValue{
  3749  					Value:      cty.NumberIntVal(1),
  3750  					SourceType: ValueFromCaller,
  3751  				},
  3752  			},
  3753  		})
  3754  
  3755  		if _, diags := ctx.Plan(); diags.HasErrors() {
  3756  			t.Fatalf("diags: %s", diags.Err())
  3757  		}
  3758  
  3759  		state, diags := ctx.Apply()
  3760  		if diags.HasErrors() {
  3761  			t.Fatalf("diags: %s", diags.Err())
  3762  		}
  3763  
  3764  		t.Logf("End state: %s", state.String())
  3765  
  3766  		actual := state.RootModule().OutputValues["output"]
  3767  		if actual == nil {
  3768  			t.Fatal("missing output")
  3769  		}
  3770  
  3771  		expected := cty.StringVal("bar0")
  3772  		if actual.Value != expected {
  3773  			t.Fatalf("wrong value\ngot:  %#v\nwant: %#v", actual.Value, expected)
  3774  		}
  3775  	}
  3776  }
  3777  
  3778  // This is a holistic test of multi-var (aka "splat variable") handling
  3779  // across several different Terraform subsystems. This is here because
  3780  // historically there were quirky differences in handling across different
  3781  // parts of Terraform and so here we want to assert the expected behavior and
  3782  // ensure that it remains consistent in future.
  3783  func TestContext2Apply_multiVarComprehensive(t *testing.T) {
  3784  	m := testModule(t, "apply-multi-var-comprehensive")
  3785  	p := testProvider("test")
  3786  
  3787  	configs := map[string]*ResourceConfig{}
  3788  	var configsLock sync.Mutex
  3789  
  3790  	p.ApplyFn = testApplyFn
  3791  
  3792  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  3793  		proposed := req.ProposedNewState
  3794  		configsLock.Lock()
  3795  		defer configsLock.Unlock()
  3796  		key := proposed.GetAttr("key").AsString()
  3797  		// This test was originally written using the legacy p.DiffFn interface,
  3798  		// and so the assertions below expect an old-style ResourceConfig, which
  3799  		// we'll construct via our shim for now to avoid rewriting all of the
  3800  		// assertions.
  3801  		configs[key] = NewResourceConfigShimmed(req.Config, p.GetSchemaReturn.ResourceTypes["test_thing"])
  3802  
  3803  		retVals := make(map[string]cty.Value)
  3804  		for it := proposed.ElementIterator(); it.Next(); {
  3805  			idxVal, val := it.Element()
  3806  			idx := idxVal.AsString()
  3807  
  3808  			switch idx {
  3809  			case "id":
  3810  				retVals[idx] = cty.UnknownVal(cty.String)
  3811  			case "name":
  3812  				retVals[idx] = cty.StringVal(key)
  3813  			default:
  3814  				retVals[idx] = val
  3815  			}
  3816  		}
  3817  
  3818  		return providers.PlanResourceChangeResponse{
  3819  			PlannedState: cty.ObjectVal(retVals),
  3820  		}
  3821  	}
  3822  
  3823  	p.GetSchemaReturn = &ProviderSchema{
  3824  		ResourceTypes: map[string]*configschema.Block{
  3825  			"test_thing": {
  3826  				Attributes: map[string]*configschema.Attribute{
  3827  					"key": {Type: cty.String, Required: true},
  3828  
  3829  					"source_id":              {Type: cty.String, Optional: true},
  3830  					"source_name":            {Type: cty.String, Optional: true},
  3831  					"first_source_id":        {Type: cty.String, Optional: true},
  3832  					"first_source_name":      {Type: cty.String, Optional: true},
  3833  					"source_ids":             {Type: cty.List(cty.String), Optional: true},
  3834  					"source_names":           {Type: cty.List(cty.String), Optional: true},
  3835  					"source_ids_from_func":   {Type: cty.List(cty.String), Optional: true},
  3836  					"source_names_from_func": {Type: cty.List(cty.String), Optional: true},
  3837  					"source_ids_wrapped":     {Type: cty.List(cty.List(cty.String)), Optional: true},
  3838  					"source_names_wrapped":   {Type: cty.List(cty.List(cty.String)), Optional: true},
  3839  
  3840  					"id":   {Type: cty.String, Computed: true},
  3841  					"name": {Type: cty.String, Computed: true},
  3842  				},
  3843  			},
  3844  		},
  3845  	}
  3846  
  3847  	// First, apply with a count of 3
  3848  	ctx := testContext2(t, &ContextOpts{
  3849  		Config: m,
  3850  		ProviderResolver: providers.ResolverFixed(
  3851  			map[string]providers.Factory{
  3852  				"test": testProviderFuncFixed(p),
  3853  			},
  3854  		),
  3855  		Variables: InputValues{
  3856  			"num": &InputValue{
  3857  				Value:      cty.NumberIntVal(3),
  3858  				SourceType: ValueFromCaller,
  3859  			},
  3860  		},
  3861  	})
  3862  
  3863  	if _, diags := ctx.Plan(); diags.HasErrors() {
  3864  		logDiagnostics(t, diags)
  3865  		t.Fatalf("errors during plan")
  3866  	}
  3867  
  3868  	checkConfig := func(key string, want map[string]interface{}) {
  3869  		configsLock.Lock()
  3870  		defer configsLock.Unlock()
  3871  
  3872  		if _, ok := configs[key]; !ok {
  3873  			t.Errorf("no config recorded for %s; expected a configuration", key)
  3874  			return
  3875  		}
  3876  		got := configs[key].Config
  3877  		t.Run("config for "+key, func(t *testing.T) {
  3878  			want["key"] = key // to avoid doing this for every example
  3879  			for _, problem := range deep.Equal(got, want) {
  3880  				t.Errorf(problem)
  3881  			}
  3882  		})
  3883  	}
  3884  
  3885  	checkConfig("multi_count_var.0", map[string]interface{}{
  3886  		"source_id":   hcl2shim.UnknownVariableValue,
  3887  		"source_name": "source.0",
  3888  	})
  3889  	checkConfig("multi_count_var.2", map[string]interface{}{
  3890  		"source_id":   hcl2shim.UnknownVariableValue,
  3891  		"source_name": "source.2",
  3892  	})
  3893  	checkConfig("multi_count_derived.0", map[string]interface{}{
  3894  		"source_id":   hcl2shim.UnknownVariableValue,
  3895  		"source_name": "source.0",
  3896  	})
  3897  	checkConfig("multi_count_derived.2", map[string]interface{}{
  3898  		"source_id":   hcl2shim.UnknownVariableValue,
  3899  		"source_name": "source.2",
  3900  	})
  3901  	checkConfig("whole_splat", map[string]interface{}{
  3902  		"source_ids": []interface{}{
  3903  			hcl2shim.UnknownVariableValue,
  3904  			hcl2shim.UnknownVariableValue,
  3905  			hcl2shim.UnknownVariableValue,
  3906  		},
  3907  		"source_names": []interface{}{
  3908  			"source.0",
  3909  			"source.1",
  3910  			"source.2",
  3911  		},
  3912  		"source_ids_from_func": hcl2shim.UnknownVariableValue,
  3913  		"source_names_from_func": []interface{}{
  3914  			"source.0",
  3915  			"source.1",
  3916  			"source.2",
  3917  		},
  3918  
  3919  		"source_ids_wrapped": []interface{}{
  3920  			[]interface{}{
  3921  				hcl2shim.UnknownVariableValue,
  3922  				hcl2shim.UnknownVariableValue,
  3923  				hcl2shim.UnknownVariableValue,
  3924  			},
  3925  		},
  3926  		"source_names_wrapped": []interface{}{
  3927  			[]interface{}{
  3928  				"source.0",
  3929  				"source.1",
  3930  				"source.2",
  3931  			},
  3932  		},
  3933  
  3934  		"first_source_id":   hcl2shim.UnknownVariableValue,
  3935  		"first_source_name": "source.0",
  3936  	})
  3937  	checkConfig("child.whole_splat", map[string]interface{}{
  3938  		"source_ids": []interface{}{
  3939  			hcl2shim.UnknownVariableValue,
  3940  			hcl2shim.UnknownVariableValue,
  3941  			hcl2shim.UnknownVariableValue,
  3942  		},
  3943  		"source_names": []interface{}{
  3944  			"source.0",
  3945  			"source.1",
  3946  			"source.2",
  3947  		},
  3948  
  3949  		"source_ids_wrapped": []interface{}{
  3950  			[]interface{}{
  3951  				hcl2shim.UnknownVariableValue,
  3952  				hcl2shim.UnknownVariableValue,
  3953  				hcl2shim.UnknownVariableValue,
  3954  			},
  3955  		},
  3956  		"source_names_wrapped": []interface{}{
  3957  			[]interface{}{
  3958  				"source.0",
  3959  				"source.1",
  3960  				"source.2",
  3961  			},
  3962  		},
  3963  	})
  3964  
  3965  	t.Run("apply", func(t *testing.T) {
  3966  		state, diags := ctx.Apply()
  3967  		if diags.HasErrors() {
  3968  			t.Fatalf("error during apply: %s", diags.Err())
  3969  		}
  3970  
  3971  		want := map[string]interface{}{
  3972  			"source_ids": []interface{}{"foo", "foo", "foo"},
  3973  			"source_names": []interface{}{
  3974  				"source.0",
  3975  				"source.1",
  3976  				"source.2",
  3977  			},
  3978  		}
  3979  		got := map[string]interface{}{}
  3980  		for k, s := range state.RootModule().OutputValues {
  3981  			got[k] = hcl2shim.ConfigValueFromHCL2(s.Value)
  3982  		}
  3983  		if !reflect.DeepEqual(got, want) {
  3984  			t.Errorf(
  3985  				"wrong outputs\ngot:  %s\nwant: %s",
  3986  				spew.Sdump(got), spew.Sdump(want),
  3987  			)
  3988  		}
  3989  	})
  3990  }
  3991  
  3992  // Test that multi-var (splat) access is ordered by count, not by
  3993  // value.
  3994  func TestContext2Apply_multiVarOrder(t *testing.T) {
  3995  	m := testModule(t, "apply-multi-var-order")
  3996  	p := testProvider("aws")
  3997  	p.ApplyFn = testApplyFn
  3998  	p.DiffFn = testDiffFn
  3999  
  4000  	// First, apply with a count of 3
  4001  	ctx := testContext2(t, &ContextOpts{
  4002  		Config: m,
  4003  		ProviderResolver: providers.ResolverFixed(
  4004  			map[string]providers.Factory{
  4005  				"aws": testProviderFuncFixed(p),
  4006  			},
  4007  		),
  4008  	})
  4009  
  4010  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4011  		t.Fatalf("plan errors: %s", diags.Err())
  4012  	}
  4013  
  4014  	state, diags := ctx.Apply()
  4015  	if diags.HasErrors() {
  4016  		t.Fatalf("diags: %s", diags.Err())
  4017  	}
  4018  
  4019  	t.Logf("State: %s", state.String())
  4020  
  4021  	actual := state.RootModule().OutputValues["should-be-11"]
  4022  	expected := cty.StringVal("index-11")
  4023  	if actual == nil || actual.Value != expected {
  4024  		t.Fatalf("wrong value\ngot:  %#v\nwant: %#v", actual.Value, expected)
  4025  	}
  4026  }
  4027  
  4028  // Test that multi-var (splat) access is ordered by count, not by
  4029  // value, through interpolations.
  4030  func TestContext2Apply_multiVarOrderInterp(t *testing.T) {
  4031  	m := testModule(t, "apply-multi-var-order-interp")
  4032  	p := testProvider("aws")
  4033  	p.ApplyFn = testApplyFn
  4034  	p.DiffFn = testDiffFn
  4035  
  4036  	// First, apply with a count of 3
  4037  	ctx := testContext2(t, &ContextOpts{
  4038  		Config: m,
  4039  		ProviderResolver: providers.ResolverFixed(
  4040  			map[string]providers.Factory{
  4041  				"aws": testProviderFuncFixed(p),
  4042  			},
  4043  		),
  4044  	})
  4045  
  4046  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4047  		t.Fatalf("plan errors: %s", diags.Err())
  4048  	}
  4049  
  4050  	state, diags := ctx.Apply()
  4051  	if diags.HasErrors() {
  4052  		t.Fatalf("diags: %s", diags.Err())
  4053  	}
  4054  
  4055  	t.Logf("State: %s", state.String())
  4056  
  4057  	actual := state.RootModule().OutputValues["should-be-11"]
  4058  	expected := cty.StringVal("baz-index-11")
  4059  	if actual == nil || actual.Value != expected {
  4060  		t.Fatalf("wrong value\ngot:  %#v\nwant: %#v", actual.Value, expected)
  4061  	}
  4062  }
  4063  
  4064  // Based on GH-10440 where a graph edge wasn't properly being created
  4065  // between a modified resource and a count instance being destroyed.
  4066  func TestContext2Apply_multiVarCountDec(t *testing.T) {
  4067  	var s *states.State
  4068  
  4069  	// First create resources. Nothing sneaky here.
  4070  	{
  4071  		m := testModule(t, "apply-multi-var-count-dec")
  4072  		p := testProvider("aws")
  4073  		p.ApplyFn = testApplyFn
  4074  		p.DiffFn = testDiffFn
  4075  		ctx := testContext2(t, &ContextOpts{
  4076  			Config: m,
  4077  			ProviderResolver: providers.ResolverFixed(
  4078  				map[string]providers.Factory{
  4079  					"aws": testProviderFuncFixed(p),
  4080  				},
  4081  			),
  4082  			Variables: InputValues{
  4083  				"num": &InputValue{
  4084  					Value:      cty.NumberIntVal(2),
  4085  					SourceType: ValueFromCaller,
  4086  				},
  4087  			},
  4088  		})
  4089  
  4090  		log.Print("\n========\nStep 1 Plan\n========")
  4091  		if _, diags := ctx.Plan(); diags.HasErrors() {
  4092  			t.Fatalf("diags: %s", diags.Err())
  4093  		}
  4094  
  4095  		log.Print("\n========\nStep 1 Apply\n========")
  4096  		state, diags := ctx.Apply()
  4097  		if diags.HasErrors() {
  4098  			t.Fatalf("diags: %s", diags.Err())
  4099  		}
  4100  
  4101  		t.Logf("Step 1 state:\n%s", state)
  4102  
  4103  		s = state
  4104  	}
  4105  
  4106  	// Decrease the count by 1 and verify that everything happens in the
  4107  	// right order.
  4108  	{
  4109  		m := testModule(t, "apply-multi-var-count-dec")
  4110  		p := testProvider("aws")
  4111  		p.ApplyFn = testApplyFn
  4112  		p.DiffFn = testDiffFn
  4113  
  4114  		// Verify that aws_instance.bar is modified first and nothing
  4115  		// else happens at the same time.
  4116  		var checked bool
  4117  		var called int32
  4118  		var lock sync.Mutex
  4119  		p.ApplyFn = func(
  4120  			info *InstanceInfo,
  4121  			is *InstanceState,
  4122  			id *InstanceDiff) (*InstanceState, error) {
  4123  			lock.Lock()
  4124  			defer lock.Unlock()
  4125  
  4126  			if id != nil && id.Attributes != nil && id.Attributes["ami"] != nil && id.Attributes["ami"].New == "special" {
  4127  				checked = true
  4128  
  4129  				// Sleep to allow parallel execution
  4130  				time.Sleep(50 * time.Millisecond)
  4131  
  4132  				// Verify that called is 0 (dep not called)
  4133  				if atomic.LoadInt32(&called) != 1 {
  4134  					return nil, fmt.Errorf("nothing else should be called")
  4135  				}
  4136  			}
  4137  
  4138  			atomic.AddInt32(&called, 1)
  4139  			return testApplyFn(info, is, id)
  4140  		}
  4141  
  4142  		ctx := testContext2(t, &ContextOpts{
  4143  			State:  s,
  4144  			Config: m,
  4145  			ProviderResolver: providers.ResolverFixed(
  4146  				map[string]providers.Factory{
  4147  					"aws": testProviderFuncFixed(p),
  4148  				},
  4149  			),
  4150  			Variables: InputValues{
  4151  				"num": &InputValue{
  4152  					Value:      cty.NumberIntVal(1),
  4153  					SourceType: ValueFromCaller,
  4154  				},
  4155  			},
  4156  		})
  4157  
  4158  		log.Print("\n========\nStep 2 Plan\n========")
  4159  		plan, diags := ctx.Plan()
  4160  		if diags.HasErrors() {
  4161  			t.Fatalf("plan errors: %s", diags.Err())
  4162  		}
  4163  
  4164  		t.Logf("Step 2 plan:\n%s", legacyDiffComparisonString(plan.Changes))
  4165  
  4166  		log.Print("\n========\nStep 2 Apply\n========")
  4167  		state, diags := ctx.Apply()
  4168  		if diags.HasErrors() {
  4169  			t.Fatalf("apply errors: %s", diags.Err())
  4170  		}
  4171  
  4172  		if !checked {
  4173  			t.Error("apply never called")
  4174  		}
  4175  
  4176  		t.Logf("Step 2 state:\n%s", state)
  4177  
  4178  		s = state
  4179  	}
  4180  }
  4181  
  4182  // Test that we can resolve a multi-var (splat) for the first resource
  4183  // created in a non-root module, which happens when the module state doesn't
  4184  // exist yet.
  4185  // https://github.com/hashicorp/terraform-plugin-sdk/issues/14438
  4186  func TestContext2Apply_multiVarMissingState(t *testing.T) {
  4187  	m := testModule(t, "apply-multi-var-missing-state")
  4188  	p := testProvider("test")
  4189  	p.ApplyFn = testApplyFn
  4190  	p.DiffFn = testDiffFn
  4191  	p.GetSchemaReturn = &ProviderSchema{
  4192  		ResourceTypes: map[string]*configschema.Block{
  4193  			"test_thing": {
  4194  				Attributes: map[string]*configschema.Attribute{
  4195  					"a_ids": {Type: cty.String, Optional: true},
  4196  					"id":    {Type: cty.String, Computed: true},
  4197  				},
  4198  			},
  4199  		},
  4200  	}
  4201  
  4202  	// First, apply with a count of 3
  4203  	ctx := testContext2(t, &ContextOpts{
  4204  		Config: m,
  4205  		ProviderResolver: providers.ResolverFixed(
  4206  			map[string]providers.Factory{
  4207  				"test": testProviderFuncFixed(p),
  4208  			},
  4209  		),
  4210  	})
  4211  
  4212  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4213  		t.Fatalf("plan failed: %s", diags.Err())
  4214  	}
  4215  
  4216  	// Before the relevant bug was fixed, Tdiagsaform would panic during apply.
  4217  	if _, diags := ctx.Apply(); diags.HasErrors() {
  4218  		t.Fatalf("apply failed: %s", diags.Err())
  4219  	}
  4220  
  4221  	// If we get here with no errors or panics then our test was successful.
  4222  }
  4223  
  4224  func TestContext2Apply_nilDiff(t *testing.T) {
  4225  	m := testModule(t, "apply-good")
  4226  	p := testProvider("aws")
  4227  	p.ApplyFn = testApplyFn
  4228  	p.DiffFn = testDiffFn
  4229  	ctx := testContext2(t, &ContextOpts{
  4230  		Config: m,
  4231  		ProviderResolver: providers.ResolverFixed(
  4232  			map[string]providers.Factory{
  4233  				"aws": testProviderFuncFixed(p),
  4234  			},
  4235  		),
  4236  	})
  4237  
  4238  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4239  		t.Fatalf("plan errors: %s", diags.Err())
  4240  	}
  4241  
  4242  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  4243  		return nil, nil
  4244  	}
  4245  
  4246  	if _, diags := ctx.Apply(); diags == nil {
  4247  		t.Fatal("should error")
  4248  	}
  4249  }
  4250  
  4251  func TestContext2Apply_outputDependsOn(t *testing.T) {
  4252  	m := testModule(t, "apply-output-depends-on")
  4253  	p := testProvider("aws")
  4254  	p.DiffFn = testDiffFn
  4255  
  4256  	{
  4257  		// Create a custom apply function that sleeps a bit (to allow parallel
  4258  		// graph execution) and then returns an error to force a partial state
  4259  		// return. We then verify the output is NOT there.
  4260  		p.ApplyFn = func(
  4261  			info *InstanceInfo,
  4262  			is *InstanceState,
  4263  			id *InstanceDiff) (*InstanceState, error) {
  4264  			// Sleep to allow parallel execution
  4265  			time.Sleep(50 * time.Millisecond)
  4266  
  4267  			// Return error to force partial state
  4268  			return nil, fmt.Errorf("abcd")
  4269  		}
  4270  
  4271  		ctx := testContext2(t, &ContextOpts{
  4272  			Config: m,
  4273  			ProviderResolver: providers.ResolverFixed(
  4274  				map[string]providers.Factory{
  4275  					"aws": testProviderFuncFixed(p),
  4276  				},
  4277  			),
  4278  		})
  4279  
  4280  		if _, diags := ctx.Plan(); diags.HasErrors() {
  4281  			t.Fatalf("diags: %s", diags.Err())
  4282  		}
  4283  
  4284  		state, diags := ctx.Apply()
  4285  		if !diags.HasErrors() || !strings.Contains(diags.Err().Error(), "abcd") {
  4286  			t.Fatalf("err: %s", diags.Err())
  4287  		}
  4288  
  4289  		checkStateString(t, state, `<no state>`)
  4290  	}
  4291  
  4292  	{
  4293  		// Create the standard apply function and verify we get the output
  4294  		p.ApplyFn = testApplyFn
  4295  
  4296  		ctx := testContext2(t, &ContextOpts{
  4297  			Config: m,
  4298  			ProviderResolver: providers.ResolverFixed(
  4299  				map[string]providers.Factory{
  4300  					"aws": testProviderFuncFixed(p),
  4301  				},
  4302  			),
  4303  		})
  4304  
  4305  		if _, diags := ctx.Plan(); diags.HasErrors() {
  4306  			t.Fatalf("diags: %s", diags.Err())
  4307  		}
  4308  
  4309  		state, diags := ctx.Apply()
  4310  		if diags.HasErrors() {
  4311  			t.Fatalf("diags: %s", diags.Err())
  4312  		}
  4313  
  4314  		checkStateString(t, state, `
  4315  aws_instance.foo:
  4316    ID = foo
  4317    provider = provider.aws
  4318  
  4319  Outputs:
  4320  
  4321  value = result
  4322  		`)
  4323  	}
  4324  }
  4325  
  4326  func TestContext2Apply_outputOrphan(t *testing.T) {
  4327  	m := testModule(t, "apply-output-orphan")
  4328  	p := testProvider("aws")
  4329  	p.ApplyFn = testApplyFn
  4330  	p.DiffFn = testDiffFn
  4331  
  4332  	state := MustShimLegacyState(&State{
  4333  		Modules: []*ModuleState{
  4334  			{
  4335  				Path: rootModulePath,
  4336  				Outputs: map[string]*OutputState{
  4337  					"foo": {
  4338  						Type:      "string",
  4339  						Sensitive: false,
  4340  						Value:     "bar",
  4341  					},
  4342  					"bar": {
  4343  						Type:      "string",
  4344  						Sensitive: false,
  4345  						Value:     "baz",
  4346  					},
  4347  				},
  4348  			},
  4349  		},
  4350  	})
  4351  
  4352  	ctx := testContext2(t, &ContextOpts{
  4353  		Config: m,
  4354  		ProviderResolver: providers.ResolverFixed(
  4355  			map[string]providers.Factory{
  4356  				"aws": testProviderFuncFixed(p),
  4357  			},
  4358  		),
  4359  		State: state,
  4360  	})
  4361  
  4362  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4363  		t.Fatalf("plan errors: %s", diags.Err())
  4364  	}
  4365  
  4366  	state, diags := ctx.Apply()
  4367  	if diags.HasErrors() {
  4368  		t.Fatalf("diags: %s", diags.Err())
  4369  	}
  4370  
  4371  	actual := strings.TrimSpace(state.String())
  4372  	expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr)
  4373  	if actual != expected {
  4374  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4375  	}
  4376  }
  4377  
  4378  func TestContext2Apply_outputOrphanModule(t *testing.T) {
  4379  	m := testModule(t, "apply-output-orphan-module")
  4380  	p := testProvider("aws")
  4381  	p.ApplyFn = testApplyFn
  4382  	p.DiffFn = testDiffFn
  4383  
  4384  	state := MustShimLegacyState(&State{
  4385  		Modules: []*ModuleState{
  4386  			{
  4387  				Path: []string{"root", "child"},
  4388  				Outputs: map[string]*OutputState{
  4389  					"foo": {
  4390  						Type:  "string",
  4391  						Value: "bar",
  4392  					},
  4393  					"bar": {
  4394  						Type:  "string",
  4395  						Value: "baz",
  4396  					},
  4397  				},
  4398  			},
  4399  		},
  4400  	})
  4401  
  4402  	ctx := testContext2(t, &ContextOpts{
  4403  		Config: m,
  4404  		ProviderResolver: providers.ResolverFixed(
  4405  			map[string]providers.Factory{
  4406  				"aws": testProviderFuncFixed(p),
  4407  			},
  4408  		),
  4409  		State: state.DeepCopy(),
  4410  	})
  4411  
  4412  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4413  		t.Fatalf("plan errors: %s", diags.Err())
  4414  	}
  4415  
  4416  	state, diags := ctx.Apply()
  4417  	if diags.HasErrors() {
  4418  		t.Fatalf("diags: %s", diags.Err())
  4419  	}
  4420  
  4421  	actual := strings.TrimSpace(state.String())
  4422  	expected := strings.TrimSpace(testTerraformApplyOutputOrphanModuleStr)
  4423  	if actual != expected {
  4424  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  4425  	}
  4426  
  4427  	// now apply with no module in the config, which should remove the
  4428  	// remaining output
  4429  	ctx = testContext2(t, &ContextOpts{
  4430  		Config: configs.NewEmptyConfig(),
  4431  		ProviderResolver: providers.ResolverFixed(
  4432  			map[string]providers.Factory{
  4433  				"aws": testProviderFuncFixed(p),
  4434  			},
  4435  		),
  4436  		State: state.DeepCopy(),
  4437  	})
  4438  
  4439  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4440  		t.Fatalf("plan errors: %s", diags.Err())
  4441  	}
  4442  
  4443  	state, diags = ctx.Apply()
  4444  	if diags.HasErrors() {
  4445  		t.Fatalf("diags: %s", diags.Err())
  4446  	}
  4447  
  4448  	if !state.Empty() {
  4449  		t.Fatalf("wrong final state %s\nwant empty state", spew.Sdump(state))
  4450  	}
  4451  }
  4452  
  4453  func TestContext2Apply_providerComputedVar(t *testing.T) {
  4454  	m := testModule(t, "apply-provider-computed")
  4455  	p := testProvider("aws")
  4456  	p.ApplyFn = testApplyFn
  4457  	p.DiffFn = testDiffFn
  4458  
  4459  	pTest := testProvider("test")
  4460  	pTest.ApplyFn = testApplyFn
  4461  	pTest.DiffFn = testDiffFn
  4462  
  4463  	ctx := testContext2(t, &ContextOpts{
  4464  		Config: m,
  4465  		ProviderResolver: providers.ResolverFixed(
  4466  			map[string]providers.Factory{
  4467  				"aws":  testProviderFuncFixed(p),
  4468  				"test": testProviderFuncFixed(pTest),
  4469  			},
  4470  		),
  4471  	})
  4472  
  4473  	p.ConfigureFn = func(c *ResourceConfig) error {
  4474  		if c.IsComputed("value") {
  4475  			return fmt.Errorf("value is computed")
  4476  		}
  4477  
  4478  		v, ok := c.Get("value")
  4479  		if !ok {
  4480  			return fmt.Errorf("value is not found")
  4481  		}
  4482  		if v != "yes" {
  4483  			return fmt.Errorf("value is not 'yes': %v", v)
  4484  		}
  4485  
  4486  		return nil
  4487  	}
  4488  
  4489  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4490  		t.Fatalf("plan errors: %s", diags.Err())
  4491  	}
  4492  
  4493  	if _, diags := ctx.Apply(); diags.HasErrors() {
  4494  		t.Fatalf("apply errors: %s", diags.Err())
  4495  	}
  4496  }
  4497  
  4498  func TestContext2Apply_providerConfigureDisabled(t *testing.T) {
  4499  	m := testModule(t, "apply-provider-configure-disabled")
  4500  	p := testProvider("aws")
  4501  	p.ApplyFn = testApplyFn
  4502  	p.DiffFn = testDiffFn
  4503  
  4504  	called := false
  4505  	p.ConfigureFn = func(c *ResourceConfig) error {
  4506  		called = true
  4507  
  4508  		if _, ok := c.Get("value"); !ok {
  4509  			return fmt.Errorf("value is not found")
  4510  		}
  4511  
  4512  		return nil
  4513  	}
  4514  
  4515  	ctx := testContext2(t, &ContextOpts{
  4516  		Config: m,
  4517  		ProviderResolver: providers.ResolverFixed(
  4518  			map[string]providers.Factory{
  4519  				"aws": testProviderFuncFixed(p),
  4520  			},
  4521  		),
  4522  	})
  4523  
  4524  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4525  		t.Fatalf("plan errors: %s", diags.Err())
  4526  	}
  4527  
  4528  	if _, diags := ctx.Apply(); diags.HasErrors() {
  4529  		t.Fatalf("apply errors: %s", diags.Err())
  4530  	}
  4531  
  4532  	if !called {
  4533  		t.Fatal("configure never called")
  4534  	}
  4535  }
  4536  
  4537  func TestContext2Apply_provisionerModule(t *testing.T) {
  4538  	m := testModule(t, "apply-provisioner-module")
  4539  
  4540  	p := testProvider("aws")
  4541  	p.ApplyFn = testApplyFn
  4542  	p.DiffFn = testDiffFn
  4543  
  4544  	pr := testProvisioner()
  4545  	pr.GetSchemaResponse = provisioners.GetSchemaResponse{
  4546  		Provisioner: &configschema.Block{
  4547  			Attributes: map[string]*configschema.Attribute{
  4548  				"foo": {Type: cty.String, Optional: true},
  4549  			},
  4550  		},
  4551  	}
  4552  
  4553  	ctx := testContext2(t, &ContextOpts{
  4554  		Config: m,
  4555  		ProviderResolver: providers.ResolverFixed(
  4556  			map[string]providers.Factory{
  4557  				"aws": testProviderFuncFixed(p),
  4558  			},
  4559  		),
  4560  		Provisioners: map[string]ProvisionerFactory{
  4561  			"shell": testProvisionerFuncFixed(pr),
  4562  		},
  4563  	})
  4564  
  4565  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4566  		t.Fatalf("plan errors: %s", diags.Err())
  4567  	}
  4568  
  4569  	state, diags := ctx.Apply()
  4570  	if diags.HasErrors() {
  4571  		t.Fatalf("diags: %s", diags.Err())
  4572  	}
  4573  
  4574  	actual := strings.TrimSpace(state.String())
  4575  	expected := strings.TrimSpace(testTerraformApplyProvisionerModuleStr)
  4576  	if actual != expected {
  4577  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4578  	}
  4579  
  4580  	// Verify apply was invoked
  4581  	if !pr.ProvisionResourceCalled {
  4582  		t.Fatalf("provisioner not invoked")
  4583  	}
  4584  }
  4585  
  4586  func TestContext2Apply_Provisioner_compute(t *testing.T) {
  4587  	m := testModule(t, "apply-provisioner-compute")
  4588  	p := testProvider("aws")
  4589  	pr := testProvisioner()
  4590  	p.ApplyFn = testApplyFn
  4591  	p.DiffFn = testDiffFn
  4592  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  4593  		val, ok := c.Config["command"]
  4594  		if !ok || val != "computed_value" {
  4595  			t.Fatalf("bad value for foo: %v %#v", val, c)
  4596  		}
  4597  
  4598  		return nil
  4599  	}
  4600  	ctx := testContext2(t, &ContextOpts{
  4601  		Config: m,
  4602  		ProviderResolver: providers.ResolverFixed(
  4603  			map[string]providers.Factory{
  4604  				"aws": testProviderFuncFixed(p),
  4605  			},
  4606  		),
  4607  		Provisioners: map[string]ProvisionerFactory{
  4608  			"shell": testProvisionerFuncFixed(pr),
  4609  		},
  4610  		Variables: InputValues{
  4611  			"value": &InputValue{
  4612  				Value:      cty.NumberIntVal(1),
  4613  				SourceType: ValueFromCaller,
  4614  			},
  4615  		},
  4616  	})
  4617  
  4618  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4619  		t.Fatalf("plan errors: %s", diags.Err())
  4620  	}
  4621  
  4622  	state, diags := ctx.Apply()
  4623  	if diags.HasErrors() {
  4624  		t.Fatalf("diags: %s", diags.Err())
  4625  	}
  4626  
  4627  	actual := strings.TrimSpace(state.String())
  4628  	expected := strings.TrimSpace(testTerraformApplyProvisionerStr)
  4629  	if actual != expected {
  4630  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4631  	}
  4632  
  4633  	// Verify apply was invoked
  4634  	if !pr.ProvisionResourceCalled {
  4635  		t.Fatalf("provisioner not invoked")
  4636  	}
  4637  }
  4638  
  4639  func TestContext2Apply_provisionerCreateFail(t *testing.T) {
  4640  	m := testModule(t, "apply-provisioner-fail-create")
  4641  	p := testProvider("aws")
  4642  	pr := testProvisioner()
  4643  	p.DiffFn = testDiffFn
  4644  
  4645  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  4646  		is.ID = "foo"
  4647  		return is, fmt.Errorf("error")
  4648  	}
  4649  
  4650  	ctx := testContext2(t, &ContextOpts{
  4651  		Config: m,
  4652  		ProviderResolver: providers.ResolverFixed(
  4653  			map[string]providers.Factory{
  4654  				"aws": testProviderFuncFixed(p),
  4655  			},
  4656  		),
  4657  		Provisioners: map[string]ProvisionerFactory{
  4658  			"shell": testProvisionerFuncFixed(pr),
  4659  		},
  4660  	})
  4661  
  4662  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4663  		t.Fatalf("plan errors: %s", diags.Err())
  4664  	}
  4665  
  4666  	state, diags := ctx.Apply()
  4667  	if diags == nil {
  4668  		t.Fatal("should error")
  4669  	}
  4670  
  4671  	got := strings.TrimSpace(state.String())
  4672  	want := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr)
  4673  	if got != want {
  4674  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", got, want)
  4675  	}
  4676  }
  4677  
  4678  func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) {
  4679  	m := testModule(t, "apply-provisioner-fail-create")
  4680  	p := testProvider("aws")
  4681  	pr := testProvisioner()
  4682  	p.DiffFn = testDiffFn
  4683  
  4684  	p.ApplyFn = func(
  4685  		info *InstanceInfo,
  4686  		is *InstanceState,
  4687  		id *InstanceDiff) (*InstanceState, error) {
  4688  		return nil, fmt.Errorf("error")
  4689  	}
  4690  
  4691  	ctx := testContext2(t, &ContextOpts{
  4692  		Config: m,
  4693  		ProviderResolver: providers.ResolverFixed(
  4694  			map[string]providers.Factory{
  4695  				"aws": testProviderFuncFixed(p),
  4696  			},
  4697  		),
  4698  		Provisioners: map[string]ProvisionerFactory{
  4699  			"shell": testProvisionerFuncFixed(pr),
  4700  		},
  4701  	})
  4702  
  4703  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4704  		t.Fatalf("plan errors: %s", diags.Err())
  4705  	}
  4706  
  4707  	state, diags := ctx.Apply()
  4708  	if diags == nil {
  4709  		t.Fatal("should error")
  4710  	}
  4711  
  4712  	actual := strings.TrimSpace(state.String())
  4713  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr)
  4714  	if actual != expected {
  4715  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4716  	}
  4717  }
  4718  
  4719  func TestContext2Apply_provisionerFail(t *testing.T) {
  4720  	m := testModule(t, "apply-provisioner-fail")
  4721  	p := testProvider("aws")
  4722  	pr := testProvisioner()
  4723  	p.ApplyFn = testApplyFn
  4724  	p.DiffFn = testDiffFn
  4725  
  4726  	pr.ApplyFn = func(*InstanceState, *ResourceConfig) error {
  4727  		return fmt.Errorf("EXPLOSION")
  4728  	}
  4729  
  4730  	ctx := testContext2(t, &ContextOpts{
  4731  		Config: m,
  4732  		ProviderResolver: providers.ResolverFixed(
  4733  			map[string]providers.Factory{
  4734  				"aws": testProviderFuncFixed(p),
  4735  			},
  4736  		),
  4737  		Provisioners: map[string]ProvisionerFactory{
  4738  			"shell": testProvisionerFuncFixed(pr),
  4739  		},
  4740  		Variables: InputValues{
  4741  			"value": &InputValue{
  4742  				Value:      cty.NumberIntVal(1),
  4743  				SourceType: ValueFromCaller,
  4744  			},
  4745  		},
  4746  	})
  4747  
  4748  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4749  		t.Fatalf("plan errors: %s", diags.Err())
  4750  	}
  4751  
  4752  	state, diags := ctx.Apply()
  4753  	if diags == nil {
  4754  		t.Fatal("should error")
  4755  	}
  4756  
  4757  	actual := strings.TrimSpace(state.String())
  4758  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr)
  4759  	if actual != expected {
  4760  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4761  	}
  4762  }
  4763  
  4764  func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) {
  4765  	m := testModule(t, "apply-provisioner-fail-create-before")
  4766  	p := testProvider("aws")
  4767  	pr := testProvisioner()
  4768  	p.ApplyFn = testApplyFn
  4769  	p.DiffFn = testDiffFn
  4770  	pr.ApplyFn = func(*InstanceState, *ResourceConfig) error {
  4771  		return fmt.Errorf("EXPLOSION")
  4772  	}
  4773  
  4774  	state := MustShimLegacyState(&State{
  4775  		Modules: []*ModuleState{
  4776  			{
  4777  				Path: rootModulePath,
  4778  				Resources: map[string]*ResourceState{
  4779  					"aws_instance.bar": {
  4780  						Type: "aws_instance",
  4781  						Primary: &InstanceState{
  4782  							ID: "bar",
  4783  							Attributes: map[string]string{
  4784  								"require_new": "abc",
  4785  							},
  4786  						},
  4787  					},
  4788  				},
  4789  			},
  4790  		},
  4791  	})
  4792  	ctx := testContext2(t, &ContextOpts{
  4793  		Config: m,
  4794  		ProviderResolver: providers.ResolverFixed(
  4795  			map[string]providers.Factory{
  4796  				"aws": testProviderFuncFixed(p),
  4797  			},
  4798  		),
  4799  		Provisioners: map[string]ProvisionerFactory{
  4800  			"shell": testProvisionerFuncFixed(pr),
  4801  		},
  4802  		State: state,
  4803  	})
  4804  
  4805  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4806  		t.Fatalf("plan errors: %s", diags.Err())
  4807  	}
  4808  
  4809  	state, diags := ctx.Apply()
  4810  	if diags == nil {
  4811  		t.Fatal("should error")
  4812  	}
  4813  
  4814  	actual := strings.TrimSpace(state.String())
  4815  	expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr)
  4816  	if actual != expected {
  4817  		t.Fatalf("expected:\n%s\n:got\n%s", expected, actual)
  4818  	}
  4819  }
  4820  
  4821  func TestContext2Apply_error_createBeforeDestroy(t *testing.T) {
  4822  	m := testModule(t, "apply-error-create-before")
  4823  	p := testProvider("aws")
  4824  	state := MustShimLegacyState(&State{
  4825  		Modules: []*ModuleState{
  4826  			{
  4827  				Path: rootModulePath,
  4828  				Resources: map[string]*ResourceState{
  4829  					"aws_instance.bar": {
  4830  						Type: "aws_instance",
  4831  						Primary: &InstanceState{
  4832  							ID: "bar",
  4833  							Attributes: map[string]string{
  4834  								"require_new": "abc",
  4835  							},
  4836  						},
  4837  					},
  4838  				},
  4839  			},
  4840  		},
  4841  	})
  4842  	ctx := testContext2(t, &ContextOpts{
  4843  		Config: m,
  4844  		ProviderResolver: providers.ResolverFixed(
  4845  			map[string]providers.Factory{
  4846  				"aws": testProviderFuncFixed(p),
  4847  			},
  4848  		),
  4849  		State: state,
  4850  	})
  4851  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  4852  		return nil, fmt.Errorf("error")
  4853  	}
  4854  	p.DiffFn = testDiffFn
  4855  
  4856  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4857  		t.Fatalf("plan errors: %s", diags.Err())
  4858  	}
  4859  
  4860  	state, diags := ctx.Apply()
  4861  	if diags == nil {
  4862  		t.Fatal("should have error")
  4863  	}
  4864  
  4865  	actual := strings.TrimSpace(state.String())
  4866  	expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr)
  4867  	if actual != expected {
  4868  		t.Fatalf("wrong final state\ngot:\n%s\n\nwant:\n%s", actual, expected)
  4869  	}
  4870  }
  4871  
  4872  func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) {
  4873  	m := testModule(t, "apply-error-create-before")
  4874  	p := testProvider("aws")
  4875  	state := MustShimLegacyState(&State{
  4876  		Modules: []*ModuleState{
  4877  			{
  4878  				Path: rootModulePath,
  4879  				Resources: map[string]*ResourceState{
  4880  					"aws_instance.bar": {
  4881  						Type: "aws_instance",
  4882  						Primary: &InstanceState{
  4883  							ID: "bar",
  4884  							Attributes: map[string]string{
  4885  								"require_new": "abc",
  4886  							},
  4887  						},
  4888  					},
  4889  				},
  4890  			},
  4891  		},
  4892  	})
  4893  	ctx := testContext2(t, &ContextOpts{
  4894  		Config: m,
  4895  		ProviderResolver: providers.ResolverFixed(
  4896  			map[string]providers.Factory{
  4897  				"aws": testProviderFuncFixed(p),
  4898  			},
  4899  		),
  4900  		State: state,
  4901  	})
  4902  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  4903  		// Fail the destroy!
  4904  		if id.Destroy {
  4905  			return is, fmt.Errorf("error")
  4906  		}
  4907  
  4908  		// Create should work
  4909  		is = &InstanceState{
  4910  			ID: "foo",
  4911  			Attributes: map[string]string{
  4912  				"type":        "aws_instance",
  4913  				"require_new": "xyz",
  4914  			},
  4915  		}
  4916  		return is, nil
  4917  	}
  4918  	p.DiffFn = testDiffFn
  4919  
  4920  	if _, diags := ctx.Plan(); diags.HasErrors() {
  4921  		t.Fatalf("plan errors: %s", diags.Err())
  4922  	}
  4923  
  4924  	state, diags := ctx.Apply()
  4925  	if diags == nil {
  4926  		t.Fatal("should have error")
  4927  	}
  4928  
  4929  	actual := strings.TrimSpace(state.String())
  4930  	expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr)
  4931  	if actual != expected {
  4932  		t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected)
  4933  	}
  4934  }
  4935  
  4936  func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) {
  4937  	m := testModule(t, "apply-multi-depose-create-before-destroy")
  4938  	p := testProvider("aws")
  4939  	p.GetSchemaReturn = &ProviderSchema{
  4940  		ResourceTypes: map[string]*configschema.Block{
  4941  			"aws_instance": {
  4942  				Attributes: map[string]*configschema.Attribute{
  4943  					"require_new": {Type: cty.String, Optional: true},
  4944  					"id":          {Type: cty.String, Computed: true},
  4945  				},
  4946  			},
  4947  		},
  4948  	}
  4949  	ps := map[string]providers.Factory{"aws": testProviderFuncFixed(p)}
  4950  	state := MustShimLegacyState(&State{
  4951  		Modules: []*ModuleState{
  4952  			{
  4953  				Path: rootModulePath,
  4954  				Resources: map[string]*ResourceState{
  4955  					"aws_instance.web": {
  4956  						Type:    "aws_instance",
  4957  						Primary: &InstanceState{ID: "foo"},
  4958  					},
  4959  				},
  4960  			},
  4961  		},
  4962  	})
  4963  
  4964  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  4965  		if rc == nil {
  4966  			return &InstanceDiff{
  4967  				Destroy: true,
  4968  			}, nil
  4969  		}
  4970  
  4971  		rn, _ := rc.Get("require_new")
  4972  		return &InstanceDiff{
  4973  			Attributes: map[string]*ResourceAttrDiff{
  4974  				"id": {
  4975  					New:         hcl2shim.UnknownVariableValue,
  4976  					NewComputed: true,
  4977  					RequiresNew: true,
  4978  				},
  4979  				"require_new": {
  4980  					Old:         s.Attributes["require_new"],
  4981  					New:         rn.(string),
  4982  					RequiresNew: true,
  4983  				},
  4984  			},
  4985  		}, nil
  4986  	}
  4987  
  4988  	ctx := testContext2(t, &ContextOpts{
  4989  		Config:           m,
  4990  		ProviderResolver: providers.ResolverFixed(ps),
  4991  		State:            state,
  4992  	})
  4993  	createdInstanceId := "bar"
  4994  	// Create works
  4995  	createFunc := func(is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  4996  		return &InstanceState{
  4997  			ID: createdInstanceId,
  4998  			Attributes: map[string]string{
  4999  				"require_new": id.Attributes["require_new"].New,
  5000  			},
  5001  		}, nil
  5002  	}
  5003  	// Destroy starts broken
  5004  	destroyFunc := func(is *InstanceState) (*InstanceState, error) {
  5005  		return is, fmt.Errorf("destroy failed")
  5006  	}
  5007  	p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) {
  5008  		if id.Destroy {
  5009  			return destroyFunc(is)
  5010  		} else {
  5011  			return createFunc(is, id)
  5012  		}
  5013  	}
  5014  
  5015  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5016  		t.Fatalf("plan errors: %s", diags.Err())
  5017  	}
  5018  
  5019  	// Destroy is broken, so even though CBD successfully replaces the instance,
  5020  	// we'll have to save the Deposed instance to destroy later
  5021  	state, diags := ctx.Apply()
  5022  	if diags == nil {
  5023  		t.Fatal("should have error")
  5024  	}
  5025  
  5026  	checkStateString(t, state, `
  5027  aws_instance.web: (1 deposed)
  5028    ID = bar
  5029    provider = provider.aws
  5030    require_new = yes
  5031    Deposed ID 1 = foo
  5032  	`)
  5033  
  5034  	createdInstanceId = "baz"
  5035  	ctx = testContext2(t, &ContextOpts{
  5036  		Config:           m,
  5037  		ProviderResolver: providers.ResolverFixed(ps),
  5038  		State:            state,
  5039  	})
  5040  
  5041  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5042  		t.Fatalf("plan errors: %s", diags.Err())
  5043  	}
  5044  
  5045  	// We're replacing the primary instance once again. Destroy is _still_
  5046  	// broken, so the Deposed list gets longer
  5047  	state, diags = ctx.Apply()
  5048  	if diags == nil {
  5049  		t.Fatal("should have error")
  5050  	}
  5051  
  5052  	// For this one we can't rely on checkStateString because its result is
  5053  	// not deterministic when multiple deposed objects are present. Instead,
  5054  	// we will probe the state object directly.
  5055  	{
  5056  		is := state.RootModule().Resources["aws_instance.web"].Instances[addrs.NoKey]
  5057  		t.Logf("aws_instance.web is %s", spew.Sdump(is))
  5058  		if is.Current == nil {
  5059  			t.Fatalf("no current object for aws_instance web; should have one")
  5060  		}
  5061  		if !bytes.Contains(is.Current.AttrsJSON, []byte("baz")) {
  5062  			t.Fatalf("incorrect current object attrs %s; want id=baz", is.Current.AttrsJSON)
  5063  		}
  5064  		if got, want := len(is.Deposed), 2; got != want {
  5065  			t.Fatalf("wrong number of deposed instances %d; want %d", got, want)
  5066  		}
  5067  		var foos, bars int
  5068  		for _, obj := range is.Deposed {
  5069  			if bytes.Contains(obj.AttrsJSON, []byte("foo")) {
  5070  				foos++
  5071  			}
  5072  			if bytes.Contains(obj.AttrsJSON, []byte("bar")) {
  5073  				bars++
  5074  			}
  5075  		}
  5076  		if got, want := foos, 1; got != want {
  5077  			t.Fatalf("wrong number of deposed instances with id=foo %d; want %d", got, want)
  5078  		}
  5079  		if got, want := bars, 1; got != want {
  5080  			t.Fatalf("wrong number of deposed instances with id=bar %d; want %d", got, want)
  5081  		}
  5082  	}
  5083  
  5084  	// Destroy partially fixed!
  5085  	destroyFunc = func(is *InstanceState) (*InstanceState, error) {
  5086  		if is.ID == "foo" || is.ID == "baz" {
  5087  			return nil, nil
  5088  		} else {
  5089  			return is, fmt.Errorf("destroy partially failed")
  5090  		}
  5091  	}
  5092  
  5093  	createdInstanceId = "qux"
  5094  	ctx = testContext2(t, &ContextOpts{
  5095  		Config:           m,
  5096  		ProviderResolver: providers.ResolverFixed(ps),
  5097  		State:            state,
  5098  	})
  5099  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5100  		t.Fatalf("plan errors: %s", diags.Err())
  5101  	}
  5102  	state, diags = ctx.Apply()
  5103  	// Expect error because 1/2 of Deposed destroys failed
  5104  	if diags == nil {
  5105  		t.Fatal("should have error")
  5106  	}
  5107  
  5108  	// foo and baz are now gone, bar sticks around
  5109  	checkStateString(t, state, `
  5110  aws_instance.web: (1 deposed)
  5111    ID = qux
  5112    provider = provider.aws
  5113    require_new = yes
  5114    Deposed ID 1 = bar
  5115  	`)
  5116  
  5117  	// Destroy working fully!
  5118  	destroyFunc = func(is *InstanceState) (*InstanceState, error) {
  5119  		return nil, nil
  5120  	}
  5121  
  5122  	createdInstanceId = "quux"
  5123  	ctx = testContext2(t, &ContextOpts{
  5124  		Config:           m,
  5125  		ProviderResolver: providers.ResolverFixed(ps),
  5126  		State:            state,
  5127  	})
  5128  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5129  		t.Fatalf("plan errors: %s", diags.Err())
  5130  	}
  5131  	state, diags = ctx.Apply()
  5132  	if diags.HasErrors() {
  5133  		t.Fatal("should not have error:", diags.Err())
  5134  	}
  5135  
  5136  	// And finally the state is clean
  5137  	checkStateString(t, state, `
  5138  aws_instance.web:
  5139    ID = quux
  5140    provider = provider.aws
  5141    require_new = yes
  5142  	`)
  5143  }
  5144  
  5145  // Verify that a normal provisioner with on_failure "continue" set won't
  5146  // taint the resource and continues executing.
  5147  func TestContext2Apply_provisionerFailContinue(t *testing.T) {
  5148  	m := testModule(t, "apply-provisioner-fail-continue")
  5149  	p := testProvider("aws")
  5150  	pr := testProvisioner()
  5151  	p.ApplyFn = testApplyFn
  5152  	p.DiffFn = testDiffFn
  5153  
  5154  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5155  		return fmt.Errorf("provisioner error")
  5156  	}
  5157  
  5158  	ctx := testContext2(t, &ContextOpts{
  5159  		Config: m,
  5160  		ProviderResolver: providers.ResolverFixed(
  5161  			map[string]providers.Factory{
  5162  				"aws": testProviderFuncFixed(p),
  5163  			},
  5164  		),
  5165  		Provisioners: map[string]ProvisionerFactory{
  5166  			"shell": testProvisionerFuncFixed(pr),
  5167  		},
  5168  	})
  5169  
  5170  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5171  		t.Fatalf("plan errors: %s", diags.Err())
  5172  	}
  5173  
  5174  	state, diags := ctx.Apply()
  5175  	if diags.HasErrors() {
  5176  		t.Fatalf("diags: %s", diags.Err())
  5177  	}
  5178  
  5179  	checkStateString(t, state, `
  5180  aws_instance.foo:
  5181    ID = foo
  5182    provider = provider.aws
  5183    foo = bar
  5184    type = aws_instance
  5185    `)
  5186  
  5187  	// Verify apply was invoked
  5188  	if !pr.ProvisionResourceCalled {
  5189  		t.Fatalf("provisioner not invoked")
  5190  	}
  5191  }
  5192  
  5193  // Verify that a normal provisioner with on_failure "continue" records
  5194  // the error with the hook.
  5195  func TestContext2Apply_provisionerFailContinueHook(t *testing.T) {
  5196  	h := new(MockHook)
  5197  	m := testModule(t, "apply-provisioner-fail-continue")
  5198  	p := testProvider("aws")
  5199  	pr := testProvisioner()
  5200  	p.ApplyFn = testApplyFn
  5201  	p.DiffFn = testDiffFn
  5202  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5203  		return fmt.Errorf("provisioner error")
  5204  	}
  5205  
  5206  	ctx := testContext2(t, &ContextOpts{
  5207  		Config: m,
  5208  		Hooks:  []Hook{h},
  5209  		ProviderResolver: providers.ResolverFixed(
  5210  			map[string]providers.Factory{
  5211  				"aws": testProviderFuncFixed(p),
  5212  			},
  5213  		),
  5214  		Provisioners: map[string]ProvisionerFactory{
  5215  			"shell": testProvisionerFuncFixed(pr),
  5216  		},
  5217  	})
  5218  
  5219  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5220  		t.Fatalf("plan errors: %s", diags.Err())
  5221  	}
  5222  
  5223  	if _, diags := ctx.Apply(); diags.HasErrors() {
  5224  		t.Fatalf("apply errors: %s", diags.Err())
  5225  	}
  5226  
  5227  	if !h.PostProvisionInstanceStepCalled {
  5228  		t.Fatal("PostProvisionInstanceStep not called")
  5229  	}
  5230  	if h.PostProvisionInstanceStepErrorArg == nil {
  5231  		t.Fatal("should have error")
  5232  	}
  5233  }
  5234  
  5235  func TestContext2Apply_provisionerDestroy(t *testing.T) {
  5236  	m := testModule(t, "apply-provisioner-destroy")
  5237  	p := testProvider("aws")
  5238  	pr := testProvisioner()
  5239  	p.ApplyFn = testApplyFn
  5240  	p.DiffFn = testDiffFn
  5241  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5242  		val, ok := c.Config["command"]
  5243  		if !ok || val != "destroy" {
  5244  			t.Fatalf("bad value for foo: %v %#v", val, c)
  5245  		}
  5246  
  5247  		return nil
  5248  	}
  5249  
  5250  	state := MustShimLegacyState(&State{
  5251  		Modules: []*ModuleState{
  5252  			{
  5253  				Path: rootModulePath,
  5254  				Resources: map[string]*ResourceState{
  5255  					"aws_instance.foo": {
  5256  						Type: "aws_instance",
  5257  						Primary: &InstanceState{
  5258  							ID: "bar",
  5259  						},
  5260  					},
  5261  				},
  5262  			},
  5263  		},
  5264  	})
  5265  
  5266  	ctx := testContext2(t, &ContextOpts{
  5267  		Config:  m,
  5268  		State:   state,
  5269  		Destroy: true,
  5270  		ProviderResolver: providers.ResolverFixed(
  5271  			map[string]providers.Factory{
  5272  				"aws": testProviderFuncFixed(p),
  5273  			},
  5274  		),
  5275  		Provisioners: map[string]ProvisionerFactory{
  5276  			"shell": testProvisionerFuncFixed(pr),
  5277  		},
  5278  	})
  5279  
  5280  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5281  		t.Fatalf("plan errors: %s", diags.Err())
  5282  	}
  5283  
  5284  	state, diags := ctx.Apply()
  5285  	if diags.HasErrors() {
  5286  		t.Fatalf("diags: %s", diags.Err())
  5287  	}
  5288  
  5289  	checkStateString(t, state, `<no state>`)
  5290  
  5291  	// Verify apply was invoked
  5292  	if !pr.ProvisionResourceCalled {
  5293  		t.Fatalf("provisioner not invoked")
  5294  	}
  5295  }
  5296  
  5297  // Verify that on destroy provisioner failure, nothing happens to the instance
  5298  func TestContext2Apply_provisionerDestroyFail(t *testing.T) {
  5299  	m := testModule(t, "apply-provisioner-destroy")
  5300  	p := testProvider("aws")
  5301  	pr := testProvisioner()
  5302  	p.ApplyFn = testApplyFn
  5303  	p.DiffFn = testDiffFn
  5304  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5305  		return fmt.Errorf("provisioner error")
  5306  	}
  5307  
  5308  	state := MustShimLegacyState(&State{
  5309  		Modules: []*ModuleState{
  5310  			{
  5311  				Path: rootModulePath,
  5312  				Resources: map[string]*ResourceState{
  5313  					"aws_instance.foo": {
  5314  						Type: "aws_instance",
  5315  						Primary: &InstanceState{
  5316  							ID: "bar",
  5317  						},
  5318  					},
  5319  				},
  5320  			},
  5321  		},
  5322  	})
  5323  
  5324  	ctx := testContext2(t, &ContextOpts{
  5325  		Config:  m,
  5326  		State:   state,
  5327  		Destroy: true,
  5328  		ProviderResolver: providers.ResolverFixed(
  5329  			map[string]providers.Factory{
  5330  				"aws": testProviderFuncFixed(p),
  5331  			},
  5332  		),
  5333  		Provisioners: map[string]ProvisionerFactory{
  5334  			"shell": testProvisionerFuncFixed(pr),
  5335  		},
  5336  	})
  5337  
  5338  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5339  		t.Fatalf("plan errors: %s", diags.Err())
  5340  	}
  5341  
  5342  	state, diags := ctx.Apply()
  5343  	if diags == nil {
  5344  		t.Fatal("should error")
  5345  	}
  5346  
  5347  	checkStateString(t, state, `
  5348  aws_instance.foo:
  5349    ID = bar
  5350    provider = provider.aws
  5351  	`)
  5352  
  5353  	// Verify apply was invoked
  5354  	if !pr.ProvisionResourceCalled {
  5355  		t.Fatalf("provisioner not invoked")
  5356  	}
  5357  }
  5358  
  5359  // Verify that on destroy provisioner failure with "continue" that
  5360  // we continue to the next provisioner.
  5361  func TestContext2Apply_provisionerDestroyFailContinue(t *testing.T) {
  5362  	m := testModule(t, "apply-provisioner-destroy-continue")
  5363  	p := testProvider("aws")
  5364  	pr := testProvisioner()
  5365  	p.ApplyFn = testApplyFn
  5366  	p.DiffFn = testDiffFn
  5367  
  5368  	var l sync.Mutex
  5369  	var calls []string
  5370  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5371  		val, ok := c.Config["command"]
  5372  		if !ok {
  5373  			t.Fatalf("bad value for foo: %v %#v", val, c)
  5374  		}
  5375  
  5376  		l.Lock()
  5377  		defer l.Unlock()
  5378  		calls = append(calls, val.(string))
  5379  		return fmt.Errorf("provisioner error")
  5380  	}
  5381  
  5382  	state := MustShimLegacyState(&State{
  5383  		Modules: []*ModuleState{
  5384  			{
  5385  				Path: rootModulePath,
  5386  				Resources: map[string]*ResourceState{
  5387  					"aws_instance.foo": {
  5388  						Type: "aws_instance",
  5389  						Primary: &InstanceState{
  5390  							ID: "bar",
  5391  						},
  5392  					},
  5393  				},
  5394  			},
  5395  		},
  5396  	})
  5397  
  5398  	ctx := testContext2(t, &ContextOpts{
  5399  		Config:  m,
  5400  		State:   state,
  5401  		Destroy: true,
  5402  		ProviderResolver: providers.ResolverFixed(
  5403  			map[string]providers.Factory{
  5404  				"aws": testProviderFuncFixed(p),
  5405  			},
  5406  		),
  5407  		Provisioners: map[string]ProvisionerFactory{
  5408  			"shell": testProvisionerFuncFixed(pr),
  5409  		},
  5410  	})
  5411  
  5412  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5413  		t.Fatalf("plan errors: %s", diags.Err())
  5414  	}
  5415  
  5416  	state, diags := ctx.Apply()
  5417  	if diags.HasErrors() {
  5418  		t.Fatalf("diags: %s", diags.Err())
  5419  	}
  5420  
  5421  	checkStateString(t, state, `<no state>`)
  5422  
  5423  	// Verify apply was invoked
  5424  	if !pr.ProvisionResourceCalled {
  5425  		t.Fatalf("provisioner not invoked")
  5426  	}
  5427  
  5428  	expected := []string{"one", "two"}
  5429  	if !reflect.DeepEqual(calls, expected) {
  5430  		t.Fatalf("wrong commands\ngot:  %#v\nwant: %#v", calls, expected)
  5431  	}
  5432  }
  5433  
  5434  // Verify that on destroy provisioner failure with "continue" that
  5435  // we continue to the next provisioner. But if the next provisioner defines
  5436  // to fail, then we fail after running it.
  5437  func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) {
  5438  	m := testModule(t, "apply-provisioner-destroy-fail")
  5439  	p := testProvider("aws")
  5440  	pr := testProvisioner()
  5441  	p.ApplyFn = testApplyFn
  5442  	p.DiffFn = testDiffFn
  5443  
  5444  	var l sync.Mutex
  5445  	var calls []string
  5446  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5447  		val, ok := c.Config["command"]
  5448  		if !ok {
  5449  			t.Fatalf("bad value for foo: %v %#v", val, c)
  5450  		}
  5451  
  5452  		l.Lock()
  5453  		defer l.Unlock()
  5454  		calls = append(calls, val.(string))
  5455  		return fmt.Errorf("provisioner error")
  5456  	}
  5457  
  5458  	state := MustShimLegacyState(&State{
  5459  		Modules: []*ModuleState{
  5460  			{
  5461  				Path: rootModulePath,
  5462  				Resources: map[string]*ResourceState{
  5463  					"aws_instance.foo": {
  5464  						Type: "aws_instance",
  5465  						Primary: &InstanceState{
  5466  							ID: "bar",
  5467  						},
  5468  					},
  5469  				},
  5470  			},
  5471  		},
  5472  	})
  5473  
  5474  	ctx := testContext2(t, &ContextOpts{
  5475  		Config:  m,
  5476  		State:   state,
  5477  		Destroy: true,
  5478  		ProviderResolver: providers.ResolverFixed(
  5479  			map[string]providers.Factory{
  5480  				"aws": testProviderFuncFixed(p),
  5481  			},
  5482  		),
  5483  		Provisioners: map[string]ProvisionerFactory{
  5484  			"shell": testProvisionerFuncFixed(pr),
  5485  		},
  5486  	})
  5487  
  5488  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5489  		t.Fatalf("plan errors: %s", diags.Err())
  5490  	}
  5491  
  5492  	state, diags := ctx.Apply()
  5493  	if diags == nil {
  5494  		t.Fatal("apply succeeded; wanted error from second provisioner")
  5495  	}
  5496  
  5497  	checkStateString(t, state, `
  5498  aws_instance.foo:
  5499    ID = bar
  5500    provider = provider.aws
  5501    `)
  5502  
  5503  	// Verify apply was invoked
  5504  	if !pr.ProvisionResourceCalled {
  5505  		t.Fatalf("provisioner not invoked")
  5506  	}
  5507  
  5508  	expected := []string{"one", "two"}
  5509  	if !reflect.DeepEqual(calls, expected) {
  5510  		t.Fatalf("bad: %#v", calls)
  5511  	}
  5512  }
  5513  
  5514  // Verify destroy provisioners are not run for tainted instances.
  5515  func TestContext2Apply_provisionerDestroyTainted(t *testing.T) {
  5516  	m := testModule(t, "apply-provisioner-destroy")
  5517  	p := testProvider("aws")
  5518  	pr := testProvisioner()
  5519  	p.ApplyFn = testApplyFn
  5520  	p.DiffFn = testDiffFn
  5521  
  5522  	destroyCalled := false
  5523  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5524  		expected := "create"
  5525  		if rs.ID == "bar" {
  5526  			destroyCalled = true
  5527  			return nil
  5528  		}
  5529  
  5530  		val, ok := c.Config["command"]
  5531  		if !ok || val != expected {
  5532  			t.Fatalf("bad value for command: %v %#v", val, c)
  5533  		}
  5534  
  5535  		return nil
  5536  	}
  5537  
  5538  	state := MustShimLegacyState(&State{
  5539  		Modules: []*ModuleState{
  5540  			{
  5541  				Path: rootModulePath,
  5542  				Resources: map[string]*ResourceState{
  5543  					"aws_instance.foo": {
  5544  						Type: "aws_instance",
  5545  						Primary: &InstanceState{
  5546  							ID:      "bar",
  5547  							Tainted: true,
  5548  						},
  5549  					},
  5550  				},
  5551  			},
  5552  		},
  5553  	})
  5554  
  5555  	ctx := testContext2(t, &ContextOpts{
  5556  		Config: m,
  5557  		State:  state,
  5558  		ProviderResolver: providers.ResolverFixed(
  5559  			map[string]providers.Factory{
  5560  				"aws": testProviderFuncFixed(p),
  5561  			},
  5562  		),
  5563  		Provisioners: map[string]ProvisionerFactory{
  5564  			"shell": testProvisionerFuncFixed(pr),
  5565  		},
  5566  	})
  5567  
  5568  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5569  		t.Fatalf("plan errors: %s", diags.Err())
  5570  	}
  5571  
  5572  	state, diags := ctx.Apply()
  5573  	if diags.HasErrors() {
  5574  		t.Fatalf("diags: %s", diags.Err())
  5575  	}
  5576  
  5577  	checkStateString(t, state, `
  5578  aws_instance.foo:
  5579    ID = foo
  5580    provider = provider.aws
  5581    foo = bar
  5582    type = aws_instance
  5583  	`)
  5584  
  5585  	// Verify apply was invoked
  5586  	if !pr.ProvisionResourceCalled {
  5587  		t.Fatalf("provisioner not invoked")
  5588  	}
  5589  
  5590  	if destroyCalled {
  5591  		t.Fatal("destroy should not be called")
  5592  	}
  5593  }
  5594  
  5595  func TestContext2Apply_provisionerDestroyModule(t *testing.T) {
  5596  	m := testModule(t, "apply-provisioner-destroy-module")
  5597  	p := testProvider("aws")
  5598  	pr := testProvisioner()
  5599  	p.ApplyFn = testApplyFn
  5600  	p.DiffFn = testDiffFn
  5601  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5602  		val, ok := c.Config["command"]
  5603  		if !ok || val != "value" {
  5604  			t.Fatalf("bad value for foo: %v %#v", val, c)
  5605  		}
  5606  
  5607  		return nil
  5608  	}
  5609  
  5610  	state := MustShimLegacyState(&State{
  5611  		Modules: []*ModuleState{
  5612  			{
  5613  				Path: []string{"root", "child"},
  5614  				Resources: map[string]*ResourceState{
  5615  					"aws_instance.foo": {
  5616  						Type: "aws_instance",
  5617  						Primary: &InstanceState{
  5618  							ID: "bar",
  5619  						},
  5620  					},
  5621  				},
  5622  			},
  5623  		},
  5624  	})
  5625  
  5626  	ctx := testContext2(t, &ContextOpts{
  5627  		Config:  m,
  5628  		State:   state,
  5629  		Destroy: true,
  5630  		ProviderResolver: providers.ResolverFixed(
  5631  			map[string]providers.Factory{
  5632  				"aws": testProviderFuncFixed(p),
  5633  			},
  5634  		),
  5635  		Provisioners: map[string]ProvisionerFactory{
  5636  			"shell": testProvisionerFuncFixed(pr),
  5637  		},
  5638  	})
  5639  
  5640  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5641  		t.Fatalf("plan errors: %s", diags.Err())
  5642  	}
  5643  
  5644  	state, diags := ctx.Apply()
  5645  	if diags.HasErrors() {
  5646  		t.Fatalf("diags: %s", diags.Err())
  5647  	}
  5648  
  5649  	checkStateString(t, state, `<no state>`)
  5650  
  5651  	// Verify apply was invoked
  5652  	if !pr.ProvisionResourceCalled {
  5653  		t.Fatalf("provisioner not invoked")
  5654  	}
  5655  }
  5656  
  5657  func TestContext2Apply_provisionerDestroyRef(t *testing.T) {
  5658  	m := testModule(t, "apply-provisioner-destroy-ref")
  5659  	p := testProvider("aws")
  5660  	pr := testProvisioner()
  5661  	p.ApplyFn = testApplyFn
  5662  	p.DiffFn = testDiffFn
  5663  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5664  		val, ok := c.Config["command"]
  5665  		if !ok || val != "hello" {
  5666  			return fmt.Errorf("bad value for command: %v %#v", val, c)
  5667  		}
  5668  
  5669  		return nil
  5670  	}
  5671  
  5672  	state := MustShimLegacyState(&State{
  5673  		Modules: []*ModuleState{
  5674  			{
  5675  				Path: rootModulePath,
  5676  				Resources: map[string]*ResourceState{
  5677  					"aws_instance.bar": {
  5678  						Type: "aws_instance",
  5679  						Primary: &InstanceState{
  5680  							ID: "bar",
  5681  							Attributes: map[string]string{
  5682  								"value": "hello",
  5683  							},
  5684  						},
  5685  						Provider: "provider.aws",
  5686  					},
  5687  
  5688  					"aws_instance.foo": {
  5689  						Type: "aws_instance",
  5690  						Primary: &InstanceState{
  5691  							ID: "bar",
  5692  						},
  5693  						Provider: "provider.aws",
  5694  					},
  5695  				},
  5696  			},
  5697  		},
  5698  	})
  5699  
  5700  	ctx := testContext2(t, &ContextOpts{
  5701  		Config:  m,
  5702  		State:   state,
  5703  		Destroy: true,
  5704  		ProviderResolver: providers.ResolverFixed(
  5705  			map[string]providers.Factory{
  5706  				"aws": testProviderFuncFixed(p),
  5707  			},
  5708  		),
  5709  		Provisioners: map[string]ProvisionerFactory{
  5710  			"shell": testProvisionerFuncFixed(pr),
  5711  		},
  5712  	})
  5713  
  5714  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5715  		t.Fatalf("plan errors: %s", diags.Err())
  5716  	}
  5717  
  5718  	state, diags := ctx.Apply()
  5719  	if diags.HasErrors() {
  5720  		t.Fatalf("diags: %s", diags.Err())
  5721  	}
  5722  
  5723  	checkStateString(t, state, `<no state>`)
  5724  
  5725  	// Verify apply was invoked
  5726  	if !pr.ProvisionResourceCalled {
  5727  		t.Fatalf("provisioner not invoked")
  5728  	}
  5729  }
  5730  
  5731  // Test that a destroy provisioner referencing an invalid key errors.
  5732  func TestContext2Apply_provisionerDestroyRefInvalid(t *testing.T) {
  5733  	m := testModule(t, "apply-provisioner-destroy-ref-invalid")
  5734  	p := testProvider("aws")
  5735  	pr := testProvisioner()
  5736  	p.ApplyFn = testApplyFn
  5737  	p.DiffFn = testDiffFn
  5738  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5739  		return nil
  5740  	}
  5741  
  5742  	state := MustShimLegacyState(&State{
  5743  		Modules: []*ModuleState{
  5744  			{
  5745  				Path: rootModulePath,
  5746  				Resources: map[string]*ResourceState{
  5747  					"aws_instance.bar": {
  5748  						Type: "aws_instance",
  5749  						Primary: &InstanceState{
  5750  							ID: "bar",
  5751  						},
  5752  					},
  5753  
  5754  					"aws_instance.foo": {
  5755  						Type: "aws_instance",
  5756  						Primary: &InstanceState{
  5757  							ID: "bar",
  5758  						},
  5759  					},
  5760  				},
  5761  			},
  5762  		},
  5763  	})
  5764  
  5765  	ctx := testContext2(t, &ContextOpts{
  5766  		Config:  m,
  5767  		State:   state,
  5768  		Destroy: true,
  5769  		ProviderResolver: providers.ResolverFixed(
  5770  			map[string]providers.Factory{
  5771  				"aws": testProviderFuncFixed(p),
  5772  			},
  5773  		),
  5774  		Provisioners: map[string]ProvisionerFactory{
  5775  			"shell": testProvisionerFuncFixed(pr),
  5776  		},
  5777  	})
  5778  
  5779  	// this was an apply test, but this is now caught in Validation
  5780  	if diags := ctx.Validate(); !diags.HasErrors() {
  5781  		t.Fatal("expected error")
  5782  	}
  5783  }
  5784  
  5785  func TestContext2Apply_provisionerResourceRef(t *testing.T) {
  5786  	m := testModule(t, "apply-provisioner-resource-ref")
  5787  	p := testProvider("aws")
  5788  	p.ApplyFn = testApplyFn
  5789  	p.DiffFn = testDiffFn
  5790  
  5791  	pr := testProvisioner()
  5792  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5793  		val, ok := c.Config["command"]
  5794  		if !ok || val != "2" {
  5795  			t.Fatalf("bad value for foo: %v %#v", val, c)
  5796  		}
  5797  
  5798  		return nil
  5799  	}
  5800  
  5801  	ctx := testContext2(t, &ContextOpts{
  5802  		Config: m,
  5803  		ProviderResolver: providers.ResolverFixed(
  5804  			map[string]providers.Factory{
  5805  				"aws": testProviderFuncFixed(p),
  5806  			},
  5807  		),
  5808  		Provisioners: map[string]ProvisionerFactory{
  5809  			"shell": testProvisionerFuncFixed(pr),
  5810  		},
  5811  	})
  5812  
  5813  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5814  		t.Fatalf("plan errors: %s", diags.Err())
  5815  	}
  5816  
  5817  	state, diags := ctx.Apply()
  5818  	if diags.HasErrors() {
  5819  		t.Fatalf("diags: %s", diags.Err())
  5820  	}
  5821  
  5822  	actual := strings.TrimSpace(state.String())
  5823  	expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr)
  5824  	if actual != expected {
  5825  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  5826  	}
  5827  
  5828  	// Verify apply was invoked
  5829  	if !pr.ProvisionResourceCalled {
  5830  		t.Fatalf("provisioner not invoked")
  5831  	}
  5832  }
  5833  
  5834  func TestContext2Apply_provisionerSelfRef(t *testing.T) {
  5835  	m := testModule(t, "apply-provisioner-self-ref")
  5836  	p := testProvider("aws")
  5837  	pr := testProvisioner()
  5838  	p.ApplyFn = testApplyFn
  5839  	p.DiffFn = testDiffFn
  5840  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5841  		val, ok := c.Config["command"]
  5842  		if !ok || val != "bar" {
  5843  			t.Fatalf("bad value for command: %v %#v", val, c)
  5844  		}
  5845  
  5846  		return nil
  5847  	}
  5848  
  5849  	ctx := testContext2(t, &ContextOpts{
  5850  		Config: m,
  5851  		ProviderResolver: providers.ResolverFixed(
  5852  			map[string]providers.Factory{
  5853  				"aws": testProviderFuncFixed(p),
  5854  			},
  5855  		),
  5856  		Provisioners: map[string]ProvisionerFactory{
  5857  			"shell": testProvisionerFuncFixed(pr),
  5858  		},
  5859  	})
  5860  
  5861  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5862  		t.Fatalf("plan errors: %s", diags.Err())
  5863  	}
  5864  
  5865  	state, diags := ctx.Apply()
  5866  	if diags.HasErrors() {
  5867  		t.Fatalf("diags: %s", diags.Err())
  5868  	}
  5869  
  5870  	actual := strings.TrimSpace(state.String())
  5871  	expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr)
  5872  	if actual != expected {
  5873  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  5874  	}
  5875  
  5876  	// Verify apply was invoked
  5877  	if !pr.ProvisionResourceCalled {
  5878  		t.Fatalf("provisioner not invoked")
  5879  	}
  5880  }
  5881  
  5882  func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) {
  5883  	var lock sync.Mutex
  5884  	commands := make([]string, 0, 5)
  5885  
  5886  	m := testModule(t, "apply-provisioner-multi-self-ref")
  5887  	p := testProvider("aws")
  5888  	pr := testProvisioner()
  5889  	p.ApplyFn = testApplyFn
  5890  	p.DiffFn = testDiffFn
  5891  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5892  		lock.Lock()
  5893  		defer lock.Unlock()
  5894  
  5895  		val, ok := c.Config["command"]
  5896  		if !ok {
  5897  			t.Fatalf("bad value for command: %v %#v", val, c)
  5898  		}
  5899  
  5900  		commands = append(commands, val.(string))
  5901  		return nil
  5902  	}
  5903  
  5904  	ctx := testContext2(t, &ContextOpts{
  5905  		Config: m,
  5906  		ProviderResolver: providers.ResolverFixed(
  5907  			map[string]providers.Factory{
  5908  				"aws": testProviderFuncFixed(p),
  5909  			},
  5910  		),
  5911  		Provisioners: map[string]ProvisionerFactory{
  5912  			"shell": testProvisionerFuncFixed(pr),
  5913  		},
  5914  	})
  5915  
  5916  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5917  		t.Fatalf("plan errors: %s", diags.Err())
  5918  	}
  5919  
  5920  	state, diags := ctx.Apply()
  5921  	if diags.HasErrors() {
  5922  		t.Fatalf("diags: %s", diags.Err())
  5923  	}
  5924  
  5925  	actual := strings.TrimSpace(state.String())
  5926  	expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr)
  5927  	if actual != expected {
  5928  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  5929  	}
  5930  
  5931  	// Verify apply was invoked
  5932  	if !pr.ProvisionResourceCalled {
  5933  		t.Fatalf("provisioner not invoked")
  5934  	}
  5935  
  5936  	// Verify our result
  5937  	sort.Strings(commands)
  5938  	expectedCommands := []string{"number 0", "number 1", "number 2"}
  5939  	if !reflect.DeepEqual(commands, expectedCommands) {
  5940  		t.Fatalf("bad: %#v", commands)
  5941  	}
  5942  }
  5943  
  5944  func TestContext2Apply_provisionerMultiSelfRefSingle(t *testing.T) {
  5945  	var lock sync.Mutex
  5946  	order := make([]string, 0, 5)
  5947  
  5948  	m := testModule(t, "apply-provisioner-multi-self-ref-single")
  5949  	p := testProvider("aws")
  5950  	pr := testProvisioner()
  5951  	p.ApplyFn = testApplyFn
  5952  	p.DiffFn = testDiffFn
  5953  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  5954  		lock.Lock()
  5955  		defer lock.Unlock()
  5956  
  5957  		val, ok := c.Config["order"]
  5958  		if !ok {
  5959  			t.Fatalf("bad value for order: %v %#v", val, c)
  5960  		}
  5961  
  5962  		order = append(order, val.(string))
  5963  		return nil
  5964  	}
  5965  
  5966  	ctx := testContext2(t, &ContextOpts{
  5967  		Config: m,
  5968  		ProviderResolver: providers.ResolverFixed(
  5969  			map[string]providers.Factory{
  5970  				"aws": testProviderFuncFixed(p),
  5971  			},
  5972  		),
  5973  		Provisioners: map[string]ProvisionerFactory{
  5974  			"shell": testProvisionerFuncFixed(pr),
  5975  		},
  5976  	})
  5977  
  5978  	if _, diags := ctx.Plan(); diags.HasErrors() {
  5979  		t.Fatalf("plan errors: %s", diags.Err())
  5980  	}
  5981  
  5982  	state, diags := ctx.Apply()
  5983  	if diags.HasErrors() {
  5984  		t.Fatalf("diags: %s", diags.Err())
  5985  	}
  5986  
  5987  	actual := strings.TrimSpace(state.String())
  5988  	expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefSingleStr)
  5989  	if actual != expected {
  5990  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  5991  	}
  5992  
  5993  	// Verify apply was invoked
  5994  	if !pr.ProvisionResourceCalled {
  5995  		t.Fatalf("provisioner not invoked")
  5996  	}
  5997  
  5998  	// Verify our result
  5999  	sort.Strings(order)
  6000  	expectedOrder := []string{"0", "1", "2"}
  6001  	if !reflect.DeepEqual(order, expectedOrder) {
  6002  		t.Fatalf("bad: %#v", order)
  6003  	}
  6004  }
  6005  
  6006  func TestContext2Apply_provisionerExplicitSelfRef(t *testing.T) {
  6007  	m := testModule(t, "apply-provisioner-explicit-self-ref")
  6008  	p := testProvider("aws")
  6009  	pr := testProvisioner()
  6010  	p.ApplyFn = testApplyFn
  6011  	p.DiffFn = testDiffFn
  6012  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  6013  		val, ok := c.Config["command"]
  6014  		if !ok || val != "bar" {
  6015  			t.Fatalf("bad value for command: %v %#v", val, c)
  6016  		}
  6017  
  6018  		return nil
  6019  	}
  6020  
  6021  	var state *states.State
  6022  	{
  6023  		ctx := testContext2(t, &ContextOpts{
  6024  			Config: m,
  6025  			ProviderResolver: providers.ResolverFixed(
  6026  				map[string]providers.Factory{
  6027  					"aws": testProviderFuncFixed(p),
  6028  				},
  6029  			),
  6030  			Provisioners: map[string]ProvisionerFactory{
  6031  				"shell": testProvisionerFuncFixed(pr),
  6032  			},
  6033  		})
  6034  
  6035  		_, diags := ctx.Plan()
  6036  		if diags.HasErrors() {
  6037  			t.Fatalf("diags: %s", diags.Err())
  6038  		}
  6039  
  6040  		state, diags = ctx.Apply()
  6041  		if diags.HasErrors() {
  6042  			t.Fatalf("diags: %s", diags.Err())
  6043  		}
  6044  
  6045  		// Verify apply was invoked
  6046  		if !pr.ProvisionResourceCalled {
  6047  			t.Fatalf("provisioner not invoked")
  6048  		}
  6049  	}
  6050  
  6051  	{
  6052  		ctx := testContext2(t, &ContextOpts{
  6053  			Config:  m,
  6054  			Destroy: true,
  6055  			State:   state,
  6056  			ProviderResolver: providers.ResolverFixed(
  6057  				map[string]providers.Factory{
  6058  					"aws": testProviderFuncFixed(p),
  6059  				},
  6060  			),
  6061  			Provisioners: map[string]ProvisionerFactory{
  6062  				"shell": testProvisionerFuncFixed(pr),
  6063  			},
  6064  		})
  6065  
  6066  		_, diags := ctx.Plan()
  6067  		if diags.HasErrors() {
  6068  			t.Fatalf("diags: %s", diags.Err())
  6069  		}
  6070  
  6071  		state, diags = ctx.Apply()
  6072  		if diags.HasErrors() {
  6073  			t.Fatalf("diags: %s", diags.Err())
  6074  		}
  6075  
  6076  		checkStateString(t, state, `<no state>`)
  6077  	}
  6078  }
  6079  
  6080  // Provisioner should NOT run on a diff, only create
  6081  func TestContext2Apply_Provisioner_Diff(t *testing.T) {
  6082  	m := testModule(t, "apply-provisioner-diff")
  6083  	p := testProvider("aws")
  6084  	pr := testProvisioner()
  6085  	p.ApplyFn = testApplyFn
  6086  	p.DiffFn = testDiffFn
  6087  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  6088  		return nil
  6089  	}
  6090  	ctx := testContext2(t, &ContextOpts{
  6091  		Config: m,
  6092  		ProviderResolver: providers.ResolverFixed(
  6093  			map[string]providers.Factory{
  6094  				"aws": testProviderFuncFixed(p),
  6095  			},
  6096  		),
  6097  		Provisioners: map[string]ProvisionerFactory{
  6098  			"shell": testProvisionerFuncFixed(pr),
  6099  		},
  6100  	})
  6101  
  6102  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6103  		logDiagnostics(t, diags)
  6104  		t.Fatal("plan failed")
  6105  	}
  6106  
  6107  	state, diags := ctx.Apply()
  6108  	if diags.HasErrors() {
  6109  		logDiagnostics(t, diags)
  6110  		t.Fatal("apply failed")
  6111  	}
  6112  
  6113  	actual := strings.TrimSpace(state.String())
  6114  	expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr)
  6115  	if actual != expected {
  6116  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  6117  	}
  6118  
  6119  	// Verify apply was invoked
  6120  	if !pr.ProvisionResourceCalled {
  6121  		t.Fatalf("provisioner was not called on first apply")
  6122  	}
  6123  	pr.ProvisionResourceCalled = false
  6124  
  6125  	// Change the state to force a diff
  6126  	mod := state.RootModule()
  6127  	obj := mod.Resources["aws_instance.bar"].Instances[addrs.NoKey].Current
  6128  	var attrs map[string]interface{}
  6129  	err := json.Unmarshal(obj.AttrsJSON, &attrs)
  6130  	if err != nil {
  6131  		t.Fatal(err)
  6132  	}
  6133  	attrs["foo"] = "baz"
  6134  	obj.AttrsJSON, err = json.Marshal(attrs)
  6135  	if err != nil {
  6136  		t.Fatal(err)
  6137  	}
  6138  
  6139  	// Re-create context with state
  6140  	ctx = testContext2(t, &ContextOpts{
  6141  		Config: m,
  6142  		ProviderResolver: providers.ResolverFixed(
  6143  			map[string]providers.Factory{
  6144  				"aws": testProviderFuncFixed(p),
  6145  			},
  6146  		),
  6147  		Provisioners: map[string]ProvisionerFactory{
  6148  			"shell": testProvisionerFuncFixed(pr),
  6149  		},
  6150  		State: state,
  6151  	})
  6152  
  6153  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6154  		logDiagnostics(t, diags)
  6155  		t.Fatal("plan failed")
  6156  	}
  6157  
  6158  	state2, diags := ctx.Apply()
  6159  	if diags.HasErrors() {
  6160  		logDiagnostics(t, diags)
  6161  		t.Fatal("apply failed")
  6162  	}
  6163  
  6164  	actual = strings.TrimSpace(state2.String())
  6165  	if actual != expected {
  6166  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  6167  	}
  6168  
  6169  	// Verify apply was NOT invoked
  6170  	if pr.ProvisionResourceCalled {
  6171  		t.Fatalf("provisioner was called on second apply; should not have been")
  6172  	}
  6173  }
  6174  
  6175  func TestContext2Apply_outputDiffVars(t *testing.T) {
  6176  	m := testModule(t, "apply-good")
  6177  	p := testProvider("aws")
  6178  	s := MustShimLegacyState(&State{
  6179  		Modules: []*ModuleState{
  6180  			{
  6181  				Path: rootModulePath,
  6182  				Resources: map[string]*ResourceState{
  6183  					"aws_instance.baz": { // This one is not in config, so should be destroyed
  6184  						Type: "aws_instance",
  6185  						Primary: &InstanceState{
  6186  							ID: "bar",
  6187  						},
  6188  					},
  6189  				},
  6190  			},
  6191  		},
  6192  	})
  6193  	ctx := testContext2(t, &ContextOpts{
  6194  		Config: m,
  6195  		ProviderResolver: providers.ResolverFixed(
  6196  			map[string]providers.Factory{
  6197  				"aws": testProviderFuncFixed(p),
  6198  			},
  6199  		),
  6200  		State: s,
  6201  	})
  6202  
  6203  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  6204  		if d.Destroy {
  6205  			return nil, nil
  6206  		}
  6207  
  6208  		result := s.MergeDiff(d)
  6209  		result.ID = "foo"
  6210  		return result, nil
  6211  	}
  6212  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  6213  		d := &InstanceDiff{
  6214  			Attributes: map[string]*ResourceAttrDiff{},
  6215  		}
  6216  		if new, ok := rc.Get("value"); ok {
  6217  			d.Attributes["value"] = &ResourceAttrDiff{
  6218  				New: new.(string),
  6219  			}
  6220  		}
  6221  		if new, ok := rc.Get("foo"); ok {
  6222  			d.Attributes["foo"] = &ResourceAttrDiff{
  6223  				New: new.(string),
  6224  			}
  6225  		} else if rc.IsComputed("foo") {
  6226  			d.Attributes["foo"] = &ResourceAttrDiff{
  6227  				NewComputed: true,
  6228  				Type:        DiffAttrOutput, // This doesn't actually really do anything anymore, but this test originally set it.
  6229  			}
  6230  		}
  6231  		if new, ok := rc.Get("num"); ok {
  6232  			d.Attributes["num"] = &ResourceAttrDiff{
  6233  				New: fmt.Sprintf("%#v", new),
  6234  			}
  6235  		}
  6236  		return d, nil
  6237  	}
  6238  
  6239  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6240  		logDiagnostics(t, diags)
  6241  		t.Fatal("plan failed")
  6242  	}
  6243  	if _, diags := ctx.Apply(); diags.HasErrors() {
  6244  		logDiagnostics(t, diags)
  6245  		t.Fatal("apply failed")
  6246  	}
  6247  }
  6248  
  6249  func TestContext2Apply_destroyX(t *testing.T) {
  6250  	m := testModule(t, "apply-destroy")
  6251  	h := new(HookRecordApplyOrder)
  6252  	p := testProvider("aws")
  6253  	p.ApplyFn = testApplyFn
  6254  	p.DiffFn = testDiffFn
  6255  	ctx := testContext2(t, &ContextOpts{
  6256  		Config: m,
  6257  		Hooks:  []Hook{h},
  6258  		ProviderResolver: providers.ResolverFixed(
  6259  			map[string]providers.Factory{
  6260  				"aws": testProviderFuncFixed(p),
  6261  			},
  6262  		),
  6263  	})
  6264  
  6265  	// First plan and apply a create operation
  6266  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6267  		t.Fatalf("plan errors: %s", diags.Err())
  6268  	}
  6269  
  6270  	state, diags := ctx.Apply()
  6271  	if diags.HasErrors() {
  6272  		t.Fatalf("diags: %s", diags.Err())
  6273  	}
  6274  
  6275  	// Next, plan and apply a destroy operation
  6276  	h.Active = true
  6277  	ctx = testContext2(t, &ContextOpts{
  6278  		Destroy: true,
  6279  		State:   state,
  6280  		Config:  m,
  6281  		Hooks:   []Hook{h},
  6282  		ProviderResolver: providers.ResolverFixed(
  6283  			map[string]providers.Factory{
  6284  				"aws": testProviderFuncFixed(p),
  6285  			},
  6286  		),
  6287  	})
  6288  
  6289  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6290  		t.Fatalf("plan errors: %s", diags.Err())
  6291  	}
  6292  
  6293  	state, diags = ctx.Apply()
  6294  	if diags.HasErrors() {
  6295  		t.Fatalf("diags: %s", diags.Err())
  6296  	}
  6297  
  6298  	// Test that things were destroyed
  6299  	actual := strings.TrimSpace(state.String())
  6300  	expected := strings.TrimSpace(testTerraformApplyDestroyStr)
  6301  	if actual != expected {
  6302  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  6303  	}
  6304  
  6305  	// Test that things were destroyed _in the right order_
  6306  	expected2 := []string{"aws_instance.bar", "aws_instance.foo"}
  6307  	actual2 := h.IDs
  6308  	if !reflect.DeepEqual(actual2, expected2) {
  6309  		t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2)
  6310  	}
  6311  }
  6312  
  6313  func TestContext2Apply_destroyOrder(t *testing.T) {
  6314  	m := testModule(t, "apply-destroy")
  6315  	h := new(HookRecordApplyOrder)
  6316  	p := testProvider("aws")
  6317  	p.ApplyFn = testApplyFn
  6318  	p.DiffFn = testDiffFn
  6319  	ctx := testContext2(t, &ContextOpts{
  6320  		Config: m,
  6321  		Hooks:  []Hook{h},
  6322  		ProviderResolver: providers.ResolverFixed(
  6323  			map[string]providers.Factory{
  6324  				"aws": testProviderFuncFixed(p),
  6325  			},
  6326  		),
  6327  	})
  6328  
  6329  	// First plan and apply a create operation
  6330  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6331  		t.Fatalf("plan errors: %s", diags.Err())
  6332  	}
  6333  
  6334  	state, diags := ctx.Apply()
  6335  	if diags.HasErrors() {
  6336  		t.Fatalf("diags: %s", diags.Err())
  6337  	}
  6338  
  6339  	t.Logf("State 1: %s", state)
  6340  
  6341  	// Next, plan and apply a destroy
  6342  	h.Active = true
  6343  	ctx = testContext2(t, &ContextOpts{
  6344  		Destroy: true,
  6345  		State:   state,
  6346  		Config:  m,
  6347  		Hooks:   []Hook{h},
  6348  		ProviderResolver: providers.ResolverFixed(
  6349  			map[string]providers.Factory{
  6350  				"aws": testProviderFuncFixed(p),
  6351  			},
  6352  		),
  6353  	})
  6354  
  6355  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6356  		t.Fatalf("plan errors: %s", diags.Err())
  6357  	}
  6358  
  6359  	state, diags = ctx.Apply()
  6360  	if diags.HasErrors() {
  6361  		t.Fatalf("diags: %s", diags.Err())
  6362  	}
  6363  
  6364  	// Test that things were destroyed
  6365  	actual := strings.TrimSpace(state.String())
  6366  	expected := strings.TrimSpace(testTerraformApplyDestroyStr)
  6367  	if actual != expected {
  6368  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  6369  	}
  6370  
  6371  	// Test that things were destroyed _in the right order_
  6372  	expected2 := []string{"aws_instance.bar", "aws_instance.foo"}
  6373  	actual2 := h.IDs
  6374  	if !reflect.DeepEqual(actual2, expected2) {
  6375  		t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2)
  6376  	}
  6377  }
  6378  
  6379  // https://github.com/hashicorp/terraform-plugin-sdk/issues/2767
  6380  func TestContext2Apply_destroyModulePrefix(t *testing.T) {
  6381  	m := testModule(t, "apply-destroy-module-resource-prefix")
  6382  	h := new(MockHook)
  6383  	p := testProvider("aws")
  6384  	p.ApplyFn = testApplyFn
  6385  	p.DiffFn = testDiffFn
  6386  	ctx := testContext2(t, &ContextOpts{
  6387  		Config: m,
  6388  		Hooks:  []Hook{h},
  6389  		ProviderResolver: providers.ResolverFixed(
  6390  			map[string]providers.Factory{
  6391  				"aws": testProviderFuncFixed(p),
  6392  			},
  6393  		),
  6394  	})
  6395  
  6396  	// First plan and apply a create operation
  6397  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6398  		t.Fatalf("plan errors: %s", diags.Err())
  6399  	}
  6400  
  6401  	state, diags := ctx.Apply()
  6402  	if diags.HasErrors() {
  6403  		t.Fatalf("diags: %s", diags.Err())
  6404  	}
  6405  
  6406  	// Verify that we got the apply info correct
  6407  	if v := h.PreApplyAddr.String(); v != "module.child.aws_instance.foo" {
  6408  		t.Fatalf("bad: %s", v)
  6409  	}
  6410  
  6411  	// Next, plan and apply a destroy operation and reset the hook
  6412  	h = new(MockHook)
  6413  	ctx = testContext2(t, &ContextOpts{
  6414  		Destroy: true,
  6415  		State:   state,
  6416  		Config:  m,
  6417  		Hooks:   []Hook{h},
  6418  		ProviderResolver: providers.ResolverFixed(
  6419  			map[string]providers.Factory{
  6420  				"aws": testProviderFuncFixed(p),
  6421  			},
  6422  		),
  6423  	})
  6424  
  6425  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6426  		t.Fatalf("plan errors: %s", diags.Err())
  6427  	}
  6428  
  6429  	state, diags = ctx.Apply()
  6430  	if diags.HasErrors() {
  6431  		t.Fatalf("diags: %s", diags.Err())
  6432  	}
  6433  
  6434  	// Test that things were destroyed
  6435  	if v := h.PreApplyAddr.String(); v != "module.child.aws_instance.foo" {
  6436  		t.Fatalf("bad: %s", v)
  6437  	}
  6438  }
  6439  
  6440  func TestContext2Apply_destroyNestedModule(t *testing.T) {
  6441  	m := testModule(t, "apply-destroy-nested-module")
  6442  	p := testProvider("aws")
  6443  	p.ApplyFn = testApplyFn
  6444  	p.DiffFn = testDiffFn
  6445  
  6446  	s := MustShimLegacyState(&State{
  6447  		Modules: []*ModuleState{
  6448  			{
  6449  				Path: []string{"root", "child", "subchild"},
  6450  				Resources: map[string]*ResourceState{
  6451  					"aws_instance.bar": {
  6452  						Type: "aws_instance",
  6453  						Primary: &InstanceState{
  6454  							ID: "bar",
  6455  						},
  6456  						Provider: "provider.aws",
  6457  					},
  6458  				},
  6459  			},
  6460  		},
  6461  	})
  6462  
  6463  	ctx := testContext2(t, &ContextOpts{
  6464  		Config: m,
  6465  		ProviderResolver: providers.ResolverFixed(
  6466  			map[string]providers.Factory{
  6467  				"aws": testProviderFuncFixed(p),
  6468  			},
  6469  		),
  6470  		State: s,
  6471  	})
  6472  
  6473  	// First plan and apply a create operation
  6474  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6475  		t.Fatalf("plan errors: %s", diags.Err())
  6476  	}
  6477  
  6478  	state, diags := ctx.Apply()
  6479  	if diags.HasErrors() {
  6480  		t.Fatalf("diags: %s", diags.Err())
  6481  	}
  6482  
  6483  	// Test that things were destroyed
  6484  	actual := strings.TrimSpace(state.String())
  6485  	if actual != "<no state>" {
  6486  		t.Fatalf("expected no state, got: %s", actual)
  6487  	}
  6488  }
  6489  
  6490  func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) {
  6491  	m := testModule(t, "apply-destroy-deeply-nested-module")
  6492  	p := testProvider("aws")
  6493  	p.ApplyFn = testApplyFn
  6494  	p.DiffFn = testDiffFn
  6495  
  6496  	s := MustShimLegacyState(&State{
  6497  		Modules: []*ModuleState{
  6498  			{
  6499  				Path: []string{"root", "child", "subchild", "subsubchild"},
  6500  				Resources: map[string]*ResourceState{
  6501  					"aws_instance.bar": {
  6502  						Type: "aws_instance",
  6503  						Primary: &InstanceState{
  6504  							ID: "bar",
  6505  						},
  6506  						Provider: "provider.aws",
  6507  					},
  6508  				},
  6509  			},
  6510  		},
  6511  	})
  6512  
  6513  	ctx := testContext2(t, &ContextOpts{
  6514  		Config: m,
  6515  		ProviderResolver: providers.ResolverFixed(
  6516  			map[string]providers.Factory{
  6517  				"aws": testProviderFuncFixed(p),
  6518  			},
  6519  		),
  6520  		State: s,
  6521  	})
  6522  
  6523  	// First plan and apply a create operation
  6524  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6525  		t.Fatalf("plan errors: %s", diags.Err())
  6526  	}
  6527  
  6528  	state, diags := ctx.Apply()
  6529  	if diags.HasErrors() {
  6530  		t.Fatalf("diags: %s", diags.Err())
  6531  	}
  6532  
  6533  	// Test that things were destroyed
  6534  	if !state.Empty() {
  6535  		t.Fatalf("wrong final state %s\nwant empty state", spew.Sdump(state))
  6536  	}
  6537  }
  6538  
  6539  // https://github.com/hashicorp/terraform-plugin-sdk/issues/5440
  6540  func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) {
  6541  	m, snap := testModuleWithSnapshot(t, "apply-destroy-module-with-attrs")
  6542  	p := testProvider("aws")
  6543  	p.ApplyFn = testApplyFn
  6544  	p.DiffFn = testDiffFn
  6545  
  6546  	var state *states.State
  6547  	{
  6548  		ctx := testContext2(t, &ContextOpts{
  6549  			Config: m,
  6550  			ProviderResolver: providers.ResolverFixed(
  6551  				map[string]providers.Factory{
  6552  					"aws": testProviderFuncFixed(p),
  6553  				},
  6554  			),
  6555  		})
  6556  
  6557  		// First plan and apply a create operation
  6558  		if p, diags := ctx.Plan(); diags.HasErrors() {
  6559  			t.Fatalf("plan diags: %s", diags.Err())
  6560  		} else {
  6561  			t.Logf("Step 1 plan: %s", legacyDiffComparisonString(p.Changes))
  6562  		}
  6563  
  6564  		var diags tfdiags.Diagnostics
  6565  		state, diags = ctx.Apply()
  6566  		if diags.HasErrors() {
  6567  			t.Fatalf("apply errs: %s", diags.Err())
  6568  		}
  6569  
  6570  		t.Logf("Step 1 state: %s", state)
  6571  	}
  6572  
  6573  	h := new(HookRecordApplyOrder)
  6574  	h.Active = true
  6575  
  6576  	{
  6577  		ctx := testContext2(t, &ContextOpts{
  6578  			Destroy: true,
  6579  			Config:  m,
  6580  			State:   state,
  6581  			Hooks:   []Hook{h},
  6582  			ProviderResolver: providers.ResolverFixed(
  6583  				map[string]providers.Factory{
  6584  					"aws": testProviderFuncFixed(p),
  6585  				},
  6586  			),
  6587  			Variables: InputValues{
  6588  				"key_name": &InputValue{
  6589  					Value:      cty.StringVal("foobarkey"),
  6590  					SourceType: ValueFromCaller,
  6591  				},
  6592  			},
  6593  		})
  6594  
  6595  		// First plan and apply a create operation
  6596  		plan, diags := ctx.Plan()
  6597  		if diags.HasErrors() {
  6598  			t.Fatalf("destroy plan err: %s", diags.Err())
  6599  		}
  6600  
  6601  		t.Logf("Step 2 plan: %s", legacyDiffComparisonString(plan.Changes))
  6602  
  6603  		ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  6604  		if err != nil {
  6605  			t.Fatalf("failed to round-trip through planfile: %s", err)
  6606  		}
  6607  
  6608  		ctxOpts.ProviderResolver = providers.ResolverFixed(
  6609  			map[string]providers.Factory{
  6610  				"aws": testProviderFuncFixed(p),
  6611  			},
  6612  		)
  6613  		ctx, diags = NewContext(ctxOpts)
  6614  		if diags.HasErrors() {
  6615  			t.Fatalf("err: %s", diags.Err())
  6616  		}
  6617  
  6618  		state, diags = ctx.Apply()
  6619  		if diags.HasErrors() {
  6620  			t.Fatalf("destroy apply err: %s", diags.Err())
  6621  		}
  6622  
  6623  		t.Logf("Step 2 state: %s", state)
  6624  	}
  6625  
  6626  	//Test that things were destroyed
  6627  	actual := strings.TrimSpace(state.String())
  6628  	expected := strings.TrimSpace(`<no state>`)
  6629  	if actual != expected {
  6630  		t.Fatalf("expected:\n\n%s\n\nactual:\n\n%s", expected, actual)
  6631  	}
  6632  }
  6633  
  6634  func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) {
  6635  	m, snap := testModuleWithSnapshot(t, "apply-destroy-mod-var-and-count")
  6636  	p := testProvider("aws")
  6637  	p.ApplyFn = testApplyFn
  6638  	p.DiffFn = testDiffFn
  6639  
  6640  	var state *states.State
  6641  	var diags tfdiags.Diagnostics
  6642  	{
  6643  		ctx := testContext2(t, &ContextOpts{
  6644  			Config: m,
  6645  			ProviderResolver: providers.ResolverFixed(
  6646  				map[string]providers.Factory{
  6647  					"aws": testProviderFuncFixed(p),
  6648  				},
  6649  			),
  6650  		})
  6651  
  6652  		// First plan and apply a create operation
  6653  		if _, diags := ctx.Plan(); diags.HasErrors() {
  6654  			t.Fatalf("plan err: %s", diags.Err())
  6655  		}
  6656  
  6657  		state, diags = ctx.Apply()
  6658  		if diags.HasErrors() {
  6659  			t.Fatalf("apply err: %s", diags.Err())
  6660  		}
  6661  	}
  6662  
  6663  	h := new(HookRecordApplyOrder)
  6664  	h.Active = true
  6665  
  6666  	{
  6667  		ctx := testContext2(t, &ContextOpts{
  6668  			Destroy: true,
  6669  			Config:  m,
  6670  			State:   state,
  6671  			Hooks:   []Hook{h},
  6672  			ProviderResolver: providers.ResolverFixed(
  6673  				map[string]providers.Factory{
  6674  					"aws": testProviderFuncFixed(p),
  6675  				},
  6676  			),
  6677  		})
  6678  
  6679  		// First plan and apply a create operation
  6680  		plan, diags := ctx.Plan()
  6681  		if diags.HasErrors() {
  6682  			t.Fatalf("destroy plan err: %s", diags.Err())
  6683  		}
  6684  
  6685  		ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  6686  		if err != nil {
  6687  			t.Fatalf("failed to round-trip through planfile: %s", err)
  6688  		}
  6689  
  6690  		ctxOpts.ProviderResolver = providers.ResolverFixed(
  6691  			map[string]providers.Factory{
  6692  				"aws": testProviderFuncFixed(p),
  6693  			},
  6694  		)
  6695  		ctx, diags = NewContext(ctxOpts)
  6696  		if diags.HasErrors() {
  6697  			t.Fatalf("err: %s", diags.Err())
  6698  		}
  6699  
  6700  		state, diags = ctx.Apply()
  6701  		if diags.HasErrors() {
  6702  			t.Fatalf("destroy apply err: %s", diags.Err())
  6703  		}
  6704  	}
  6705  
  6706  	//Test that things were destroyed
  6707  	actual := strings.TrimSpace(state.String())
  6708  	expected := strings.TrimSpace(`
  6709  <no state>
  6710  module.child:
  6711  		`)
  6712  	if actual != expected {
  6713  		t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
  6714  	}
  6715  }
  6716  
  6717  func TestContext2Apply_destroyTargetWithModuleVariableAndCount(t *testing.T) {
  6718  	m := testModule(t, "apply-destroy-mod-var-and-count")
  6719  	p := testProvider("aws")
  6720  	p.ApplyFn = testApplyFn
  6721  	p.DiffFn = testDiffFn
  6722  
  6723  	var state *states.State
  6724  	var diags tfdiags.Diagnostics
  6725  	{
  6726  		ctx := testContext2(t, &ContextOpts{
  6727  			Config: m,
  6728  			ProviderResolver: providers.ResolverFixed(
  6729  				map[string]providers.Factory{
  6730  					"aws": testProviderFuncFixed(p),
  6731  				},
  6732  			),
  6733  		})
  6734  
  6735  		// First plan and apply a create operation
  6736  		if _, diags := ctx.Plan(); diags.HasErrors() {
  6737  			t.Fatalf("plan err: %s", diags.Err())
  6738  		}
  6739  
  6740  		state, diags = ctx.Apply()
  6741  		if diags.HasErrors() {
  6742  			t.Fatalf("apply err: %s", diags.Err())
  6743  		}
  6744  	}
  6745  
  6746  	{
  6747  		ctx := testContext2(t, &ContextOpts{
  6748  			Destroy: true,
  6749  			Config:  m,
  6750  			State:   state,
  6751  			ProviderResolver: providers.ResolverFixed(
  6752  				map[string]providers.Factory{
  6753  					"aws": testProviderFuncFixed(p),
  6754  				},
  6755  			),
  6756  			Targets: []addrs.Targetable{
  6757  				addrs.RootModuleInstance.Child("child", addrs.NoKey),
  6758  			},
  6759  		})
  6760  
  6761  		_, diags := ctx.Plan()
  6762  		if diags.HasErrors() {
  6763  			t.Fatalf("plan err: %s", diags)
  6764  		}
  6765  		if len(diags) != 1 {
  6766  			// Should have one warning that -target is in effect.
  6767  			t.Fatalf("got %d diagnostics in plan; want 1", len(diags))
  6768  		}
  6769  		if got, want := diags[0].Severity(), tfdiags.Warning; got != want {
  6770  			t.Errorf("wrong diagnostic severity %#v; want %#v", got, want)
  6771  		}
  6772  		if got, want := diags[0].Description().Summary, "Resource targeting is in effect"; got != want {
  6773  			t.Errorf("wrong diagnostic summary %#v; want %#v", got, want)
  6774  		}
  6775  
  6776  		// Destroy, targeting the module explicitly
  6777  		state, diags = ctx.Apply()
  6778  		if diags.HasErrors() {
  6779  			t.Fatalf("destroy apply err: %s", diags)
  6780  		}
  6781  		if len(diags) != 1 {
  6782  			t.Fatalf("got %d diagnostics; want 1", len(diags))
  6783  		}
  6784  		if got, want := diags[0].Severity(), tfdiags.Warning; got != want {
  6785  			t.Errorf("wrong diagnostic severity %#v; want %#v", got, want)
  6786  		}
  6787  		if got, want := diags[0].Description().Summary, "Applied changes may be incomplete"; got != want {
  6788  			t.Errorf("wrong diagnostic summary %#v; want %#v", got, want)
  6789  		}
  6790  	}
  6791  
  6792  	//Test that things were destroyed
  6793  	actual := strings.TrimSpace(state.String())
  6794  	expected := strings.TrimSpace(`<no state>`)
  6795  	if actual != expected {
  6796  		t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
  6797  	}
  6798  }
  6799  
  6800  func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) {
  6801  	m, snap := testModuleWithSnapshot(t, "apply-destroy-mod-var-and-count-nested")
  6802  	p := testProvider("aws")
  6803  	p.ApplyFn = testApplyFn
  6804  	p.DiffFn = testDiffFn
  6805  
  6806  	var state *states.State
  6807  	var diags tfdiags.Diagnostics
  6808  	{
  6809  		ctx := testContext2(t, &ContextOpts{
  6810  			Config: m,
  6811  			ProviderResolver: providers.ResolverFixed(
  6812  				map[string]providers.Factory{
  6813  					"aws": testProviderFuncFixed(p),
  6814  				},
  6815  			),
  6816  		})
  6817  
  6818  		// First plan and apply a create operation
  6819  		if _, diags := ctx.Plan(); diags.HasErrors() {
  6820  			t.Fatalf("plan err: %s", diags.Err())
  6821  		}
  6822  
  6823  		state, diags = ctx.Apply()
  6824  		if diags.HasErrors() {
  6825  			t.Fatalf("apply err: %s", diags.Err())
  6826  		}
  6827  	}
  6828  
  6829  	h := new(HookRecordApplyOrder)
  6830  	h.Active = true
  6831  
  6832  	{
  6833  		ctx := testContext2(t, &ContextOpts{
  6834  			Destroy: true,
  6835  			Config:  m,
  6836  			State:   state,
  6837  			Hooks:   []Hook{h},
  6838  			ProviderResolver: providers.ResolverFixed(
  6839  				map[string]providers.Factory{
  6840  					"aws": testProviderFuncFixed(p),
  6841  				},
  6842  			),
  6843  		})
  6844  
  6845  		// First plan and apply a create operation
  6846  		plan, diags := ctx.Plan()
  6847  		if diags.HasErrors() {
  6848  			t.Fatalf("destroy plan err: %s", diags.Err())
  6849  		}
  6850  
  6851  		ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  6852  		if err != nil {
  6853  			t.Fatalf("failed to round-trip through planfile: %s", err)
  6854  		}
  6855  
  6856  		ctxOpts.ProviderResolver = providers.ResolverFixed(
  6857  			map[string]providers.Factory{
  6858  				"aws": testProviderFuncFixed(p),
  6859  			},
  6860  		)
  6861  		ctx, diags = NewContext(ctxOpts)
  6862  		if diags.HasErrors() {
  6863  			t.Fatalf("err: %s", diags.Err())
  6864  		}
  6865  
  6866  		state, diags = ctx.Apply()
  6867  		if diags.HasErrors() {
  6868  			t.Fatalf("destroy apply err: %s", diags.Err())
  6869  		}
  6870  	}
  6871  
  6872  	//Test that things were destroyed
  6873  	actual := strings.TrimSpace(state.String())
  6874  	expected := strings.TrimSpace(`
  6875  <no state>
  6876  module.child.child2:
  6877  		`)
  6878  	if actual != expected {
  6879  		t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
  6880  	}
  6881  }
  6882  
  6883  func TestContext2Apply_destroyOutputs(t *testing.T) {
  6884  	m := testModule(t, "apply-destroy-outputs")
  6885  	p := testProvider("aws")
  6886  	p.ApplyFn = testApplyFn
  6887  	p.DiffFn = testDiffFn
  6888  	ctx := testContext2(t, &ContextOpts{
  6889  		Config: m,
  6890  		ProviderResolver: providers.ResolverFixed(
  6891  			map[string]providers.Factory{
  6892  				"aws": testProviderFuncFixed(p),
  6893  			},
  6894  		),
  6895  	})
  6896  
  6897  	// First plan and apply a create operation
  6898  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6899  		t.Fatalf("plan errors: %s", diags.Err())
  6900  	}
  6901  
  6902  	state, diags := ctx.Apply()
  6903  
  6904  	if diags.HasErrors() {
  6905  		t.Fatalf("diags: %s", diags.Err())
  6906  	}
  6907  
  6908  	// Next, plan and apply a destroy operation
  6909  	ctx = testContext2(t, &ContextOpts{
  6910  		Destroy: true,
  6911  		State:   state,
  6912  		Config:  m,
  6913  		ProviderResolver: providers.ResolverFixed(
  6914  			map[string]providers.Factory{
  6915  				"aws": testProviderFuncFixed(p),
  6916  			},
  6917  		),
  6918  	})
  6919  
  6920  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6921  		t.Fatalf("plan errors: %s", diags.Err())
  6922  	}
  6923  
  6924  	state, diags = ctx.Apply()
  6925  	if diags.HasErrors() {
  6926  		t.Fatalf("diags: %s", diags.Err())
  6927  	}
  6928  
  6929  	mod := state.RootModule()
  6930  	if len(mod.Resources) > 0 {
  6931  		t.Fatalf("expected no resources, got: %#v", mod)
  6932  	}
  6933  
  6934  	// destroying again should produce no errors
  6935  	ctx = testContext2(t, &ContextOpts{
  6936  		Destroy: true,
  6937  		State:   state,
  6938  		Config:  m,
  6939  		ProviderResolver: providers.ResolverFixed(
  6940  			map[string]providers.Factory{
  6941  				"aws": testProviderFuncFixed(p),
  6942  			},
  6943  		),
  6944  	})
  6945  	if _, diags := ctx.Plan(); diags.HasErrors() {
  6946  		t.Fatal(diags.Err())
  6947  	}
  6948  
  6949  	if _, diags := ctx.Apply(); diags.HasErrors() {
  6950  		t.Fatal(diags.Err())
  6951  	}
  6952  }
  6953  
  6954  func TestContext2Apply_destroyOrphan(t *testing.T) {
  6955  	m := testModule(t, "apply-error")
  6956  	p := testProvider("aws")
  6957  	s := MustShimLegacyState(&State{
  6958  		Modules: []*ModuleState{
  6959  			{
  6960  				Path: rootModulePath,
  6961  				Resources: map[string]*ResourceState{
  6962  					"aws_instance.baz": {
  6963  						Type: "aws_instance",
  6964  						Primary: &InstanceState{
  6965  							ID: "bar",
  6966  						},
  6967  					},
  6968  				},
  6969  			},
  6970  		},
  6971  	})
  6972  	ctx := testContext2(t, &ContextOpts{
  6973  		Config: m,
  6974  		ProviderResolver: providers.ResolverFixed(
  6975  			map[string]providers.Factory{
  6976  				"aws": testProviderFuncFixed(p),
  6977  			},
  6978  		),
  6979  		State: s,
  6980  	})
  6981  
  6982  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  6983  		if d.Destroy {
  6984  			return nil, nil
  6985  		}
  6986  
  6987  		result := s.MergeDiff(d)
  6988  		result.ID = "foo"
  6989  		return result, nil
  6990  	}
  6991  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  6992  		d := &InstanceDiff{
  6993  			Attributes: map[string]*ResourceAttrDiff{},
  6994  		}
  6995  		if new, ok := rc.Get("value"); ok {
  6996  			d.Attributes["value"] = &ResourceAttrDiff{
  6997  				New: new.(string),
  6998  			}
  6999  		}
  7000  		if new, ok := rc.Get("foo"); ok {
  7001  			d.Attributes["foo"] = &ResourceAttrDiff{
  7002  				New: new.(string),
  7003  			}
  7004  		}
  7005  		return d, nil
  7006  	}
  7007  
  7008  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7009  		t.Fatalf("plan errors: %s", diags.Err())
  7010  	}
  7011  
  7012  	state, diags := ctx.Apply()
  7013  	if diags.HasErrors() {
  7014  		t.Fatalf("diags: %s", diags.Err())
  7015  	}
  7016  
  7017  	mod := state.RootModule()
  7018  	if _, ok := mod.Resources["aws_instance.baz"]; ok {
  7019  		t.Fatalf("bad: %#v", mod.Resources)
  7020  	}
  7021  }
  7022  
  7023  func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) {
  7024  	m := testModule(t, "apply-destroy-provisioner")
  7025  	p := testProvider("aws")
  7026  	pr := testProvisioner()
  7027  	p.ApplyFn = testApplyFn
  7028  	p.DiffFn = testDiffFn
  7029  
  7030  	called := false
  7031  	pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error {
  7032  		called = true
  7033  		return nil
  7034  	}
  7035  
  7036  	s := MustShimLegacyState(&State{
  7037  		Modules: []*ModuleState{
  7038  			{
  7039  				Path: rootModulePath,
  7040  				Resources: map[string]*ResourceState{
  7041  					"aws_instance.foo": {
  7042  						Type: "aws_instance",
  7043  						Primary: &InstanceState{
  7044  							ID: "bar",
  7045  							Attributes: map[string]string{
  7046  								"id": "bar",
  7047  							},
  7048  							Tainted: true,
  7049  						},
  7050  					},
  7051  				},
  7052  			},
  7053  		},
  7054  	})
  7055  
  7056  	ctx := testContext2(t, &ContextOpts{
  7057  		Config: m,
  7058  		ProviderResolver: providers.ResolverFixed(
  7059  			map[string]providers.Factory{
  7060  				"aws": testProviderFuncFixed(p),
  7061  			},
  7062  		),
  7063  		Provisioners: map[string]ProvisionerFactory{
  7064  			"shell": testProvisionerFuncFixed(pr),
  7065  		},
  7066  		State:   s,
  7067  		Destroy: true,
  7068  	})
  7069  
  7070  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7071  		t.Fatalf("plan errors: %s", diags.Err())
  7072  	}
  7073  
  7074  	state, diags := ctx.Apply()
  7075  	if diags.HasErrors() {
  7076  		t.Fatalf("diags: %s", diags.Err())
  7077  	}
  7078  
  7079  	if called {
  7080  		t.Fatal("provisioner should not be called")
  7081  	}
  7082  
  7083  	actual := strings.TrimSpace(state.String())
  7084  	expected := strings.TrimSpace("<no state>")
  7085  	if actual != expected {
  7086  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  7087  	}
  7088  }
  7089  
  7090  func TestContext2Apply_error(t *testing.T) {
  7091  	errored := false
  7092  
  7093  	m := testModule(t, "apply-error")
  7094  	p := testProvider("aws")
  7095  	ctx := testContext2(t, &ContextOpts{
  7096  		Config: m,
  7097  		ProviderResolver: providers.ResolverFixed(
  7098  			map[string]providers.Factory{
  7099  				"aws": testProviderFuncFixed(p),
  7100  			},
  7101  		),
  7102  	})
  7103  
  7104  	p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) {
  7105  		if errored {
  7106  			state := &InstanceState{
  7107  				ID: "bar",
  7108  			}
  7109  			return state, fmt.Errorf("error")
  7110  		}
  7111  		errored = true
  7112  
  7113  		return &InstanceState{
  7114  			ID: "foo",
  7115  			Attributes: map[string]string{
  7116  				"value": "2",
  7117  			},
  7118  		}, nil
  7119  	}
  7120  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  7121  		d := &InstanceDiff{
  7122  			Attributes: map[string]*ResourceAttrDiff{},
  7123  		}
  7124  		if new, ok := rc.Get("value"); ok {
  7125  			d.Attributes["value"] = &ResourceAttrDiff{
  7126  				New: new.(string),
  7127  			}
  7128  		}
  7129  		if new, ok := rc.Get("foo"); ok {
  7130  			d.Attributes["foo"] = &ResourceAttrDiff{
  7131  				New: new.(string),
  7132  			}
  7133  		}
  7134  		return d, nil
  7135  	}
  7136  
  7137  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7138  		t.Fatalf("plan errors: %s", diags.Err())
  7139  	}
  7140  
  7141  	state, diags := ctx.Apply()
  7142  	if diags == nil {
  7143  		t.Fatal("should have error")
  7144  	}
  7145  
  7146  	actual := strings.TrimSpace(state.String())
  7147  	expected := strings.TrimSpace(testTerraformApplyErrorStr)
  7148  	if actual != expected {
  7149  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  7150  	}
  7151  }
  7152  
  7153  func TestContext2Apply_errorDestroy(t *testing.T) {
  7154  	m := testModule(t, "empty")
  7155  	p := testProvider("test")
  7156  
  7157  	p.GetSchemaReturn = &ProviderSchema{
  7158  		ResourceTypes: map[string]*configschema.Block{
  7159  			"test_thing": {
  7160  				Attributes: map[string]*configschema.Attribute{
  7161  					"id": {Type: cty.String, Optional: true},
  7162  				},
  7163  			},
  7164  		},
  7165  	}
  7166  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  7167  		// Should actually be called for this test, because Terraform Core
  7168  		// constructs the plan for a destroy operation itself.
  7169  		return providers.PlanResourceChangeResponse{
  7170  			PlannedState: req.ProposedNewState,
  7171  		}
  7172  	}
  7173  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  7174  		// The apply (in this case, a destroy) always fails, so we can verify
  7175  		// that the object stays in the state after a destroy fails even though
  7176  		// we aren't returning a new state object here.
  7177  		return providers.ApplyResourceChangeResponse{
  7178  			Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("failed")),
  7179  		}
  7180  	}
  7181  
  7182  	ctx := testContext2(t, &ContextOpts{
  7183  		Config: m,
  7184  		State: states.BuildState(func(ss *states.SyncState) {
  7185  			ss.SetResourceInstanceCurrent(
  7186  				addrs.Resource{
  7187  					Mode: addrs.ManagedResourceMode,
  7188  					Type: "test_thing",
  7189  					Name: "foo",
  7190  				}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  7191  				&states.ResourceInstanceObjectSrc{
  7192  					Status:    states.ObjectReady,
  7193  					AttrsJSON: []byte(`{"id":"baz"}`),
  7194  				},
  7195  				addrs.ProviderConfig{
  7196  					Type: "test",
  7197  				}.Absolute(addrs.RootModuleInstance),
  7198  			)
  7199  		}),
  7200  		ProviderResolver: providers.ResolverFixed(
  7201  			map[string]providers.Factory{
  7202  				"test": testProviderFuncFixed(p),
  7203  			},
  7204  		),
  7205  	})
  7206  
  7207  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7208  		t.Fatalf("plan errors: %s", diags.Err())
  7209  	}
  7210  
  7211  	state, diags := ctx.Apply()
  7212  	if diags == nil {
  7213  		t.Fatal("should have error")
  7214  	}
  7215  
  7216  	actual := strings.TrimSpace(state.String())
  7217  	expected := strings.TrimSpace(`
  7218  test_thing.foo:
  7219    ID = baz
  7220    provider = provider.test
  7221  `) // test_thing.foo is still here, even though provider returned no new state along with its error
  7222  	if actual != expected {
  7223  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  7224  	}
  7225  }
  7226  
  7227  func TestContext2Apply_errorCreateInvalidNew(t *testing.T) {
  7228  	m := testModule(t, "apply-error")
  7229  
  7230  	p := testProvider("aws")
  7231  	p.GetSchemaReturn = &ProviderSchema{
  7232  		ResourceTypes: map[string]*configschema.Block{
  7233  			"aws_instance": {
  7234  				Attributes: map[string]*configschema.Attribute{
  7235  					"value": {Type: cty.String, Optional: true},
  7236  					"foo":   {Type: cty.String, Optional: true},
  7237  				},
  7238  			},
  7239  		},
  7240  	}
  7241  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  7242  		return providers.PlanResourceChangeResponse{
  7243  			PlannedState: req.ProposedNewState,
  7244  		}
  7245  	}
  7246  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  7247  		// We're intentionally returning an inconsistent new state here
  7248  		// because we want to test that Terraform ignores the inconsistency
  7249  		// when accompanied by another error.
  7250  		return providers.ApplyResourceChangeResponse{
  7251  			NewState: cty.ObjectVal(map[string]cty.Value{
  7252  				"value": cty.StringVal("wrong wrong wrong wrong"),
  7253  				"foo":   cty.StringVal("absolutely brimming over with wrongability"),
  7254  			}),
  7255  			Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("forced error")),
  7256  		}
  7257  	}
  7258  
  7259  	ctx := testContext2(t, &ContextOpts{
  7260  		Config: m,
  7261  		ProviderResolver: providers.ResolverFixed(
  7262  			map[string]providers.Factory{
  7263  				"aws": testProviderFuncFixed(p),
  7264  			},
  7265  		),
  7266  	})
  7267  
  7268  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7269  		t.Fatalf("plan errors: %s", diags.Err())
  7270  	}
  7271  
  7272  	state, diags := ctx.Apply()
  7273  	if diags == nil {
  7274  		t.Fatal("should have error")
  7275  	}
  7276  	if got, want := len(diags), 1; got != want {
  7277  		// There should be no additional diagnostics generated by Terraform's own eval logic,
  7278  		// because the provider's own error supersedes them.
  7279  		t.Errorf("wrong number of diagnostics %d; want %d\n%s", got, want, diags.Err())
  7280  	}
  7281  	if got, want := diags.Err().Error(), "forced error"; !strings.Contains(got, want) {
  7282  		t.Errorf("returned error does not contain %q, but it should\n%s", want, diags.Err())
  7283  	}
  7284  	if got, want := len(state.RootModule().Resources), 2; got != want {
  7285  		t.Errorf("%d resources in state before prune; should have %d\n%s", got, want, spew.Sdump(state))
  7286  	}
  7287  	state.PruneResourceHusks() // aws_instance.bar with no instances gets left behind when we bail out, but that's okay
  7288  	if got, want := len(state.RootModule().Resources), 1; got != want {
  7289  		t.Errorf("%d resources in state after prune; should have only one (aws_instance.foo, tainted)\n%s", got, spew.Sdump(state))
  7290  	}
  7291  }
  7292  
  7293  func TestContext2Apply_errorUpdateNullNew(t *testing.T) {
  7294  	m := testModule(t, "apply-error")
  7295  
  7296  	p := testProvider("aws")
  7297  	p.GetSchemaReturn = &ProviderSchema{
  7298  		ResourceTypes: map[string]*configschema.Block{
  7299  			"aws_instance": {
  7300  				Attributes: map[string]*configschema.Attribute{
  7301  					"value": {Type: cty.String, Optional: true},
  7302  					"foo":   {Type: cty.String, Optional: true},
  7303  				},
  7304  			},
  7305  		},
  7306  	}
  7307  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
  7308  		return providers.PlanResourceChangeResponse{
  7309  			PlannedState: req.ProposedNewState,
  7310  		}
  7311  	}
  7312  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
  7313  		// We're intentionally returning no NewState here because we want to
  7314  		// test that Terraform retains the prior state, rather than treating
  7315  		// the returned null as "no state" (object deleted).
  7316  		return providers.ApplyResourceChangeResponse{
  7317  			Diagnostics: tfdiags.Diagnostics(nil).Append(fmt.Errorf("forced error")),
  7318  		}
  7319  	}
  7320  
  7321  	ctx := testContext2(t, &ContextOpts{
  7322  		Config: m,
  7323  		State: states.BuildState(func(ss *states.SyncState) {
  7324  			ss.SetResourceInstanceCurrent(
  7325  				addrs.Resource{
  7326  					Mode: addrs.ManagedResourceMode,
  7327  					Type: "aws_instance",
  7328  					Name: "foo",
  7329  				}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
  7330  				&states.ResourceInstanceObjectSrc{
  7331  					Status:    states.ObjectReady,
  7332  					AttrsJSON: []byte(`{"value":"old"}`),
  7333  				},
  7334  				addrs.ProviderConfig{
  7335  					Type: "aws",
  7336  				}.Absolute(addrs.RootModuleInstance),
  7337  			)
  7338  		}),
  7339  		ProviderResolver: providers.ResolverFixed(
  7340  			map[string]providers.Factory{
  7341  				"aws": testProviderFuncFixed(p),
  7342  			},
  7343  		),
  7344  	})
  7345  
  7346  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7347  		t.Fatalf("plan errors: %s", diags.Err())
  7348  	}
  7349  
  7350  	state, diags := ctx.Apply()
  7351  	if diags == nil {
  7352  		t.Fatal("should have error")
  7353  	}
  7354  	if got, want := len(diags), 1; got != want {
  7355  		// There should be no additional diagnostics generated by Terraform's own eval logic,
  7356  		// because the provider's own error supersedes them.
  7357  		t.Errorf("wrong number of diagnostics %d; want %d\n%s", got, want, diags.Err())
  7358  	}
  7359  	if got, want := diags.Err().Error(), "forced error"; !strings.Contains(got, want) {
  7360  		t.Errorf("returned error does not contain %q, but it should\n%s", want, diags.Err())
  7361  	}
  7362  	state.PruneResourceHusks()
  7363  	if got, want := len(state.RootModule().Resources), 1; got != want {
  7364  		t.Fatalf("%d resources in state; should have only one (aws_instance.foo, unmodified)\n%s", got, spew.Sdump(state))
  7365  	}
  7366  
  7367  	is := state.ResourceInstance(addrs.Resource{
  7368  		Mode: addrs.ManagedResourceMode,
  7369  		Type: "aws_instance",
  7370  		Name: "foo",
  7371  	}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
  7372  	if is == nil {
  7373  		t.Fatalf("aws_instance.foo is not in the state after apply")
  7374  	}
  7375  	if got, want := is.Current.AttrsJSON, []byte(`"old"`); !bytes.Contains(got, want) {
  7376  		t.Fatalf("incorrect attributes for aws_instance.foo\ngot: %s\nwant: JSON containing %s\n\n%s", got, want, spew.Sdump(is))
  7377  	}
  7378  }
  7379  
  7380  func TestContext2Apply_errorPartial(t *testing.T) {
  7381  	errored := false
  7382  
  7383  	m := testModule(t, "apply-error")
  7384  	p := testProvider("aws")
  7385  	s := MustShimLegacyState(&State{
  7386  		Modules: []*ModuleState{
  7387  			{
  7388  				Path: rootModulePath,
  7389  				Resources: map[string]*ResourceState{
  7390  					"aws_instance.bar": {
  7391  						Type: "aws_instance",
  7392  						Primary: &InstanceState{
  7393  							ID: "bar",
  7394  						},
  7395  					},
  7396  				},
  7397  			},
  7398  		},
  7399  	})
  7400  	ctx := testContext2(t, &ContextOpts{
  7401  		Config: m,
  7402  		ProviderResolver: providers.ResolverFixed(
  7403  			map[string]providers.Factory{
  7404  				"aws": testProviderFuncFixed(p),
  7405  			},
  7406  		),
  7407  		State: s,
  7408  	})
  7409  
  7410  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  7411  		if errored {
  7412  			return s, fmt.Errorf("error")
  7413  		}
  7414  		errored = true
  7415  
  7416  		return &InstanceState{
  7417  			ID: "foo",
  7418  			Attributes: map[string]string{
  7419  				"value": "2",
  7420  			},
  7421  		}, nil
  7422  	}
  7423  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, rc *ResourceConfig) (*InstanceDiff, error) {
  7424  		d := &InstanceDiff{
  7425  			Attributes: map[string]*ResourceAttrDiff{},
  7426  		}
  7427  		if new, ok := rc.Get("value"); ok {
  7428  			d.Attributes["value"] = &ResourceAttrDiff{
  7429  				New: new.(string),
  7430  			}
  7431  		}
  7432  		if new, ok := rc.Get("foo"); ok {
  7433  			d.Attributes["foo"] = &ResourceAttrDiff{
  7434  				New: new.(string),
  7435  			}
  7436  		}
  7437  		return d, nil
  7438  	}
  7439  
  7440  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7441  		t.Fatalf("plan errors: %s", diags.Err())
  7442  	}
  7443  
  7444  	state, diags := ctx.Apply()
  7445  	if diags == nil {
  7446  		t.Fatal("should have error")
  7447  	}
  7448  
  7449  	mod := state.RootModule()
  7450  	if len(mod.Resources) != 2 {
  7451  		t.Fatalf("bad: %#v", mod.Resources)
  7452  	}
  7453  
  7454  	actual := strings.TrimSpace(state.String())
  7455  	expected := strings.TrimSpace(testTerraformApplyErrorPartialStr)
  7456  	if actual != expected {
  7457  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  7458  	}
  7459  }
  7460  
  7461  func TestContext2Apply_hook(t *testing.T) {
  7462  	m := testModule(t, "apply-good")
  7463  	h := new(MockHook)
  7464  	p := testProvider("aws")
  7465  	p.ApplyFn = testApplyFn
  7466  	p.DiffFn = testDiffFn
  7467  	ctx := testContext2(t, &ContextOpts{
  7468  		Config: m,
  7469  		Hooks:  []Hook{h},
  7470  		ProviderResolver: providers.ResolverFixed(
  7471  			map[string]providers.Factory{
  7472  				"aws": testProviderFuncFixed(p),
  7473  			},
  7474  		),
  7475  	})
  7476  
  7477  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7478  		t.Fatalf("plan errors: %s", diags.Err())
  7479  	}
  7480  
  7481  	if _, diags := ctx.Apply(); diags.HasErrors() {
  7482  		t.Fatalf("apply errors: %s", diags.Err())
  7483  	}
  7484  
  7485  	if !h.PreApplyCalled {
  7486  		t.Fatal("should be called")
  7487  	}
  7488  	if !h.PostApplyCalled {
  7489  		t.Fatal("should be called")
  7490  	}
  7491  	if !h.PostStateUpdateCalled {
  7492  		t.Fatalf("should call post state update")
  7493  	}
  7494  }
  7495  
  7496  func TestContext2Apply_hookOrphan(t *testing.T) {
  7497  	m := testModule(t, "apply-blank")
  7498  	h := new(MockHook)
  7499  	p := testProvider("aws")
  7500  	p.ApplyFn = testApplyFn
  7501  	p.DiffFn = testDiffFn
  7502  
  7503  	state := MustShimLegacyState(&State{
  7504  		Modules: []*ModuleState{
  7505  			{
  7506  				Path: rootModulePath,
  7507  				Resources: map[string]*ResourceState{
  7508  					"aws_instance.bar": {
  7509  						Type: "aws_instance",
  7510  						Primary: &InstanceState{
  7511  							ID: "bar",
  7512  						},
  7513  						Provider: "provider.aws",
  7514  					},
  7515  				},
  7516  			},
  7517  		},
  7518  	})
  7519  
  7520  	ctx := testContext2(t, &ContextOpts{
  7521  		Config: m,
  7522  		State:  state,
  7523  		Hooks:  []Hook{h},
  7524  		ProviderResolver: providers.ResolverFixed(
  7525  			map[string]providers.Factory{
  7526  				"aws": testProviderFuncFixed(p),
  7527  			},
  7528  		),
  7529  	})
  7530  
  7531  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7532  		t.Fatalf("plan errors: %s", diags.Err())
  7533  	}
  7534  
  7535  	if _, diags := ctx.Apply(); diags.HasErrors() {
  7536  		t.Fatalf("apply errors: %s", diags.Err())
  7537  	}
  7538  
  7539  	if !h.PreApplyCalled {
  7540  		t.Fatal("should be called")
  7541  	}
  7542  	if !h.PostApplyCalled {
  7543  		t.Fatal("should be called")
  7544  	}
  7545  	if !h.PostStateUpdateCalled {
  7546  		t.Fatalf("should call post state update")
  7547  	}
  7548  }
  7549  
  7550  func TestContext2Apply_idAttr(t *testing.T) {
  7551  	m := testModule(t, "apply-idattr")
  7552  	p := testProvider("aws")
  7553  	ctx := testContext2(t, &ContextOpts{
  7554  		Config: m,
  7555  		ProviderResolver: providers.ResolverFixed(
  7556  			map[string]providers.Factory{
  7557  				"aws": testProviderFuncFixed(p),
  7558  			},
  7559  		),
  7560  	})
  7561  
  7562  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  7563  		result := s.MergeDiff(d)
  7564  		result.ID = "foo"
  7565  		result.Attributes = map[string]string{
  7566  			"id":  "bar",
  7567  			"num": "42",
  7568  		}
  7569  
  7570  		return result, nil
  7571  	}
  7572  	p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) {
  7573  		return &InstanceDiff{
  7574  			Attributes: map[string]*ResourceAttrDiff{
  7575  				"num": {
  7576  					New: "42",
  7577  				},
  7578  			},
  7579  		}, nil
  7580  	}
  7581  
  7582  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7583  		t.Fatalf("plan errors: %s", diags.Err())
  7584  	}
  7585  
  7586  	state, diags := ctx.Apply()
  7587  	if diags.HasErrors() {
  7588  		t.Fatalf("apply errors: %s", diags.Err())
  7589  	}
  7590  
  7591  	mod := state.RootModule()
  7592  	rs, ok := mod.Resources["aws_instance.foo"]
  7593  	if !ok {
  7594  		t.Fatal("not in state")
  7595  	}
  7596  	var attrs map[string]interface{}
  7597  	err := json.Unmarshal(rs.Instances[addrs.NoKey].Current.AttrsJSON, &attrs)
  7598  	if err != nil {
  7599  		t.Fatal(err)
  7600  	}
  7601  	if got, want := attrs["id"], "foo"; got != want {
  7602  		t.Fatalf("wrong id\ngot:  %#v\nwant: %#v", got, want)
  7603  	}
  7604  }
  7605  
  7606  func TestContext2Apply_outputBasic(t *testing.T) {
  7607  	m := testModule(t, "apply-output")
  7608  	p := testProvider("aws")
  7609  	p.ApplyFn = testApplyFn
  7610  	p.DiffFn = testDiffFn
  7611  	ctx := testContext2(t, &ContextOpts{
  7612  		Config: m,
  7613  		ProviderResolver: providers.ResolverFixed(
  7614  			map[string]providers.Factory{
  7615  				"aws": testProviderFuncFixed(p),
  7616  			},
  7617  		),
  7618  	})
  7619  
  7620  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7621  		t.Fatalf("plan errors: %s", diags.Err())
  7622  	}
  7623  
  7624  	state, diags := ctx.Apply()
  7625  	if diags.HasErrors() {
  7626  		t.Fatalf("diags: %s", diags.Err())
  7627  	}
  7628  
  7629  	actual := strings.TrimSpace(state.String())
  7630  	expected := strings.TrimSpace(testTerraformApplyOutputStr)
  7631  	if actual != expected {
  7632  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  7633  	}
  7634  }
  7635  
  7636  func TestContext2Apply_outputAdd(t *testing.T) {
  7637  	m1 := testModule(t, "apply-output-add-before")
  7638  	p1 := testProvider("aws")
  7639  	p1.ApplyFn = testApplyFn
  7640  	p1.DiffFn = testDiffFn
  7641  	ctx1 := testContext2(t, &ContextOpts{
  7642  		Config: m1,
  7643  		ProviderResolver: providers.ResolverFixed(
  7644  			map[string]providers.Factory{
  7645  				"aws": testProviderFuncFixed(p1),
  7646  			},
  7647  		),
  7648  	})
  7649  
  7650  	if _, diags := ctx1.Plan(); diags.HasErrors() {
  7651  		t.Fatalf("diags: %s", diags.Err())
  7652  	}
  7653  
  7654  	state1, diags := ctx1.Apply()
  7655  	if diags.HasErrors() {
  7656  		t.Fatalf("diags: %s", diags.Err())
  7657  	}
  7658  
  7659  	m2 := testModule(t, "apply-output-add-after")
  7660  	p2 := testProvider("aws")
  7661  	p2.ApplyFn = testApplyFn
  7662  	p2.DiffFn = testDiffFn
  7663  	ctx2 := testContext2(t, &ContextOpts{
  7664  		Config: m2,
  7665  		ProviderResolver: providers.ResolverFixed(
  7666  			map[string]providers.Factory{
  7667  				"aws": testProviderFuncFixed(p2),
  7668  			},
  7669  		),
  7670  		State: state1,
  7671  	})
  7672  
  7673  	if _, diags := ctx2.Plan(); diags.HasErrors() {
  7674  		t.Fatalf("diags: %s", diags.Err())
  7675  	}
  7676  
  7677  	state2, diags := ctx2.Apply()
  7678  	if diags.HasErrors() {
  7679  		t.Fatalf("diags: %s", diags.Err())
  7680  	}
  7681  
  7682  	actual := strings.TrimSpace(state2.String())
  7683  	expected := strings.TrimSpace(testTerraformApplyOutputAddStr)
  7684  	if actual != expected {
  7685  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  7686  	}
  7687  }
  7688  
  7689  func TestContext2Apply_outputList(t *testing.T) {
  7690  	m := testModule(t, "apply-output-list")
  7691  	p := testProvider("aws")
  7692  	p.ApplyFn = testApplyFn
  7693  	p.DiffFn = testDiffFn
  7694  	ctx := testContext2(t, &ContextOpts{
  7695  		Config: m,
  7696  		ProviderResolver: providers.ResolverFixed(
  7697  			map[string]providers.Factory{
  7698  				"aws": testProviderFuncFixed(p),
  7699  			},
  7700  		),
  7701  	})
  7702  
  7703  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7704  		t.Fatalf("plan errors: %s", diags.Err())
  7705  	}
  7706  
  7707  	state, diags := ctx.Apply()
  7708  	if diags.HasErrors() {
  7709  		t.Fatalf("diags: %s", diags.Err())
  7710  	}
  7711  
  7712  	actual := strings.TrimSpace(state.String())
  7713  	expected := strings.TrimSpace(testTerraformApplyOutputListStr)
  7714  	if actual != expected {
  7715  		t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual)
  7716  	}
  7717  }
  7718  
  7719  func TestContext2Apply_outputMulti(t *testing.T) {
  7720  	m := testModule(t, "apply-output-multi")
  7721  	p := testProvider("aws")
  7722  	p.ApplyFn = testApplyFn
  7723  	p.DiffFn = testDiffFn
  7724  	ctx := testContext2(t, &ContextOpts{
  7725  		Config: m,
  7726  		ProviderResolver: providers.ResolverFixed(
  7727  			map[string]providers.Factory{
  7728  				"aws": testProviderFuncFixed(p),
  7729  			},
  7730  		),
  7731  	})
  7732  
  7733  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7734  		t.Fatalf("plan errors: %s", diags.Err())
  7735  	}
  7736  
  7737  	state, diags := ctx.Apply()
  7738  	if diags.HasErrors() {
  7739  		t.Fatalf("diags: %s", diags.Err())
  7740  	}
  7741  
  7742  	actual := strings.TrimSpace(state.String())
  7743  	expected := strings.TrimSpace(testTerraformApplyOutputMultiStr)
  7744  	if actual != expected {
  7745  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  7746  	}
  7747  }
  7748  
  7749  func TestContext2Apply_outputMultiIndex(t *testing.T) {
  7750  	m := testModule(t, "apply-output-multi-index")
  7751  	p := testProvider("aws")
  7752  	p.ApplyFn = testApplyFn
  7753  	p.DiffFn = testDiffFn
  7754  	ctx := testContext2(t, &ContextOpts{
  7755  		Config: m,
  7756  		ProviderResolver: providers.ResolverFixed(
  7757  			map[string]providers.Factory{
  7758  				"aws": testProviderFuncFixed(p),
  7759  			},
  7760  		),
  7761  	})
  7762  
  7763  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7764  		t.Fatalf("plan errors: %s", diags.Err())
  7765  	}
  7766  
  7767  	state, diags := ctx.Apply()
  7768  	if diags.HasErrors() {
  7769  		t.Fatalf("diags: %s", diags.Err())
  7770  	}
  7771  
  7772  	actual := strings.TrimSpace(state.String())
  7773  	expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr)
  7774  	if actual != expected {
  7775  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  7776  	}
  7777  }
  7778  
  7779  func TestContext2Apply_taintX(t *testing.T) {
  7780  	m := testModule(t, "apply-taint")
  7781  	p := testProvider("aws")
  7782  	// destroyCount tests against regression of
  7783  	// https://github.com/hashicorp/terraform-plugin-sdk/issues/1056
  7784  	var destroyCount = int32(0)
  7785  	var once sync.Once
  7786  	simulateProviderDelay := func() {
  7787  		time.Sleep(10 * time.Millisecond)
  7788  	}
  7789  
  7790  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  7791  		once.Do(simulateProviderDelay)
  7792  		if d.Destroy {
  7793  			atomic.AddInt32(&destroyCount, 1)
  7794  		}
  7795  		return testApplyFn(info, s, d)
  7796  	}
  7797  	p.DiffFn = testDiffFn
  7798  	s := MustShimLegacyState(&State{
  7799  		Modules: []*ModuleState{
  7800  			{
  7801  				Path: rootModulePath,
  7802  				Resources: map[string]*ResourceState{
  7803  					"aws_instance.bar": {
  7804  						Type: "aws_instance",
  7805  						Primary: &InstanceState{
  7806  							ID: "baz",
  7807  							Attributes: map[string]string{
  7808  								"num":  "2",
  7809  								"type": "aws_instance",
  7810  							},
  7811  							Tainted: true,
  7812  						},
  7813  					},
  7814  				},
  7815  			},
  7816  		},
  7817  	})
  7818  	ctx := testContext2(t, &ContextOpts{
  7819  		Config: m,
  7820  		ProviderResolver: providers.ResolverFixed(
  7821  			map[string]providers.Factory{
  7822  				"aws": testProviderFuncFixed(p),
  7823  			},
  7824  		),
  7825  		State: s,
  7826  	})
  7827  
  7828  	if p, diags := ctx.Plan(); diags.HasErrors() {
  7829  		t.Fatalf("diags: %s", diags.Err())
  7830  	} else {
  7831  		t.Logf("plan: %s", legacyDiffComparisonString(p.Changes))
  7832  	}
  7833  
  7834  	state, diags := ctx.Apply()
  7835  	if diags.HasErrors() {
  7836  		t.Fatalf("diags: %s", diags.Err())
  7837  	}
  7838  
  7839  	actual := strings.TrimSpace(state.String())
  7840  	expected := strings.TrimSpace(testTerraformApplyTaintStr)
  7841  	if actual != expected {
  7842  		t.Fatalf("bad:\n%s", actual)
  7843  	}
  7844  
  7845  	if destroyCount != 1 {
  7846  		t.Fatalf("Expected 1 destroy, got %d", destroyCount)
  7847  	}
  7848  }
  7849  
  7850  func TestContext2Apply_taintDep(t *testing.T) {
  7851  	m := testModule(t, "apply-taint-dep")
  7852  	p := testProvider("aws")
  7853  	p.ApplyFn = testApplyFn
  7854  	p.DiffFn = testDiffFn
  7855  	s := MustShimLegacyState(&State{
  7856  		Modules: []*ModuleState{
  7857  			{
  7858  				Path: rootModulePath,
  7859  				Resources: map[string]*ResourceState{
  7860  					"aws_instance.foo": {
  7861  						Type: "aws_instance",
  7862  						Primary: &InstanceState{
  7863  							ID: "baz",
  7864  							Attributes: map[string]string{
  7865  								"num":  "2",
  7866  								"type": "aws_instance",
  7867  							},
  7868  							Tainted: true,
  7869  						},
  7870  					},
  7871  					"aws_instance.bar": {
  7872  						Type: "aws_instance",
  7873  						Primary: &InstanceState{
  7874  							ID: "bar",
  7875  							Attributes: map[string]string{
  7876  								"foo":  "baz",
  7877  								"num":  "2",
  7878  								"type": "aws_instance",
  7879  							},
  7880  						},
  7881  					},
  7882  				},
  7883  			},
  7884  		},
  7885  	})
  7886  	ctx := testContext2(t, &ContextOpts{
  7887  		Config: m,
  7888  		ProviderResolver: providers.ResolverFixed(
  7889  			map[string]providers.Factory{
  7890  				"aws": testProviderFuncFixed(p),
  7891  			},
  7892  		),
  7893  		State: s,
  7894  	})
  7895  
  7896  	if p, diags := ctx.Plan(); diags.HasErrors() {
  7897  		t.Fatalf("diags: %s", diags.Err())
  7898  	} else {
  7899  		t.Logf("plan: %s", legacyDiffComparisonString(p.Changes))
  7900  	}
  7901  
  7902  	state, diags := ctx.Apply()
  7903  	if diags.HasErrors() {
  7904  		t.Fatalf("diags: %s", diags.Err())
  7905  	}
  7906  
  7907  	actual := strings.TrimSpace(state.String())
  7908  	expected := strings.TrimSpace(testTerraformApplyTaintDepStr)
  7909  	if actual != expected {
  7910  		t.Fatalf("bad:\n%s", actual)
  7911  	}
  7912  }
  7913  
  7914  func TestContext2Apply_taintDepRequiresNew(t *testing.T) {
  7915  	m := testModule(t, "apply-taint-dep-requires-new")
  7916  	p := testProvider("aws")
  7917  	p.ApplyFn = testApplyFn
  7918  	p.DiffFn = testDiffFn
  7919  	s := MustShimLegacyState(&State{
  7920  		Modules: []*ModuleState{
  7921  			{
  7922  				Path: rootModulePath,
  7923  				Resources: map[string]*ResourceState{
  7924  					"aws_instance.foo": {
  7925  						Type: "aws_instance",
  7926  						Primary: &InstanceState{
  7927  							ID: "baz",
  7928  							Attributes: map[string]string{
  7929  								"num":  "2",
  7930  								"type": "aws_instance",
  7931  							},
  7932  							Tainted: true,
  7933  						},
  7934  					},
  7935  					"aws_instance.bar": {
  7936  						Type: "aws_instance",
  7937  						Primary: &InstanceState{
  7938  							ID: "bar",
  7939  							Attributes: map[string]string{
  7940  								"foo":  "baz",
  7941  								"num":  "2",
  7942  								"type": "aws_instance",
  7943  							},
  7944  						},
  7945  					},
  7946  				},
  7947  			},
  7948  		},
  7949  	})
  7950  	ctx := testContext2(t, &ContextOpts{
  7951  		Config: m,
  7952  		ProviderResolver: providers.ResolverFixed(
  7953  			map[string]providers.Factory{
  7954  				"aws": testProviderFuncFixed(p),
  7955  			},
  7956  		),
  7957  		State: s,
  7958  	})
  7959  
  7960  	if p, diags := ctx.Plan(); diags.HasErrors() {
  7961  		t.Fatalf("diags: %s", diags.Err())
  7962  	} else {
  7963  		t.Logf("plan: %s", legacyDiffComparisonString(p.Changes))
  7964  	}
  7965  
  7966  	state, diags := ctx.Apply()
  7967  	if diags.HasErrors() {
  7968  		t.Fatalf("diags: %s", diags.Err())
  7969  	}
  7970  
  7971  	actual := strings.TrimSpace(state.String())
  7972  	expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr)
  7973  	if actual != expected {
  7974  		t.Fatalf("bad:\n%s", actual)
  7975  	}
  7976  }
  7977  
  7978  func TestContext2Apply_targeted(t *testing.T) {
  7979  	m := testModule(t, "apply-targeted")
  7980  	p := testProvider("aws")
  7981  	p.ApplyFn = testApplyFn
  7982  	p.DiffFn = testDiffFn
  7983  	ctx := testContext2(t, &ContextOpts{
  7984  		Config: m,
  7985  		ProviderResolver: providers.ResolverFixed(
  7986  			map[string]providers.Factory{
  7987  				"aws": testProviderFuncFixed(p),
  7988  			},
  7989  		),
  7990  		Targets: []addrs.Targetable{
  7991  			addrs.RootModuleInstance.Resource(
  7992  				addrs.ManagedResourceMode, "aws_instance", "foo",
  7993  			),
  7994  		},
  7995  	})
  7996  
  7997  	if _, diags := ctx.Plan(); diags.HasErrors() {
  7998  		t.Fatalf("plan errors: %s", diags.Err())
  7999  	}
  8000  
  8001  	state, diags := ctx.Apply()
  8002  	if diags.HasErrors() {
  8003  		t.Fatalf("diags: %s", diags.Err())
  8004  	}
  8005  
  8006  	mod := state.RootModule()
  8007  	if len(mod.Resources) != 1 {
  8008  		t.Fatalf("expected 1 resource, got: %#v", mod.Resources)
  8009  	}
  8010  
  8011  	checkStateString(t, state, `
  8012  aws_instance.foo:
  8013    ID = foo
  8014    provider = provider.aws
  8015    num = 2
  8016    type = aws_instance
  8017  	`)
  8018  }
  8019  
  8020  func TestContext2Apply_targetedCount(t *testing.T) {
  8021  	m := testModule(t, "apply-targeted-count")
  8022  	p := testProvider("aws")
  8023  	p.ApplyFn = testApplyFn
  8024  	p.DiffFn = testDiffFn
  8025  	ctx := testContext2(t, &ContextOpts{
  8026  		Config: m,
  8027  		ProviderResolver: providers.ResolverFixed(
  8028  			map[string]providers.Factory{
  8029  				"aws": testProviderFuncFixed(p),
  8030  			},
  8031  		),
  8032  		Targets: []addrs.Targetable{
  8033  			addrs.RootModuleInstance.Resource(
  8034  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8035  			),
  8036  		},
  8037  	})
  8038  
  8039  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8040  		t.Fatalf("plan errors: %s", diags.Err())
  8041  	}
  8042  
  8043  	state, diags := ctx.Apply()
  8044  	if diags.HasErrors() {
  8045  		t.Fatalf("diags: %s", diags.Err())
  8046  	}
  8047  
  8048  	checkStateString(t, state, `
  8049  aws_instance.foo.0:
  8050    ID = foo
  8051    provider = provider.aws
  8052  aws_instance.foo.1:
  8053    ID = foo
  8054    provider = provider.aws
  8055  aws_instance.foo.2:
  8056    ID = foo
  8057    provider = provider.aws
  8058  	`)
  8059  }
  8060  
  8061  func TestContext2Apply_targetedCountIndex(t *testing.T) {
  8062  	m := testModule(t, "apply-targeted-count")
  8063  	p := testProvider("aws")
  8064  	p.ApplyFn = testApplyFn
  8065  	p.DiffFn = testDiffFn
  8066  	ctx := testContext2(t, &ContextOpts{
  8067  		Config: m,
  8068  		ProviderResolver: providers.ResolverFixed(
  8069  			map[string]providers.Factory{
  8070  				"aws": testProviderFuncFixed(p),
  8071  			},
  8072  		),
  8073  		Targets: []addrs.Targetable{
  8074  			addrs.RootModuleInstance.ResourceInstance(
  8075  				addrs.ManagedResourceMode, "aws_instance", "foo", addrs.IntKey(1),
  8076  			),
  8077  		},
  8078  	})
  8079  
  8080  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8081  		t.Fatalf("plan errors: %s", diags.Err())
  8082  	}
  8083  
  8084  	state, diags := ctx.Apply()
  8085  	if diags.HasErrors() {
  8086  		t.Fatalf("diags: %s", diags.Err())
  8087  	}
  8088  
  8089  	checkStateString(t, state, `
  8090  aws_instance.foo.1:
  8091    ID = foo
  8092    provider = provider.aws
  8093  	`)
  8094  }
  8095  
  8096  func TestContext2Apply_targetedDestroy(t *testing.T) {
  8097  	m := testModule(t, "apply-targeted")
  8098  	p := testProvider("aws")
  8099  	p.ApplyFn = testApplyFn
  8100  	p.DiffFn = testDiffFn
  8101  	ctx := testContext2(t, &ContextOpts{
  8102  		Config: m,
  8103  		ProviderResolver: providers.ResolverFixed(
  8104  			map[string]providers.Factory{
  8105  				"aws": testProviderFuncFixed(p),
  8106  			},
  8107  		),
  8108  		State: MustShimLegacyState(&State{
  8109  			Modules: []*ModuleState{
  8110  				{
  8111  					Path: rootModulePath,
  8112  					Resources: map[string]*ResourceState{
  8113  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  8114  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  8115  					},
  8116  				},
  8117  			},
  8118  		}),
  8119  		Targets: []addrs.Targetable{
  8120  			addrs.RootModuleInstance.Resource(
  8121  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8122  			),
  8123  		},
  8124  		Destroy: true,
  8125  	})
  8126  
  8127  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8128  		t.Fatalf("plan errors: %s", diags.Err())
  8129  	}
  8130  
  8131  	state, diags := ctx.Apply()
  8132  	if diags.HasErrors() {
  8133  		t.Fatalf("diags: %s", diags.Err())
  8134  	}
  8135  
  8136  	mod := state.RootModule()
  8137  	if len(mod.Resources) != 1 {
  8138  		t.Fatalf("expected 1 resource, got: %#v", mod.Resources)
  8139  	}
  8140  
  8141  	checkStateString(t, state, `
  8142  aws_instance.bar:
  8143    ID = i-abc123
  8144    provider = provider.aws
  8145  	`)
  8146  }
  8147  
  8148  func TestContext2Apply_destroyProvisionerWithLocals(t *testing.T) {
  8149  	m := testModule(t, "apply-provisioner-destroy-locals")
  8150  	p := testProvider("aws")
  8151  	p.ApplyFn = testApplyFn
  8152  	p.DiffFn = testDiffFn
  8153  
  8154  	pr := testProvisioner()
  8155  	pr.ApplyFn = func(_ *InstanceState, rc *ResourceConfig) error {
  8156  		cmd, ok := rc.Get("command")
  8157  		if !ok || cmd != "local" {
  8158  			return fmt.Errorf("provisioner got %v:%s", ok, cmd)
  8159  		}
  8160  		return nil
  8161  	}
  8162  	pr.GetSchemaResponse = provisioners.GetSchemaResponse{
  8163  		Provisioner: &configschema.Block{
  8164  			Attributes: map[string]*configschema.Attribute{
  8165  				"command": {
  8166  					Type:     cty.String,
  8167  					Required: true,
  8168  				},
  8169  				"when": {
  8170  					Type:     cty.String,
  8171  					Optional: true,
  8172  				},
  8173  			},
  8174  		},
  8175  	}
  8176  
  8177  	ctx := testContext2(t, &ContextOpts{
  8178  		Config: m,
  8179  		ProviderResolver: providers.ResolverFixed(
  8180  			map[string]providers.Factory{
  8181  				"aws": testProviderFuncFixed(p),
  8182  			},
  8183  		),
  8184  		Provisioners: map[string]ProvisionerFactory{
  8185  			"shell": testProvisionerFuncFixed(pr),
  8186  		},
  8187  		State: MustShimLegacyState(&State{
  8188  			Modules: []*ModuleState{
  8189  				{
  8190  					Path: []string{"root"},
  8191  					Resources: map[string]*ResourceState{
  8192  						"aws_instance.foo": resourceState("aws_instance", "1234"),
  8193  					},
  8194  				},
  8195  			},
  8196  		}),
  8197  		Destroy: true,
  8198  		// the test works without targeting, but this also tests that the local
  8199  		// node isn't inadvertently pruned because of the wrong evaluation
  8200  		// order.
  8201  		Targets: []addrs.Targetable{
  8202  			addrs.RootModuleInstance.Resource(
  8203  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8204  			),
  8205  		},
  8206  	})
  8207  
  8208  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8209  		t.Fatal(diags.Err())
  8210  	}
  8211  
  8212  	if _, diags := ctx.Apply(); diags.HasErrors() {
  8213  		t.Fatal(diags.Err())
  8214  	}
  8215  
  8216  	if !pr.ProvisionResourceCalled {
  8217  		t.Fatal("provisioner not called")
  8218  	}
  8219  }
  8220  
  8221  // this also tests a local value in the config referencing a resource that
  8222  // wasn't in the state during destroy.
  8223  func TestContext2Apply_destroyProvisionerWithMultipleLocals(t *testing.T) {
  8224  	m := testModule(t, "apply-provisioner-destroy-multiple-locals")
  8225  	p := testProvider("aws")
  8226  	p.ApplyFn = testApplyFn
  8227  	p.DiffFn = testDiffFn
  8228  
  8229  	pr := testProvisioner()
  8230  	pr.GetSchemaResponse = provisioners.GetSchemaResponse{
  8231  		Provisioner: &configschema.Block{
  8232  			Attributes: map[string]*configschema.Attribute{
  8233  				"id": {
  8234  					Type:     cty.String,
  8235  					Required: true,
  8236  				},
  8237  				"command": {
  8238  					Type:     cty.String,
  8239  					Required: true,
  8240  				},
  8241  				"when": {
  8242  					Type:     cty.String,
  8243  					Optional: true,
  8244  				},
  8245  			},
  8246  		},
  8247  	}
  8248  
  8249  	pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error {
  8250  		cmd, ok := rc.Get("command")
  8251  		if !ok {
  8252  			return errors.New("no command in provisioner")
  8253  		}
  8254  		id, ok := rc.Get("id")
  8255  		if !ok {
  8256  			return errors.New("no id in provisioner")
  8257  		}
  8258  
  8259  		switch id {
  8260  		case "1234":
  8261  			if cmd != "local" {
  8262  				return fmt.Errorf("provisioner %q got:%q", is.ID, cmd)
  8263  			}
  8264  		case "3456":
  8265  			if cmd != "1234" {
  8266  				return fmt.Errorf("provisioner %q got:%q", is.ID, cmd)
  8267  			}
  8268  		default:
  8269  			t.Fatal("unknown instance")
  8270  		}
  8271  		return nil
  8272  	}
  8273  
  8274  	ctx := testContext2(t, &ContextOpts{
  8275  		Config: m,
  8276  		ProviderResolver: providers.ResolverFixed(
  8277  			map[string]providers.Factory{
  8278  				"aws": testProviderFuncFixed(p),
  8279  			},
  8280  		),
  8281  		Provisioners: map[string]ProvisionerFactory{
  8282  			"shell": testProvisionerFuncFixed(pr),
  8283  		},
  8284  		State: MustShimLegacyState(&State{
  8285  			Modules: []*ModuleState{
  8286  				{
  8287  					Path: []string{"root"},
  8288  					Resources: map[string]*ResourceState{
  8289  						"aws_instance.foo": resourceState("aws_instance", "1234"),
  8290  						"aws_instance.bar": resourceState("aws_instance", "3456"),
  8291  					},
  8292  				},
  8293  			},
  8294  		}),
  8295  		Destroy: true,
  8296  	})
  8297  
  8298  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8299  		t.Fatal(diags.Err())
  8300  	}
  8301  
  8302  	if _, diags := ctx.Apply(); diags.HasErrors() {
  8303  		t.Fatal(diags.Err())
  8304  	}
  8305  
  8306  	if !pr.ProvisionResourceCalled {
  8307  		t.Fatal("provisioner not called")
  8308  	}
  8309  }
  8310  
  8311  func TestContext2Apply_destroyProvisionerWithOutput(t *testing.T) {
  8312  	m := testModule(t, "apply-provisioner-destroy-outputs")
  8313  	p := testProvider("aws")
  8314  	p.ApplyFn = testApplyFn
  8315  	p.DiffFn = testDiffFn
  8316  
  8317  	pr := testProvisioner()
  8318  	pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error {
  8319  		cmd, ok := rc.Get("command")
  8320  		if !ok || cmd != "3" {
  8321  			return fmt.Errorf("provisioner for %s got %v:%s", is.ID, ok, cmd)
  8322  		}
  8323  		return nil
  8324  	}
  8325  	ctx := testContext2(t, &ContextOpts{
  8326  		Config: m,
  8327  		ProviderResolver: providers.ResolverFixed(
  8328  			map[string]providers.Factory{
  8329  				"aws": testProviderFuncFixed(p),
  8330  			},
  8331  		),
  8332  		Provisioners: map[string]ProvisionerFactory{
  8333  			"shell": testProvisionerFuncFixed(pr),
  8334  		},
  8335  		State: MustShimLegacyState(&State{
  8336  			Modules: []*ModuleState{
  8337  				{
  8338  					Path: []string{"root"},
  8339  					Resources: map[string]*ResourceState{
  8340  						"aws_instance.foo": resourceState("aws_instance", "1"),
  8341  					},
  8342  					Outputs: map[string]*OutputState{
  8343  						"value": {
  8344  							Type:  "string",
  8345  							Value: "3",
  8346  						},
  8347  					},
  8348  				},
  8349  				{
  8350  					Path: []string{"root", "mod"},
  8351  					Resources: map[string]*ResourceState{
  8352  						"aws_instance.baz": resourceState("aws_instance", "3"),
  8353  					},
  8354  					// state needs to be properly initialized
  8355  					Outputs: map[string]*OutputState{},
  8356  				},
  8357  				{
  8358  					Path: []string{"root", "mod2"},
  8359  					Resources: map[string]*ResourceState{
  8360  						"aws_instance.bar": resourceState("aws_instance", "2"),
  8361  					},
  8362  				},
  8363  			},
  8364  		}),
  8365  		Destroy: true,
  8366  
  8367  		// targeting the source of the value used by all resources should still
  8368  		// destroy them all.
  8369  		Targets: []addrs.Targetable{
  8370  			addrs.RootModuleInstance.Child("mod", addrs.NoKey).Resource(
  8371  				addrs.ManagedResourceMode, "aws_instance", "baz",
  8372  			),
  8373  		},
  8374  	})
  8375  
  8376  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8377  		t.Fatal(diags.Err())
  8378  	}
  8379  
  8380  	state, diags := ctx.Apply()
  8381  	if diags.HasErrors() {
  8382  		t.Fatal(diags.Err())
  8383  	}
  8384  	if !pr.ProvisionResourceCalled {
  8385  		t.Fatal("provisioner not called")
  8386  	}
  8387  
  8388  	// confirm all outputs were removed too
  8389  	for _, mod := range state.Modules {
  8390  		if len(mod.OutputValues) > 0 {
  8391  			t.Fatalf("output left in module state: %#v\n", mod)
  8392  		}
  8393  	}
  8394  }
  8395  
  8396  func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) {
  8397  	m := testModule(t, "apply-destroy-targeted-count")
  8398  	p := testProvider("aws")
  8399  	p.ApplyFn = testApplyFn
  8400  	p.DiffFn = testDiffFn
  8401  	ctx := testContext2(t, &ContextOpts{
  8402  		Config: m,
  8403  		ProviderResolver: providers.ResolverFixed(
  8404  			map[string]providers.Factory{
  8405  				"aws": testProviderFuncFixed(p),
  8406  			},
  8407  		),
  8408  		State: MustShimLegacyState(&State{
  8409  			Modules: []*ModuleState{
  8410  				{
  8411  					Path: rootModulePath,
  8412  					Resources: map[string]*ResourceState{
  8413  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  8414  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  8415  					},
  8416  				},
  8417  			},
  8418  		}),
  8419  		Targets: []addrs.Targetable{
  8420  			addrs.RootModuleInstance.Resource(
  8421  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8422  			),
  8423  		},
  8424  		Destroy: true,
  8425  	})
  8426  
  8427  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8428  		t.Fatalf("plan errors: %s", diags.Err())
  8429  	}
  8430  
  8431  	state, diags := ctx.Apply()
  8432  	if diags.HasErrors() {
  8433  		t.Fatalf("diags: %s", diags.Err())
  8434  	}
  8435  
  8436  	checkStateString(t, state, `<no state>`)
  8437  }
  8438  
  8439  // https://github.com/hashicorp/terraform-plugin-sdk/issues/4462
  8440  func TestContext2Apply_targetedDestroyModule(t *testing.T) {
  8441  	m := testModule(t, "apply-targeted-module")
  8442  	p := testProvider("aws")
  8443  	p.ApplyFn = testApplyFn
  8444  	p.DiffFn = testDiffFn
  8445  	ctx := testContext2(t, &ContextOpts{
  8446  		Config: m,
  8447  		ProviderResolver: providers.ResolverFixed(
  8448  			map[string]providers.Factory{
  8449  				"aws": testProviderFuncFixed(p),
  8450  			},
  8451  		),
  8452  		State: MustShimLegacyState(&State{
  8453  			Modules: []*ModuleState{
  8454  				{
  8455  					Path: rootModulePath,
  8456  					Resources: map[string]*ResourceState{
  8457  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  8458  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  8459  					},
  8460  				},
  8461  				{
  8462  					Path: []string{"root", "child"},
  8463  					Resources: map[string]*ResourceState{
  8464  						"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
  8465  						"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
  8466  					},
  8467  				},
  8468  			},
  8469  		}),
  8470  		Targets: []addrs.Targetable{
  8471  			addrs.RootModuleInstance.Child("child", addrs.NoKey).Resource(
  8472  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8473  			),
  8474  		},
  8475  		Destroy: true,
  8476  	})
  8477  
  8478  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8479  		t.Fatalf("plan errors: %s", diags.Err())
  8480  	}
  8481  
  8482  	state, diags := ctx.Apply()
  8483  	if diags.HasErrors() {
  8484  		t.Fatalf("diags: %s", diags.Err())
  8485  	}
  8486  
  8487  	checkStateString(t, state, `
  8488  aws_instance.bar:
  8489    ID = i-abc123
  8490    provider = provider.aws
  8491  aws_instance.foo:
  8492    ID = i-bcd345
  8493    provider = provider.aws
  8494  
  8495  module.child:
  8496    aws_instance.bar:
  8497      ID = i-abc123
  8498      provider = provider.aws
  8499  	`)
  8500  }
  8501  
  8502  func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) {
  8503  	m := testModule(t, "apply-targeted-count")
  8504  	p := testProvider("aws")
  8505  	p.ApplyFn = testApplyFn
  8506  	p.DiffFn = testDiffFn
  8507  	ctx := testContext2(t, &ContextOpts{
  8508  		Config: m,
  8509  		ProviderResolver: providers.ResolverFixed(
  8510  			map[string]providers.Factory{
  8511  				"aws": testProviderFuncFixed(p),
  8512  			},
  8513  		),
  8514  		State: MustShimLegacyState(&State{
  8515  			Modules: []*ModuleState{
  8516  				{
  8517  					Path: rootModulePath,
  8518  					Resources: map[string]*ResourceState{
  8519  						"aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"),
  8520  						"aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"),
  8521  						"aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"),
  8522  						"aws_instance.bar.0": resourceState("aws_instance", "i-abc123"),
  8523  						"aws_instance.bar.1": resourceState("aws_instance", "i-abc123"),
  8524  						"aws_instance.bar.2": resourceState("aws_instance", "i-abc123"),
  8525  					},
  8526  				},
  8527  			},
  8528  		}),
  8529  		Targets: []addrs.Targetable{
  8530  			addrs.RootModuleInstance.ResourceInstance(
  8531  				addrs.ManagedResourceMode, "aws_instance", "foo", addrs.IntKey(2),
  8532  			),
  8533  			addrs.RootModuleInstance.ResourceInstance(
  8534  				addrs.ManagedResourceMode, "aws_instance", "bar", addrs.IntKey(1),
  8535  			),
  8536  		},
  8537  		Destroy: true,
  8538  	})
  8539  
  8540  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8541  		t.Fatalf("plan errors: %s", diags.Err())
  8542  	}
  8543  
  8544  	state, diags := ctx.Apply()
  8545  	if diags.HasErrors() {
  8546  		t.Fatalf("diags: %s", diags.Err())
  8547  	}
  8548  
  8549  	checkStateString(t, state, `
  8550  aws_instance.bar.0:
  8551    ID = i-abc123
  8552    provider = provider.aws
  8553  aws_instance.bar.2:
  8554    ID = i-abc123
  8555    provider = provider.aws
  8556  aws_instance.foo.0:
  8557    ID = i-bcd345
  8558    provider = provider.aws
  8559  aws_instance.foo.1:
  8560    ID = i-bcd345
  8561    provider = provider.aws
  8562  	`)
  8563  }
  8564  
  8565  func TestContext2Apply_targetedModule(t *testing.T) {
  8566  	m := testModule(t, "apply-targeted-module")
  8567  	p := testProvider("aws")
  8568  	p.ApplyFn = testApplyFn
  8569  	p.DiffFn = testDiffFn
  8570  	ctx := testContext2(t, &ContextOpts{
  8571  		Config: m,
  8572  		ProviderResolver: providers.ResolverFixed(
  8573  			map[string]providers.Factory{
  8574  				"aws": testProviderFuncFixed(p),
  8575  			},
  8576  		),
  8577  		Targets: []addrs.Targetable{
  8578  			addrs.RootModuleInstance.Child("child", addrs.NoKey),
  8579  		},
  8580  	})
  8581  
  8582  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8583  		t.Fatalf("plan errors: %s", diags.Err())
  8584  	}
  8585  
  8586  	state, diags := ctx.Apply()
  8587  	if diags.HasErrors() {
  8588  		t.Fatalf("diags: %s", diags.Err())
  8589  	}
  8590  
  8591  	mod := state.Module(addrs.RootModuleInstance.Child("child", addrs.NoKey))
  8592  	if mod == nil {
  8593  		t.Fatalf("no child module found in the state!\n\n%#v", state)
  8594  	}
  8595  	if len(mod.Resources) != 2 {
  8596  		t.Fatalf("expected 2 resources, got: %#v", mod.Resources)
  8597  	}
  8598  
  8599  	checkStateString(t, state, `
  8600  <no state>
  8601  module.child:
  8602    aws_instance.bar:
  8603      ID = foo
  8604      provider = provider.aws
  8605      num = 2
  8606      type = aws_instance
  8607    aws_instance.foo:
  8608      ID = foo
  8609      provider = provider.aws
  8610      num = 2
  8611      type = aws_instance
  8612  	`)
  8613  }
  8614  
  8615  // GH-1858
  8616  func TestContext2Apply_targetedModuleDep(t *testing.T) {
  8617  	m := testModule(t, "apply-targeted-module-dep")
  8618  	p := testProvider("aws")
  8619  	p.ApplyFn = testApplyFn
  8620  	p.DiffFn = testDiffFn
  8621  	ctx := testContext2(t, &ContextOpts{
  8622  		Config: m,
  8623  		ProviderResolver: providers.ResolverFixed(
  8624  			map[string]providers.Factory{
  8625  				"aws": testProviderFuncFixed(p),
  8626  			},
  8627  		),
  8628  		Targets: []addrs.Targetable{
  8629  			addrs.RootModuleInstance.Resource(
  8630  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8631  			),
  8632  		},
  8633  	})
  8634  
  8635  	if p, diags := ctx.Plan(); diags.HasErrors() {
  8636  		t.Fatalf("diags: %s", diags.Err())
  8637  	} else {
  8638  		t.Logf("Diff: %s", legacyDiffComparisonString(p.Changes))
  8639  	}
  8640  
  8641  	state, diags := ctx.Apply()
  8642  	if diags.HasErrors() {
  8643  		t.Fatalf("diags: %s", diags.Err())
  8644  	}
  8645  
  8646  	checkStateString(t, state, `
  8647  aws_instance.foo:
  8648    ID = foo
  8649    provider = provider.aws
  8650    foo = foo
  8651    type = aws_instance
  8652  
  8653    Dependencies:
  8654      module.child
  8655  
  8656  module.child:
  8657    aws_instance.mod:
  8658      ID = foo
  8659      provider = provider.aws
  8660  
  8661    Outputs:
  8662  
  8663    output = foo
  8664  	`)
  8665  }
  8666  
  8667  // GH-10911 untargeted outputs should not be in the graph, and therefore
  8668  // not execute.
  8669  func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) {
  8670  	m := testModule(t, "apply-targeted-module-unrelated-outputs")
  8671  	p := testProvider("aws")
  8672  	p.ApplyFn = testApplyFn
  8673  	p.DiffFn = testDiffFn
  8674  	ctx := testContext2(t, &ContextOpts{
  8675  		Config: m,
  8676  		ProviderResolver: providers.ResolverFixed(
  8677  			map[string]providers.Factory{
  8678  				"aws": testProviderFuncFixed(p),
  8679  			},
  8680  		),
  8681  		Targets: []addrs.Targetable{
  8682  			addrs.RootModuleInstance.Child("child2", addrs.NoKey),
  8683  		},
  8684  		State: MustShimLegacyState(&State{
  8685  			Modules: []*ModuleState{
  8686  				{
  8687  					Path:      []string{"root"},
  8688  					Outputs:   map[string]*OutputState{},
  8689  					Resources: map[string]*ResourceState{},
  8690  				},
  8691  				{
  8692  					Path: []string{"root", "child1"},
  8693  					Outputs: map[string]*OutputState{
  8694  						"instance_id": {
  8695  							Type:  "string",
  8696  							Value: "foo-bar-baz",
  8697  						},
  8698  					},
  8699  					Resources: map[string]*ResourceState{},
  8700  				},
  8701  				{
  8702  					Path:      []string{"root", "child2"},
  8703  					Outputs:   map[string]*OutputState{},
  8704  					Resources: map[string]*ResourceState{},
  8705  				},
  8706  			},
  8707  		}),
  8708  	})
  8709  
  8710  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8711  		t.Fatalf("plan errors: %s", diags.Err())
  8712  	}
  8713  
  8714  	state, diags := ctx.Apply()
  8715  	if diags.HasErrors() {
  8716  		t.Fatalf("diags: %s", diags.Err())
  8717  	}
  8718  
  8719  	// - module.child1's instance_id output is dropped because we don't preserve
  8720  	//   non-root module outputs between runs (they can be recalculated from config)
  8721  	// - module.child2's instance_id is updated because its dependency is updated
  8722  	// - child2_id is updated because if its transitive dependency via module.child2
  8723  	checkStateString(t, state, `
  8724  <no state>
  8725  Outputs:
  8726  
  8727  child2_id = foo
  8728  
  8729  module.child2:
  8730    aws_instance.foo:
  8731      ID = foo
  8732      provider = provider.aws
  8733  
  8734    Outputs:
  8735  
  8736    instance_id = foo
  8737  `)
  8738  }
  8739  
  8740  func TestContext2Apply_targetedModuleResource(t *testing.T) {
  8741  	m := testModule(t, "apply-targeted-module-resource")
  8742  	p := testProvider("aws")
  8743  	p.ApplyFn = testApplyFn
  8744  	p.DiffFn = testDiffFn
  8745  	ctx := testContext2(t, &ContextOpts{
  8746  		Config: m,
  8747  		ProviderResolver: providers.ResolverFixed(
  8748  			map[string]providers.Factory{
  8749  				"aws": testProviderFuncFixed(p),
  8750  			},
  8751  		),
  8752  		Targets: []addrs.Targetable{
  8753  			addrs.RootModuleInstance.Child("child", addrs.NoKey).Resource(
  8754  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8755  			),
  8756  		},
  8757  	})
  8758  
  8759  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8760  		t.Fatalf("plan errors: %s", diags.Err())
  8761  	}
  8762  
  8763  	state, diags := ctx.Apply()
  8764  	if diags.HasErrors() {
  8765  		t.Fatalf("diags: %s", diags.Err())
  8766  	}
  8767  
  8768  	mod := state.Module(addrs.RootModuleInstance.Child("child", addrs.NoKey))
  8769  	if mod == nil || len(mod.Resources) != 1 {
  8770  		t.Fatalf("expected 1 resource, got: %#v", mod)
  8771  	}
  8772  
  8773  	checkStateString(t, state, `
  8774  <no state>
  8775  module.child:
  8776    aws_instance.foo:
  8777      ID = foo
  8778      provider = provider.aws
  8779      num = 2
  8780      type = aws_instance
  8781  	`)
  8782  }
  8783  
  8784  func TestContext2Apply_targetedResourceOrphanModule(t *testing.T) {
  8785  	m := testModule(t, "apply-targeted-resource-orphan-module")
  8786  	p := testProvider("aws")
  8787  	p.ApplyFn = testApplyFn
  8788  	p.DiffFn = testDiffFn
  8789  
  8790  	// Create a state with an orphan module
  8791  	state := MustShimLegacyState(&State{
  8792  		Modules: []*ModuleState{
  8793  			{
  8794  				Path: []string{"root", "child"},
  8795  				Resources: map[string]*ResourceState{
  8796  					"aws_instance.bar": {
  8797  						Type:     "aws_instance",
  8798  						Primary:  &InstanceState{},
  8799  						Provider: "provider.aws",
  8800  					},
  8801  				},
  8802  			},
  8803  		},
  8804  	})
  8805  
  8806  	ctx := testContext2(t, &ContextOpts{
  8807  		Config: m,
  8808  		ProviderResolver: providers.ResolverFixed(
  8809  			map[string]providers.Factory{
  8810  				"aws": testProviderFuncFixed(p),
  8811  			},
  8812  		),
  8813  		State: state,
  8814  		Targets: []addrs.Targetable{
  8815  			addrs.RootModuleInstance.Resource(
  8816  				addrs.ManagedResourceMode, "aws_instance", "foo",
  8817  			),
  8818  		},
  8819  	})
  8820  
  8821  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8822  		t.Fatalf("plan errors: %s", diags.Err())
  8823  	}
  8824  
  8825  	if _, diags := ctx.Apply(); diags.HasErrors() {
  8826  		t.Fatalf("apply errors: %s", diags.Err())
  8827  	}
  8828  }
  8829  
  8830  func TestContext2Apply_unknownAttribute(t *testing.T) {
  8831  	m := testModule(t, "apply-unknown")
  8832  	p := testProvider("aws")
  8833  	p.ApplyFn = testApplyFn
  8834  	p.DiffFn = testDiffFn
  8835  	ctx := testContext2(t, &ContextOpts{
  8836  		Config: m,
  8837  		ProviderResolver: providers.ResolverFixed(
  8838  			map[string]providers.Factory{
  8839  				"aws": testProviderFuncFixed(p),
  8840  			},
  8841  		),
  8842  	})
  8843  
  8844  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8845  		t.Fatalf("plan errors: %s", diags.Err())
  8846  	}
  8847  
  8848  	state, diags := ctx.Apply()
  8849  	if !diags.HasErrors() {
  8850  		t.Error("should error, because attribute 'unknown' is still unknown after apply")
  8851  	}
  8852  
  8853  	actual := strings.TrimSpace(state.String())
  8854  	expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr)
  8855  	if actual != expected {
  8856  		t.Fatalf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  8857  	}
  8858  }
  8859  
  8860  func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) {
  8861  	m := testModule(t, "apply-unknown-interpolate")
  8862  	p := testProvider("aws")
  8863  	p.ApplyFn = testApplyFn
  8864  	p.DiffFn = testDiffFn
  8865  	ctx := testContext2(t, &ContextOpts{
  8866  		Config: m,
  8867  		ProviderResolver: providers.ResolverFixed(
  8868  			map[string]providers.Factory{
  8869  				"aws": testProviderFuncFixed(p),
  8870  			},
  8871  		),
  8872  	})
  8873  
  8874  	if _, diags := ctx.Plan(); diags == nil {
  8875  		t.Fatal("should error")
  8876  	}
  8877  }
  8878  
  8879  func TestContext2Apply_vars(t *testing.T) {
  8880  	fixture := contextFixtureApplyVars(t)
  8881  	opts := fixture.ContextOpts()
  8882  	opts.Variables = InputValues{
  8883  		"foo": &InputValue{
  8884  			Value:      cty.StringVal("us-east-1"),
  8885  			SourceType: ValueFromCaller,
  8886  		},
  8887  		"test_list": &InputValue{
  8888  			Value: cty.ListVal([]cty.Value{
  8889  				cty.StringVal("Hello"),
  8890  				cty.StringVal("World"),
  8891  			}),
  8892  			SourceType: ValueFromCaller,
  8893  		},
  8894  		"test_map": &InputValue{
  8895  			Value: cty.MapVal(map[string]cty.Value{
  8896  				"Hello": cty.StringVal("World"),
  8897  				"Foo":   cty.StringVal("Bar"),
  8898  				"Baz":   cty.StringVal("Foo"),
  8899  			}),
  8900  			SourceType: ValueFromCaller,
  8901  		},
  8902  		"amis": &InputValue{
  8903  			Value: cty.MapVal(map[string]cty.Value{
  8904  				"us-east-1": cty.StringVal("override"),
  8905  			}),
  8906  			SourceType: ValueFromCaller,
  8907  		},
  8908  	}
  8909  	ctx := testContext2(t, opts)
  8910  
  8911  	diags := ctx.Validate()
  8912  	if len(diags) != 0 {
  8913  		t.Fatalf("bad: %s", diags.ErrWithWarnings())
  8914  	}
  8915  
  8916  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8917  		t.Fatalf("err: %s", diags.Err())
  8918  	}
  8919  
  8920  	state, diags := ctx.Apply()
  8921  	if diags.HasErrors() {
  8922  		t.Fatalf("err: %s", diags.Err())
  8923  	}
  8924  
  8925  	got := strings.TrimSpace(state.String())
  8926  	want := strings.TrimSpace(testTerraformApplyVarsStr)
  8927  	if got != want {
  8928  		t.Errorf("wrong result\n\ngot:\n%s\n\nwant:\n%s", got, want)
  8929  	}
  8930  }
  8931  
  8932  func TestContext2Apply_varsEnv(t *testing.T) {
  8933  	fixture := contextFixtureApplyVarsEnv(t)
  8934  	opts := fixture.ContextOpts()
  8935  	opts.Variables = InputValues{
  8936  		"string": &InputValue{
  8937  			Value:      cty.StringVal("baz"),
  8938  			SourceType: ValueFromEnvVar,
  8939  		},
  8940  		"list": &InputValue{
  8941  			Value: cty.ListVal([]cty.Value{
  8942  				cty.StringVal("Hello"),
  8943  				cty.StringVal("World"),
  8944  			}),
  8945  			SourceType: ValueFromEnvVar,
  8946  		},
  8947  		"map": &InputValue{
  8948  			Value: cty.MapVal(map[string]cty.Value{
  8949  				"Hello": cty.StringVal("World"),
  8950  				"Foo":   cty.StringVal("Bar"),
  8951  				"Baz":   cty.StringVal("Foo"),
  8952  			}),
  8953  			SourceType: ValueFromEnvVar,
  8954  		},
  8955  	}
  8956  	ctx := testContext2(t, opts)
  8957  
  8958  	diags := ctx.Validate()
  8959  	if len(diags) != 0 {
  8960  		t.Fatalf("bad: %s", diags.ErrWithWarnings())
  8961  	}
  8962  
  8963  	if _, diags := ctx.Plan(); diags.HasErrors() {
  8964  		t.Fatalf("err: %s", diags.Err())
  8965  	}
  8966  
  8967  	state, diags := ctx.Apply()
  8968  	if diags.HasErrors() {
  8969  		t.Fatalf("err: %s", diags.Err())
  8970  	}
  8971  
  8972  	actual := strings.TrimSpace(state.String())
  8973  	expected := strings.TrimSpace(testTerraformApplyVarsEnvStr)
  8974  	if actual != expected {
  8975  		t.Errorf("wrong result\n\ngot:\n%s\n\nwant:\n%s", actual, expected)
  8976  	}
  8977  }
  8978  
  8979  func TestContext2Apply_createBefore_depends(t *testing.T) {
  8980  	m := testModule(t, "apply-depends-create-before")
  8981  	h := new(HookRecordApplyOrder)
  8982  	p := testProvider("aws")
  8983  	p.ApplyFn = testApplyFn
  8984  	p.DiffFn = testDiffFn
  8985  	state := MustShimLegacyState(&State{
  8986  		Modules: []*ModuleState{
  8987  			{
  8988  				Path: rootModulePath,
  8989  				Resources: map[string]*ResourceState{
  8990  					"aws_instance.web": {
  8991  						Type: "aws_instance",
  8992  						Primary: &InstanceState{
  8993  							ID: "bar",
  8994  							Attributes: map[string]string{
  8995  								"require_new": "ami-old",
  8996  							},
  8997  						},
  8998  					},
  8999  					"aws_instance.lb": {
  9000  						Type: "aws_instance",
  9001  						Primary: &InstanceState{
  9002  							ID: "baz",
  9003  							Attributes: map[string]string{
  9004  								"instance": "bar",
  9005  							},
  9006  						},
  9007  					},
  9008  				},
  9009  			},
  9010  		},
  9011  	})
  9012  	ctx := testContext2(t, &ContextOpts{
  9013  		Config: m,
  9014  		Hooks:  []Hook{h},
  9015  		ProviderResolver: providers.ResolverFixed(
  9016  			map[string]providers.Factory{
  9017  				"aws": testProviderFuncFixed(p),
  9018  			},
  9019  		),
  9020  		State: state,
  9021  	})
  9022  
  9023  	if p, diags := ctx.Plan(); diags.HasErrors() {
  9024  		logDiagnostics(t, diags)
  9025  		t.Fatal("plan failed")
  9026  	} else {
  9027  		t.Logf("plan:\n%s", legacyDiffComparisonString(p.Changes))
  9028  	}
  9029  
  9030  	h.Active = true
  9031  	state, diags := ctx.Apply()
  9032  	if diags.HasErrors() {
  9033  		logDiagnostics(t, diags)
  9034  		t.Fatal("apply failed")
  9035  	}
  9036  
  9037  	mod := state.RootModule()
  9038  	if len(mod.Resources) < 2 {
  9039  		t.Logf("state after apply:\n%s", state.String())
  9040  		t.Fatalf("only %d resources in root module; want at least 2", len(mod.Resources))
  9041  	}
  9042  
  9043  	got := strings.TrimSpace(state.String())
  9044  	want := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr)
  9045  	if got != want {
  9046  		t.Fatalf("wrong final state\ngot:\n%s\n\nwant:\n%s", got, want)
  9047  	}
  9048  
  9049  	// Test that things were managed _in the right order_
  9050  	order := h.States
  9051  	diffs := h.Diffs
  9052  	if !order[0].IsNull() || diffs[0].Action == plans.Delete {
  9053  		t.Fatalf("should create new instance first: %#v", order)
  9054  	}
  9055  
  9056  	if order[1].GetAttr("id").AsString() != "baz" {
  9057  		t.Fatalf("update must happen after create: %#v", order)
  9058  	}
  9059  
  9060  	if order[2].GetAttr("id").AsString() != "bar" || diffs[2].Action != plans.Delete {
  9061  		t.Fatalf("destroy must happen after update: %#v", order)
  9062  	}
  9063  }
  9064  
  9065  func TestContext2Apply_singleDestroy(t *testing.T) {
  9066  	m := testModule(t, "apply-depends-create-before")
  9067  	h := new(HookRecordApplyOrder)
  9068  	p := testProvider("aws")
  9069  	invokeCount := 0
  9070  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  9071  		invokeCount++
  9072  		switch invokeCount {
  9073  		case 1:
  9074  			if d.Destroy {
  9075  				t.Fatalf("should not destroy")
  9076  			}
  9077  			if s.ID != "" {
  9078  				t.Fatalf("should not have ID")
  9079  			}
  9080  		case 2:
  9081  			if d.Destroy {
  9082  				t.Fatalf("should not destroy")
  9083  			}
  9084  			if s.ID != "baz" {
  9085  				t.Fatalf("should have id")
  9086  			}
  9087  		case 3:
  9088  			if !d.Destroy {
  9089  				t.Fatalf("should destroy")
  9090  			}
  9091  			if s.ID == "" {
  9092  				t.Fatalf("should have ID")
  9093  			}
  9094  		default:
  9095  			t.Fatalf("bad invoke count %d", invokeCount)
  9096  		}
  9097  		return testApplyFn(info, s, d)
  9098  	}
  9099  	p.DiffFn = testDiffFn
  9100  	state := MustShimLegacyState(&State{
  9101  		Modules: []*ModuleState{
  9102  			{
  9103  				Path: rootModulePath,
  9104  				Resources: map[string]*ResourceState{
  9105  					"aws_instance.web": {
  9106  						Type: "aws_instance",
  9107  						Primary: &InstanceState{
  9108  							ID: "bar",
  9109  							Attributes: map[string]string{
  9110  								"require_new": "ami-old",
  9111  							},
  9112  						},
  9113  					},
  9114  					"aws_instance.lb": {
  9115  						Type: "aws_instance",
  9116  						Primary: &InstanceState{
  9117  							ID: "baz",
  9118  							Attributes: map[string]string{
  9119  								"instance": "bar",
  9120  							},
  9121  						},
  9122  					},
  9123  				},
  9124  			},
  9125  		},
  9126  	})
  9127  	ctx := testContext2(t, &ContextOpts{
  9128  		Config: m,
  9129  		Hooks:  []Hook{h},
  9130  		ProviderResolver: providers.ResolverFixed(
  9131  			map[string]providers.Factory{
  9132  				"aws": testProviderFuncFixed(p),
  9133  			},
  9134  		),
  9135  		State: state,
  9136  	})
  9137  
  9138  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9139  		t.Fatalf("plan errors: %s", diags.Err())
  9140  	}
  9141  
  9142  	h.Active = true
  9143  	state, diags := ctx.Apply()
  9144  	if diags.HasErrors() {
  9145  		t.Fatalf("diags: %s", diags.Err())
  9146  	}
  9147  
  9148  	if invokeCount != 3 {
  9149  		t.Fatalf("bad: %d", invokeCount)
  9150  	}
  9151  }
  9152  
  9153  // GH-7824
  9154  func TestContext2Apply_issue7824(t *testing.T) {
  9155  	p := testProvider("template")
  9156  	p.ApplyFn = testApplyFn
  9157  	p.DiffFn = testDiffFn
  9158  	p.GetSchemaReturn = &ProviderSchema{
  9159  		ResourceTypes: map[string]*configschema.Block{
  9160  			"template_file": {
  9161  				Attributes: map[string]*configschema.Attribute{
  9162  					"template":                {Type: cty.String, Optional: true},
  9163  					"__template_requires_new": {Type: cty.Bool, Optional: true},
  9164  				},
  9165  			},
  9166  		},
  9167  	}
  9168  
  9169  	m, snap := testModuleWithSnapshot(t, "issue-7824")
  9170  
  9171  	// Apply cleanly step 0
  9172  	ctx := testContext2(t, &ContextOpts{
  9173  		Config: m,
  9174  		ProviderResolver: providers.ResolverFixed(
  9175  			map[string]providers.Factory{
  9176  				"template": testProviderFuncFixed(p),
  9177  			},
  9178  		),
  9179  	})
  9180  
  9181  	plan, diags := ctx.Plan()
  9182  	if diags.HasErrors() {
  9183  		t.Fatalf("err: %s", diags.Err())
  9184  	}
  9185  
  9186  	// Write / Read plan to simulate running it through a Plan file
  9187  	ctxOpts, err := contextOptsForPlanViaFile(snap, ctx.State(), plan)
  9188  	if err != nil {
  9189  		t.Fatalf("failed to round-trip through planfile: %s", err)
  9190  	}
  9191  
  9192  	ctxOpts.ProviderResolver = providers.ResolverFixed(
  9193  		map[string]providers.Factory{
  9194  			"template": testProviderFuncFixed(p),
  9195  		},
  9196  	)
  9197  	ctx, diags = NewContext(ctxOpts)
  9198  	if diags.HasErrors() {
  9199  		t.Fatalf("err: %s", diags.Err())
  9200  	}
  9201  
  9202  	_, diags = ctx.Apply()
  9203  	if diags.HasErrors() {
  9204  		t.Fatalf("err: %s", diags.Err())
  9205  	}
  9206  }
  9207  
  9208  // This deals with the situation where a splat expression is used referring
  9209  // to another resource whose count is non-constant.
  9210  func TestContext2Apply_issue5254(t *testing.T) {
  9211  	// Create a provider. We use "template" here just to match the repro
  9212  	// we got from the issue itself.
  9213  	p := testProvider("template")
  9214  	p.ApplyFn = testApplyFn
  9215  	p.DiffFn = testDiffFn
  9216  	p.GetSchemaReturn = &ProviderSchema{
  9217  		ResourceTypes: map[string]*configschema.Block{
  9218  			"template_file": {
  9219  				Attributes: map[string]*configschema.Attribute{
  9220  					"template":                {Type: cty.String, Optional: true},
  9221  					"__template_requires_new": {Type: cty.Bool, Optional: true},
  9222  					"id":                      {Type: cty.String, Computed: true},
  9223  					"type":                    {Type: cty.String, Computed: true},
  9224  				},
  9225  			},
  9226  		},
  9227  	}
  9228  
  9229  	// Apply cleanly step 0
  9230  	ctx := testContext2(t, &ContextOpts{
  9231  		Config: testModule(t, "issue-5254/step-0"),
  9232  		ProviderResolver: providers.ResolverFixed(
  9233  			map[string]providers.Factory{
  9234  				"template": testProviderFuncFixed(p),
  9235  			},
  9236  		),
  9237  	})
  9238  
  9239  	plan, diags := ctx.Plan()
  9240  	if diags.HasErrors() {
  9241  		t.Fatalf("err: %s", diags.Err())
  9242  	}
  9243  
  9244  	state, diags := ctx.Apply()
  9245  	if diags.HasErrors() {
  9246  		t.Fatalf("err: %s", diags.Err())
  9247  	}
  9248  
  9249  	m, snap := testModuleWithSnapshot(t, "issue-5254/step-1")
  9250  
  9251  	// Application success. Now make the modification and store a plan
  9252  	ctx = testContext2(t, &ContextOpts{
  9253  		Config: m,
  9254  		State:  state,
  9255  		ProviderResolver: providers.ResolverFixed(
  9256  			map[string]providers.Factory{
  9257  				"template": testProviderFuncFixed(p),
  9258  			},
  9259  		),
  9260  	})
  9261  
  9262  	plan, diags = ctx.Plan()
  9263  	if diags.HasErrors() {
  9264  		t.Fatalf("err: %s", diags.Err())
  9265  	}
  9266  
  9267  	// Write / Read plan to simulate running it through a Plan file
  9268  	ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  9269  	if err != nil {
  9270  		t.Fatalf("failed to round-trip through planfile: %s", err)
  9271  	}
  9272  
  9273  	ctxOpts.ProviderResolver = providers.ResolverFixed(
  9274  		map[string]providers.Factory{
  9275  			"template": testProviderFuncFixed(p),
  9276  		},
  9277  	)
  9278  	ctx, diags = NewContext(ctxOpts)
  9279  	if diags.HasErrors() {
  9280  		t.Fatalf("err: %s", diags.Err())
  9281  	}
  9282  
  9283  	state, diags = ctx.Apply()
  9284  	if diags.HasErrors() {
  9285  		t.Fatalf("err: %s", diags.Err())
  9286  	}
  9287  
  9288  	actual := strings.TrimSpace(state.String())
  9289  	expected := strings.TrimSpace(`
  9290  template_file.child:
  9291    ID = foo
  9292    provider = provider.template
  9293    __template_requires_new = true
  9294    template = Hi
  9295    type = template_file
  9296  
  9297    Dependencies:
  9298      template_file.parent
  9299  template_file.parent.0:
  9300    ID = foo
  9301    provider = provider.template
  9302    template = Hi
  9303    type = template_file
  9304  `)
  9305  	if actual != expected {
  9306  		t.Fatalf("wrong final state\ngot:\n%s\n\nwant:\n%s", actual, expected)
  9307  	}
  9308  }
  9309  
  9310  func TestContext2Apply_targetedWithTaintedInState(t *testing.T) {
  9311  	p := testProvider("aws")
  9312  	p.DiffFn = testDiffFn
  9313  	p.ApplyFn = testApplyFn
  9314  	m, snap := testModuleWithSnapshot(t, "apply-tainted-targets")
  9315  	ctx := testContext2(t, &ContextOpts{
  9316  		Config: m,
  9317  		ProviderResolver: providers.ResolverFixed(
  9318  			map[string]providers.Factory{
  9319  				"aws": testProviderFuncFixed(p),
  9320  			},
  9321  		),
  9322  		Targets: []addrs.Targetable{
  9323  			addrs.RootModuleInstance.Resource(
  9324  				addrs.ManagedResourceMode, "aws_instance", "iambeingadded",
  9325  			),
  9326  		},
  9327  		State: MustShimLegacyState(&State{
  9328  			Modules: []*ModuleState{
  9329  				{
  9330  					Path: rootModulePath,
  9331  					Resources: map[string]*ResourceState{
  9332  						"aws_instance.ifailedprovisioners": {
  9333  							Type: "aws_instance",
  9334  							Primary: &InstanceState{
  9335  								ID:      "ifailedprovisioners",
  9336  								Tainted: true,
  9337  							},
  9338  						},
  9339  					},
  9340  				},
  9341  			},
  9342  		}),
  9343  	})
  9344  
  9345  	plan, diags := ctx.Plan()
  9346  	if diags.HasErrors() {
  9347  		t.Fatalf("err: %s", diags.Err())
  9348  	}
  9349  
  9350  	// Write / Read plan to simulate running it through a Plan file
  9351  	ctxOpts, err := contextOptsForPlanViaFile(snap, ctx.State(), plan)
  9352  	if err != nil {
  9353  		t.Fatalf("failed to round-trip through planfile: %s", err)
  9354  	}
  9355  
  9356  	ctxOpts.ProviderResolver = providers.ResolverFixed(
  9357  		map[string]providers.Factory{
  9358  			"aws": testProviderFuncFixed(p),
  9359  		},
  9360  	)
  9361  	ctx, diags = NewContext(ctxOpts)
  9362  	if diags.HasErrors() {
  9363  		t.Fatalf("err: %s", diags.Err())
  9364  	}
  9365  
  9366  	state, diags := ctx.Apply()
  9367  	if diags.HasErrors() {
  9368  		t.Fatalf("err: %s", diags.Err())
  9369  	}
  9370  
  9371  	actual := strings.TrimSpace(state.String())
  9372  	expected := strings.TrimSpace(`
  9373  aws_instance.iambeingadded:
  9374    ID = foo
  9375    provider = provider.aws
  9376  aws_instance.ifailedprovisioners: (tainted)
  9377    ID = ifailedprovisioners
  9378    provider = provider.aws
  9379  		`)
  9380  	if actual != expected {
  9381  		t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual)
  9382  	}
  9383  }
  9384  
  9385  // Higher level test exposing the bug this covers in
  9386  // TestResource_ignoreChangesRequired
  9387  func TestContext2Apply_ignoreChangesCreate(t *testing.T) {
  9388  	m := testModule(t, "apply-ignore-changes-create")
  9389  	p := testProvider("aws")
  9390  	p.ApplyFn = testApplyFn
  9391  	p.DiffFn = testDiffFn
  9392  
  9393  	instanceSchema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
  9394  	instanceSchema.Attributes["required_field"] = &configschema.Attribute{
  9395  		Type:     cty.String,
  9396  		Required: true,
  9397  	}
  9398  
  9399  	ctx := testContext2(t, &ContextOpts{
  9400  		Config: m,
  9401  		ProviderResolver: providers.ResolverFixed(
  9402  			map[string]providers.Factory{
  9403  				"aws": testProviderFuncFixed(p),
  9404  			},
  9405  		),
  9406  	})
  9407  
  9408  	if p, diags := ctx.Plan(); diags.HasErrors() {
  9409  		t.Fatalf("diags: %s", diags.Err())
  9410  	} else {
  9411  		t.Logf(legacyDiffComparisonString(p.Changes))
  9412  	}
  9413  
  9414  	state, diags := ctx.Apply()
  9415  	if diags.HasErrors() {
  9416  		t.Fatalf("diags: %s", diags.Err())
  9417  	}
  9418  
  9419  	mod := state.RootModule()
  9420  	if len(mod.Resources) != 1 {
  9421  		t.Fatalf("bad: %s", state)
  9422  	}
  9423  
  9424  	actual := strings.TrimSpace(state.String())
  9425  	// Expect no changes from original state
  9426  	expected := strings.TrimSpace(`
  9427  aws_instance.foo:
  9428    ID = foo
  9429    provider = provider.aws
  9430    required_field = set
  9431    type = aws_instance
  9432  `)
  9433  	if actual != expected {
  9434  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
  9435  	}
  9436  }
  9437  
  9438  func TestContext2Apply_ignoreChangesWithDep(t *testing.T) {
  9439  	m := testModule(t, "apply-ignore-changes-dep")
  9440  	p := testProvider("aws")
  9441  	p.ApplyFn = testApplyFn
  9442  
  9443  	p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  9444  		switch i.Type {
  9445  		case "aws_instance":
  9446  			newAmi, _ := c.Get("ami")
  9447  			return &InstanceDiff{
  9448  				Attributes: map[string]*ResourceAttrDiff{
  9449  					"ami": {
  9450  						Old:         s.Attributes["ami"],
  9451  						New:         newAmi.(string),
  9452  						RequiresNew: true,
  9453  					},
  9454  				},
  9455  			}, nil
  9456  		case "aws_eip":
  9457  			return testDiffFn(i, s, c)
  9458  		default:
  9459  			t.Fatalf("Unexpected type: %s", i.Type)
  9460  			return nil, nil
  9461  		}
  9462  	}
  9463  	s := MustShimLegacyState(&State{
  9464  		Modules: []*ModuleState{
  9465  			{
  9466  				Path: rootModulePath,
  9467  				Resources: map[string]*ResourceState{
  9468  					"aws_instance.foo.0": {
  9469  						Type: "aws_instance",
  9470  						Primary: &InstanceState{
  9471  							ID: "i-abc123",
  9472  							Attributes: map[string]string{
  9473  								"ami": "ami-abcd1234",
  9474  								"id":  "i-abc123",
  9475  							},
  9476  						},
  9477  					},
  9478  					"aws_instance.foo.1": {
  9479  						Type: "aws_instance",
  9480  						Primary: &InstanceState{
  9481  							ID: "i-bcd234",
  9482  							Attributes: map[string]string{
  9483  								"ami": "ami-abcd1234",
  9484  								"id":  "i-bcd234",
  9485  							},
  9486  						},
  9487  					},
  9488  					"aws_eip.foo.0": {
  9489  						Type: "aws_eip",
  9490  						Primary: &InstanceState{
  9491  							ID: "eip-abc123",
  9492  							Attributes: map[string]string{
  9493  								"id":       "eip-abc123",
  9494  								"instance": "i-abc123",
  9495  							},
  9496  						},
  9497  					},
  9498  					"aws_eip.foo.1": {
  9499  						Type: "aws_eip",
  9500  						Primary: &InstanceState{
  9501  							ID: "eip-bcd234",
  9502  							Attributes: map[string]string{
  9503  								"id":       "eip-bcd234",
  9504  								"instance": "i-bcd234",
  9505  							},
  9506  						},
  9507  					},
  9508  				},
  9509  			},
  9510  		},
  9511  	})
  9512  	ctx := testContext2(t, &ContextOpts{
  9513  		Config: m,
  9514  		ProviderResolver: providers.ResolverFixed(
  9515  			map[string]providers.Factory{
  9516  				"aws": testProviderFuncFixed(p),
  9517  			},
  9518  		),
  9519  		State: s,
  9520  	})
  9521  
  9522  	_, diags := ctx.Plan()
  9523  	assertNoErrors(t, diags)
  9524  
  9525  	state, diags := ctx.Apply()
  9526  	assertNoErrors(t, diags)
  9527  
  9528  	actual := strings.TrimSpace(state.String())
  9529  	expected := strings.TrimSpace(s.String())
  9530  	if actual != expected {
  9531  		t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual)
  9532  	}
  9533  }
  9534  
  9535  func TestContext2Apply_ignoreChangesWildcard(t *testing.T) {
  9536  	m := testModule(t, "apply-ignore-changes-wildcard")
  9537  	p := testProvider("aws")
  9538  	p.ApplyFn = testApplyFn
  9539  	p.DiffFn = testDiffFn
  9540  
  9541  	instanceSchema := p.GetSchemaReturn.ResourceTypes["aws_instance"]
  9542  	instanceSchema.Attributes["required_field"] = &configschema.Attribute{
  9543  		Type:     cty.String,
  9544  		Required: true,
  9545  	}
  9546  
  9547  	ctx := testContext2(t, &ContextOpts{
  9548  		Config: m,
  9549  		ProviderResolver: providers.ResolverFixed(
  9550  			map[string]providers.Factory{
  9551  				"aws": testProviderFuncFixed(p),
  9552  			},
  9553  		),
  9554  	})
  9555  
  9556  	if p, diags := ctx.Plan(); diags.HasErrors() {
  9557  		logDiagnostics(t, diags)
  9558  		t.Fatal("plan failed")
  9559  	} else {
  9560  		t.Logf(legacyDiffComparisonString(p.Changes))
  9561  	}
  9562  
  9563  	state, diags := ctx.Apply()
  9564  	assertNoErrors(t, diags)
  9565  
  9566  	mod := state.RootModule()
  9567  	if len(mod.Resources) != 1 {
  9568  		t.Fatalf("bad: %s", state)
  9569  	}
  9570  
  9571  	actual := strings.TrimSpace(state.String())
  9572  	// Expect no changes from original state
  9573  	expected := strings.TrimSpace(`
  9574  aws_instance.foo:
  9575    ID = foo
  9576    provider = provider.aws
  9577    required_field = set
  9578    type = aws_instance
  9579  `)
  9580  	if actual != expected {
  9581  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual)
  9582  	}
  9583  }
  9584  
  9585  // https://github.com/hashicorp/terraform-plugin-sdk/issues/7378
  9586  func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) {
  9587  	m, snap := testModuleWithSnapshot(t, "apply-destroy-nested-module-with-attrs")
  9588  	p := testProvider("null")
  9589  	p.ApplyFn = testApplyFn
  9590  	p.DiffFn = testDiffFn
  9591  
  9592  	var state *states.State
  9593  	var diags tfdiags.Diagnostics
  9594  	{
  9595  		ctx := testContext2(t, &ContextOpts{
  9596  			Config: m,
  9597  			ProviderResolver: providers.ResolverFixed(
  9598  				map[string]providers.Factory{
  9599  					"null": testProviderFuncFixed(p),
  9600  				},
  9601  			),
  9602  		})
  9603  
  9604  		// First plan and apply a create operation
  9605  		if _, diags := ctx.Plan(); diags.HasErrors() {
  9606  			t.Fatalf("plan err: %s", diags.Err())
  9607  		}
  9608  
  9609  		state, diags = ctx.Apply()
  9610  		if diags.HasErrors() {
  9611  			t.Fatalf("apply err: %s", diags.Err())
  9612  		}
  9613  	}
  9614  
  9615  	{
  9616  		ctx := testContext2(t, &ContextOpts{
  9617  			Destroy: true,
  9618  			Config:  m,
  9619  			State:   state,
  9620  			ProviderResolver: providers.ResolverFixed(
  9621  				map[string]providers.Factory{
  9622  					"null": testProviderFuncFixed(p),
  9623  				},
  9624  			),
  9625  		})
  9626  
  9627  		plan, diags := ctx.Plan()
  9628  		if diags.HasErrors() {
  9629  			t.Fatalf("destroy plan err: %s", diags.Err())
  9630  		}
  9631  
  9632  		ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
  9633  		if err != nil {
  9634  			t.Fatalf("failed to round-trip through planfile: %s", err)
  9635  		}
  9636  
  9637  		ctxOpts.ProviderResolver = providers.ResolverFixed(
  9638  			map[string]providers.Factory{
  9639  				"null": testProviderFuncFixed(p),
  9640  			},
  9641  		)
  9642  		ctx, diags = NewContext(ctxOpts)
  9643  		if diags.HasErrors() {
  9644  			t.Fatalf("err: %s", diags.Err())
  9645  		}
  9646  
  9647  		state, diags = ctx.Apply()
  9648  		if diags.HasErrors() {
  9649  			t.Fatalf("destroy apply err: %s", diags.Err())
  9650  		}
  9651  	}
  9652  
  9653  	if !state.Empty() {
  9654  		t.Fatalf("state after apply: %s\nwant empty state", spew.Sdump(state))
  9655  	}
  9656  }
  9657  
  9658  // If a data source explicitly depends on another resource, it's because we need
  9659  // that resource to be applied first.
  9660  func TestContext2Apply_dataDependsOn(t *testing.T) {
  9661  	p := testProvider("null")
  9662  	m := testModule(t, "apply-data-depends-on")
  9663  
  9664  	ctx := testContext2(t, &ContextOpts{
  9665  		Config: m,
  9666  		ProviderResolver: providers.ResolverFixed(
  9667  			map[string]providers.Factory{
  9668  				"null": testProviderFuncFixed(p),
  9669  			},
  9670  		),
  9671  	})
  9672  
  9673  	// the "provisioner" here writes to this variable, because the intent is to
  9674  	// create a dependency which can't be viewed through the graph, and depends
  9675  	// solely on the configuration providing "depends_on"
  9676  	provisionerOutput := ""
  9677  
  9678  	p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) {
  9679  		// the side effect of the resource being applied
  9680  		provisionerOutput = "APPLIED"
  9681  		return testApplyFn(info, s, d)
  9682  	}
  9683  
  9684  	p.DiffFn = testDiffFn
  9685  	p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
  9686  		return providers.ReadDataSourceResponse{
  9687  			State: cty.ObjectVal(map[string]cty.Value{
  9688  				"id":  cty.StringVal("boop"),
  9689  				"foo": cty.StringVal(provisionerOutput),
  9690  			}),
  9691  		}
  9692  	}
  9693  
  9694  	_, diags := ctx.Refresh()
  9695  	assertNoErrors(t, diags)
  9696  
  9697  	_, diags = ctx.Plan()
  9698  	assertNoErrors(t, diags)
  9699  
  9700  	state, diags := ctx.Apply()
  9701  	assertNoErrors(t, diags)
  9702  
  9703  	root := state.Module(addrs.RootModuleInstance)
  9704  	is := root.ResourceInstance(addrs.Resource{
  9705  		Mode: addrs.DataResourceMode,
  9706  		Type: "null_data_source",
  9707  		Name: "read",
  9708  	}.Instance(addrs.NoKey))
  9709  	if is == nil {
  9710  		t.Fatal("data resource instance is not present in state; should be")
  9711  	}
  9712  	var attrs map[string]interface{}
  9713  	err := json.Unmarshal(is.Current.AttrsJSON, &attrs)
  9714  	if err != nil {
  9715  		t.Fatal(err)
  9716  	}
  9717  	actual := attrs["foo"]
  9718  	expected := "APPLIED"
  9719  	if actual != expected {
  9720  		t.Fatalf("bad:\n%s", strings.TrimSpace(state.String()))
  9721  	}
  9722  }
  9723  
  9724  func TestContext2Apply_terraformWorkspace(t *testing.T) {
  9725  	m := testModule(t, "apply-terraform-workspace")
  9726  	p := testProvider("aws")
  9727  	p.ApplyFn = testApplyFn
  9728  	p.DiffFn = testDiffFn
  9729  
  9730  	ctx := testContext2(t, &ContextOpts{
  9731  		Meta:   &ContextMeta{Env: "foo"},
  9732  		Config: m,
  9733  		ProviderResolver: providers.ResolverFixed(
  9734  			map[string]providers.Factory{
  9735  				"aws": testProviderFuncFixed(p),
  9736  			},
  9737  		),
  9738  	})
  9739  
  9740  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9741  		t.Fatalf("plan errors: %s", diags.Err())
  9742  	}
  9743  
  9744  	state, diags := ctx.Apply()
  9745  	if diags.HasErrors() {
  9746  		t.Fatalf("diags: %s", diags.Err())
  9747  	}
  9748  
  9749  	actual := state.RootModule().OutputValues["output"]
  9750  	expected := cty.StringVal("foo")
  9751  	if actual == nil || actual.Value != expected {
  9752  		t.Fatalf("wrong value\ngot:  %#v\nwant: %#v", actual.Value, expected)
  9753  	}
  9754  }
  9755  
  9756  // verify that multiple config references only create a single depends_on entry
  9757  func TestContext2Apply_multiRef(t *testing.T) {
  9758  	m := testModule(t, "apply-multi-ref")
  9759  	p := testProvider("aws")
  9760  	p.ApplyFn = testApplyFn
  9761  	p.DiffFn = testDiffFn
  9762  	ctx := testContext2(t, &ContextOpts{
  9763  		Config: m,
  9764  		ProviderResolver: providers.ResolverFixed(
  9765  			map[string]providers.Factory{
  9766  				"aws": testProviderFuncFixed(p),
  9767  			},
  9768  		),
  9769  	})
  9770  
  9771  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9772  		t.Fatalf("err: %s", diags.Err())
  9773  	}
  9774  
  9775  	state, diags := ctx.Apply()
  9776  	if diags.HasErrors() {
  9777  		t.Fatalf("err: %s", diags.Err())
  9778  	}
  9779  
  9780  	deps := state.Modules[""].Resources["aws_instance.other"].Instances[addrs.NoKey].Current.Dependencies
  9781  	if len(deps) != 1 || deps[0].String() != "aws_instance.create" {
  9782  		t.Fatalf("expected 1 depends_on entry for aws_instance.create, got %q", deps)
  9783  	}
  9784  }
  9785  
  9786  func TestContext2Apply_targetedModuleRecursive(t *testing.T) {
  9787  	m := testModule(t, "apply-targeted-module-recursive")
  9788  	p := testProvider("aws")
  9789  	p.ApplyFn = testApplyFn
  9790  	p.DiffFn = testDiffFn
  9791  	ctx := testContext2(t, &ContextOpts{
  9792  		Config: m,
  9793  		ProviderResolver: providers.ResolverFixed(
  9794  			map[string]providers.Factory{
  9795  				"aws": testProviderFuncFixed(p),
  9796  			},
  9797  		),
  9798  		Targets: []addrs.Targetable{
  9799  			addrs.RootModuleInstance.Child("child", addrs.NoKey),
  9800  		},
  9801  	})
  9802  
  9803  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9804  		t.Fatalf("err: %s", diags.Err())
  9805  	}
  9806  
  9807  	state, diags := ctx.Apply()
  9808  	if diags.HasErrors() {
  9809  		t.Fatalf("err: %s", diags.Err())
  9810  	}
  9811  
  9812  	mod := state.Module(
  9813  		addrs.RootModuleInstance.Child("child", addrs.NoKey).Child("subchild", addrs.NoKey),
  9814  	)
  9815  	if mod == nil {
  9816  		t.Fatalf("no subchild module found in the state!\n\n%#v", state)
  9817  	}
  9818  	if len(mod.Resources) != 1 {
  9819  		t.Fatalf("expected 1 resources, got: %#v", mod.Resources)
  9820  	}
  9821  
  9822  	checkStateString(t, state, `
  9823  <no state>
  9824  module.child.subchild:
  9825    aws_instance.foo:
  9826      ID = foo
  9827      provider = provider.aws
  9828      num = 2
  9829      type = aws_instance
  9830  	`)
  9831  }
  9832  
  9833  func TestContext2Apply_localVal(t *testing.T) {
  9834  	m := testModule(t, "apply-local-val")
  9835  	ctx := testContext2(t, &ContextOpts{
  9836  		Config: m,
  9837  		ProviderResolver: providers.ResolverFixed(
  9838  			map[string]providers.Factory{},
  9839  		),
  9840  	})
  9841  
  9842  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9843  		t.Fatalf("error during plan: %s", diags.Err())
  9844  	}
  9845  
  9846  	state, diags := ctx.Apply()
  9847  	if diags.HasErrors() {
  9848  		t.Fatalf("error during apply: %s", diags.Err())
  9849  	}
  9850  
  9851  	got := strings.TrimSpace(state.String())
  9852  	want := strings.TrimSpace(`
  9853  <no state>
  9854  Outputs:
  9855  
  9856  result_1 = hello
  9857  result_3 = hello world
  9858  
  9859  module.child:
  9860    <no state>
  9861    Outputs:
  9862  
  9863    result = hello
  9864  `)
  9865  	if got != want {
  9866  		t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want)
  9867  	}
  9868  }
  9869  
  9870  func TestContext2Apply_destroyWithLocals(t *testing.T) {
  9871  	m := testModule(t, "apply-destroy-with-locals")
  9872  	p := testProvider("aws")
  9873  	p.ApplyFn = testApplyFn
  9874  	p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) {
  9875  		d, err := testDiffFn(info, s, c)
  9876  		return d, err
  9877  	}
  9878  	s := MustShimLegacyState(&State{
  9879  		Modules: []*ModuleState{
  9880  			{
  9881  				Path: rootModulePath,
  9882  				Outputs: map[string]*OutputState{
  9883  					"name": {
  9884  						Type:  "string",
  9885  						Value: "test-bar",
  9886  					},
  9887  				},
  9888  				Resources: map[string]*ResourceState{
  9889  					"aws_instance.foo": {
  9890  						Type: "aws_instance",
  9891  						Primary: &InstanceState{
  9892  							ID: "foo",
  9893  							// FIXME: id should only exist in one place
  9894  							Attributes: map[string]string{
  9895  								"id": "foo",
  9896  							},
  9897  						},
  9898  						Provider: "provider.aws",
  9899  					},
  9900  				},
  9901  			},
  9902  		},
  9903  	})
  9904  
  9905  	ctx := testContext2(t, &ContextOpts{
  9906  		Config: m,
  9907  		ProviderResolver: providers.ResolverFixed(
  9908  			map[string]providers.Factory{
  9909  				"aws": testProviderFuncFixed(p),
  9910  			},
  9911  		),
  9912  		State:   s,
  9913  		Destroy: true,
  9914  	})
  9915  
  9916  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9917  		t.Fatalf("err: %s", diags.Err())
  9918  	}
  9919  
  9920  	state, diags := ctx.Apply()
  9921  	if diags.HasErrors() {
  9922  		t.Fatalf("error during apply: %s", diags.Err())
  9923  	}
  9924  
  9925  	got := strings.TrimSpace(state.String())
  9926  	want := strings.TrimSpace(`<no state>`)
  9927  	if got != want {
  9928  		t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want)
  9929  	}
  9930  }
  9931  
  9932  func TestContext2Apply_providerWithLocals(t *testing.T) {
  9933  	m := testModule(t, "provider-with-locals")
  9934  	p := testProvider("aws")
  9935  
  9936  	providerRegion := ""
  9937  	// this should not be overridden during destroy
  9938  	p.ConfigureFn = func(c *ResourceConfig) error {
  9939  		if r, ok := c.Get("region"); ok {
  9940  			providerRegion = r.(string)
  9941  		}
  9942  		return nil
  9943  	}
  9944  	p.DiffFn = testDiffFn
  9945  	p.ApplyFn = testApplyFn
  9946  	ctx := testContext2(t, &ContextOpts{
  9947  		Config: m,
  9948  		ProviderResolver: providers.ResolverFixed(
  9949  			map[string]providers.Factory{
  9950  				"aws": testProviderFuncFixed(p),
  9951  			},
  9952  		),
  9953  	})
  9954  
  9955  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9956  		t.Fatalf("err: %s", diags.Err())
  9957  	}
  9958  
  9959  	state, diags := ctx.Apply()
  9960  	if diags.HasErrors() {
  9961  		t.Fatalf("err: %s", diags.Err())
  9962  	}
  9963  
  9964  	ctx = testContext2(t, &ContextOpts{
  9965  		Config: m,
  9966  		ProviderResolver: providers.ResolverFixed(
  9967  			map[string]providers.Factory{
  9968  				"aws": testProviderFuncFixed(p),
  9969  			},
  9970  		),
  9971  		State:   state,
  9972  		Destroy: true,
  9973  	})
  9974  
  9975  	if _, diags := ctx.Plan(); diags.HasErrors() {
  9976  		t.Fatalf("err: %s", diags.Err())
  9977  	}
  9978  
  9979  	state, diags = ctx.Apply()
  9980  	if diags.HasErrors() {
  9981  		t.Fatalf("err: %s", diags.Err())
  9982  	}
  9983  
  9984  	if state.HasResources() {
  9985  		t.Fatal("expected no state, got:", state)
  9986  	}
  9987  
  9988  	if providerRegion != "bar" {
  9989  		t.Fatalf("expected region %q, got: %q", "bar", providerRegion)
  9990  	}
  9991  }
  9992  
  9993  func TestContext2Apply_destroyWithProviders(t *testing.T) {
  9994  	m := testModule(t, "destroy-module-with-provider")
  9995  	p := testProvider("aws")
  9996  	p.ApplyFn = testApplyFn
  9997  	p.DiffFn = testDiffFn
  9998  
  9999  	s := MustShimLegacyState(&State{
 10000  		Modules: []*ModuleState{
 10001  			{
 10002  				Path: rootModulePath,
 10003  			},
 10004  			{
 10005  				Path: []string{"root", "child"},
 10006  			},
 10007  			{
 10008  				Path: []string{"root", "mod", "removed"},
 10009  				Resources: map[string]*ResourceState{
 10010  					"aws_instance.child": {
 10011  						Type: "aws_instance",
 10012  						Primary: &InstanceState{
 10013  							ID: "bar",
 10014  						},
 10015  						// this provider doesn't exist
 10016  						Provider: "provider.aws.baz",
 10017  					},
 10018  				},
 10019  			},
 10020  		},
 10021  	})
 10022  
 10023  	ctx := testContext2(t, &ContextOpts{
 10024  		Config: m,
 10025  		ProviderResolver: providers.ResolverFixed(
 10026  			map[string]providers.Factory{
 10027  				"aws": testProviderFuncFixed(p),
 10028  			},
 10029  		),
 10030  		State:   s,
 10031  		Destroy: true,
 10032  	})
 10033  
 10034  	// test that we can't destroy if the provider is missing
 10035  	if _, diags := ctx.Plan(); diags == nil {
 10036  		t.Fatal("expected plan error, provider.aws.baz doesn't exist")
 10037  	}
 10038  
 10039  	// correct the state
 10040  	s.Modules["module.mod.module.removed"].Resources["aws_instance.child"].ProviderConfig = addrs.ProviderConfig{
 10041  		Type:  "aws",
 10042  		Alias: "bar",
 10043  	}.Absolute(addrs.RootModuleInstance)
 10044  
 10045  	if _, diags := ctx.Plan(); diags.HasErrors() {
 10046  		t.Fatal(diags.Err())
 10047  	}
 10048  	state, diags := ctx.Apply()
 10049  	if diags.HasErrors() {
 10050  		t.Fatalf("error during apply: %s", diags.Err())
 10051  	}
 10052  
 10053  	got := strings.TrimSpace(state.String())
 10054  
 10055  	want := strings.TrimSpace("<no state>")
 10056  	if got != want {
 10057  		t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want)
 10058  	}
 10059  }
 10060  
 10061  func TestContext2Apply_providersFromState(t *testing.T) {
 10062  	m := configs.NewEmptyConfig()
 10063  	p := testProvider("aws")
 10064  	p.DiffFn = testDiffFn
 10065  
 10066  	for _, tc := range []struct {
 10067  		name   string
 10068  		state  *states.State
 10069  		output string
 10070  		err    bool
 10071  	}{
 10072  		{
 10073  			name: "add implicit provider",
 10074  			state: MustShimLegacyState(&State{
 10075  				Modules: []*ModuleState{
 10076  					{
 10077  						Path: []string{"root"},
 10078  						Resources: map[string]*ResourceState{
 10079  							"aws_instance.a": {
 10080  								Type: "aws_instance",
 10081  								Primary: &InstanceState{
 10082  									ID: "bar",
 10083  								},
 10084  								Provider: "provider.aws",
 10085  							},
 10086  						},
 10087  					},
 10088  				},
 10089  			}),
 10090  			err:    false,
 10091  			output: "<no state>",
 10092  		},
 10093  
 10094  		// an aliased provider must be in the config to remove a resource
 10095  		{
 10096  			name: "add aliased provider",
 10097  			state: MustShimLegacyState(&State{
 10098  				Modules: []*ModuleState{
 10099  					{
 10100  						Path: []string{"root"},
 10101  						Resources: map[string]*ResourceState{
 10102  							"aws_instance.a": {
 10103  								Type: "aws_instance",
 10104  								Primary: &InstanceState{
 10105  									ID: "bar",
 10106  								},
 10107  								Provider: "provider.aws.bar",
 10108  							},
 10109  						},
 10110  					},
 10111  				},
 10112  			}),
 10113  			err: true,
 10114  		},
 10115  
 10116  		// a provider in a module implies some sort of config, so this isn't
 10117  		// allowed even without an alias
 10118  		{
 10119  			name: "add unaliased module provider",
 10120  			state: MustShimLegacyState(&State{
 10121  				Modules: []*ModuleState{
 10122  					{
 10123  						Path: []string{"root", "child"},
 10124  						Resources: map[string]*ResourceState{
 10125  							"aws_instance.a": {
 10126  								Type: "aws_instance",
 10127  								Primary: &InstanceState{
 10128  									ID: "bar",
 10129  								},
 10130  								Provider: "module.child.provider.aws",
 10131  							},
 10132  						},
 10133  					},
 10134  				},
 10135  			}),
 10136  			err: true,
 10137  		},
 10138  	} {
 10139  
 10140  		t.Run(tc.name, func(t *testing.T) {
 10141  			ctx := testContext2(t, &ContextOpts{
 10142  				Config: m,
 10143  				ProviderResolver: providers.ResolverFixed(
 10144  					map[string]providers.Factory{
 10145  						"aws": testProviderFuncFixed(p),
 10146  					},
 10147  				),
 10148  				State: tc.state,
 10149  			})
 10150  
 10151  			_, diags := ctx.Plan()
 10152  			if tc.err {
 10153  				if diags == nil {
 10154  					t.Fatal("expected error")
 10155  				} else {
 10156  					return
 10157  				}
 10158  			}
 10159  			if !tc.err && diags.HasErrors() {
 10160  				t.Fatal(diags.Err())
 10161  			}
 10162  
 10163  			state, diags := ctx.Apply()
 10164  			if diags.HasErrors() {
 10165  				t.Fatalf("diags: %s", diags.Err())
 10166  			}
 10167  
 10168  			checkStateString(t, state, "<no state>")
 10169  
 10170  		})
 10171  	}
 10172  }
 10173  
 10174  func TestContext2Apply_plannedInterpolatedCount(t *testing.T) {
 10175  	m, snap := testModuleWithSnapshot(t, "apply-interpolated-count")
 10176  
 10177  	p := testProvider("aws")
 10178  	p.ApplyFn = testApplyFn
 10179  	p.DiffFn = testDiffFn
 10180  
 10181  	providerResolver := providers.ResolverFixed(
 10182  		map[string]providers.Factory{
 10183  			"aws": testProviderFuncFixed(p),
 10184  		},
 10185  	)
 10186  
 10187  	s := MustShimLegacyState(&State{
 10188  		Modules: []*ModuleState{
 10189  			{
 10190  				Path: rootModulePath,
 10191  				Resources: map[string]*ResourceState{
 10192  					"aws_instance.test": {
 10193  						Type: "aws_instance",
 10194  						Primary: &InstanceState{
 10195  							ID: "foo",
 10196  						},
 10197  						Provider: "provider.aws",
 10198  					},
 10199  				},
 10200  			},
 10201  		},
 10202  	})
 10203  
 10204  	ctx := testContext2(t, &ContextOpts{
 10205  		Config:           m,
 10206  		ProviderResolver: providerResolver,
 10207  		State:            s,
 10208  	})
 10209  
 10210  	plan, diags := ctx.Plan()
 10211  	if diags.HasErrors() {
 10212  		t.Fatalf("plan failed: %s", diags.Err())
 10213  	}
 10214  
 10215  	// We'll marshal and unmarshal the plan here, to ensure that we have
 10216  	// a clean new context as would be created if we separately ran
 10217  	// terraform plan -out=tfplan && terraform apply tfplan
 10218  	ctxOpts, err := contextOptsForPlanViaFile(snap, ctx.State(), plan)
 10219  	if err != nil {
 10220  		t.Fatalf("failed to round-trip through planfile: %s", err)
 10221  	}
 10222  
 10223  	ctxOpts.ProviderResolver = providerResolver
 10224  	ctx, diags = NewContext(ctxOpts)
 10225  	if diags.HasErrors() {
 10226  		t.Fatalf("err: %s", diags.Err())
 10227  	}
 10228  
 10229  	// Applying the plan should now succeed
 10230  	_, diags = ctx.Apply()
 10231  	if diags.HasErrors() {
 10232  		t.Fatalf("apply failed: %s", diags.Err())
 10233  	}
 10234  }
 10235  
 10236  func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) {
 10237  	m, snap := testModuleWithSnapshot(t, "plan-destroy-interpolated-count")
 10238  
 10239  	p := testProvider("aws")
 10240  	p.ApplyFn = testApplyFn
 10241  	p.DiffFn = testDiffFn
 10242  
 10243  	providerResolver := providers.ResolverFixed(
 10244  		map[string]providers.Factory{
 10245  			"aws": testProviderFuncFixed(p),
 10246  		},
 10247  	)
 10248  
 10249  	s := MustShimLegacyState(&State{
 10250  		Modules: []*ModuleState{
 10251  			{
 10252  				Path: rootModulePath,
 10253  				Resources: map[string]*ResourceState{
 10254  					"aws_instance.a.0": {
 10255  						Type: "aws_instance",
 10256  						Primary: &InstanceState{
 10257  							ID: "foo",
 10258  						},
 10259  						Provider: "provider.aws",
 10260  					},
 10261  					"aws_instance.a.1": {
 10262  						Type: "aws_instance",
 10263  						Primary: &InstanceState{
 10264  							ID: "foo",
 10265  						},
 10266  						Provider: "provider.aws",
 10267  					},
 10268  				},
 10269  				Outputs: map[string]*OutputState{
 10270  					"out": {
 10271  						Type:  "list",
 10272  						Value: []string{"foo", "foo"},
 10273  					},
 10274  				},
 10275  			},
 10276  		},
 10277  	})
 10278  
 10279  	ctx := testContext2(t, &ContextOpts{
 10280  		Config:           m,
 10281  		ProviderResolver: providerResolver,
 10282  		State:            s,
 10283  		Destroy:          true,
 10284  	})
 10285  
 10286  	plan, diags := ctx.Plan()
 10287  	if diags.HasErrors() {
 10288  		t.Fatalf("plan failed: %s", diags.Err())
 10289  	}
 10290  
 10291  	// We'll marshal and unmarshal the plan here, to ensure that we have
 10292  	// a clean new context as would be created if we separately ran
 10293  	// terraform plan -out=tfplan && terraform apply tfplan
 10294  	ctxOpts, err := contextOptsForPlanViaFile(snap, ctx.State(), plan)
 10295  	if err != nil {
 10296  		t.Fatalf("failed to round-trip through planfile: %s", err)
 10297  	}
 10298  
 10299  	ctxOpts.ProviderResolver = providerResolver
 10300  	ctxOpts.Destroy = true
 10301  	ctx, diags = NewContext(ctxOpts)
 10302  	if diags.HasErrors() {
 10303  		t.Fatalf("err: %s", diags.Err())
 10304  	}
 10305  
 10306  	// Applying the plan should now succeed
 10307  	_, diags = ctx.Apply()
 10308  	if diags.HasErrors() {
 10309  		t.Fatalf("apply failed: %s", diags.Err())
 10310  	}
 10311  }
 10312  
 10313  func TestContext2Apply_scaleInMultivarRef(t *testing.T) {
 10314  	m := testModule(t, "apply-resource-scale-in")
 10315  
 10316  	p := testProvider("aws")
 10317  	p.ApplyFn = testApplyFn
 10318  	p.DiffFn = testDiffFn
 10319  
 10320  	providerResolver := providers.ResolverFixed(
 10321  		map[string]providers.Factory{
 10322  			"aws": testProviderFuncFixed(p),
 10323  		},
 10324  	)
 10325  
 10326  	s := MustShimLegacyState(&State{
 10327  		Modules: []*ModuleState{
 10328  			{
 10329  				Path: rootModulePath,
 10330  				Resources: map[string]*ResourceState{
 10331  					"aws_instance.one": {
 10332  						Type: "aws_instance",
 10333  						Primary: &InstanceState{
 10334  							ID: "foo",
 10335  						},
 10336  						Provider: "provider.aws",
 10337  					},
 10338  					"aws_instance.two": {
 10339  						Type: "aws_instance",
 10340  						Primary: &InstanceState{
 10341  							ID: "foo",
 10342  							Attributes: map[string]string{
 10343  								"value": "foo",
 10344  							},
 10345  						},
 10346  						Provider: "provider.aws",
 10347  					},
 10348  				},
 10349  			},
 10350  		},
 10351  	})
 10352  
 10353  	ctx := testContext2(t, &ContextOpts{
 10354  		Config:           m,
 10355  		ProviderResolver: providerResolver,
 10356  		State:            s,
 10357  		Variables: InputValues{
 10358  			"instance_count": {
 10359  				Value:      cty.NumberIntVal(0),
 10360  				SourceType: ValueFromCaller,
 10361  			},
 10362  		},
 10363  	})
 10364  
 10365  	_, diags := ctx.Plan()
 10366  	assertNoErrors(t, diags)
 10367  
 10368  	// Applying the plan should now succeed
 10369  	_, diags = ctx.Apply()
 10370  	assertNoErrors(t, diags)
 10371  }
 10372  
 10373  func TestContext2Apply_inconsistentWithPlan(t *testing.T) {
 10374  	m := testModule(t, "apply-inconsistent-with-plan")
 10375  	p := testProvider("test")
 10376  	p.GetSchemaReturn = &ProviderSchema{
 10377  		ResourceTypes: map[string]*configschema.Block{
 10378  			"test": {
 10379  				Attributes: map[string]*configschema.Attribute{
 10380  					"id": {Type: cty.String, Computed: true},
 10381  				},
 10382  			},
 10383  		},
 10384  	}
 10385  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
 10386  		return providers.PlanResourceChangeResponse{
 10387  			PlannedState: cty.ObjectVal(map[string]cty.Value{
 10388  				"id": cty.StringVal("before"),
 10389  			}),
 10390  		}
 10391  	}
 10392  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
 10393  		return providers.ApplyResourceChangeResponse{
 10394  			NewState: cty.ObjectVal(map[string]cty.Value{
 10395  				// This is intentionally incorrect: because id was fixed at "before"
 10396  				// during plan, it must not change during apply.
 10397  				"id": cty.StringVal("after"),
 10398  			}),
 10399  		}
 10400  	}
 10401  	ctx := testContext2(t, &ContextOpts{
 10402  		Config: m,
 10403  		ProviderResolver: providers.ResolverFixed(
 10404  			map[string]providers.Factory{
 10405  				"test": testProviderFuncFixed(p),
 10406  			},
 10407  		),
 10408  	})
 10409  
 10410  	if _, diags := ctx.Plan(); diags.HasErrors() {
 10411  		t.Fatalf("plan errors: %s", diags.Err())
 10412  	}
 10413  
 10414  	_, diags := ctx.Apply()
 10415  	if !diags.HasErrors() {
 10416  		t.Fatalf("apply succeeded; want error")
 10417  	}
 10418  	if got, want := diags.Err().Error(), "Provider produced inconsistent result after apply"; !strings.Contains(got, want) {
 10419  		t.Fatalf("wrong error\ngot: %s\nshould contain: %s", got, want)
 10420  	}
 10421  }
 10422  
 10423  // Issue 19908 was about retaining an existing object in the state when an
 10424  // update to it fails and the provider does not return a partially-updated
 10425  // value for it. Previously we were incorrectly removing it from the state
 10426  // in that case, but instead it should be retained so the update can be
 10427  // retried.
 10428  func TestContext2Apply_issue19908(t *testing.T) {
 10429  	m := testModule(t, "apply-issue19908")
 10430  	p := testProvider("test")
 10431  	p.GetSchemaReturn = &ProviderSchema{
 10432  		ResourceTypes: map[string]*configschema.Block{
 10433  			"test": {
 10434  				Attributes: map[string]*configschema.Attribute{
 10435  					"baz": {Type: cty.String, Required: true},
 10436  				},
 10437  			},
 10438  		},
 10439  	}
 10440  	p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
 10441  		return providers.PlanResourceChangeResponse{
 10442  			PlannedState: req.ProposedNewState,
 10443  		}
 10444  	}
 10445  	p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
 10446  		var diags tfdiags.Diagnostics
 10447  		diags = diags.Append(fmt.Errorf("update failed"))
 10448  		return providers.ApplyResourceChangeResponse{
 10449  			Diagnostics: diags,
 10450  		}
 10451  	}
 10452  	ctx := testContext2(t, &ContextOpts{
 10453  		Config: m,
 10454  		State: states.BuildState(func(s *states.SyncState) {
 10455  			s.SetResourceInstanceCurrent(
 10456  				addrs.Resource{
 10457  					Mode: addrs.ManagedResourceMode,
 10458  					Type: "test",
 10459  					Name: "foo",
 10460  				}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
 10461  				&states.ResourceInstanceObjectSrc{
 10462  					AttrsJSON: []byte(`{"baz":"old"}`),
 10463  					Status:    states.ObjectReady,
 10464  				},
 10465  				addrs.ProviderConfig{
 10466  					Type: "test",
 10467  				}.Absolute(addrs.RootModuleInstance),
 10468  			)
 10469  		}),
 10470  		ProviderResolver: providers.ResolverFixed(
 10471  			map[string]providers.Factory{
 10472  				"test": testProviderFuncFixed(p),
 10473  			},
 10474  		),
 10475  	})
 10476  
 10477  	if _, diags := ctx.Plan(); diags.HasErrors() {
 10478  		t.Fatalf("plan errors: %s", diags.Err())
 10479  	}
 10480  
 10481  	state, diags := ctx.Apply()
 10482  	if !diags.HasErrors() {
 10483  		t.Fatalf("apply succeeded; want error")
 10484  	}
 10485  	if got, want := diags.Err().Error(), "update failed"; !strings.Contains(got, want) {
 10486  		t.Fatalf("wrong error\ngot: %s\nshould contain: %s", got, want)
 10487  	}
 10488  
 10489  	mod := state.RootModule()
 10490  	rs := mod.Resources["test.foo"]
 10491  	if rs == nil {
 10492  		t.Fatalf("test.foo not in state after apply, but should be")
 10493  	}
 10494  	is := rs.Instances[addrs.NoKey]
 10495  	if is == nil {
 10496  		t.Fatalf("test.foo not in state after apply, but should be")
 10497  	}
 10498  	obj := is.Current
 10499  	if obj == nil {
 10500  		t.Fatalf("test.foo has no current object in state after apply, but should do")
 10501  	}
 10502  
 10503  	if got, want := obj.Status, states.ObjectReady; got != want {
 10504  		t.Errorf("test.foo has wrong status %s after apply; want %s", got, want)
 10505  	}
 10506  	if got, want := obj.AttrsJSON, []byte(`"old"`); !bytes.Contains(got, want) {
 10507  		t.Errorf("test.foo attributes JSON doesn't contain %s after apply\ngot: %s", want, got)
 10508  	}
 10509  }
 10510  
 10511  func TestContext2Apply_invalidIndexRef(t *testing.T) {
 10512  	p := testProvider("test")
 10513  	p.GetSchemaReturn = &ProviderSchema{
 10514  		ResourceTypes: map[string]*configschema.Block{
 10515  			"test_instance": {
 10516  				Attributes: map[string]*configschema.Attribute{
 10517  					"value": {Type: cty.String, Optional: true, Computed: true},
 10518  				},
 10519  			},
 10520  		},
 10521  	}
 10522  	p.DiffFn = testDiffFn
 10523  
 10524  	m := testModule(t, "apply-invalid-index")
 10525  	c := testContext2(t, &ContextOpts{
 10526  		Config: m,
 10527  		ProviderResolver: providers.ResolverFixed(
 10528  			map[string]providers.Factory{
 10529  				"test": testProviderFuncFixed(p),
 10530  			},
 10531  		),
 10532  	})
 10533  
 10534  	diags := c.Validate()
 10535  	if diags.HasErrors() {
 10536  		t.Fatalf("unexpected validation failure: %s", diags.Err())
 10537  	}
 10538  
 10539  	wantErr := `The given key does not identify an element in this collection value`
 10540  	_, diags = c.Plan()
 10541  
 10542  	if !diags.HasErrors() {
 10543  		t.Fatalf("plan succeeded; want error")
 10544  	}
 10545  	gotErr := diags.Err().Error()
 10546  
 10547  	if !strings.Contains(gotErr, wantErr) {
 10548  		t.Fatalf("missing expected error\ngot: %s\n\nwant: error containing %q", gotErr, wantErr)
 10549  	}
 10550  }
 10551  
 10552  func TestContext2Apply_moduleReplaceCycle(t *testing.T) {
 10553  	for _, mode := range []string{"normal", "cbd"} {
 10554  		var m *configs.Config
 10555  
 10556  		switch mode {
 10557  		case "normal":
 10558  			m = testModule(t, "apply-module-replace-cycle")
 10559  		case "cbd":
 10560  			m = testModule(t, "apply-module-replace-cycle-cbd")
 10561  		}
 10562  
 10563  		p := testProvider("aws")
 10564  		p.DiffFn = testDiffFn
 10565  		p.ApplyFn = testApplyFn
 10566  
 10567  		instanceSchema := &configschema.Block{
 10568  			Attributes: map[string]*configschema.Attribute{
 10569  				"id":          {Type: cty.String, Computed: true},
 10570  				"require_new": {Type: cty.String, Optional: true},
 10571  			},
 10572  		}
 10573  
 10574  		p.GetSchemaReturn = &ProviderSchema{
 10575  			ResourceTypes: map[string]*configschema.Block{
 10576  				"aws_instance": instanceSchema,
 10577  			},
 10578  		}
 10579  
 10580  		state := states.NewState()
 10581  		modA := state.EnsureModule(addrs.RootModuleInstance.Child("a", addrs.NoKey))
 10582  		modA.SetResourceInstanceCurrent(
 10583  			addrs.Resource{
 10584  				Mode: addrs.ManagedResourceMode,
 10585  				Type: "aws_instance",
 10586  				Name: "a",
 10587  			}.Instance(addrs.NoKey),
 10588  			&states.ResourceInstanceObjectSrc{
 10589  				Status:    states.ObjectReady,
 10590  				AttrsJSON: []byte(`{"id":"a","require_new":"old"}`),
 10591  			},
 10592  			addrs.ProviderConfig{
 10593  				Type: "aws",
 10594  			}.Absolute(addrs.RootModuleInstance),
 10595  		)
 10596  
 10597  		modB := state.EnsureModule(addrs.RootModuleInstance.Child("b", addrs.NoKey))
 10598  		modB.SetResourceInstanceCurrent(
 10599  			addrs.Resource{
 10600  				Mode: addrs.ManagedResourceMode,
 10601  				Type: "aws_instance",
 10602  				Name: "b",
 10603  			}.Instance(addrs.IntKey(0)),
 10604  			&states.ResourceInstanceObjectSrc{
 10605  				Status:    states.ObjectReady,
 10606  				AttrsJSON: []byte(`{"id":"b","require_new":"old"}`),
 10607  			},
 10608  			addrs.ProviderConfig{
 10609  				Type: "aws",
 10610  			}.Absolute(addrs.RootModuleInstance),
 10611  		)
 10612  
 10613  		aBefore, _ := plans.NewDynamicValue(
 10614  			cty.ObjectVal(map[string]cty.Value{
 10615  				"id":          cty.StringVal("a"),
 10616  				"require_new": cty.StringVal("old"),
 10617  			}), instanceSchema.ImpliedType())
 10618  		aAfter, _ := plans.NewDynamicValue(
 10619  			cty.ObjectVal(map[string]cty.Value{
 10620  				"id":          cty.UnknownVal(cty.String),
 10621  				"require_new": cty.StringVal("new"),
 10622  			}), instanceSchema.ImpliedType())
 10623  		bBefore, _ := plans.NewDynamicValue(
 10624  			cty.ObjectVal(map[string]cty.Value{
 10625  				"id":          cty.StringVal("b"),
 10626  				"require_new": cty.StringVal("old"),
 10627  			}), instanceSchema.ImpliedType())
 10628  		bAfter, _ := plans.NewDynamicValue(
 10629  			cty.ObjectVal(map[string]cty.Value{
 10630  				"id":          cty.UnknownVal(cty.String),
 10631  				"require_new": cty.UnknownVal(cty.String),
 10632  			}), instanceSchema.ImpliedType())
 10633  
 10634  		var aAction plans.Action
 10635  		switch mode {
 10636  		case "normal":
 10637  			aAction = plans.DeleteThenCreate
 10638  		case "cbd":
 10639  			aAction = plans.CreateThenDelete
 10640  		}
 10641  
 10642  		changes := &plans.Changes{
 10643  			Resources: []*plans.ResourceInstanceChangeSrc{
 10644  				{
 10645  					Addr: addrs.Resource{
 10646  						Mode: addrs.ManagedResourceMode,
 10647  						Type: "aws_instance",
 10648  						Name: "a",
 10649  					}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance.Child("a", addrs.NoKey)),
 10650  					ProviderAddr: addrs.ProviderConfig{
 10651  						Type: "aws",
 10652  					}.Absolute(addrs.RootModuleInstance),
 10653  					ChangeSrc: plans.ChangeSrc{
 10654  						Action: aAction,
 10655  						Before: aBefore,
 10656  						After:  aAfter,
 10657  					},
 10658  				},
 10659  				{
 10660  					Addr: addrs.Resource{
 10661  						Mode: addrs.ManagedResourceMode,
 10662  						Type: "aws_instance",
 10663  						Name: "b",
 10664  					}.Instance(addrs.IntKey(0)).Absolute(addrs.RootModuleInstance.Child("b", addrs.NoKey)),
 10665  					ProviderAddr: addrs.ProviderConfig{
 10666  						Type: "aws",
 10667  					}.Absolute(addrs.RootModuleInstance),
 10668  					ChangeSrc: plans.ChangeSrc{
 10669  						Action: plans.DeleteThenCreate,
 10670  						Before: bBefore,
 10671  						After:  bAfter,
 10672  					},
 10673  				},
 10674  			},
 10675  		}
 10676  
 10677  		ctx := testContext2(t, &ContextOpts{
 10678  			Config: m,
 10679  			ProviderResolver: providers.ResolverFixed(
 10680  				map[string]providers.Factory{
 10681  					"aws": testProviderFuncFixed(p),
 10682  				},
 10683  			),
 10684  			State:   state,
 10685  			Changes: changes,
 10686  		})
 10687  
 10688  		t.Run(mode, func(t *testing.T) {
 10689  			_, diags := ctx.Apply()
 10690  			if diags.HasErrors() {
 10691  				t.Fatal(diags.Err())
 10692  			}
 10693  		})
 10694  	}
 10695  }
 10696  
 10697  func TestContext2Apply_destroyDataCycle(t *testing.T) {
 10698  	m, snap := testModuleWithSnapshot(t, "apply-destroy-data-cycle")
 10699  	p := testProvider("null")
 10700  	p.ApplyFn = testApplyFn
 10701  	p.DiffFn = testDiffFn
 10702  
 10703  	state := states.NewState()
 10704  	root := state.EnsureModule(addrs.RootModuleInstance)
 10705  	root.SetResourceInstanceCurrent(
 10706  		addrs.Resource{
 10707  			Mode: addrs.ManagedResourceMode,
 10708  			Type: "null_resource",
 10709  			Name: "a",
 10710  		}.Instance(addrs.IntKey(0)),
 10711  		&states.ResourceInstanceObjectSrc{
 10712  			Status:    states.ObjectReady,
 10713  			AttrsJSON: []byte(`{"id":"a"}`),
 10714  		},
 10715  		addrs.ProviderConfig{
 10716  			Type: "null",
 10717  		}.Absolute(addrs.RootModuleInstance),
 10718  	)
 10719  	root.SetResourceInstanceCurrent(
 10720  		addrs.Resource{
 10721  			Mode: addrs.DataResourceMode,
 10722  			Type: "null_data_source",
 10723  			Name: "d",
 10724  		}.Instance(addrs.NoKey),
 10725  		&states.ResourceInstanceObjectSrc{
 10726  			Status:    states.ObjectReady,
 10727  			AttrsJSON: []byte(`{"id":"data"}`),
 10728  		},
 10729  		addrs.ProviderConfig{
 10730  			Type: "null",
 10731  		}.Absolute(addrs.RootModuleInstance),
 10732  	)
 10733  
 10734  	providerResolver := providers.ResolverFixed(
 10735  		map[string]providers.Factory{
 10736  			"null": testProviderFuncFixed(p),
 10737  		},
 10738  	)
 10739  
 10740  	hook := &testHook{}
 10741  	ctx := testContext2(t, &ContextOpts{
 10742  		Config:           m,
 10743  		ProviderResolver: providerResolver,
 10744  		State:            state,
 10745  		Destroy:          true,
 10746  		Hooks:            []Hook{hook},
 10747  	})
 10748  
 10749  	plan, diags := ctx.Plan()
 10750  	diags.HasErrors()
 10751  	if diags.HasErrors() {
 10752  		t.Fatalf("diags: %s", diags.Err())
 10753  	}
 10754  
 10755  	// We'll marshal and unmarshal the plan here, to ensure that we have
 10756  	// a clean new context as would be created if we separately ran
 10757  	// terraform plan -out=tfplan && terraform apply tfplan
 10758  	ctxOpts, err := contextOptsForPlanViaFile(snap, state, plan)
 10759  	if err != nil {
 10760  		t.Fatal(err)
 10761  	}
 10762  	ctxOpts.ProviderResolver = providerResolver
 10763  	ctx, diags = NewContext(ctxOpts)
 10764  	if diags.HasErrors() {
 10765  		t.Fatalf("failed to create context for plan: %s", diags.Err())
 10766  	}
 10767  
 10768  	_, diags = ctx.Apply()
 10769  	if diags.HasErrors() {
 10770  		t.Fatalf("diags: %s", diags.Err())
 10771  	}
 10772  }