github.phpd.cn/hashicorp/packer@v1.3.2/packer/rpc/builder.go (about) 1 package rpc 2 3 import ( 4 "log" 5 "net/rpc" 6 7 "github.com/hashicorp/packer/packer" 8 ) 9 10 // An implementation of packer.Builder where the builder is actually executed 11 // over an RPC connection. 12 type builder struct { 13 client *rpc.Client 14 mux *muxBroker 15 } 16 17 // BuilderServer wraps a packer.Builder implementation and makes it exportable 18 // as part of a Golang RPC server. 19 type BuilderServer struct { 20 builder packer.Builder 21 mux *muxBroker 22 } 23 24 type BuilderPrepareArgs struct { 25 Configs []interface{} 26 } 27 28 type BuilderPrepareResponse struct { 29 Warnings []string 30 Error *BasicError 31 } 32 33 func (b *builder) Prepare(config ...interface{}) ([]string, error) { 34 var resp BuilderPrepareResponse 35 cerr := b.client.Call("Builder.Prepare", &BuilderPrepareArgs{config}, &resp) 36 if cerr != nil { 37 return nil, cerr 38 } 39 var err error = nil 40 if resp.Error != nil { 41 err = resp.Error 42 } 43 44 return resp.Warnings, err 45 } 46 47 func (b *builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 48 nextId := b.mux.NextId() 49 server := newServerWithMux(b.mux, nextId) 50 server.RegisterCache(cache) 51 server.RegisterHook(hook) 52 server.RegisterUi(ui) 53 go server.Serve() 54 55 var responseId uint32 56 if err := b.client.Call("Builder.Run", nextId, &responseId); err != nil { 57 return nil, err 58 } 59 60 if responseId == 0 { 61 return nil, nil 62 } 63 64 client, err := newClientWithMux(b.mux, responseId) 65 if err != nil { 66 return nil, err 67 } 68 69 return client.Artifact(), nil 70 } 71 72 func (b *builder) Cancel() { 73 if err := b.client.Call("Builder.Cancel", new(interface{}), new(interface{})); err != nil { 74 log.Printf("Error cancelling builder: %s", err) 75 } 76 } 77 78 func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *BuilderPrepareResponse) error { 79 warnings, err := b.builder.Prepare(args.Configs...) 80 *reply = BuilderPrepareResponse{ 81 Warnings: warnings, 82 Error: NewBasicError(err), 83 } 84 return nil 85 } 86 87 func (b *BuilderServer) Run(streamId uint32, reply *uint32) error { 88 client, err := newClientWithMux(b.mux, streamId) 89 if err != nil { 90 return NewBasicError(err) 91 } 92 defer client.Close() 93 94 artifact, err := b.builder.Run(client.Ui(), client.Hook(), client.Cache()) 95 if err != nil { 96 return NewBasicError(err) 97 } 98 99 *reply = 0 100 if artifact != nil { 101 streamId = b.mux.NextId() 102 server := newServerWithMux(b.mux, streamId) 103 server.RegisterArtifact(artifact) 104 go server.Serve() 105 *reply = streamId 106 } 107 108 return nil 109 } 110 111 func (b *BuilderServer) Cancel(args *interface{}, reply *interface{}) error { 112 b.builder.Cancel() 113 return nil 114 }