172 lines
4.2 KiB
Go
172 lines
4.2 KiB
Go
package plugin
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"sort"
|
|
|
|
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
|
pluginVersion "github.com/hashicorp/packer/packer-plugin-sdk/version"
|
|
"github.com/hashicorp/packer/version"
|
|
)
|
|
|
|
// Set is a plugin set. It's API is meant to be very close to what is returned
|
|
// by plugin.Server
|
|
// It can describe itself or run a single plugin using the CLI arguments.
|
|
type Set struct {
|
|
version string
|
|
sdkVersion string
|
|
Builders map[string]packersdk.Builder
|
|
PostProcessors map[string]packersdk.PostProcessor
|
|
Provisioners map[string]packersdk.Provisioner
|
|
}
|
|
|
|
// SetDescription describes a Set.
|
|
type SetDescription struct {
|
|
Version string `json:"version"`
|
|
SDKVersion string `json:"sdk_version"`
|
|
Builders []string `json:"builders"`
|
|
PostProcessors []string `json:"post_processors"`
|
|
Provisioners []string `json:"provisioners"`
|
|
}
|
|
|
|
////
|
|
// Setup
|
|
////
|
|
|
|
func NewSet() *Set {
|
|
return &Set{
|
|
version: version.String(),
|
|
sdkVersion: version.String(), // TODO: Set me after the split
|
|
Builders: map[string]packersdk.Builder{},
|
|
PostProcessors: map[string]packersdk.PostProcessor{},
|
|
Provisioners: map[string]packersdk.Provisioner{},
|
|
}
|
|
}
|
|
|
|
func (i *Set) SetVersion(version *pluginVersion.PluginVersion) {
|
|
i.version = version.String()
|
|
}
|
|
|
|
func (i *Set) RegisterBuilder(name string, builder packersdk.Builder) {
|
|
if _, found := i.Builders[name]; found {
|
|
panic(fmt.Errorf("registering duplicate %s builder", name))
|
|
}
|
|
i.Builders[name] = builder
|
|
}
|
|
|
|
func (i *Set) RegisterPostProcessor(name string, postProcessor packersdk.PostProcessor) {
|
|
if _, found := i.PostProcessors[name]; found {
|
|
panic(fmt.Errorf("registering duplicate %s post-processor", name))
|
|
}
|
|
i.PostProcessors[name] = postProcessor
|
|
}
|
|
|
|
func (i *Set) RegisterProvisioner(name string, provisioner packersdk.Provisioner) {
|
|
if _, found := i.Provisioners[name]; found {
|
|
panic(fmt.Errorf("registering duplicate %s provisioner", name))
|
|
}
|
|
i.Provisioners[name] = provisioner
|
|
}
|
|
|
|
// Run takes the os Args and runs a packer plugin command from it.
|
|
// * "describe" command makes the plugin set describe itself.
|
|
// * "start builder builder-name" starts the builder "builder-name"
|
|
// * "start post-processor example" starts the post-processor "example"
|
|
func (i *Set) Run() error {
|
|
args := os.Args[1:]
|
|
return i.RunCommand(args...)
|
|
}
|
|
|
|
func (i *Set) RunCommand(args ...string) error {
|
|
if len(args) < 1 {
|
|
return fmt.Errorf("needs at least one argument")
|
|
}
|
|
|
|
switch args[0] {
|
|
case "describe":
|
|
return i.jsonDescribe(os.Stdout)
|
|
case "start":
|
|
args = args[1:]
|
|
if len(args) != 2 {
|
|
return fmt.Errorf("start takes two arguments, for example 'start builder example-builder'. Found: %v", args)
|
|
}
|
|
return i.start(args[0], args[1])
|
|
default:
|
|
return fmt.Errorf("Unknown command: %q", args[0])
|
|
}
|
|
}
|
|
|
|
func (i *Set) start(kind, name string) error {
|
|
server, err := Server()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[TRACE] starting %s %s", kind, name)
|
|
|
|
switch kind {
|
|
case "builder":
|
|
err = server.RegisterBuilder(i.Builders[name])
|
|
case "post-processor":
|
|
err = server.RegisterPostProcessor(i.PostProcessors[name])
|
|
case "provisioners":
|
|
err = server.RegisterProvisioner(i.Provisioners[name])
|
|
default:
|
|
err = fmt.Errorf("Unknown plugin type: %s", kind)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
server.Serve()
|
|
return nil
|
|
}
|
|
|
|
////
|
|
// Describe
|
|
////
|
|
|
|
func (i *Set) description() SetDescription {
|
|
return SetDescription{
|
|
Version: i.version,
|
|
SDKVersion: i.sdkVersion,
|
|
Builders: i.buildersDescription(),
|
|
PostProcessors: i.postProcessorsDescription(),
|
|
Provisioners: i.provisionersDescription(),
|
|
}
|
|
}
|
|
|
|
func (i *Set) jsonDescribe(out io.Writer) error {
|
|
return json.NewEncoder(out).Encode(i.description())
|
|
}
|
|
|
|
func (i *Set) buildersDescription() []string {
|
|
out := []string{}
|
|
for key := range i.Builders {
|
|
out = append(out, key)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
func (i *Set) postProcessorsDescription() []string {
|
|
out := []string{}
|
|
for key := range i.PostProcessors {
|
|
out = append(out, key)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
func (i *Set) provisionersDescription() []string {
|
|
out := []string{}
|
|
for key := range i.Provisioners {
|
|
out = append(out, key)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|