github.com/fluxrad/terraform@v0.6.4-0.20150906191316-06627ccf39fa/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  func (p *ResourceProvider) Close() error {
   178  	return p.Client.Close()
   179  }
   180  
   181  // ResourceProviderServer is a net/rpc compatible structure for serving
   182  // a ResourceProvider. This should not be used directly.
   183  type ResourceProviderServer struct {
   184  	Broker   *muxBroker
   185  	Provider terraform.ResourceProvider
   186  }
   187  
   188  type ResourceProviderConfigureResponse struct {
   189  	Error *BasicError
   190  }
   191  
   192  type ResourceProviderInputArgs struct {
   193  	InputId uint32
   194  	Config  *terraform.ResourceConfig
   195  }
   196  
   197  type ResourceProviderInputResponse struct {
   198  	Config *terraform.ResourceConfig
   199  	Error  *BasicError
   200  }
   201  
   202  type ResourceProviderApplyArgs struct {
   203  	Info  *terraform.InstanceInfo
   204  	State *terraform.InstanceState
   205  	Diff  *terraform.InstanceDiff
   206  }
   207  
   208  type ResourceProviderApplyResponse struct {
   209  	State *terraform.InstanceState
   210  	Error *BasicError
   211  }
   212  
   213  type ResourceProviderDiffArgs struct {
   214  	Info   *terraform.InstanceInfo
   215  	State  *terraform.InstanceState
   216  	Config *terraform.ResourceConfig
   217  }
   218  
   219  type ResourceProviderDiffResponse struct {
   220  	Diff  *terraform.InstanceDiff
   221  	Error *BasicError
   222  }
   223  
   224  type ResourceProviderRefreshArgs struct {
   225  	Info  *terraform.InstanceInfo
   226  	State *terraform.InstanceState
   227  }
   228  
   229  type ResourceProviderRefreshResponse struct {
   230  	State *terraform.InstanceState
   231  	Error *BasicError
   232  }
   233  
   234  type ResourceProviderValidateArgs struct {
   235  	Config *terraform.ResourceConfig
   236  }
   237  
   238  type ResourceProviderValidateResponse struct {
   239  	Warnings []string
   240  	Errors   []*BasicError
   241  }
   242  
   243  type ResourceProviderValidateResourceArgs struct {
   244  	Config *terraform.ResourceConfig
   245  	Type   string
   246  }
   247  
   248  type ResourceProviderValidateResourceResponse struct {
   249  	Warnings []string
   250  	Errors   []*BasicError
   251  }
   252  
   253  func (s *ResourceProviderServer) Input(
   254  	args *ResourceProviderInputArgs,
   255  	reply *ResourceProviderInputResponse) error {
   256  	conn, err := s.Broker.Dial(args.InputId)
   257  	if err != nil {
   258  		*reply = ResourceProviderInputResponse{
   259  			Error: NewBasicError(err),
   260  		}
   261  		return nil
   262  	}
   263  	client := rpc.NewClient(conn)
   264  	defer client.Close()
   265  
   266  	input := &UIInput{
   267  		Client: client,
   268  		Name:   "UIInput",
   269  	}
   270  
   271  	config, err := s.Provider.Input(input, args.Config)
   272  	*reply = ResourceProviderInputResponse{
   273  		Config: config,
   274  		Error:  NewBasicError(err),
   275  	}
   276  
   277  	return nil
   278  }
   279  
   280  func (s *ResourceProviderServer) Validate(
   281  	args *ResourceProviderValidateArgs,
   282  	reply *ResourceProviderValidateResponse) error {
   283  	warns, errs := s.Provider.Validate(args.Config)
   284  	berrs := make([]*BasicError, len(errs))
   285  	for i, err := range errs {
   286  		berrs[i] = NewBasicError(err)
   287  	}
   288  	*reply = ResourceProviderValidateResponse{
   289  		Warnings: warns,
   290  		Errors:   berrs,
   291  	}
   292  	return nil
   293  }
   294  
   295  func (s *ResourceProviderServer) ValidateResource(
   296  	args *ResourceProviderValidateResourceArgs,
   297  	reply *ResourceProviderValidateResourceResponse) error {
   298  	warns, errs := s.Provider.ValidateResource(args.Type, args.Config)
   299  	berrs := make([]*BasicError, len(errs))
   300  	for i, err := range errs {
   301  		berrs[i] = NewBasicError(err)
   302  	}
   303  	*reply = ResourceProviderValidateResourceResponse{
   304  		Warnings: warns,
   305  		Errors:   berrs,
   306  	}
   307  	return nil
   308  }
   309  
   310  func (s *ResourceProviderServer) Configure(
   311  	config *terraform.ResourceConfig,
   312  	reply *ResourceProviderConfigureResponse) error {
   313  	err := s.Provider.Configure(config)
   314  	*reply = ResourceProviderConfigureResponse{
   315  		Error: NewBasicError(err),
   316  	}
   317  	return nil
   318  }
   319  
   320  func (s *ResourceProviderServer) Apply(
   321  	args *ResourceProviderApplyArgs,
   322  	result *ResourceProviderApplyResponse) error {
   323  	state, err := s.Provider.Apply(args.Info, args.State, args.Diff)
   324  	*result = ResourceProviderApplyResponse{
   325  		State: state,
   326  		Error: NewBasicError(err),
   327  	}
   328  	return nil
   329  }
   330  
   331  func (s *ResourceProviderServer) Diff(
   332  	args *ResourceProviderDiffArgs,
   333  	result *ResourceProviderDiffResponse) error {
   334  	diff, err := s.Provider.Diff(args.Info, args.State, args.Config)
   335  	*result = ResourceProviderDiffResponse{
   336  		Diff:  diff,
   337  		Error: NewBasicError(err),
   338  	}
   339  	return nil
   340  }
   341  
   342  func (s *ResourceProviderServer) Refresh(
   343  	args *ResourceProviderRefreshArgs,
   344  	result *ResourceProviderRefreshResponse) error {
   345  	newState, err := s.Provider.Refresh(args.Info, args.State)
   346  	*result = ResourceProviderRefreshResponse{
   347  		State: newState,
   348  		Error: NewBasicError(err),
   349  	}
   350  	return nil
   351  }
   352  
   353  func (s *ResourceProviderServer) Resources(
   354  	nothing interface{},
   355  	result *[]terraform.ResourceType) error {
   356  	*result = s.Provider.Resources()
   357  	return nil
   358  }