packer-cn/packer-plugin-sdk/rpc/common.go

72 lines
1.8 KiB
Go

package rpc
import (
"bytes"
"encoding/gob"
"fmt"
"net/rpc"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// commonClient allows to rpc call funcs that can be defined on the different
// build blocks of packer
type commonClient struct {
// endpoint is usually the type of build block we are connecting to.
//
// eg: Provisioner / PostProcessor / Builder / Artifact / Communicator
endpoint string
client *rpc.Client
mux *muxBroker
}
type commonServer struct {
mux *muxBroker
selfConfigurable interface {
ConfigSpec() hcldec.ObjectSpec
}
}
type ConfigSpecResponse struct {
ConfigSpec []byte
}
func (p *commonClient) ConfigSpec() hcldec.ObjectSpec {
// TODO(azr): the RPC Call can fail but the ConfigSpec signature doesn't
// return an error; should we simply panic ? Logging this for now; will
// decide later. The correct approach would probably be to return an error
// in ConfigSpec but that will break a lot of things.
resp := &ConfigSpecResponse{}
cerr := p.client.Call(p.endpoint+".ConfigSpec", new(interface{}), resp)
if cerr != nil {
err := fmt.Errorf("ConfigSpec failed: %v", cerr)
panic(err.Error())
}
res := hcldec.ObjectSpec{}
err := gob.NewDecoder(bytes.NewReader(resp.ConfigSpec)).Decode(&res)
if err != nil {
panic("ici:" + err.Error())
}
return res
}
func (s *commonServer) ConfigSpec(_ interface{}, reply *ConfigSpecResponse) error {
spec := s.selfConfigurable.ConfigSpec()
b := bytes.NewBuffer(nil)
err := gob.NewEncoder(b).Encode(spec)
reply.ConfigSpec = b.Bytes()
return err
}
func init() {
gob.Register(new(hcldec.AttrSpec))
gob.Register(new(hcldec.BlockSpec))
gob.Register(new(hcldec.BlockAttrsSpec))
gob.Register(new(hcldec.BlockListSpec))
gob.Register(new(hcldec.BlockObjectSpec))
gob.Register(new(cty.Value))
}