github.com/adamar/terraform@v0.2.2-0.20141016210445-2e703afdad0e/rpc/resource_provider.go (about)

     1  package rpc
     2  
     3  import (
     4  	"net/rpc"
     5  
     6  	"github.com/hashicorp/terraform/terraform"
     7  )
     8  
     9  // ResourceProvider is an implementation of terraform.ResourceProvider
    10  // that communicates over RPC.
    11  type ResourceProvider struct {
    12  	Broker *muxBroker
    13  	Client *rpc.Client
    14  	Name   string
    15  }
    16  
    17  func (p *ResourceProvider) Input(
    18  	input terraform.UIInput,
    19  	c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
    20  	id := p.Broker.NextId()
    21  	go acceptAndServe(p.Broker, id, "UIInput", &UIInputServer{
    22  		UIInput: input,
    23  	})
    24  
    25  	var resp ResourceProviderInputResponse
    26  	args := ResourceProviderInputArgs{
    27  		InputId: id,
    28  		Config:  c,
    29  	}
    30  
    31  	err := p.Client.Call(p.Name+".Input", &args, &resp)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  	if resp.Error != nil {
    36  		err = resp.Error
    37  		return nil, err
    38  	}
    39  
    40  	return resp.Config, nil
    41  }
    42  
    43  func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) {
    44  	var resp ResourceProviderValidateResponse
    45  	args := ResourceProviderValidateArgs{
    46  		Config: c,
    47  	}
    48  
    49  	err := p.Client.Call(p.Name+".Validate", &args, &resp)
    50  	if err != nil {
    51  		return nil, []error{err}
    52  	}
    53  
    54  	var errs []error
    55  	if len(resp.Errors) > 0 {
    56  		errs = make([]error, len(resp.Errors))
    57  		for i, err := range resp.Errors {
    58  			errs[i] = err
    59  		}
    60  	}
    61  
    62  	return resp.Warnings, errs
    63  }
    64  
    65  func (p *ResourceProvider) ValidateResource(
    66  	t string, c *terraform.ResourceConfig) ([]string, []error) {
    67  	var resp ResourceProviderValidateResourceResponse
    68  	args := ResourceProviderValidateResourceArgs{
    69  		Config: c,
    70  		Type:   t,
    71  	}
    72  
    73  	err := p.Client.Call(p.Name+".ValidateResource", &args, &resp)
    74  	if err != nil {
    75  		return nil, []error{err}
    76  	}
    77  
    78  	var errs []error
    79  	if len(resp.Errors) > 0 {
    80  		errs = make([]error, len(resp.Errors))
    81  		for i, err := range resp.Errors {
    82  			errs[i] = err
    83  		}
    84  	}
    85  
    86  	return resp.Warnings, errs
    87  }
    88  
    89  func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
    90  	var resp ResourceProviderConfigureResponse
    91  	err := p.Client.Call(p.Name+".Configure", c, &resp)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	if resp.Error != nil {
    96  		err = resp.Error
    97  	}
    98  
    99  	return err
   100  }
   101  
   102  func (p *ResourceProvider) Apply(
   103  	info *terraform.InstanceInfo,
   104  	s *terraform.InstanceState,
   105  	d *terraform.InstanceDiff) (*terraform.InstanceState, error) {
   106  	var resp ResourceProviderApplyResponse
   107  	args := &ResourceProviderApplyArgs{
   108  		Info:  info,
   109  		State: s,
   110  		Diff:  d,
   111  	}
   112  
   113  	err := p.Client.Call(p.Name+".Apply", args, &resp)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	if resp.Error != nil {
   118  		err = resp.Error
   119  	}
   120  
   121  	return resp.State, err
   122  }
   123  
   124  func (p *ResourceProvider) Diff(
   125  	info *terraform.InstanceInfo,
   126  	s *terraform.InstanceState,
   127  	c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) {
   128  	var resp ResourceProviderDiffResponse
   129  	args := &ResourceProviderDiffArgs{
   130  		Info:   info,
   131  		State:  s,
   132  		Config: c,
   133  	}
   134  	err := p.Client.Call(p.Name+".Diff", args, &resp)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  	if resp.Error != nil {
   139  		err = resp.Error
   140  	}
   141  
   142  	return resp.Diff, err
   143  }
   144  
   145  func (p *ResourceProvider) Refresh(
   146  	info *terraform.InstanceInfo,
   147  	s *terraform.InstanceState) (*terraform.InstanceState, error) {
   148  	var resp ResourceProviderRefreshResponse
   149  	args := &ResourceProviderRefreshArgs{
   150  		Info:  info,
   151  		State: s,
   152  	}
   153  
   154  	err := p.Client.Call(p.Name+".Refresh", args, &resp)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	if resp.Error != nil {
   159  		err = resp.Error
   160  	}
   161  
   162  	return resp.State, err
   163  }
   164  
   165  func (p *ResourceProvider) Resources() []terraform.ResourceType {
   166  	var result []terraform.ResourceType
   167  
   168  	err := p.Client.Call(p.Name+".Resources", new(interface{}), &result)
   169  	if err != nil {
   170  		// TODO: panic, log, what?
   171  		return nil
   172  	}
   173  
   174  	return result
   175  }
   176  
   177  // ResourceProviderServer is a net/rpc compatible structure for serving
   178  // a ResourceProvider. This should not be used directly.
   179  type ResourceProviderServer struct {
   180  	Broker   *muxBroker
   181  	Provider terraform.ResourceProvider
   182  }
   183  
   184  type ResourceProviderConfigureResponse struct {
   185  	Error *BasicError
   186  }
   187  
   188  type ResourceProviderInputArgs struct {
   189  	InputId uint32
   190  	Config  *terraform.ResourceConfig
   191  }
   192  
   193  type ResourceProviderInputResponse struct {
   194  	Config *terraform.ResourceConfig
   195  	Error  *BasicError
   196  }
   197  
   198  type ResourceProviderApplyArgs struct {
   199  	Info  *terraform.InstanceInfo
   200  	State *terraform.InstanceState
   201  	Diff  *terraform.InstanceDiff
   202  }
   203  
   204  type ResourceProviderApplyResponse struct {
   205  	State *terraform.InstanceState
   206  	Error *BasicError
   207  }
   208  
   209  type ResourceProviderDiffArgs struct {
   210  	Info   *terraform.InstanceInfo
   211  	State  *terraform.InstanceState
   212  	Config *terraform.ResourceConfig
   213  }
   214  
   215  type ResourceProviderDiffResponse struct {
   216  	Diff  *terraform.InstanceDiff
   217  	Error *BasicError
   218  }
   219  
   220  type ResourceProviderRefreshArgs struct {
   221  	Info  *terraform.InstanceInfo
   222  	State *terraform.InstanceState
   223  }
   224  
   225  type ResourceProviderRefreshResponse struct {
   226  	State *terraform.InstanceState
   227  	Error *BasicError
   228  }
   229  
   230  type ResourceProviderValidateArgs struct {
   231  	Config *terraform.ResourceConfig
   232  }
   233  
   234  type ResourceProviderValidateResponse struct {
   235  	Warnings []string
   236  	Errors   []*BasicError
   237  }
   238  
   239  type ResourceProviderValidateResourceArgs struct {
   240  	Config *terraform.ResourceConfig
   241  	Type   string
   242  }
   243  
   244  type ResourceProviderValidateResourceResponse struct {
   245  	Warnings []string
   246  	Errors   []*BasicError
   247  }
   248  
   249  func (s *ResourceProviderServer) Input(
   250  	args *ResourceProviderInputArgs,
   251  	reply *ResourceProviderInputResponse) error {
   252  	conn, err := s.Broker.Dial(args.InputId)
   253  	if err != nil {
   254  		*reply = ResourceProviderInputResponse{
   255  			Error: NewBasicError(err),
   256  		}
   257  		return nil
   258  	}
   259  	client := rpc.NewClient(conn)
   260  	defer client.Close()
   261  
   262  	input := &UIInput{
   263  		Client: client,
   264  		Name:   "UIInput",
   265  	}
   266  
   267  	config, err := s.Provider.Input(input, args.Config)
   268  	*reply = ResourceProviderInputResponse{
   269  		Config: config,
   270  		Error:  NewBasicError(err),
   271  	}
   272  
   273  	return nil
   274  }
   275  
   276  func (s *ResourceProviderServer) Validate(
   277  	args *ResourceProviderValidateArgs,
   278  	reply *ResourceProviderValidateResponse) error {
   279  	warns, errs := s.Provider.Validate(args.Config)
   280  	berrs := make([]*BasicError, len(errs))
   281  	for i, err := range errs {
   282  		berrs[i] = NewBasicError(err)
   283  	}
   284  	*reply = ResourceProviderValidateResponse{
   285  		Warnings: warns,
   286  		Errors:   berrs,
   287  	}
   288  	return nil
   289  }
   290  
   291  func (s *ResourceProviderServer) ValidateResource(
   292  	args *ResourceProviderValidateResourceArgs,
   293  	reply *ResourceProviderValidateResourceResponse) error {
   294  	warns, errs := s.Provider.ValidateResource(args.Type, args.Config)
   295  	berrs := make([]*BasicError, len(errs))
   296  	for i, err := range errs {
   297  		berrs[i] = NewBasicError(err)
   298  	}
   299  	*reply = ResourceProviderValidateResourceResponse{
   300  		Warnings: warns,
   301  		Errors:   berrs,
   302  	}
   303  	return nil
   304  }
   305  
   306  func (s *ResourceProviderServer) Configure(
   307  	config *terraform.ResourceConfig,
   308  	reply *ResourceProviderConfigureResponse) error {
   309  	err := s.Provider.Configure(config)
   310  	*reply = ResourceProviderConfigureResponse{
   311  		Error: NewBasicError(err),
   312  	}
   313  	return nil
   314  }
   315  
   316  func (s *ResourceProviderServer) Apply(
   317  	args *ResourceProviderApplyArgs,
   318  	result *ResourceProviderApplyResponse) error {
   319  	state, err := s.Provider.Apply(args.Info, args.State, args.Diff)
   320  	*result = ResourceProviderApplyResponse{
   321  		State: state,
   322  		Error: NewBasicError(err),
   323  	}
   324  	return nil
   325  }
   326  
   327  func (s *ResourceProviderServer) Diff(
   328  	args *ResourceProviderDiffArgs,
   329  	result *ResourceProviderDiffResponse) error {
   330  	diff, err := s.Provider.Diff(args.Info, args.State, args.Config)
   331  	*result = ResourceProviderDiffResponse{
   332  		Diff:  diff,
   333  		Error: NewBasicError(err),
   334  	}
   335  	return nil
   336  }
   337  
   338  func (s *ResourceProviderServer) Refresh(
   339  	args *ResourceProviderRefreshArgs,
   340  	result *ResourceProviderRefreshResponse) error {
   341  	newState, err := s.Provider.Refresh(args.Info, args.State)
   342  	*result = ResourceProviderRefreshResponse{
   343  		State: newState,
   344  		Error: NewBasicError(err),
   345  	}
   346  	return nil
   347  }
   348  
   349  func (s *ResourceProviderServer) Resources(
   350  	nothing interface{},
   351  	result *[]terraform.ResourceType) error {
   352  	*result = s.Provider.Resources()
   353  	return nil
   354  }