github.com/bendemaree/terraform@v0.5.4-0.20150613200311-f50d97d6eee6/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 }