github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/packer/rpc/builder.go (about)

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