github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/legacy/terraform/provider_mock.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package terraform
     5  
     6  import (
     7  	"encoding/json"
     8  	"sync"
     9  
    10  	"github.com/zclconf/go-cty/cty"
    11  	ctyjson "github.com/zclconf/go-cty/cty/json"
    12  
    13  	"github.com/terramate-io/tf/configs/hcl2shim"
    14  	"github.com/terramate-io/tf/providers"
    15  )
    16  
    17  var _ providers.Interface = (*MockProvider)(nil)
    18  
    19  // MockProvider implements providers.Interface but mocks out all the
    20  // calls for testing purposes.
    21  type MockProvider struct {
    22  	sync.Mutex
    23  
    24  	// Anything you want, in case you need to store extra data with the mock.
    25  	Meta interface{}
    26  
    27  	GetSchemaCalled bool
    28  	GetSchemaReturn *ProviderSchema // This is using ProviderSchema directly rather than providers.GetProviderSchemaResponse for compatibility with old tests
    29  
    30  	ValidateProviderConfigCalled   bool
    31  	ValidateProviderConfigResponse providers.ValidateProviderConfigResponse
    32  	ValidateProviderConfigRequest  providers.ValidateProviderConfigRequest
    33  	ValidateProviderConfigFn       func(providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse
    34  
    35  	ValidateResourceConfigCalled   bool
    36  	ValidateResourceConfigTypeName string
    37  	ValidateResourceConfigResponse providers.ValidateResourceConfigResponse
    38  	ValidateResourceConfigRequest  providers.ValidateResourceConfigRequest
    39  	ValidateResourceConfigFn       func(providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse
    40  
    41  	ValidateDataResourceConfigCalled   bool
    42  	ValidateDataResourceConfigTypeName string
    43  	ValidateDataResourceConfigResponse providers.ValidateDataResourceConfigResponse
    44  	ValidateDataResourceConfigRequest  providers.ValidateDataResourceConfigRequest
    45  	ValidateDataResourceConfigFn       func(providers.ValidateDataResourceConfigRequest) providers.ValidateDataResourceConfigResponse
    46  
    47  	UpgradeResourceStateCalled   bool
    48  	UpgradeResourceStateTypeName string
    49  	UpgradeResourceStateResponse providers.UpgradeResourceStateResponse
    50  	UpgradeResourceStateRequest  providers.UpgradeResourceStateRequest
    51  	UpgradeResourceStateFn       func(providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse
    52  
    53  	ConfigureProviderCalled   bool
    54  	ConfigureProviderResponse providers.ConfigureProviderResponse
    55  	ConfigureProviderRequest  providers.ConfigureProviderRequest
    56  	ConfigureProviderFn       func(providers.ConfigureProviderRequest) providers.ConfigureProviderResponse
    57  
    58  	StopCalled   bool
    59  	StopFn       func() error
    60  	StopResponse error
    61  
    62  	ReadResourceCalled   bool
    63  	ReadResourceResponse providers.ReadResourceResponse
    64  	ReadResourceRequest  providers.ReadResourceRequest
    65  	ReadResourceFn       func(providers.ReadResourceRequest) providers.ReadResourceResponse
    66  
    67  	PlanResourceChangeCalled   bool
    68  	PlanResourceChangeResponse providers.PlanResourceChangeResponse
    69  	PlanResourceChangeRequest  providers.PlanResourceChangeRequest
    70  	PlanResourceChangeFn       func(providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse
    71  
    72  	ApplyResourceChangeCalled   bool
    73  	ApplyResourceChangeResponse providers.ApplyResourceChangeResponse
    74  	ApplyResourceChangeRequest  providers.ApplyResourceChangeRequest
    75  	ApplyResourceChangeFn       func(providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse
    76  
    77  	ImportResourceStateCalled   bool
    78  	ImportResourceStateResponse providers.ImportResourceStateResponse
    79  	ImportResourceStateRequest  providers.ImportResourceStateRequest
    80  	ImportResourceStateFn       func(providers.ImportResourceStateRequest) providers.ImportResourceStateResponse
    81  	// Legacy return type for existing tests, which will be shimmed into an
    82  	// ImportResourceStateResponse if set
    83  	ImportStateReturn []*InstanceState
    84  
    85  	ReadDataSourceCalled   bool
    86  	ReadDataSourceResponse providers.ReadDataSourceResponse
    87  	ReadDataSourceRequest  providers.ReadDataSourceRequest
    88  	ReadDataSourceFn       func(providers.ReadDataSourceRequest) providers.ReadDataSourceResponse
    89  
    90  	CloseCalled bool
    91  	CloseError  error
    92  }
    93  
    94  func (p *MockProvider) GetProviderSchema() providers.GetProviderSchemaResponse {
    95  	p.Lock()
    96  	defer p.Unlock()
    97  	p.GetSchemaCalled = true
    98  	return p.getSchema()
    99  }
   100  
   101  func (p *MockProvider) getSchema() providers.GetProviderSchemaResponse {
   102  	// This version of getSchema doesn't do any locking, so it's suitable to
   103  	// call from other methods of this mock as long as they are already
   104  	// holding the lock.
   105  
   106  	ret := providers.GetProviderSchemaResponse{
   107  		Provider:      providers.Schema{},
   108  		DataSources:   map[string]providers.Schema{},
   109  		ResourceTypes: map[string]providers.Schema{},
   110  	}
   111  	if p.GetSchemaReturn != nil {
   112  		ret.Provider.Block = p.GetSchemaReturn.Provider
   113  		ret.ProviderMeta.Block = p.GetSchemaReturn.ProviderMeta
   114  		for n, s := range p.GetSchemaReturn.DataSources {
   115  			ret.DataSources[n] = providers.Schema{
   116  				Block: s,
   117  			}
   118  		}
   119  		for n, s := range p.GetSchemaReturn.ResourceTypes {
   120  			ret.ResourceTypes[n] = providers.Schema{
   121  				Version: int64(p.GetSchemaReturn.ResourceTypeSchemaVersions[n]),
   122  				Block:   s,
   123  			}
   124  		}
   125  	}
   126  
   127  	return ret
   128  }
   129  
   130  func (p *MockProvider) ValidateProviderConfig(r providers.ValidateProviderConfigRequest) providers.ValidateProviderConfigResponse {
   131  	p.Lock()
   132  	defer p.Unlock()
   133  
   134  	p.ValidateProviderConfigCalled = true
   135  	p.ValidateProviderConfigRequest = r
   136  	if p.ValidateProviderConfigFn != nil {
   137  		return p.ValidateProviderConfigFn(r)
   138  	}
   139  	return p.ValidateProviderConfigResponse
   140  }
   141  
   142  func (p *MockProvider) ValidateResourceConfig(r providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse {
   143  	p.Lock()
   144  	defer p.Unlock()
   145  
   146  	p.ValidateResourceConfigCalled = true
   147  	p.ValidateResourceConfigRequest = r
   148  
   149  	if p.ValidateResourceConfigFn != nil {
   150  		return p.ValidateResourceConfigFn(r)
   151  	}
   152  
   153  	return p.ValidateResourceConfigResponse
   154  }
   155  
   156  func (p *MockProvider) ValidateDataResourceConfig(r providers.ValidateDataResourceConfigRequest) providers.ValidateDataResourceConfigResponse {
   157  	p.Lock()
   158  	defer p.Unlock()
   159  
   160  	p.ValidateDataResourceConfigCalled = true
   161  	p.ValidateDataResourceConfigRequest = r
   162  
   163  	if p.ValidateDataResourceConfigFn != nil {
   164  		return p.ValidateDataResourceConfigFn(r)
   165  	}
   166  
   167  	return p.ValidateDataResourceConfigResponse
   168  }
   169  
   170  func (p *MockProvider) UpgradeResourceState(r providers.UpgradeResourceStateRequest) providers.UpgradeResourceStateResponse {
   171  	p.Lock()
   172  	defer p.Unlock()
   173  
   174  	schemas := p.getSchema()
   175  	schema := schemas.ResourceTypes[r.TypeName]
   176  	schemaType := schema.Block.ImpliedType()
   177  
   178  	p.UpgradeResourceStateCalled = true
   179  	p.UpgradeResourceStateRequest = r
   180  
   181  	if p.UpgradeResourceStateFn != nil {
   182  		return p.UpgradeResourceStateFn(r)
   183  	}
   184  
   185  	resp := p.UpgradeResourceStateResponse
   186  
   187  	if resp.UpgradedState == cty.NilVal {
   188  		switch {
   189  		case r.RawStateFlatmap != nil:
   190  			v, err := hcl2shim.HCL2ValueFromFlatmap(r.RawStateFlatmap, schemaType)
   191  			if err != nil {
   192  				resp.Diagnostics = resp.Diagnostics.Append(err)
   193  				return resp
   194  			}
   195  			resp.UpgradedState = v
   196  		case len(r.RawStateJSON) > 0:
   197  			v, err := ctyjson.Unmarshal(r.RawStateJSON, schemaType)
   198  
   199  			if err != nil {
   200  				resp.Diagnostics = resp.Diagnostics.Append(err)
   201  				return resp
   202  			}
   203  			resp.UpgradedState = v
   204  		}
   205  	}
   206  	return resp
   207  }
   208  
   209  func (p *MockProvider) ConfigureProvider(r providers.ConfigureProviderRequest) providers.ConfigureProviderResponse {
   210  	p.Lock()
   211  	defer p.Unlock()
   212  
   213  	p.ConfigureProviderCalled = true
   214  	p.ConfigureProviderRequest = r
   215  
   216  	if p.ConfigureProviderFn != nil {
   217  		return p.ConfigureProviderFn(r)
   218  	}
   219  
   220  	return p.ConfigureProviderResponse
   221  }
   222  
   223  func (p *MockProvider) Stop() error {
   224  	// We intentionally don't lock in this one because the whole point of this
   225  	// method is to be called concurrently with another operation that can
   226  	// be cancelled.  The provider itself is responsible for handling
   227  	// any concurrency concerns in this case.
   228  
   229  	p.StopCalled = true
   230  	if p.StopFn != nil {
   231  		return p.StopFn()
   232  	}
   233  
   234  	return p.StopResponse
   235  }
   236  
   237  func (p *MockProvider) ReadResource(r providers.ReadResourceRequest) providers.ReadResourceResponse {
   238  	p.Lock()
   239  	defer p.Unlock()
   240  
   241  	p.ReadResourceCalled = true
   242  	p.ReadResourceRequest = r
   243  
   244  	if p.ReadResourceFn != nil {
   245  		return p.ReadResourceFn(r)
   246  	}
   247  
   248  	resp := p.ReadResourceResponse
   249  	if resp.NewState != cty.NilVal {
   250  		// make sure the NewState fits the schema
   251  		// This isn't always the case for the existing tests
   252  		newState, err := p.GetSchemaReturn.ResourceTypes[r.TypeName].CoerceValue(resp.NewState)
   253  		if err != nil {
   254  			panic(err)
   255  		}
   256  		resp.NewState = newState
   257  		return resp
   258  	}
   259  
   260  	// just return the same state we received
   261  	resp.NewState = r.PriorState
   262  	return resp
   263  }
   264  
   265  func (p *MockProvider) PlanResourceChange(r providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
   266  	p.Lock()
   267  	defer p.Unlock()
   268  
   269  	p.PlanResourceChangeCalled = true
   270  	p.PlanResourceChangeRequest = r
   271  
   272  	if p.PlanResourceChangeFn != nil {
   273  		return p.PlanResourceChangeFn(r)
   274  	}
   275  
   276  	return p.PlanResourceChangeResponse
   277  }
   278  
   279  func (p *MockProvider) ApplyResourceChange(r providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
   280  	p.Lock()
   281  	p.ApplyResourceChangeCalled = true
   282  	p.ApplyResourceChangeRequest = r
   283  	p.Unlock()
   284  
   285  	if p.ApplyResourceChangeFn != nil {
   286  		return p.ApplyResourceChangeFn(r)
   287  	}
   288  
   289  	return p.ApplyResourceChangeResponse
   290  }
   291  
   292  func (p *MockProvider) ImportResourceState(r providers.ImportResourceStateRequest) providers.ImportResourceStateResponse {
   293  	p.Lock()
   294  	defer p.Unlock()
   295  
   296  	if p.ImportStateReturn != nil {
   297  		for _, is := range p.ImportStateReturn {
   298  			if is.Attributes == nil {
   299  				is.Attributes = make(map[string]string)
   300  			}
   301  			is.Attributes["id"] = is.ID
   302  
   303  			typeName := is.Ephemeral.Type
   304  			// Use the requested type if the resource has no type of it's own.
   305  			// We still return the empty type, which will error, but this prevents a panic.
   306  			if typeName == "" {
   307  				typeName = r.TypeName
   308  			}
   309  
   310  			schema := p.GetSchemaReturn.ResourceTypes[typeName]
   311  			if schema == nil {
   312  				panic("no schema found for " + typeName)
   313  			}
   314  
   315  			private, err := json.Marshal(is.Meta)
   316  			if err != nil {
   317  				panic(err)
   318  			}
   319  
   320  			state, err := hcl2shim.HCL2ValueFromFlatmap(is.Attributes, schema.ImpliedType())
   321  			if err != nil {
   322  				panic(err)
   323  			}
   324  
   325  			state, err = schema.CoerceValue(state)
   326  			if err != nil {
   327  				panic(err)
   328  			}
   329  
   330  			p.ImportResourceStateResponse.ImportedResources = append(
   331  				p.ImportResourceStateResponse.ImportedResources,
   332  				providers.ImportedResource{
   333  					TypeName: is.Ephemeral.Type,
   334  					State:    state,
   335  					Private:  private,
   336  				})
   337  		}
   338  	}
   339  
   340  	p.ImportResourceStateCalled = true
   341  	p.ImportResourceStateRequest = r
   342  	if p.ImportResourceStateFn != nil {
   343  		return p.ImportResourceStateFn(r)
   344  	}
   345  
   346  	return p.ImportResourceStateResponse
   347  }
   348  
   349  func (p *MockProvider) ReadDataSource(r providers.ReadDataSourceRequest) providers.ReadDataSourceResponse {
   350  	p.Lock()
   351  	defer p.Unlock()
   352  
   353  	p.ReadDataSourceCalled = true
   354  	p.ReadDataSourceRequest = r
   355  
   356  	if p.ReadDataSourceFn != nil {
   357  		return p.ReadDataSourceFn(r)
   358  	}
   359  
   360  	return p.ReadDataSourceResponse
   361  }
   362  
   363  func (p *MockProvider) Close() error {
   364  	p.CloseCalled = true
   365  	return p.CloseError
   366  }