github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/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 }