github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/node_resource_abstract_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/internal/addrs"
     8  	"github.com/hashicorp/terraform/internal/configs"
     9  	"github.com/hashicorp/terraform/internal/configs/configschema"
    10  	"github.com/hashicorp/terraform/internal/providers"
    11  	"github.com/hashicorp/terraform/internal/states"
    12  	"github.com/zclconf/go-cty/cty"
    13  )
    14  
    15  func TestNodeAbstractResourceProvider(t *testing.T) {
    16  	tests := []struct {
    17  		Addr   addrs.ConfigResource
    18  		Config *configs.Resource
    19  		Want   addrs.Provider
    20  	}{
    21  		{
    22  			Addr: addrs.Resource{
    23  				Mode: addrs.ManagedResourceMode,
    24  				Type: "null_resource",
    25  				Name: "baz",
    26  			}.InModule(addrs.RootModule),
    27  			Want: addrs.Provider{
    28  				Hostname:  addrs.DefaultProviderRegistryHost,
    29  				Namespace: "hashicorp",
    30  				Type:      "null",
    31  			},
    32  		},
    33  		{
    34  			Addr: addrs.Resource{
    35  				Mode: addrs.DataResourceMode,
    36  				Type: "terraform_remote_state",
    37  				Name: "baz",
    38  			}.InModule(addrs.RootModule),
    39  			Want: addrs.Provider{
    40  				// As a special case, the type prefix "terraform_" maps to
    41  				// the builtin provider, not the default one.
    42  				Hostname:  addrs.BuiltInProviderHost,
    43  				Namespace: addrs.BuiltInProviderNamespace,
    44  				Type:      "terraform",
    45  			},
    46  		},
    47  		{
    48  			Addr: addrs.Resource{
    49  				Mode: addrs.ManagedResourceMode,
    50  				Type: "null_resource",
    51  				Name: "baz",
    52  			}.InModule(addrs.RootModule),
    53  			Config: &configs.Resource{
    54  				// Just enough configs.Resource for the Provider method. Not
    55  				// actually valid for general use.
    56  				Provider: addrs.Provider{
    57  					Hostname:  addrs.DefaultProviderRegistryHost,
    58  					Namespace: "awesomecorp",
    59  					Type:      "happycloud",
    60  				},
    61  			},
    62  			// The config overrides the default behavior.
    63  			Want: addrs.Provider{
    64  				Hostname:  addrs.DefaultProviderRegistryHost,
    65  				Namespace: "awesomecorp",
    66  				Type:      "happycloud",
    67  			},
    68  		},
    69  		{
    70  			Addr: addrs.Resource{
    71  				Mode: addrs.DataResourceMode,
    72  				Type: "terraform_remote_state",
    73  				Name: "baz",
    74  			}.InModule(addrs.RootModule),
    75  			Config: &configs.Resource{
    76  				// Just enough configs.Resource for the Provider method. Not
    77  				// actually valid for general use.
    78  				Provider: addrs.Provider{
    79  					Hostname:  addrs.DefaultProviderRegistryHost,
    80  					Namespace: "awesomecorp",
    81  					Type:      "happycloud",
    82  				},
    83  			},
    84  			// The config overrides the default behavior.
    85  			Want: addrs.Provider{
    86  				Hostname:  addrs.DefaultProviderRegistryHost,
    87  				Namespace: "awesomecorp",
    88  				Type:      "happycloud",
    89  			},
    90  		},
    91  	}
    92  
    93  	for _, test := range tests {
    94  		var name string
    95  		if test.Config != nil {
    96  			name = fmt.Sprintf("%s with configured %s", test.Addr, test.Config.Provider)
    97  		} else {
    98  			name = fmt.Sprintf("%s with no configuration", test.Addr)
    99  		}
   100  		t.Run(name, func(t *testing.T) {
   101  			node := &NodeAbstractResource{
   102  				// Just enough NodeAbstractResource for the Provider function.
   103  				// (This would not be valid for some other functions.)
   104  				Addr:   test.Addr,
   105  				Config: test.Config,
   106  			}
   107  			got := node.Provider()
   108  			if got != test.Want {
   109  				t.Errorf("wrong result\naddr:  %s\nconfig: %#v\ngot:   %s\nwant:  %s", test.Addr, test.Config, got, test.Want)
   110  			}
   111  		})
   112  	}
   113  }
   114  
   115  func TestNodeAbstractResource_ReadResourceInstanceState(t *testing.T) {
   116  	mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{
   117  		Attributes: map[string]*configschema.Attribute{
   118  			"id": {
   119  				Type:     cty.String,
   120  				Optional: true,
   121  			},
   122  		},
   123  	})
   124  	// This test does not configure the provider, but the mock provider will
   125  	// check that this was called and report errors.
   126  	mockProvider.ConfigureProviderCalled = true
   127  
   128  	tests := map[string]struct {
   129  		State              *states.State
   130  		Node               *NodeAbstractResource
   131  		ExpectedInstanceId string
   132  	}{
   133  		"ReadState gets primary instance state": {
   134  			State: states.BuildState(func(s *states.SyncState) {
   135  				providerAddr := addrs.AbsProviderConfig{
   136  					Provider: addrs.NewDefaultProvider("aws"),
   137  					Module:   addrs.RootModule,
   138  				}
   139  				oneAddr := addrs.Resource{
   140  					Mode: addrs.ManagedResourceMode,
   141  					Type: "aws_instance",
   142  					Name: "bar",
   143  				}.Absolute(addrs.RootModuleInstance)
   144  				s.SetResourceProvider(oneAddr, providerAddr)
   145  				s.SetResourceInstanceCurrent(oneAddr.Instance(addrs.NoKey), &states.ResourceInstanceObjectSrc{
   146  					Status:    states.ObjectReady,
   147  					AttrsJSON: []byte(`{"id":"i-abc123"}`),
   148  				}, providerAddr)
   149  			}),
   150  			Node: &NodeAbstractResource{
   151  				Addr:             mustConfigResourceAddr("aws_instance.bar"),
   152  				ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`),
   153  			},
   154  			ExpectedInstanceId: "i-abc123",
   155  		},
   156  	}
   157  
   158  	for k, test := range tests {
   159  		t.Run(k, func(t *testing.T) {
   160  			ctx := new(MockEvalContext)
   161  			ctx.StateState = test.State.SyncWrapper()
   162  			ctx.PathPath = addrs.RootModuleInstance
   163  			ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
   164  
   165  			ctx.ProviderProvider = providers.Interface(mockProvider)
   166  
   167  			got, readDiags := test.Node.readResourceInstanceState(ctx, test.Node.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance))
   168  			if readDiags.HasErrors() {
   169  				t.Fatalf("[%s] Got err: %#v", k, readDiags.Err())
   170  			}
   171  
   172  			expected := test.ExpectedInstanceId
   173  
   174  			if !(got != nil && got.Value.GetAttr("id") == cty.StringVal(expected)) {
   175  				t.Fatalf("[%s] Expected output with ID %#v, got: %#v", k, expected, got)
   176  			}
   177  		})
   178  	}
   179  }
   180  
   181  func TestNodeAbstractResource_ReadResourceInstanceStateDeposed(t *testing.T) {
   182  	mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{
   183  		Attributes: map[string]*configschema.Attribute{
   184  			"id": {
   185  				Type:     cty.String,
   186  				Optional: true,
   187  			},
   188  		},
   189  	})
   190  	// This test does not configure the provider, but the mock provider will
   191  	// check that this was called and report errors.
   192  	mockProvider.ConfigureProviderCalled = true
   193  
   194  	tests := map[string]struct {
   195  		State              *states.State
   196  		Node               *NodeAbstractResource
   197  		ExpectedInstanceId string
   198  	}{
   199  		"ReadStateDeposed gets deposed instance": {
   200  			State: states.BuildState(func(s *states.SyncState) {
   201  				providerAddr := addrs.AbsProviderConfig{
   202  					Provider: addrs.NewDefaultProvider("aws"),
   203  					Module:   addrs.RootModule,
   204  				}
   205  				oneAddr := addrs.Resource{
   206  					Mode: addrs.ManagedResourceMode,
   207  					Type: "aws_instance",
   208  					Name: "bar",
   209  				}.Absolute(addrs.RootModuleInstance)
   210  				s.SetResourceProvider(oneAddr, providerAddr)
   211  				s.SetResourceInstanceDeposed(oneAddr.Instance(addrs.NoKey), states.DeposedKey("00000001"), &states.ResourceInstanceObjectSrc{
   212  					Status:    states.ObjectReady,
   213  					AttrsJSON: []byte(`{"id":"i-abc123"}`),
   214  				}, providerAddr)
   215  			}),
   216  			Node: &NodeAbstractResource{
   217  				Addr:             mustConfigResourceAddr("aws_instance.bar"),
   218  				ResolvedProvider: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`),
   219  			},
   220  			ExpectedInstanceId: "i-abc123",
   221  		},
   222  	}
   223  	for k, test := range tests {
   224  		t.Run(k, func(t *testing.T) {
   225  			ctx := new(MockEvalContext)
   226  			ctx.StateState = test.State.SyncWrapper()
   227  			ctx.PathPath = addrs.RootModuleInstance
   228  			ctx.ProviderSchemaSchema = mockProvider.ProviderSchema()
   229  			ctx.ProviderProvider = providers.Interface(mockProvider)
   230  
   231  			key := states.DeposedKey("00000001") // shim from legacy state assigns 0th deposed index this key
   232  
   233  			got, readDiags := test.Node.readResourceInstanceStateDeposed(ctx, test.Node.Addr.Resource.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), key)
   234  			if readDiags.HasErrors() {
   235  				t.Fatalf("[%s] Got err: %#v", k, readDiags.Err())
   236  			}
   237  
   238  			expected := test.ExpectedInstanceId
   239  
   240  			if !(got != nil && got.Value.GetAttr("id") == cty.StringVal(expected)) {
   241  				t.Fatalf("[%s] Expected output with ID %#v, got: %#v", k, expected, got)
   242  			}
   243  		})
   244  	}
   245  }