github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/terraform/shadow_resource_provider.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "sync" 8 9 "github.com/hashicorp/go-multierror" 10 "github.com/hashicorp/terraform/helper/shadow" 11 ) 12 13 // shadowResourceProvider implements ResourceProvider for the shadow 14 // eval context defined in eval_context_shadow.go. 15 // 16 // This is used to verify behavior with a real provider. This shouldn't 17 // be used directly. 18 type shadowResourceProvider interface { 19 ResourceProvider 20 Shadow 21 } 22 23 // newShadowResourceProvider creates a new shadowed ResourceProvider. 24 // 25 // This will assume a well behaved real ResourceProvider. For example, 26 // it assumes that the `Resources` call underneath doesn't change values 27 // since once it is called on the real provider, it will be cached and 28 // returned in the shadow since number of calls to that shouldn't affect 29 // actual behavior. 30 // 31 // However, with calls like Apply, call order is taken into account, 32 // parameters are checked for equality, etc. 33 func newShadowResourceProvider(p ResourceProvider) (ResourceProvider, shadowResourceProvider) { 34 // Create the shared data 35 shared := shadowResourceProviderShared{} 36 37 // Create the real provider that does actual work 38 real := &shadowResourceProviderReal{ 39 ResourceProvider: p, 40 Shared: &shared, 41 } 42 43 // Create the shadow that watches the real value 44 shadow := &shadowResourceProviderShadow{ 45 Shared: &shared, 46 47 resources: p.Resources(), 48 dataSources: p.DataSources(), 49 } 50 51 return real, shadow 52 } 53 54 // shadowResourceProviderReal is the real resource provider. Function calls 55 // to this will perform real work. This records the parameters and return 56 // values and call order for the shadow to reproduce. 57 type shadowResourceProviderReal struct { 58 ResourceProvider 59 60 Shared *shadowResourceProviderShared 61 } 62 63 func (p *shadowResourceProviderReal) Close() error { 64 var result error 65 if c, ok := p.ResourceProvider.(ResourceProviderCloser); ok { 66 result = c.Close() 67 } 68 69 p.Shared.CloseErr.SetValue(result) 70 return result 71 } 72 73 func (p *shadowResourceProviderReal) Input( 74 input UIInput, c *ResourceConfig) (*ResourceConfig, error) { 75 cCopy := c.DeepCopy() 76 77 result, err := p.ResourceProvider.Input(input, c) 78 p.Shared.Input.SetValue(&shadowResourceProviderInput{ 79 Config: cCopy, 80 Result: result.DeepCopy(), 81 ResultErr: err, 82 }) 83 84 return result, err 85 } 86 87 func (p *shadowResourceProviderReal) Validate(c *ResourceConfig) ([]string, []error) { 88 warns, errs := p.ResourceProvider.Validate(c) 89 p.Shared.Validate.SetValue(&shadowResourceProviderValidate{ 90 Config: c.DeepCopy(), 91 ResultWarn: warns, 92 ResultErr: errs, 93 }) 94 95 return warns, errs 96 } 97 98 func (p *shadowResourceProviderReal) Configure(c *ResourceConfig) error { 99 cCopy := c.DeepCopy() 100 101 err := p.ResourceProvider.Configure(c) 102 p.Shared.Configure.SetValue(&shadowResourceProviderConfigure{ 103 Config: cCopy, 104 Result: err, 105 }) 106 107 return err 108 } 109 110 func (p *shadowResourceProviderReal) Stop() error { 111 return p.ResourceProvider.Stop() 112 } 113 114 func (p *shadowResourceProviderReal) ValidateResource( 115 t string, c *ResourceConfig) ([]string, []error) { 116 key := t 117 configCopy := c.DeepCopy() 118 119 // Real operation 120 warns, errs := p.ResourceProvider.ValidateResource(t, c) 121 122 // Initialize to ensure we always have a wrapper with a lock 123 p.Shared.ValidateResource.Init( 124 key, &shadowResourceProviderValidateResourceWrapper{}) 125 126 // Get the result 127 raw := p.Shared.ValidateResource.Value(key) 128 wrapper, ok := raw.(*shadowResourceProviderValidateResourceWrapper) 129 if !ok { 130 // If this fails then we just continue with our day... the shadow 131 // will fail to but there isn't much we can do. 132 log.Printf( 133 "[ERROR] unknown value in ValidateResource shadow value: %#v", raw) 134 return warns, errs 135 } 136 137 // Lock the wrapper for writing and record our call 138 wrapper.Lock() 139 defer wrapper.Unlock() 140 141 wrapper.Calls = append(wrapper.Calls, &shadowResourceProviderValidateResource{ 142 Config: configCopy, 143 Warns: warns, 144 Errors: errs, 145 }) 146 147 // With it locked, call SetValue again so that it triggers WaitForChange 148 p.Shared.ValidateResource.SetValue(key, wrapper) 149 150 // Return the result 151 return warns, errs 152 } 153 154 func (p *shadowResourceProviderReal) Apply( 155 info *InstanceInfo, 156 state *InstanceState, 157 diff *InstanceDiff) (*InstanceState, error) { 158 // Thse have to be copied before the call since call can modify 159 stateCopy := state.DeepCopy() 160 diffCopy := diff.DeepCopy() 161 162 result, err := p.ResourceProvider.Apply(info, state, diff) 163 p.Shared.Apply.SetValue(info.uniqueId(), &shadowResourceProviderApply{ 164 State: stateCopy, 165 Diff: diffCopy, 166 Result: result.DeepCopy(), 167 ResultErr: err, 168 }) 169 170 return result, err 171 } 172 173 func (p *shadowResourceProviderReal) Diff( 174 info *InstanceInfo, 175 state *InstanceState, 176 desired *ResourceConfig) (*InstanceDiff, error) { 177 // Thse have to be copied before the call since call can modify 178 stateCopy := state.DeepCopy() 179 desiredCopy := desired.DeepCopy() 180 181 result, err := p.ResourceProvider.Diff(info, state, desired) 182 p.Shared.Diff.SetValue(info.uniqueId(), &shadowResourceProviderDiff{ 183 State: stateCopy, 184 Desired: desiredCopy, 185 Result: result.DeepCopy(), 186 ResultErr: err, 187 }) 188 189 return result, err 190 } 191 192 func (p *shadowResourceProviderReal) Refresh( 193 info *InstanceInfo, 194 state *InstanceState) (*InstanceState, error) { 195 // Thse have to be copied before the call since call can modify 196 stateCopy := state.DeepCopy() 197 198 result, err := p.ResourceProvider.Refresh(info, state) 199 p.Shared.Refresh.SetValue(info.uniqueId(), &shadowResourceProviderRefresh{ 200 State: stateCopy, 201 Result: result.DeepCopy(), 202 ResultErr: err, 203 }) 204 205 return result, err 206 } 207 208 func (p *shadowResourceProviderReal) ValidateDataSource( 209 t string, c *ResourceConfig) ([]string, []error) { 210 key := t 211 configCopy := c.DeepCopy() 212 213 // Real operation 214 warns, errs := p.ResourceProvider.ValidateDataSource(t, c) 215 216 // Initialize 217 p.Shared.ValidateDataSource.Init( 218 key, &shadowResourceProviderValidateDataSourceWrapper{}) 219 220 // Get the result 221 raw := p.Shared.ValidateDataSource.Value(key) 222 wrapper, ok := raw.(*shadowResourceProviderValidateDataSourceWrapper) 223 if !ok { 224 // If this fails then we just continue with our day... the shadow 225 // will fail to but there isn't much we can do. 226 log.Printf( 227 "[ERROR] unknown value in ValidateDataSource shadow value: %#v", raw) 228 return warns, errs 229 } 230 231 // Lock the wrapper for writing and record our call 232 wrapper.Lock() 233 defer wrapper.Unlock() 234 235 wrapper.Calls = append(wrapper.Calls, &shadowResourceProviderValidateDataSource{ 236 Config: configCopy, 237 Warns: warns, 238 Errors: errs, 239 }) 240 241 // Set it 242 p.Shared.ValidateDataSource.SetValue(key, wrapper) 243 244 // Return the result 245 return warns, errs 246 } 247 248 func (p *shadowResourceProviderReal) ReadDataDiff( 249 info *InstanceInfo, 250 desired *ResourceConfig) (*InstanceDiff, error) { 251 // These have to be copied before the call since call can modify 252 desiredCopy := desired.DeepCopy() 253 254 result, err := p.ResourceProvider.ReadDataDiff(info, desired) 255 p.Shared.ReadDataDiff.SetValue(info.uniqueId(), &shadowResourceProviderReadDataDiff{ 256 Desired: desiredCopy, 257 Result: result.DeepCopy(), 258 ResultErr: err, 259 }) 260 261 return result, err 262 } 263 264 func (p *shadowResourceProviderReal) ReadDataApply( 265 info *InstanceInfo, 266 diff *InstanceDiff) (*InstanceState, error) { 267 // Thse have to be copied before the call since call can modify 268 diffCopy := diff.DeepCopy() 269 270 result, err := p.ResourceProvider.ReadDataApply(info, diff) 271 p.Shared.ReadDataApply.SetValue(info.uniqueId(), &shadowResourceProviderReadDataApply{ 272 Diff: diffCopy, 273 Result: result.DeepCopy(), 274 ResultErr: err, 275 }) 276 277 return result, err 278 } 279 280 // shadowResourceProviderShadow is the shadow resource provider. Function 281 // calls never affect real resources. This is paired with the "real" side 282 // which must be called properly to enable recording. 283 type shadowResourceProviderShadow struct { 284 Shared *shadowResourceProviderShared 285 286 // Cached values that are expected to not change 287 resources []ResourceType 288 dataSources []DataSource 289 290 Error error // Error is the list of errors from the shadow 291 ErrorLock sync.Mutex 292 } 293 294 type shadowResourceProviderShared struct { 295 // NOTE: Anytime a value is added here, be sure to add it to 296 // the Close() method so that it is closed. 297 298 CloseErr shadow.Value 299 Input shadow.Value 300 Validate shadow.Value 301 Configure shadow.Value 302 ValidateResource shadow.KeyedValue 303 Apply shadow.KeyedValue 304 Diff shadow.KeyedValue 305 Refresh shadow.KeyedValue 306 ValidateDataSource shadow.KeyedValue 307 ReadDataDiff shadow.KeyedValue 308 ReadDataApply shadow.KeyedValue 309 } 310 311 func (p *shadowResourceProviderShared) Close() error { 312 closers := []io.Closer{ 313 &p.CloseErr, &p.Input, &p.Validate, 314 &p.Configure, &p.ValidateResource, &p.Apply, &p.Diff, 315 &p.Refresh, &p.ValidateDataSource, &p.ReadDataDiff, 316 } 317 318 for _, c := range closers { 319 // This should never happen, but we don't panic because a panic 320 // could affect the real behavior of Terraform and a shadow should 321 // never be able to do that. 322 if err := c.Close(); err != nil { 323 return err 324 } 325 } 326 327 return nil 328 } 329 330 func (p *shadowResourceProviderShadow) CloseShadow() error { 331 err := p.Shared.Close() 332 if err != nil { 333 err = fmt.Errorf("close error: %s", err) 334 } 335 336 return err 337 } 338 339 func (p *shadowResourceProviderShadow) ShadowError() error { 340 return p.Error 341 } 342 343 func (p *shadowResourceProviderShadow) Resources() []ResourceType { 344 return p.resources 345 } 346 347 func (p *shadowResourceProviderShadow) DataSources() []DataSource { 348 return p.dataSources 349 } 350 351 func (p *shadowResourceProviderShadow) Close() error { 352 v := p.Shared.CloseErr.Value() 353 if v == nil { 354 return nil 355 } 356 357 return v.(error) 358 } 359 360 func (p *shadowResourceProviderShadow) Input( 361 input UIInput, c *ResourceConfig) (*ResourceConfig, error) { 362 // Get the result of the input call 363 raw := p.Shared.Input.Value() 364 if raw == nil { 365 return nil, nil 366 } 367 368 result, ok := raw.(*shadowResourceProviderInput) 369 if !ok { 370 p.ErrorLock.Lock() 371 defer p.ErrorLock.Unlock() 372 p.Error = multierror.Append(p.Error, fmt.Errorf( 373 "Unknown 'input' shadow value: %#v", raw)) 374 return nil, nil 375 } 376 377 // Compare the parameters, which should be identical 378 if !c.Equal(result.Config) { 379 p.ErrorLock.Lock() 380 p.Error = multierror.Append(p.Error, fmt.Errorf( 381 "Input had unequal configurations (real, then shadow):\n\n%#v\n\n%#v", 382 result.Config, c)) 383 p.ErrorLock.Unlock() 384 } 385 386 // Return the results 387 return result.Result, result.ResultErr 388 } 389 390 func (p *shadowResourceProviderShadow) Validate(c *ResourceConfig) ([]string, []error) { 391 // Get the result of the validate call 392 raw := p.Shared.Validate.Value() 393 if raw == nil { 394 return nil, nil 395 } 396 397 result, ok := raw.(*shadowResourceProviderValidate) 398 if !ok { 399 p.ErrorLock.Lock() 400 defer p.ErrorLock.Unlock() 401 p.Error = multierror.Append(p.Error, fmt.Errorf( 402 "Unknown 'validate' shadow value: %#v", raw)) 403 return nil, nil 404 } 405 406 // Compare the parameters, which should be identical 407 if !c.Equal(result.Config) { 408 p.ErrorLock.Lock() 409 p.Error = multierror.Append(p.Error, fmt.Errorf( 410 "Validate had unequal configurations (real, then shadow):\n\n%#v\n\n%#v", 411 result.Config, c)) 412 p.ErrorLock.Unlock() 413 } 414 415 // Return the results 416 return result.ResultWarn, result.ResultErr 417 } 418 419 func (p *shadowResourceProviderShadow) Configure(c *ResourceConfig) error { 420 // Get the result of the call 421 raw := p.Shared.Configure.Value() 422 if raw == nil { 423 return nil 424 } 425 426 result, ok := raw.(*shadowResourceProviderConfigure) 427 if !ok { 428 p.ErrorLock.Lock() 429 defer p.ErrorLock.Unlock() 430 p.Error = multierror.Append(p.Error, fmt.Errorf( 431 "Unknown 'configure' shadow value: %#v", raw)) 432 return nil 433 } 434 435 // Compare the parameters, which should be identical 436 if !c.Equal(result.Config) { 437 p.ErrorLock.Lock() 438 p.Error = multierror.Append(p.Error, fmt.Errorf( 439 "Configure had unequal configurations (real, then shadow):\n\n%#v\n\n%#v", 440 result.Config, c)) 441 p.ErrorLock.Unlock() 442 } 443 444 // Return the results 445 return result.Result 446 } 447 448 // Stop returns immediately. 449 func (p *shadowResourceProviderShadow) Stop() error { 450 return nil 451 } 452 453 func (p *shadowResourceProviderShadow) ValidateResource(t string, c *ResourceConfig) ([]string, []error) { 454 // Unique key 455 key := t 456 457 // Get the initial value 458 raw := p.Shared.ValidateResource.Value(key) 459 460 // Find a validation with our configuration 461 var result *shadowResourceProviderValidateResource 462 for { 463 // Get the value 464 if raw == nil { 465 p.ErrorLock.Lock() 466 defer p.ErrorLock.Unlock() 467 p.Error = multierror.Append(p.Error, fmt.Errorf( 468 "Unknown 'ValidateResource' call for %q:\n\n%#v", 469 key, c)) 470 return nil, nil 471 } 472 473 wrapper, ok := raw.(*shadowResourceProviderValidateResourceWrapper) 474 if !ok { 475 p.ErrorLock.Lock() 476 defer p.ErrorLock.Unlock() 477 p.Error = multierror.Append(p.Error, fmt.Errorf( 478 "Unknown 'ValidateResource' shadow value: %#v", raw)) 479 return nil, nil 480 } 481 482 // Look for the matching call with our configuration 483 wrapper.RLock() 484 for _, call := range wrapper.Calls { 485 if call.Config.Equal(c) { 486 result = call 487 break 488 } 489 } 490 wrapper.RUnlock() 491 492 // If we found a result, exit 493 if result != nil { 494 break 495 } 496 497 // Wait for a change so we can get the wrapper again 498 raw = p.Shared.ValidateResource.WaitForChange(key) 499 } 500 501 return result.Warns, result.Errors 502 } 503 504 func (p *shadowResourceProviderShadow) Apply( 505 info *InstanceInfo, 506 state *InstanceState, 507 diff *InstanceDiff) (*InstanceState, error) { 508 // Unique key 509 key := info.uniqueId() 510 raw := p.Shared.Apply.Value(key) 511 if raw == nil { 512 p.ErrorLock.Lock() 513 defer p.ErrorLock.Unlock() 514 p.Error = multierror.Append(p.Error, fmt.Errorf( 515 "Unknown 'apply' call for %q:\n\n%#v\n\n%#v", 516 key, state, diff)) 517 return nil, nil 518 } 519 520 result, ok := raw.(*shadowResourceProviderApply) 521 if !ok { 522 p.ErrorLock.Lock() 523 defer p.ErrorLock.Unlock() 524 p.Error = multierror.Append(p.Error, fmt.Errorf( 525 "Unknown 'apply' shadow value for %q: %#v", key, raw)) 526 return nil, nil 527 } 528 529 // Compare the parameters, which should be identical 530 if !state.Equal(result.State) { 531 p.ErrorLock.Lock() 532 p.Error = multierror.Append(p.Error, fmt.Errorf( 533 "Apply %q: state had unequal states (real, then shadow):\n\n%#v\n\n%#v", 534 key, result.State, state)) 535 p.ErrorLock.Unlock() 536 } 537 538 if !diff.Equal(result.Diff) { 539 p.ErrorLock.Lock() 540 p.Error = multierror.Append(p.Error, fmt.Errorf( 541 "Apply %q: unequal diffs (real, then shadow):\n\n%#v\n\n%#v", 542 key, result.Diff, diff)) 543 p.ErrorLock.Unlock() 544 } 545 546 return result.Result, result.ResultErr 547 } 548 549 func (p *shadowResourceProviderShadow) Diff( 550 info *InstanceInfo, 551 state *InstanceState, 552 desired *ResourceConfig) (*InstanceDiff, error) { 553 // Unique key 554 key := info.uniqueId() 555 raw := p.Shared.Diff.Value(key) 556 if raw == nil { 557 p.ErrorLock.Lock() 558 defer p.ErrorLock.Unlock() 559 p.Error = multierror.Append(p.Error, fmt.Errorf( 560 "Unknown 'diff' call for %q:\n\n%#v\n\n%#v", 561 key, state, desired)) 562 return nil, nil 563 } 564 565 result, ok := raw.(*shadowResourceProviderDiff) 566 if !ok { 567 p.ErrorLock.Lock() 568 defer p.ErrorLock.Unlock() 569 p.Error = multierror.Append(p.Error, fmt.Errorf( 570 "Unknown 'diff' shadow value: %#v", raw)) 571 return nil, nil 572 } 573 574 // Compare the parameters, which should be identical 575 if !state.Equal(result.State) { 576 p.ErrorLock.Lock() 577 p.Error = multierror.Append(p.Error, fmt.Errorf( 578 "Diff %q had unequal states (real, then shadow):\n\n%#v\n\n%#v", 579 key, result.State, state)) 580 p.ErrorLock.Unlock() 581 } 582 if !desired.Equal(result.Desired) { 583 p.ErrorLock.Lock() 584 p.Error = multierror.Append(p.Error, fmt.Errorf( 585 "Diff %q had unequal states (real, then shadow):\n\n%#v\n\n%#v", 586 key, result.Desired, desired)) 587 p.ErrorLock.Unlock() 588 } 589 590 return result.Result, result.ResultErr 591 } 592 593 func (p *shadowResourceProviderShadow) Refresh( 594 info *InstanceInfo, 595 state *InstanceState) (*InstanceState, error) { 596 // Unique key 597 key := info.uniqueId() 598 raw := p.Shared.Refresh.Value(key) 599 if raw == nil { 600 p.ErrorLock.Lock() 601 defer p.ErrorLock.Unlock() 602 p.Error = multierror.Append(p.Error, fmt.Errorf( 603 "Unknown 'refresh' call for %q:\n\n%#v", 604 key, state)) 605 return nil, nil 606 } 607 608 result, ok := raw.(*shadowResourceProviderRefresh) 609 if !ok { 610 p.ErrorLock.Lock() 611 defer p.ErrorLock.Unlock() 612 p.Error = multierror.Append(p.Error, fmt.Errorf( 613 "Unknown 'refresh' shadow value: %#v", raw)) 614 return nil, nil 615 } 616 617 // Compare the parameters, which should be identical 618 if !state.Equal(result.State) { 619 p.ErrorLock.Lock() 620 p.Error = multierror.Append(p.Error, fmt.Errorf( 621 "Refresh %q had unequal states (real, then shadow):\n\n%#v\n\n%#v", 622 key, result.State, state)) 623 p.ErrorLock.Unlock() 624 } 625 626 return result.Result, result.ResultErr 627 } 628 629 func (p *shadowResourceProviderShadow) ValidateDataSource( 630 t string, c *ResourceConfig) ([]string, []error) { 631 // Unique key 632 key := t 633 634 // Get the initial value 635 raw := p.Shared.ValidateDataSource.Value(key) 636 637 // Find a validation with our configuration 638 var result *shadowResourceProviderValidateDataSource 639 for { 640 // Get the value 641 if raw == nil { 642 p.ErrorLock.Lock() 643 defer p.ErrorLock.Unlock() 644 p.Error = multierror.Append(p.Error, fmt.Errorf( 645 "Unknown 'ValidateDataSource' call for %q:\n\n%#v", 646 key, c)) 647 return nil, nil 648 } 649 650 wrapper, ok := raw.(*shadowResourceProviderValidateDataSourceWrapper) 651 if !ok { 652 p.ErrorLock.Lock() 653 defer p.ErrorLock.Unlock() 654 p.Error = multierror.Append(p.Error, fmt.Errorf( 655 "Unknown 'ValidateDataSource' shadow value: %#v", raw)) 656 return nil, nil 657 } 658 659 // Look for the matching call with our configuration 660 wrapper.RLock() 661 for _, call := range wrapper.Calls { 662 if call.Config.Equal(c) { 663 result = call 664 break 665 } 666 } 667 wrapper.RUnlock() 668 669 // If we found a result, exit 670 if result != nil { 671 break 672 } 673 674 // Wait for a change so we can get the wrapper again 675 raw = p.Shared.ValidateDataSource.WaitForChange(key) 676 } 677 678 return result.Warns, result.Errors 679 } 680 681 func (p *shadowResourceProviderShadow) ReadDataDiff( 682 info *InstanceInfo, 683 desired *ResourceConfig) (*InstanceDiff, error) { 684 // Unique key 685 key := info.uniqueId() 686 raw := p.Shared.ReadDataDiff.Value(key) 687 if raw == nil { 688 p.ErrorLock.Lock() 689 defer p.ErrorLock.Unlock() 690 p.Error = multierror.Append(p.Error, fmt.Errorf( 691 "Unknown 'ReadDataDiff' call for %q:\n\n%#v", 692 key, desired)) 693 return nil, nil 694 } 695 696 result, ok := raw.(*shadowResourceProviderReadDataDiff) 697 if !ok { 698 p.ErrorLock.Lock() 699 defer p.ErrorLock.Unlock() 700 p.Error = multierror.Append(p.Error, fmt.Errorf( 701 "Unknown 'ReadDataDiff' shadow value: %#v", raw)) 702 return nil, nil 703 } 704 705 // Compare the parameters, which should be identical 706 if !desired.Equal(result.Desired) { 707 p.ErrorLock.Lock() 708 p.Error = multierror.Append(p.Error, fmt.Errorf( 709 "ReadDataDiff %q had unequal configs (real, then shadow):\n\n%#v\n\n%#v", 710 key, result.Desired, desired)) 711 p.ErrorLock.Unlock() 712 } 713 714 return result.Result, result.ResultErr 715 } 716 717 func (p *shadowResourceProviderShadow) ReadDataApply( 718 info *InstanceInfo, 719 d *InstanceDiff) (*InstanceState, error) { 720 // Unique key 721 key := info.uniqueId() 722 raw := p.Shared.ReadDataApply.Value(key) 723 if raw == nil { 724 p.ErrorLock.Lock() 725 defer p.ErrorLock.Unlock() 726 p.Error = multierror.Append(p.Error, fmt.Errorf( 727 "Unknown 'ReadDataApply' call for %q:\n\n%#v", 728 key, d)) 729 return nil, nil 730 } 731 732 result, ok := raw.(*shadowResourceProviderReadDataApply) 733 if !ok { 734 p.ErrorLock.Lock() 735 defer p.ErrorLock.Unlock() 736 p.Error = multierror.Append(p.Error, fmt.Errorf( 737 "Unknown 'ReadDataApply' shadow value: %#v", raw)) 738 return nil, nil 739 } 740 741 // Compare the parameters, which should be identical 742 if !d.Equal(result.Diff) { 743 p.ErrorLock.Lock() 744 p.Error = multierror.Append(p.Error, fmt.Errorf( 745 "ReadDataApply: unequal diffs (real, then shadow):\n\n%#v\n\n%#v", 746 result.Diff, d)) 747 p.ErrorLock.Unlock() 748 } 749 750 return result.Result, result.ResultErr 751 } 752 753 func (p *shadowResourceProviderShadow) ImportState(info *InstanceInfo, id string) ([]*InstanceState, error) { 754 panic("import not supported by shadow graph") 755 } 756 757 // The structs for the various function calls are put below. These structs 758 // are used to carry call information across the real/shadow boundaries. 759 760 type shadowResourceProviderInput struct { 761 Config *ResourceConfig 762 Result *ResourceConfig 763 ResultErr error 764 } 765 766 type shadowResourceProviderValidate struct { 767 Config *ResourceConfig 768 ResultWarn []string 769 ResultErr []error 770 } 771 772 type shadowResourceProviderConfigure struct { 773 Config *ResourceConfig 774 Result error 775 } 776 777 type shadowResourceProviderValidateResourceWrapper struct { 778 sync.RWMutex 779 780 Calls []*shadowResourceProviderValidateResource 781 } 782 783 type shadowResourceProviderValidateResource struct { 784 Config *ResourceConfig 785 Warns []string 786 Errors []error 787 } 788 789 type shadowResourceProviderApply struct { 790 State *InstanceState 791 Diff *InstanceDiff 792 Result *InstanceState 793 ResultErr error 794 } 795 796 type shadowResourceProviderDiff struct { 797 State *InstanceState 798 Desired *ResourceConfig 799 Result *InstanceDiff 800 ResultErr error 801 } 802 803 type shadowResourceProviderRefresh struct { 804 State *InstanceState 805 Result *InstanceState 806 ResultErr error 807 } 808 809 type shadowResourceProviderValidateDataSourceWrapper struct { 810 sync.RWMutex 811 812 Calls []*shadowResourceProviderValidateDataSource 813 } 814 815 type shadowResourceProviderValidateDataSource struct { 816 Config *ResourceConfig 817 Warns []string 818 Errors []error 819 } 820 821 type shadowResourceProviderReadDataDiff struct { 822 Desired *ResourceConfig 823 Result *InstanceDiff 824 ResultErr error 825 } 826 827 type shadowResourceProviderReadDataApply struct { 828 Diff *InstanceDiff 829 Result *InstanceState 830 ResultErr error 831 }