mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 18:01:01 -06:00
e6592dc710
Implement a new provider_meta block in the terraform block of modules, allowing provider-keyed metadata to be communicated from HCL to provider binaries. Bundled in this change for minimal protocol version bumping is the addition of markdown support for attribute descriptions and the ability to indicate when an attribute is deprecated, so this information can be shown in the schema dump. Co-authored-by: Paul Tyng <paul@paultyng.net>
621 lines
14 KiB
Go
621 lines
14 KiB
Go
package plugin
|
|
|
|
import (
|
|
"net/rpc"
|
|
|
|
plugin "github.com/hashicorp/go-plugin"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
// ResourceProviderPlugin is the plugin.Plugin implementation.
|
|
type ResourceProviderPlugin struct {
|
|
ResourceProvider func() terraform.ResourceProvider
|
|
}
|
|
|
|
func (p *ResourceProviderPlugin) Server(b *plugin.MuxBroker) (interface{}, error) {
|
|
return &ResourceProviderServer{
|
|
Broker: b,
|
|
Provider: p.ResourceProvider(),
|
|
}, nil
|
|
}
|
|
|
|
func (p *ResourceProviderPlugin) Client(
|
|
b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
|
|
return &ResourceProvider{Broker: b, Client: c}, nil
|
|
}
|
|
|
|
// ResourceProvider is an implementation of terraform.ResourceProvider
|
|
// that communicates over RPC.
|
|
type ResourceProvider struct {
|
|
Broker *plugin.MuxBroker
|
|
Client *rpc.Client
|
|
}
|
|
|
|
func (p *ResourceProvider) Stop() error {
|
|
var resp ResourceProviderStopResponse
|
|
err := p.Client.Call("Plugin.Stop", new(interface{}), &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (p *ResourceProvider) GetSchema(req *terraform.ProviderSchemaRequest) (*terraform.ProviderSchema, error) {
|
|
var result ResourceProviderGetSchemaResponse
|
|
args := &ResourceProviderGetSchemaArgs{
|
|
Req: req,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.GetSchema", args, &result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if result.Error != nil {
|
|
err = result.Error
|
|
}
|
|
|
|
return result.Schema, err
|
|
}
|
|
|
|
func (p *ResourceProvider) Input(
|
|
input terraform.UIInput,
|
|
c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
|
|
id := p.Broker.NextId()
|
|
go p.Broker.AcceptAndServe(id, &UIInputServer{
|
|
UIInput: input,
|
|
})
|
|
|
|
var resp ResourceProviderInputResponse
|
|
args := ResourceProviderInputArgs{
|
|
InputId: id,
|
|
Config: c,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.Input", &args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
return nil, err
|
|
}
|
|
|
|
return resp.Config, nil
|
|
}
|
|
|
|
func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
|
var resp ResourceProviderValidateResponse
|
|
args := ResourceProviderValidateArgs{
|
|
Config: c,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.Validate", &args, &resp)
|
|
if err != nil {
|
|
return nil, []error{err}
|
|
}
|
|
|
|
var errs []error
|
|
if len(resp.Errors) > 0 {
|
|
errs = make([]error, len(resp.Errors))
|
|
for i, err := range resp.Errors {
|
|
errs[i] = err
|
|
}
|
|
}
|
|
|
|
return resp.Warnings, errs
|
|
}
|
|
|
|
func (p *ResourceProvider) ValidateResource(
|
|
t string, c *terraform.ResourceConfig) ([]string, []error) {
|
|
var resp ResourceProviderValidateResourceResponse
|
|
args := ResourceProviderValidateResourceArgs{
|
|
Config: c,
|
|
Type: t,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.ValidateResource", &args, &resp)
|
|
if err != nil {
|
|
return nil, []error{err}
|
|
}
|
|
|
|
var errs []error
|
|
if len(resp.Errors) > 0 {
|
|
errs = make([]error, len(resp.Errors))
|
|
for i, err := range resp.Errors {
|
|
errs[i] = err
|
|
}
|
|
}
|
|
|
|
return resp.Warnings, errs
|
|
}
|
|
|
|
func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
|
|
var resp ResourceProviderConfigureResponse
|
|
err := p.Client.Call("Plugin.Configure", c, &resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func (p *ResourceProvider) Apply(
|
|
info *terraform.InstanceInfo,
|
|
s *terraform.InstanceState,
|
|
d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
|
|
var resp ResourceProviderApplyResponse
|
|
args := &ResourceProviderApplyArgs{
|
|
Info: info,
|
|
State: s,
|
|
Diff: d,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.Apply", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.State, err
|
|
}
|
|
|
|
func (p *ResourceProvider) Diff(
|
|
info *terraform.InstanceInfo,
|
|
s *terraform.InstanceState,
|
|
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
|
|
var resp ResourceProviderDiffResponse
|
|
args := &ResourceProviderDiffArgs{
|
|
Info: info,
|
|
State: s,
|
|
Config: c,
|
|
}
|
|
err := p.Client.Call("Plugin.Diff", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.Diff, err
|
|
}
|
|
|
|
func (p *ResourceProvider) ValidateDataSource(
|
|
t string, c *terraform.ResourceConfig) ([]string, []error) {
|
|
var resp ResourceProviderValidateResourceResponse
|
|
args := ResourceProviderValidateResourceArgs{
|
|
Config: c,
|
|
Type: t,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.ValidateDataSource", &args, &resp)
|
|
if err != nil {
|
|
return nil, []error{err}
|
|
}
|
|
|
|
var errs []error
|
|
if len(resp.Errors) > 0 {
|
|
errs = make([]error, len(resp.Errors))
|
|
for i, err := range resp.Errors {
|
|
errs[i] = err
|
|
}
|
|
}
|
|
|
|
return resp.Warnings, errs
|
|
}
|
|
|
|
func (p *ResourceProvider) Refresh(
|
|
info *terraform.InstanceInfo,
|
|
s *terraform.InstanceState) (*terraform.InstanceState, error) {
|
|
var resp ResourceProviderRefreshResponse
|
|
args := &ResourceProviderRefreshArgs{
|
|
Info: info,
|
|
State: s,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.Refresh", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.State, err
|
|
}
|
|
|
|
func (p *ResourceProvider) ImportState(
|
|
info *terraform.InstanceInfo,
|
|
id string) ([]*terraform.InstanceState, error) {
|
|
var resp ResourceProviderImportStateResponse
|
|
args := &ResourceProviderImportStateArgs{
|
|
Info: info,
|
|
Id: id,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.ImportState", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.State, err
|
|
}
|
|
|
|
func (p *ResourceProvider) Resources() []terraform.ResourceType {
|
|
var result []terraform.ResourceType
|
|
|
|
err := p.Client.Call("Plugin.Resources", new(interface{}), &result)
|
|
if err != nil {
|
|
// TODO: panic, log, what?
|
|
return nil
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (p *ResourceProvider) ReadDataDiff(
|
|
info *terraform.InstanceInfo,
|
|
c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
|
|
var resp ResourceProviderReadDataDiffResponse
|
|
args := &ResourceProviderReadDataDiffArgs{
|
|
Info: info,
|
|
Config: c,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.ReadDataDiff", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.Diff, err
|
|
}
|
|
|
|
func (p *ResourceProvider) ReadDataApply(
|
|
info *terraform.InstanceInfo,
|
|
d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
|
|
var resp ResourceProviderReadDataApplyResponse
|
|
args := &ResourceProviderReadDataApplyArgs{
|
|
Info: info,
|
|
Diff: d,
|
|
}
|
|
|
|
err := p.Client.Call("Plugin.ReadDataApply", args, &resp)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Error != nil {
|
|
err = resp.Error
|
|
}
|
|
|
|
return resp.State, err
|
|
}
|
|
|
|
func (p *ResourceProvider) DataSources() []terraform.DataSource {
|
|
var result []terraform.DataSource
|
|
|
|
err := p.Client.Call("Plugin.DataSources", new(interface{}), &result)
|
|
if err != nil {
|
|
// TODO: panic, log, what?
|
|
return nil
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (p *ResourceProvider) Close() error {
|
|
return p.Client.Close()
|
|
}
|
|
|
|
// ResourceProviderServer is a net/rpc compatible structure for serving
|
|
// a ResourceProvider. This should not be used directly.
|
|
type ResourceProviderServer struct {
|
|
Broker *plugin.MuxBroker
|
|
Provider terraform.ResourceProvider
|
|
}
|
|
|
|
type ResourceProviderStopResponse struct {
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderGetSchemaArgs struct {
|
|
Req *terraform.ProviderSchemaRequest
|
|
}
|
|
|
|
type ResourceProviderGetSchemaResponse struct {
|
|
Schema *terraform.ProviderSchema
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderConfigureResponse struct {
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderInputArgs struct {
|
|
InputId uint32
|
|
Config *terraform.ResourceConfig
|
|
}
|
|
|
|
type ResourceProviderInputResponse struct {
|
|
Config *terraform.ResourceConfig
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderApplyArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
State *terraform.InstanceState
|
|
Diff *terraform.InstanceDiff
|
|
}
|
|
|
|
type ResourceProviderApplyResponse struct {
|
|
State *terraform.InstanceState
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderDiffArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
State *terraform.InstanceState
|
|
Config *terraform.ResourceConfig
|
|
}
|
|
|
|
type ResourceProviderDiffResponse struct {
|
|
Diff *terraform.InstanceDiff
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderRefreshArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
State *terraform.InstanceState
|
|
}
|
|
|
|
type ResourceProviderRefreshResponse struct {
|
|
State *terraform.InstanceState
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderImportStateArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
Id string
|
|
}
|
|
|
|
type ResourceProviderImportStateResponse struct {
|
|
State []*terraform.InstanceState
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderReadDataApplyArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
Diff *terraform.InstanceDiff
|
|
}
|
|
|
|
type ResourceProviderReadDataApplyResponse struct {
|
|
State *terraform.InstanceState
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderReadDataDiffArgs struct {
|
|
Info *terraform.InstanceInfo
|
|
Config *terraform.ResourceConfig
|
|
}
|
|
|
|
type ResourceProviderReadDataDiffResponse struct {
|
|
Diff *terraform.InstanceDiff
|
|
Error *plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderValidateArgs struct {
|
|
Config *terraform.ResourceConfig
|
|
}
|
|
|
|
type ResourceProviderValidateResponse struct {
|
|
Warnings []string
|
|
Errors []*plugin.BasicError
|
|
}
|
|
|
|
type ResourceProviderValidateResourceArgs struct {
|
|
Config *terraform.ResourceConfig
|
|
Type string
|
|
}
|
|
|
|
type ResourceProviderValidateResourceResponse struct {
|
|
Warnings []string
|
|
Errors []*plugin.BasicError
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Stop(
|
|
_ interface{},
|
|
reply *ResourceProviderStopResponse) error {
|
|
err := s.Provider.Stop()
|
|
*reply = ResourceProviderStopResponse{
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) GetSchema(
|
|
args *ResourceProviderGetSchemaArgs,
|
|
result *ResourceProviderGetSchemaResponse,
|
|
) error {
|
|
schema, err := s.Provider.GetSchema(args.Req)
|
|
result.Schema = schema
|
|
if err != nil {
|
|
result.Error = plugin.NewBasicError(err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Input(
|
|
args *ResourceProviderInputArgs,
|
|
reply *ResourceProviderInputResponse) error {
|
|
conn, err := s.Broker.Dial(args.InputId)
|
|
if err != nil {
|
|
*reply = ResourceProviderInputResponse{
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
client := rpc.NewClient(conn)
|
|
defer client.Close()
|
|
|
|
input := &UIInput{Client: client}
|
|
|
|
config, err := s.Provider.Input(input, args.Config)
|
|
*reply = ResourceProviderInputResponse{
|
|
Config: config,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Validate(
|
|
args *ResourceProviderValidateArgs,
|
|
reply *ResourceProviderValidateResponse) error {
|
|
warns, errs := s.Provider.Validate(args.Config)
|
|
berrs := make([]*plugin.BasicError, len(errs))
|
|
for i, err := range errs {
|
|
berrs[i] = plugin.NewBasicError(err)
|
|
}
|
|
*reply = ResourceProviderValidateResponse{
|
|
Warnings: warns,
|
|
Errors: berrs,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) ValidateResource(
|
|
args *ResourceProviderValidateResourceArgs,
|
|
reply *ResourceProviderValidateResourceResponse) error {
|
|
warns, errs := s.Provider.ValidateResource(args.Type, args.Config)
|
|
berrs := make([]*plugin.BasicError, len(errs))
|
|
for i, err := range errs {
|
|
berrs[i] = plugin.NewBasicError(err)
|
|
}
|
|
*reply = ResourceProviderValidateResourceResponse{
|
|
Warnings: warns,
|
|
Errors: berrs,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Configure(
|
|
config *terraform.ResourceConfig,
|
|
reply *ResourceProviderConfigureResponse) error {
|
|
err := s.Provider.Configure(config)
|
|
*reply = ResourceProviderConfigureResponse{
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Apply(
|
|
args *ResourceProviderApplyArgs,
|
|
result *ResourceProviderApplyResponse) error {
|
|
state, err := s.Provider.Apply(args.Info, args.State, args.Diff)
|
|
*result = ResourceProviderApplyResponse{
|
|
State: state,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Diff(
|
|
args *ResourceProviderDiffArgs,
|
|
result *ResourceProviderDiffResponse) error {
|
|
diff, err := s.Provider.Diff(args.Info, args.State, args.Config)
|
|
*result = ResourceProviderDiffResponse{
|
|
Diff: diff,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Refresh(
|
|
args *ResourceProviderRefreshArgs,
|
|
result *ResourceProviderRefreshResponse) error {
|
|
newState, err := s.Provider.Refresh(args.Info, args.State)
|
|
*result = ResourceProviderRefreshResponse{
|
|
State: newState,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) ImportState(
|
|
args *ResourceProviderImportStateArgs,
|
|
result *ResourceProviderImportStateResponse) error {
|
|
states, err := s.Provider.ImportState(args.Info, args.Id)
|
|
*result = ResourceProviderImportStateResponse{
|
|
State: states,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) Resources(
|
|
nothing interface{},
|
|
result *[]terraform.ResourceType) error {
|
|
*result = s.Provider.Resources()
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) ValidateDataSource(
|
|
args *ResourceProviderValidateResourceArgs,
|
|
reply *ResourceProviderValidateResourceResponse) error {
|
|
warns, errs := s.Provider.ValidateDataSource(args.Type, args.Config)
|
|
berrs := make([]*plugin.BasicError, len(errs))
|
|
for i, err := range errs {
|
|
berrs[i] = plugin.NewBasicError(err)
|
|
}
|
|
*reply = ResourceProviderValidateResourceResponse{
|
|
Warnings: warns,
|
|
Errors: berrs,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) ReadDataDiff(
|
|
args *ResourceProviderReadDataDiffArgs,
|
|
result *ResourceProviderReadDataDiffResponse) error {
|
|
diff, err := s.Provider.ReadDataDiff(args.Info, args.Config)
|
|
*result = ResourceProviderReadDataDiffResponse{
|
|
Diff: diff,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) ReadDataApply(
|
|
args *ResourceProviderReadDataApplyArgs,
|
|
result *ResourceProviderReadDataApplyResponse) error {
|
|
newState, err := s.Provider.ReadDataApply(args.Info, args.Diff)
|
|
*result = ResourceProviderReadDataApplyResponse{
|
|
State: newState,
|
|
Error: plugin.NewBasicError(err),
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *ResourceProviderServer) DataSources(
|
|
nothing interface{},
|
|
result *[]terraform.DataSource) error {
|
|
*result = s.Provider.DataSources()
|
|
return nil
|
|
}
|