github.com/posener/terraform@v0.11.0-beta1.0.20171103235147-645df36af025/plugin/resource_provider.go (about) 1 package plugin 2 3 import ( 4 "net/rpc" 5 6 "github.com/hashicorp/go-plugin" 7 "github.com/hashicorp/terraform/terraform" 8 ) 9 10 // ResourceProviderPlugin is the plugin.Plugin implementation. 11 type ResourceProviderPlugin struct { 12 F func() terraform.ResourceProvider 13 } 14 15 func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) { 16 return &ResourceProviderServer{Broker: b, Provider: p.F()}, nil 17 } 18 19 func (p *ResourceProviderPlugin) Client( 20 b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) { 21 return &ResourceProvider{Broker: b, Client: c}, nil 22 } 23 24 // ResourceProvider is an implementation of terraform.ResourceProvider 25 // that communicates over RPC. 26 type ResourceProvider struct { 27 Broker *plugin.MuxBroker 28 Client *rpc.Client 29 } 30 31 func (p *ResourceProvider) Stop() error { 32 var resp ResourceProviderStopResponse 33 err := p.Client.Call("Plugin.Stop", new(interface{}), &resp) 34 if err != nil { 35 return err 36 } 37 if resp.Error != nil { 38 err = resp.Error 39 } 40 41 return err 42 } 43 44 func (p *ResourceProvider) GetSchema(req *terraform.ProviderSchemaRequest) (*terraform.ProviderSchema, error) { 45 var result ResourceProviderGetSchemaResponse 46 args := &ResourceProviderGetSchemaArgs{ 47 Req: req, 48 } 49 50 err := p.Client.Call("Plugin.GetSchema", args, &result) 51 if err != nil { 52 return nil, err 53 } 54 55 if result.Error != nil { 56 err = result.Error 57 } 58 59 return result.Schema, err 60 } 61 62 func (p *ResourceProvider) Input( 63 input terraform.UIInput, 64 c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) { 65 id := p.Broker.NextId() 66 go p.Broker.AcceptAndServe(id, &UIInputServer{ 67 UIInput: input, 68 }) 69 70 var resp ResourceProviderInputResponse 71 args := ResourceProviderInputArgs{ 72 InputId: id, 73 Config: c, 74 } 75 76 err := p.Client.Call("Plugin.Input", &args, &resp) 77 if err != nil { 78 return nil, err 79 } 80 if resp.Error != nil { 81 err = resp.Error 82 return nil, err 83 } 84 85 return resp.Config, nil 86 } 87 88 func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) { 89 var resp ResourceProviderValidateResponse 90 args := ResourceProviderValidateArgs{ 91 Config: c, 92 } 93 94 err := p.Client.Call("Plugin.Validate", &args, &resp) 95 if err != nil { 96 return nil, []error{err} 97 } 98 99 var errs []error 100 if len(resp.Errors) > 0 { 101 errs = make([]error, len(resp.Errors)) 102 for i, err := range resp.Errors { 103 errs[i] = err 104 } 105 } 106 107 return resp.Warnings, errs 108 } 109 110 func (p *ResourceProvider) ValidateResource( 111 t string, c *terraform.ResourceConfig) ([]string, []error) { 112 var resp ResourceProviderValidateResourceResponse 113 args := ResourceProviderValidateResourceArgs{ 114 Config: c, 115 Type: t, 116 } 117 118 err := p.Client.Call("Plugin.ValidateResource", &args, &resp) 119 if err != nil { 120 return nil, []error{err} 121 } 122 123 var errs []error 124 if len(resp.Errors) > 0 { 125 errs = make([]error, len(resp.Errors)) 126 for i, err := range resp.Errors { 127 errs[i] = err 128 } 129 } 130 131 return resp.Warnings, errs 132 } 133 134 func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error { 135 var resp ResourceProviderConfigureResponse 136 err := p.Client.Call("Plugin.Configure", c, &resp) 137 if err != nil { 138 return err 139 } 140 if resp.Error != nil { 141 err = resp.Error 142 } 143 144 return err 145 } 146 147 func (p *ResourceProvider) Apply( 148 info *terraform.InstanceInfo, 149 s *terraform.InstanceState, 150 d *terraform.InstanceDiff) (*terraform.InstanceState, error) { 151 var resp ResourceProviderApplyResponse 152 args := &ResourceProviderApplyArgs{ 153 Info: info, 154 State: s, 155 Diff: d, 156 } 157 158 err := p.Client.Call("Plugin.Apply", args, &resp) 159 if err != nil { 160 return nil, err 161 } 162 if resp.Error != nil { 163 err = resp.Error 164 } 165 166 return resp.State, err 167 } 168 169 func (p *ResourceProvider) Diff( 170 info *terraform.InstanceInfo, 171 s *terraform.InstanceState, 172 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 173 var resp ResourceProviderDiffResponse 174 args := &ResourceProviderDiffArgs{ 175 Info: info, 176 State: s, 177 Config: c, 178 } 179 err := p.Client.Call("Plugin.Diff", args, &resp) 180 if err != nil { 181 return nil, err 182 } 183 if resp.Error != nil { 184 err = resp.Error 185 } 186 187 return resp.Diff, err 188 } 189 190 func (p *ResourceProvider) ValidateDataSource( 191 t string, c *terraform.ResourceConfig) ([]string, []error) { 192 var resp ResourceProviderValidateResourceResponse 193 args := ResourceProviderValidateResourceArgs{ 194 Config: c, 195 Type: t, 196 } 197 198 err := p.Client.Call("Plugin.ValidateDataSource", &args, &resp) 199 if err != nil { 200 return nil, []error{err} 201 } 202 203 var errs []error 204 if len(resp.Errors) > 0 { 205 errs = make([]error, len(resp.Errors)) 206 for i, err := range resp.Errors { 207 errs[i] = err 208 } 209 } 210 211 return resp.Warnings, errs 212 } 213 214 func (p *ResourceProvider) Refresh( 215 info *terraform.InstanceInfo, 216 s *terraform.InstanceState) (*terraform.InstanceState, error) { 217 var resp ResourceProviderRefreshResponse 218 args := &ResourceProviderRefreshArgs{ 219 Info: info, 220 State: s, 221 } 222 223 err := p.Client.Call("Plugin.Refresh", args, &resp) 224 if err != nil { 225 return nil, err 226 } 227 if resp.Error != nil { 228 err = resp.Error 229 } 230 231 return resp.State, err 232 } 233 234 func (p *ResourceProvider) ImportState( 235 info *terraform.InstanceInfo, 236 id string) ([]*terraform.InstanceState, error) { 237 var resp ResourceProviderImportStateResponse 238 args := &ResourceProviderImportStateArgs{ 239 Info: info, 240 Id: id, 241 } 242 243 err := p.Client.Call("Plugin.ImportState", args, &resp) 244 if err != nil { 245 return nil, err 246 } 247 if resp.Error != nil { 248 err = resp.Error 249 } 250 251 return resp.State, err 252 } 253 254 func (p *ResourceProvider) Resources() []terraform.ResourceType { 255 var result []terraform.ResourceType 256 257 err := p.Client.Call("Plugin.Resources", new(interface{}), &result) 258 if err != nil { 259 // TODO: panic, log, what? 260 return nil 261 } 262 263 return result 264 } 265 266 func (p *ResourceProvider) ReadDataDiff( 267 info *terraform.InstanceInfo, 268 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 269 var resp ResourceProviderReadDataDiffResponse 270 args := &ResourceProviderReadDataDiffArgs{ 271 Info: info, 272 Config: c, 273 } 274 275 err := p.Client.Call("Plugin.ReadDataDiff", args, &resp) 276 if err != nil { 277 return nil, err 278 } 279 if resp.Error != nil { 280 err = resp.Error 281 } 282 283 return resp.Diff, err 284 } 285 286 func (p *ResourceProvider) ReadDataApply( 287 info *terraform.InstanceInfo, 288 d *terraform.InstanceDiff) (*terraform.InstanceState, error) { 289 var resp ResourceProviderReadDataApplyResponse 290 args := &ResourceProviderReadDataApplyArgs{ 291 Info: info, 292 Diff: d, 293 } 294 295 err := p.Client.Call("Plugin.ReadDataApply", args, &resp) 296 if err != nil { 297 return nil, err 298 } 299 if resp.Error != nil { 300 err = resp.Error 301 } 302 303 return resp.State, err 304 } 305 306 func (p *ResourceProvider) DataSources() []terraform.DataSource { 307 var result []terraform.DataSource 308 309 err := p.Client.Call("Plugin.DataSources", new(interface{}), &result) 310 if err != nil { 311 // TODO: panic, log, what? 312 return nil 313 } 314 315 return result 316 } 317 318 func (p *ResourceProvider) Close() error { 319 return p.Client.Close() 320 } 321 322 // ResourceProviderServer is a net/rpc compatible structure for serving 323 // a ResourceProvider. This should not be used directly. 324 type ResourceProviderServer struct { 325 Broker *plugin.MuxBroker 326 Provider terraform.ResourceProvider 327 } 328 329 type ResourceProviderStopResponse struct { 330 Error *plugin.BasicError 331 } 332 333 type ResourceProviderGetSchemaArgs struct { 334 Req *terraform.ProviderSchemaRequest 335 } 336 337 type ResourceProviderGetSchemaResponse struct { 338 Schema *terraform.ProviderSchema 339 Error *plugin.BasicError 340 } 341 342 type ResourceProviderConfigureResponse struct { 343 Error *plugin.BasicError 344 } 345 346 type ResourceProviderInputArgs struct { 347 InputId uint32 348 Config *terraform.ResourceConfig 349 } 350 351 type ResourceProviderInputResponse struct { 352 Config *terraform.ResourceConfig 353 Error *plugin.BasicError 354 } 355 356 type ResourceProviderApplyArgs struct { 357 Info *terraform.InstanceInfo 358 State *terraform.InstanceState 359 Diff *terraform.InstanceDiff 360 } 361 362 type ResourceProviderApplyResponse struct { 363 State *terraform.InstanceState 364 Error *plugin.BasicError 365 } 366 367 type ResourceProviderDiffArgs struct { 368 Info *terraform.InstanceInfo 369 State *terraform.InstanceState 370 Config *terraform.ResourceConfig 371 } 372 373 type ResourceProviderDiffResponse struct { 374 Diff *terraform.InstanceDiff 375 Error *plugin.BasicError 376 } 377 378 type ResourceProviderRefreshArgs struct { 379 Info *terraform.InstanceInfo 380 State *terraform.InstanceState 381 } 382 383 type ResourceProviderRefreshResponse struct { 384 State *terraform.InstanceState 385 Error *plugin.BasicError 386 } 387 388 type ResourceProviderImportStateArgs struct { 389 Info *terraform.InstanceInfo 390 Id string 391 } 392 393 type ResourceProviderImportStateResponse struct { 394 State []*terraform.InstanceState 395 Error *plugin.BasicError 396 } 397 398 type ResourceProviderReadDataApplyArgs struct { 399 Info *terraform.InstanceInfo 400 Diff *terraform.InstanceDiff 401 } 402 403 type ResourceProviderReadDataApplyResponse struct { 404 State *terraform.InstanceState 405 Error *plugin.BasicError 406 } 407 408 type ResourceProviderReadDataDiffArgs struct { 409 Info *terraform.InstanceInfo 410 Config *terraform.ResourceConfig 411 } 412 413 type ResourceProviderReadDataDiffResponse struct { 414 Diff *terraform.InstanceDiff 415 Error *plugin.BasicError 416 } 417 418 type ResourceProviderValidateArgs struct { 419 Config *terraform.ResourceConfig 420 } 421 422 type ResourceProviderValidateResponse struct { 423 Warnings []string 424 Errors []*plugin.BasicError 425 } 426 427 type ResourceProviderValidateResourceArgs struct { 428 Config *terraform.ResourceConfig 429 Type string 430 } 431 432 type ResourceProviderValidateResourceResponse struct { 433 Warnings []string 434 Errors []*plugin.BasicError 435 } 436 437 func (s *ResourceProviderServer) Stop( 438 _ interface{}, 439 reply *ResourceProviderStopResponse) error { 440 err := s.Provider.Stop() 441 *reply = ResourceProviderStopResponse{ 442 Error: plugin.NewBasicError(err), 443 } 444 445 return nil 446 } 447 448 func (s *ResourceProviderServer) GetSchema( 449 args *ResourceProviderGetSchemaArgs, 450 result *ResourceProviderGetSchemaResponse, 451 ) error { 452 schema, err := s.Provider.GetSchema(args.Req) 453 result.Schema = schema 454 if err != nil { 455 result.Error = plugin.NewBasicError(err) 456 } 457 return nil 458 } 459 460 func (s *ResourceProviderServer) Input( 461 args *ResourceProviderInputArgs, 462 reply *ResourceProviderInputResponse) error { 463 conn, err := s.Broker.Dial(args.InputId) 464 if err != nil { 465 *reply = ResourceProviderInputResponse{ 466 Error: plugin.NewBasicError(err), 467 } 468 return nil 469 } 470 client := rpc.NewClient(conn) 471 defer client.Close() 472 473 input := &UIInput{Client: client} 474 475 config, err := s.Provider.Input(input, args.Config) 476 *reply = ResourceProviderInputResponse{ 477 Config: config, 478 Error: plugin.NewBasicError(err), 479 } 480 481 return nil 482 } 483 484 func (s *ResourceProviderServer) Validate( 485 args *ResourceProviderValidateArgs, 486 reply *ResourceProviderValidateResponse) error { 487 warns, errs := s.Provider.Validate(args.Config) 488 berrs := make([]*plugin.BasicError, len(errs)) 489 for i, err := range errs { 490 berrs[i] = plugin.NewBasicError(err) 491 } 492 *reply = ResourceProviderValidateResponse{ 493 Warnings: warns, 494 Errors: berrs, 495 } 496 return nil 497 } 498 499 func (s *ResourceProviderServer) ValidateResource( 500 args *ResourceProviderValidateResourceArgs, 501 reply *ResourceProviderValidateResourceResponse) error { 502 warns, errs := s.Provider.ValidateResource(args.Type, args.Config) 503 berrs := make([]*plugin.BasicError, len(errs)) 504 for i, err := range errs { 505 berrs[i] = plugin.NewBasicError(err) 506 } 507 *reply = ResourceProviderValidateResourceResponse{ 508 Warnings: warns, 509 Errors: berrs, 510 } 511 return nil 512 } 513 514 func (s *ResourceProviderServer) Configure( 515 config *terraform.ResourceConfig, 516 reply *ResourceProviderConfigureResponse) error { 517 err := s.Provider.Configure(config) 518 *reply = ResourceProviderConfigureResponse{ 519 Error: plugin.NewBasicError(err), 520 } 521 return nil 522 } 523 524 func (s *ResourceProviderServer) Apply( 525 args *ResourceProviderApplyArgs, 526 result *ResourceProviderApplyResponse) error { 527 state, err := s.Provider.Apply(args.Info, args.State, args.Diff) 528 *result = ResourceProviderApplyResponse{ 529 State: state, 530 Error: plugin.NewBasicError(err), 531 } 532 return nil 533 } 534 535 func (s *ResourceProviderServer) Diff( 536 args *ResourceProviderDiffArgs, 537 result *ResourceProviderDiffResponse) error { 538 diff, err := s.Provider.Diff(args.Info, args.State, args.Config) 539 *result = ResourceProviderDiffResponse{ 540 Diff: diff, 541 Error: plugin.NewBasicError(err), 542 } 543 return nil 544 } 545 546 func (s *ResourceProviderServer) Refresh( 547 args *ResourceProviderRefreshArgs, 548 result *ResourceProviderRefreshResponse) error { 549 newState, err := s.Provider.Refresh(args.Info, args.State) 550 *result = ResourceProviderRefreshResponse{ 551 State: newState, 552 Error: plugin.NewBasicError(err), 553 } 554 return nil 555 } 556 557 func (s *ResourceProviderServer) ImportState( 558 args *ResourceProviderImportStateArgs, 559 result *ResourceProviderImportStateResponse) error { 560 states, err := s.Provider.ImportState(args.Info, args.Id) 561 *result = ResourceProviderImportStateResponse{ 562 State: states, 563 Error: plugin.NewBasicError(err), 564 } 565 return nil 566 } 567 568 func (s *ResourceProviderServer) Resources( 569 nothing interface{}, 570 result *[]terraform.ResourceType) error { 571 *result = s.Provider.Resources() 572 return nil 573 } 574 575 func (s *ResourceProviderServer) ValidateDataSource( 576 args *ResourceProviderValidateResourceArgs, 577 reply *ResourceProviderValidateResourceResponse) error { 578 warns, errs := s.Provider.ValidateDataSource(args.Type, args.Config) 579 berrs := make([]*plugin.BasicError, len(errs)) 580 for i, err := range errs { 581 berrs[i] = plugin.NewBasicError(err) 582 } 583 *reply = ResourceProviderValidateResourceResponse{ 584 Warnings: warns, 585 Errors: berrs, 586 } 587 return nil 588 } 589 590 func (s *ResourceProviderServer) ReadDataDiff( 591 args *ResourceProviderReadDataDiffArgs, 592 result *ResourceProviderReadDataDiffResponse) error { 593 diff, err := s.Provider.ReadDataDiff(args.Info, args.Config) 594 *result = ResourceProviderReadDataDiffResponse{ 595 Diff: diff, 596 Error: plugin.NewBasicError(err), 597 } 598 return nil 599 } 600 601 func (s *ResourceProviderServer) ReadDataApply( 602 args *ResourceProviderReadDataApplyArgs, 603 result *ResourceProviderReadDataApplyResponse) error { 604 newState, err := s.Provider.ReadDataApply(args.Info, args.Diff) 605 *result = ResourceProviderReadDataApplyResponse{ 606 State: newState, 607 Error: plugin.NewBasicError(err), 608 } 609 return nil 610 } 611 612 func (s *ResourceProviderServer) DataSources( 613 nothing interface{}, 614 result *[]terraform.DataSource) error { 615 *result = s.Provider.DataSources() 616 return nil 617 }