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 }