Merge pull request #1629 from mitchellh/f-no-command-plugins
Remove command plugins, command interface from core, etc.
This commit is contained in:
commit
835b8c69ca
|
@ -6,11 +6,10 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/hashicorp/go-checkpoint"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/command"
|
||||
)
|
||||
|
||||
func init() {
|
||||
packer.VersionChecker = packerVersionCheck
|
||||
checkpointResult = make(chan *checkpoint.CheckResponse, 1)
|
||||
}
|
||||
|
||||
|
@ -33,9 +32,9 @@ func runCheckpoint(c *config) {
|
|||
return
|
||||
}
|
||||
|
||||
version := packer.Version
|
||||
if packer.VersionPrerelease != "" {
|
||||
version += fmt.Sprintf(".%s", packer.VersionPrerelease)
|
||||
version := Version
|
||||
if VersionPrerelease != "" {
|
||||
version += fmt.Sprintf(".%s", VersionPrerelease)
|
||||
}
|
||||
|
||||
signaturePath := filepath.Join(configDir, "checkpoint_signature")
|
||||
|
@ -58,21 +57,23 @@ func runCheckpoint(c *config) {
|
|||
checkpointResult <- resp
|
||||
}
|
||||
|
||||
// packerVersionCheck implements packer.VersionCheckFunc and is used
|
||||
// commandVersionCheck implements command.VersionCheckFunc and is used
|
||||
// as the version checker.
|
||||
func packerVersionCheck(current string) (packer.VersionCheckInfo, error) {
|
||||
func commandVersionCheck() (command.VersionCheckInfo, error) {
|
||||
// Wait for the result to come through
|
||||
info := <-checkpointResult
|
||||
if info == nil {
|
||||
var zero packer.VersionCheckInfo
|
||||
var zero command.VersionCheckInfo
|
||||
return zero, nil
|
||||
}
|
||||
|
||||
// Build the alerts that we may have received about our version
|
||||
alerts := make([]string, len(info.Alerts))
|
||||
for i, a := range info.Alerts {
|
||||
alerts[i] = a.Message
|
||||
}
|
||||
|
||||
return packer.VersionCheckInfo{
|
||||
return command.VersionCheckInfo{
|
||||
Outdated: info.Outdated,
|
||||
Latest: info.CurrentVersion,
|
||||
Alerts: alerts,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package build
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,16 +14,20 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
type Command byte
|
||||
|
||||
func (Command) Help() string {
|
||||
return strings.TrimSpace(helpText)
|
||||
type BuildCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c Command) Run(env packer.Environment, args []string) int {
|
||||
func (c BuildCommand) Run(args []string) int {
|
||||
var cfgColor, cfgDebug, cfgForce, cfgParallel bool
|
||||
buildOptions := new(cmdcommon.BuildOptions)
|
||||
|
||||
env, err := c.Meta.Environment()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
|
||||
cmdFlags.BoolVar(&cfgColor, "color", true, "enable or disable color")
|
||||
|
@ -278,6 +282,28 @@ func (c Command) Run(env packer.Environment, args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (Command) Synopsis() string {
|
||||
func (BuildCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: packer build [options] TEMPLATE
|
||||
|
||||
Will execute multiple builds in parallel as defined in the template.
|
||||
The various artifacts created by the template will be outputted.
|
||||
|
||||
Options:
|
||||
|
||||
-debug Debug mode enabled for builds
|
||||
-force Force a build to continue if artifacts exist, deletes existing artifacts
|
||||
-machine-readable Machine-readable output
|
||||
-except=foo,bar,baz Build all builds other than these
|
||||
-only=foo,bar,baz Only build the given builds by name
|
||||
-parallel=false Disable parallelization (on by default)
|
||||
-var 'key=value' Variable for templates, can be used multiple times.
|
||||
-var-file=path JSON file containing user variables.
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (BuildCommand) Synopsis() string {
|
||||
return "build image(s) from template"
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
package build
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func testEnvironment() packer.Environment {
|
||||
config := packer.DefaultEnvironmentConfig()
|
||||
config.Ui = &packer.BasicUi{
|
||||
Reader: new(bytes.Buffer),
|
||||
Writer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
env, err := packer.NewEnvironment(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
func TestCommand_Implements(t *testing.T) {
|
||||
var _ packer.Command = new(Command)
|
||||
}
|
||||
|
||||
func TestCommand_Run_NoArgs(t *testing.T) {
|
||||
command := new(Command)
|
||||
result := command.Run(testEnvironment(), make([]string, 0))
|
||||
if result != 1 {
|
||||
t.Fatalf("bad: %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommand_Run_MoreThanOneArg(t *testing.T) {
|
||||
command := new(Command)
|
||||
|
||||
args := []string{"one", "two"}
|
||||
result := command.Run(testEnvironment(), args)
|
||||
if result != 1 {
|
||||
t.Fatalf("bad: %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommand_Run_MissingFile(t *testing.T) {
|
||||
command := new(Command)
|
||||
|
||||
args := []string{"i-better-not-exist"}
|
||||
result := command.Run(testEnvironment(), args)
|
||||
if result != 1 {
|
||||
t.Fatalf("bad: %d", result)
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package build
|
||||
|
||||
const helpText = `
|
||||
Usage: packer build [options] TEMPLATE
|
||||
|
||||
Will execute multiple builds in parallel as defined in the template.
|
||||
The various artifacts created by the template will be outputted.
|
||||
|
||||
Options:
|
||||
|
||||
-debug Debug mode enabled for builds
|
||||
-force Force a build to continue if artifacts exist, deletes existing artifacts
|
||||
-machine-readable Machine-readable output
|
||||
-except=foo,bar,baz Build all builds other than these
|
||||
-only=foo,bar,baz Only build the given builds by name
|
||||
-parallel=false Disable parallelization (on by default)
|
||||
-var 'key=value' Variable for templates, can be used multiple times.
|
||||
-var-file=path JSON file containing user variables.
|
||||
`
|
|
@ -1,23 +1,28 @@
|
|||
package fix
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/packer/fix"
|
||||
)
|
||||
|
||||
type Command byte
|
||||
|
||||
func (Command) Help() string {
|
||||
return strings.TrimSpace(helpString)
|
||||
type FixCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c Command) Run(env packer.Environment, args []string) int {
|
||||
func (c *FixCommand) Run(args []string) int {
|
||||
env, err := c.Meta.Environment()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
cmdFlags := flag.NewFlagSet("fix", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
|
@ -50,9 +55,9 @@ func (c Command) Run(env packer.Environment, args []string) int {
|
|||
tplF.Close()
|
||||
|
||||
input := templateData
|
||||
for _, name := range FixerOrder {
|
||||
for _, name := range fix.FixerOrder {
|
||||
var err error
|
||||
fixer, ok := Fixers[name]
|
||||
fixer, ok := fix.Fixers[name]
|
||||
if !ok {
|
||||
panic("fixer not found: " + name)
|
||||
}
|
||||
|
@ -85,6 +90,30 @@ func (c Command) Run(env packer.Environment, args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (c Command) Synopsis() string {
|
||||
func (*FixCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: packer fix [options] TEMPLATE
|
||||
|
||||
Reads the JSON template and attempts to fix known backwards
|
||||
incompatibilities. The fixed template will be outputted to standard out.
|
||||
|
||||
If the template cannot be fixed due to an error, the command will exit
|
||||
with a non-zero exit status. Error messages will appear on standard error.
|
||||
|
||||
Fixes that are run:
|
||||
|
||||
iso-md5 Replaces "iso_md5" in builders with newer "iso_checksum"
|
||||
createtime Replaces ".CreateTime" in builder configs with "{{timestamp}}"
|
||||
virtualbox-gaattach Updates VirtualBox builders using "guest_additions_attach"
|
||||
to use "guest_additions_mode"
|
||||
pp-vagrant-override Replaces old-style provider overrides for the Vagrant
|
||||
post-processor to new-style as of Packer 0.5.0.
|
||||
virtualbox-rename Updates "virtualbox" builders to "virtualbox-iso"
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *FixCommand) Synopsis() string {
|
||||
return "fixes templates from old versions of packer"
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package fix
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommand_Impl(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = new(Command)
|
||||
if _, ok := raw.(packer.Command); !ok {
|
||||
t.Fatalf("must be a Command")
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package fix
|
||||
|
||||
const helpString = `
|
||||
Usage: packer fix [options] TEMPLATE
|
||||
|
||||
Reads the JSON template and attempts to fix known backwards
|
||||
incompatibilities. The fixed template will be outputted to standard out.
|
||||
|
||||
If the template cannot be fixed due to an error, the command will exit
|
||||
with a non-zero exit status. Error messages will appear on standard error.
|
||||
|
||||
Fixes that are run:
|
||||
|
||||
iso-md5 Replaces "iso_md5" in builders with newer "iso_checksum"
|
||||
createtime Replaces ".CreateTime" in builder configs with "{{timestamp}}"
|
||||
virtualbox-gaattach Updates VirtualBox builders using "guest_additions_attach"
|
||||
to use "guest_additions_mode"
|
||||
pp-vagrant-override Replaces old-style provider overrides for the Vagrant
|
||||
post-processor to new-style as of Packer 0.5.0.
|
||||
virtualbox-rename Updates "virtualbox" builders to "virtualbox-iso"
|
||||
|
||||
`
|
|
@ -1,4 +1,4 @@
|
|||
package inspect
|
||||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -9,17 +9,17 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type Command struct{}
|
||||
|
||||
func (Command) Help() string {
|
||||
return strings.TrimSpace(helpText)
|
||||
type InspectCommand struct{
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c Command) Synopsis() string {
|
||||
return "see components of a template"
|
||||
}
|
||||
func (c *InspectCommand) Run(args []string) int {
|
||||
env, err := c.Meta.Environment()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
func (c Command) Run(env packer.Environment, args []string) int {
|
||||
flags := flag.NewFlagSet("inspect", flag.ContinueOnError)
|
||||
flags.Usage = func() { env.Ui().Say(c.Help()) }
|
||||
if err := flags.Parse(args); err != nil {
|
||||
|
@ -148,3 +148,23 @@ func (c Command) Run(env packer.Environment, args []string) int {
|
|||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (*InspectCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: packer inspect TEMPLATE
|
||||
|
||||
Inspects a template, parsing and outputting the components a template
|
||||
defines. This does not validate the contents of a template (other than
|
||||
basic syntax by necessity).
|
||||
|
||||
Options:
|
||||
|
||||
-machine-readable Machine-readable output
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *InspectCommand) Synopsis() string {
|
||||
return "see components of a template"
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package inspect
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommand_Impl(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = new(Command)
|
||||
if _, ok := raw.(packer.Command); !ok {
|
||||
t.Fatalf("must be a Command")
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package inspect
|
||||
|
||||
const helpText = `
|
||||
Usage: packer inspect TEMPLATE
|
||||
|
||||
Inspects a template, parsing and outputting the components a template
|
||||
defines. This does not validate the contents of a template (other than
|
||||
basic syntax by necessity).
|
||||
|
||||
Options:
|
||||
|
||||
-machine-readable Machine-readable output
|
||||
`
|
|
@ -0,0 +1,15 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
type Meta struct {
|
||||
EnvConfig *packer.EnvironmentConfig
|
||||
Ui cli.Ui
|
||||
}
|
||||
|
||||
func (m *Meta) Environment() (packer.Environment, error) {
|
||||
return packer.NewEnvironment(m.EnvConfig)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package validate
|
||||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
@ -9,16 +9,20 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type Command byte
|
||||
|
||||
func (Command) Help() string {
|
||||
return strings.TrimSpace(helpString)
|
||||
type ValidateCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
func (c Command) Run(env packer.Environment, args []string) int {
|
||||
func (c *ValidateCommand) Run(args []string) int {
|
||||
var cfgSyntaxOnly bool
|
||||
buildOptions := new(cmdcommon.BuildOptions)
|
||||
|
||||
env, err := c.Meta.Environment()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
cmdFlags := flag.NewFlagSet("validate", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
|
||||
cmdFlags.BoolVar(&cfgSyntaxOnly, "syntax-only", false, "check syntax only")
|
||||
|
@ -123,6 +127,29 @@ func (c Command) Run(env packer.Environment, args []string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (Command) Synopsis() string {
|
||||
func (*ValidateCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: packer validate [options] TEMPLATE
|
||||
|
||||
Checks the template is valid by parsing the template and also
|
||||
checking the configuration with the various builders, provisioners, etc.
|
||||
|
||||
If it is not valid, the errors will be shown and the command will exit
|
||||
with a non-zero exit status. If it is valid, it will exit with a zero
|
||||
exit status.
|
||||
|
||||
Options:
|
||||
|
||||
-syntax-only Only check syntax. Do not verify config of the template.
|
||||
-except=foo,bar,baz Validate all builds other than these
|
||||
-only=foo,bar,baz Validate only these builds
|
||||
-var 'key=value' Variable for templates, can be used multiple times.
|
||||
-var-file=path JSON file containing user variables.
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (*ValidateCommand) Synopsis() string {
|
||||
return "check that a template is valid"
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCommand_Impl(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = new(Command)
|
||||
if _, ok := raw.(packer.Command); !ok {
|
||||
t.Fatalf("must be a Command")
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package validate
|
||||
|
||||
const helpString = `
|
||||
Usage: packer validate [options] TEMPLATE
|
||||
|
||||
Checks the template is valid by parsing the template and also
|
||||
checking the configuration with the various builders, provisioners, etc.
|
||||
|
||||
If it is not valid, the errors will be shown and the command will exit
|
||||
with a non-zero exit status. If it is valid, it will exit with a zero
|
||||
exit status.
|
||||
|
||||
Options:
|
||||
|
||||
-syntax-only Only check syntax. Do not verify config of the template.
|
||||
-except=foo,bar,baz Validate all builds other than these
|
||||
-only=foo,bar,baz Validate only these builds
|
||||
-var 'key=value' Variable for templates, can be used multiple times.
|
||||
-var-file=path JSON file containing user variables.
|
||||
`
|
|
@ -0,0 +1,83 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// VersionCommand is a Command implementation prints the version.
|
||||
type VersionCommand struct {
|
||||
Meta
|
||||
|
||||
Revision string
|
||||
Version string
|
||||
VersionPrerelease string
|
||||
CheckFunc VersionCheckFunc
|
||||
}
|
||||
|
||||
// VersionCheckFunc is the callback called by the Version command to
|
||||
// check if there is a new version of Packer.
|
||||
type VersionCheckFunc func() (VersionCheckInfo, error)
|
||||
|
||||
// VersionCheckInfo is the return value for the VersionCheckFunc callback
|
||||
// and tells the Version command information about the latest version
|
||||
// of Packer.
|
||||
type VersionCheckInfo struct {
|
||||
Outdated bool
|
||||
Latest string
|
||||
Alerts []string
|
||||
}
|
||||
|
||||
func (c *VersionCommand) Help() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (c *VersionCommand) Run(args []string) int {
|
||||
env, err := c.Meta.Environment()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing environment: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
env.Ui().Machine("version", c.Version)
|
||||
env.Ui().Machine("version-prelease", c.VersionPrerelease)
|
||||
env.Ui().Machine("version-commit", c.Revision)
|
||||
|
||||
var versionString bytes.Buffer
|
||||
fmt.Fprintf(&versionString, "Packer v%s", c.Version)
|
||||
if c.VersionPrerelease != "" {
|
||||
fmt.Fprintf(&versionString, ".%s", c.VersionPrerelease)
|
||||
|
||||
if c.Revision != "" {
|
||||
fmt.Fprintf(&versionString, " (%s)", c.Revision)
|
||||
}
|
||||
}
|
||||
|
||||
c.Ui.Output(versionString.String())
|
||||
|
||||
// If we have a version check function, then let's check for
|
||||
// the latest version as well.
|
||||
if c.CheckFunc != nil {
|
||||
// Separate the prior output with a newline
|
||||
c.Ui.Output("")
|
||||
|
||||
// Check the latest version
|
||||
info, err := c.CheckFunc()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error checking latest version: %s", err))
|
||||
}
|
||||
if info.Outdated {
|
||||
c.Ui.Output(fmt.Sprintf(
|
||||
"Your version of Packer is out of date! The latest version\n"+
|
||||
"is %s. You can update by downloading from www.packer.io",
|
||||
info.Latest))
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *VersionCommand) Synopsis() string {
|
||||
return "Prints the Packer version"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestVersionCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &VersionCommand{}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/packer/command"
|
||||
)
|
||||
|
||||
// Commands is the mapping of all the available Terraform commands.
|
||||
var Commands map[string]cli.CommandFactory
|
||||
|
||||
// Ui is the cli.Ui used for communicating to the outside world.
|
||||
var Ui cli.Ui
|
||||
|
||||
const ErrorPrefix = "e:"
|
||||
const OutputPrefix = "o:"
|
||||
|
||||
func init() {
|
||||
Ui = &cli.PrefixedUi{
|
||||
AskPrefix: OutputPrefix,
|
||||
OutputPrefix: OutputPrefix,
|
||||
InfoPrefix: OutputPrefix,
|
||||
ErrorPrefix: ErrorPrefix,
|
||||
Ui: &cli.BasicUi{Writer: os.Stdout},
|
||||
}
|
||||
|
||||
meta := command.Meta{
|
||||
EnvConfig: &EnvConfig,
|
||||
Ui: Ui,
|
||||
}
|
||||
|
||||
Commands = map[string]cli.CommandFactory{
|
||||
"build": func() (cli.Command, error) {
|
||||
return &command.BuildCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"fix": func() (cli.Command, error) {
|
||||
return &command.FixCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"inspect": func() (cli.Command, error) {
|
||||
return &command.InspectCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"validate": func() (cli.Command, error) {
|
||||
return &command.ValidateCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"version": func() (cli.Command, error) {
|
||||
return &command.VersionCommand{
|
||||
Meta: meta,
|
||||
Revision: GitCommit,
|
||||
Version: Version,
|
||||
VersionPrerelease: VersionPrerelease,
|
||||
CheckFunc: commandVersionCheck,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// makeShutdownCh creates an interrupt listener and returns a channel.
|
||||
// A message will be sent on the channel for every interrupt received.
|
||||
func makeShutdownCh() <-chan struct{} {
|
||||
resultCh := make(chan struct{})
|
||||
|
||||
signalCh := make(chan os.Signal, 4)
|
||||
signal.Notify(signalCh, os.Interrupt)
|
||||
go func() {
|
||||
for {
|
||||
<-signalCh
|
||||
resultCh <- struct{}{}
|
||||
}
|
||||
}()
|
||||
|
||||
return resultCh
|
||||
}
|
|
@ -3,10 +3,11 @@ package common
|
|||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
)
|
||||
|
||||
// StepDownload downloads a remote file using the download client within
|
||||
|
@ -70,7 +71,7 @@ func (s *StepDownload) Run(state multistep.StateBag) multistep.StepAction {
|
|||
CopyFile: false,
|
||||
Hash: HashForType(s.ChecksumType),
|
||||
Checksum: checksum,
|
||||
UserAgent: packer.VersionString(),
|
||||
UserAgent: "Packer",
|
||||
}
|
||||
|
||||
path, err, retry := s.download(config, state)
|
||||
|
|
32
config.go
32
config.go
|
@ -13,6 +13,9 @@ import (
|
|||
"github.com/mitchellh/packer/packer/plugin"
|
||||
)
|
||||
|
||||
// EnvConfig is the global EnvironmentConfig we use to initialize the CLI.
|
||||
var EnvConfig packer.EnvironmentConfig
|
||||
|
||||
type config struct {
|
||||
DisableCheckpoint bool `json:"disable_checkpoint"`
|
||||
DisableCheckpointSignature bool `json:"disable_checkpoint_signature"`
|
||||
|
@ -20,7 +23,6 @@ type config struct {
|
|||
PluginMaxPort uint
|
||||
|
||||
Builders map[string]string
|
||||
Commands map[string]string
|
||||
PostProcessors map[string]string `json:"post-processors"`
|
||||
Provisioners map[string]string
|
||||
}
|
||||
|
@ -79,15 +81,6 @@ func (c *config) Discover() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Returns an array of defined command names.
|
||||
func (c *config) CommandNames() (result []string) {
|
||||
result = make([]string, 0, len(c.Commands))
|
||||
for name := range c.Commands {
|
||||
result = append(result, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// This is a proper packer.BuilderFunc that can be used to load packer.Builder
|
||||
// implementations from the defined plugins.
|
||||
func (c *config) LoadBuilder(name string) (packer.Builder, error) {
|
||||
|
@ -101,19 +94,6 @@ func (c *config) LoadBuilder(name string) (packer.Builder, error) {
|
|||
return c.pluginClient(bin).Builder()
|
||||
}
|
||||
|
||||
// This is a proper packer.CommandFunc that can be used to load packer.Command
|
||||
// implementations from the defined plugins.
|
||||
func (c *config) LoadCommand(name string) (packer.Command, error) {
|
||||
log.Printf("Loading command: %s\n", name)
|
||||
bin, ok := c.Commands[name]
|
||||
if !ok {
|
||||
log.Printf("Command not found: %s\n", name)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return c.pluginClient(bin).Command()
|
||||
}
|
||||
|
||||
// This is a proper implementation of packer.HookFunc that can be used
|
||||
// to load packer.Hook implementations from the defined plugins.
|
||||
func (c *config) LoadHook(name string) (packer.Hook, error) {
|
||||
|
@ -163,12 +143,6 @@ func (c *config) discover(path string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = c.discoverSingle(
|
||||
filepath.Join(path, "packer-command-*"), &c.Commands)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.discoverSingle(
|
||||
filepath.Join(path, "packer-post-processor-*"), &c.PostProcessors)
|
||||
if err != nil {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// These are the environmental variables that determine if we log, and if
|
||||
// we log whether or not the log should go to a file.
|
||||
const EnvLog = "PACKER_LOG" //Set to True
|
||||
const EnvLogFile = "PACKER_LOG_PATH" //Set to a file
|
||||
|
||||
// logOutput determines where we should send logs (if anywhere).
|
||||
func logOutput() (logOutput io.Writer, err error) {
|
||||
logOutput = nil
|
||||
if os.Getenv(EnvLog) != "" {
|
||||
logOutput = os.Stderr
|
||||
|
||||
if logPath := os.Getenv(EnvLogFile); logPath != "" {
|
||||
var err error
|
||||
logOutput, err = os.Create(logPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -9,10 +9,13 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/packer/plugin"
|
||||
"github.com/mitchellh/panicwrap"
|
||||
"github.com/mitchellh/prefixedio"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -24,63 +27,82 @@ func main() {
|
|||
|
||||
// realMain is executed from main and returns the exit status to exit with.
|
||||
func realMain() int {
|
||||
// If there is no explicit number of Go threads to use, then set it
|
||||
if os.Getenv("GOMAXPROCS") == "" {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
var wrapConfig panicwrap.WrapConfig
|
||||
|
||||
if !panicwrap.Wrapped(&wrapConfig) {
|
||||
// Determine where logs should go in general (requested by the user)
|
||||
logWriter, err := logOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't setup log output: %s", err)
|
||||
return 1
|
||||
}
|
||||
if logWriter == nil {
|
||||
logWriter = ioutil.Discard
|
||||
}
|
||||
|
||||
// We always send logs to a temporary file that we use in case
|
||||
// there is a panic. Otherwise, we delete it.
|
||||
logTempFile, err := ioutil.TempFile("", "packer-log")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't setup logging tempfile: %s", err)
|
||||
return 1
|
||||
}
|
||||
defer os.Remove(logTempFile.Name())
|
||||
defer logTempFile.Close()
|
||||
|
||||
// Tell the logger to log to this file
|
||||
os.Setenv(EnvLog, "")
|
||||
os.Setenv(EnvLogFile, "")
|
||||
|
||||
// Setup the prefixed readers that send data properly to
|
||||
// stdout/stderr.
|
||||
doneCh := make(chan struct{})
|
||||
outR, outW := io.Pipe()
|
||||
go copyOutput(outR, doneCh)
|
||||
|
||||
// Create the configuration for panicwrap and wrap our executable
|
||||
wrapConfig.Handler = panicHandler(logTempFile)
|
||||
wrapConfig.Writer = io.MultiWriter(logTempFile, logWriter)
|
||||
wrapConfig.Stdout = outW
|
||||
exitStatus, err := panicwrap.Wrap(&wrapConfig)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't start Packer: %s", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
// If >= 0, we're the parent, so just exit
|
||||
if exitStatus >= 0 {
|
||||
// Close the stdout writer so that our copy process can finish
|
||||
outW.Close()
|
||||
|
||||
// Wait for the output copying to finish
|
||||
<-doneCh
|
||||
|
||||
return exitStatus
|
||||
}
|
||||
|
||||
// We're the child, so just close the tempfile we made in order to
|
||||
// save file handles since the tempfile is only used by the parent.
|
||||
logTempFile.Close()
|
||||
}
|
||||
|
||||
// Determine where logs should go in general (requested by the user)
|
||||
logWriter, err := logOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't setup log output: %s", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
// We also always send logs to a temporary file that we use in case
|
||||
// there is a panic. Otherwise, we delete it.
|
||||
logTempFile, err := ioutil.TempFile("", "packer-log")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't setup logging tempfile: %s", err)
|
||||
return 1
|
||||
}
|
||||
defer os.Remove(logTempFile.Name())
|
||||
defer logTempFile.Close()
|
||||
|
||||
// Reset the log variables to minimize work in the subprocess
|
||||
os.Setenv("PACKER_LOG", "")
|
||||
os.Setenv("PACKER_LOG_FILE", "")
|
||||
|
||||
// Create the configuration for panicwrap and wrap our executable
|
||||
wrapConfig := &panicwrap.WrapConfig{
|
||||
Handler: panicHandler(logTempFile),
|
||||
Writer: io.MultiWriter(logTempFile, logWriter),
|
||||
}
|
||||
|
||||
exitStatus, err := panicwrap.Wrap(wrapConfig)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Couldn't start Packer: %s", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
if exitStatus >= 0 {
|
||||
return exitStatus
|
||||
}
|
||||
|
||||
// We're the child, so just close the tempfile we made in order to
|
||||
// save file handles since the tempfile is only used by the parent.
|
||||
logTempFile.Close()
|
||||
|
||||
// Call the real main
|
||||
return wrappedMain()
|
||||
}
|
||||
|
||||
// wrappedMain is called only when we're wrapped by panicwrap and
|
||||
// returns the exit status to exit with.
|
||||
func wrappedMain() int {
|
||||
// If there is no explicit number of Go threads to use, then set it
|
||||
if os.Getenv("GOMAXPROCS") == "" {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
log.SetOutput(os.Stderr)
|
||||
|
||||
log.Printf(
|
||||
"Packer Version: %s %s %s",
|
||||
packer.Version, packer.VersionPrerelease, packer.GitCommit)
|
||||
"[INFO] Packer version: %s %s %s",
|
||||
Version, VersionPrerelease, GitCommit)
|
||||
log.Printf("Packer Target OS/Arch: %s %s", runtime.GOOS, runtime.GOARCH)
|
||||
log.Printf("Built with Go Version: %s", runtime.Version())
|
||||
|
||||
|
@ -118,16 +140,14 @@ func wrappedMain() int {
|
|||
defer plugin.CleanupClients()
|
||||
|
||||
// Create the environment configuration
|
||||
envConfig := packer.DefaultEnvironmentConfig()
|
||||
envConfig.Cache = cache
|
||||
envConfig.Commands = config.CommandNames()
|
||||
envConfig.Components.Builder = config.LoadBuilder
|
||||
envConfig.Components.Command = config.LoadCommand
|
||||
envConfig.Components.Hook = config.LoadHook
|
||||
envConfig.Components.PostProcessor = config.LoadPostProcessor
|
||||
envConfig.Components.Provisioner = config.LoadProvisioner
|
||||
EnvConfig = *packer.DefaultEnvironmentConfig()
|
||||
EnvConfig.Cache = cache
|
||||
EnvConfig.Components.Builder = config.LoadBuilder
|
||||
EnvConfig.Components.Hook = config.LoadHook
|
||||
EnvConfig.Components.PostProcessor = config.LoadPostProcessor
|
||||
EnvConfig.Components.Provisioner = config.LoadProvisioner
|
||||
if machineReadable {
|
||||
envConfig.Ui = &packer.MachineReadableUi{
|
||||
EnvConfig.Ui = &packer.MachineReadableUi{
|
||||
Writer: os.Stdout,
|
||||
}
|
||||
|
||||
|
@ -139,17 +159,18 @@ func wrappedMain() int {
|
|||
}
|
||||
}
|
||||
|
||||
env, err := packer.NewEnvironment(envConfig)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Packer initialization error: \n\n%s\n", err)
|
||||
return 1
|
||||
//setupSignalHandlers(env)
|
||||
|
||||
cli := &cli.CLI{
|
||||
Args: args,
|
||||
Commands: Commands,
|
||||
HelpFunc: cli.BasicHelpFunc("packer"),
|
||||
HelpWriter: os.Stdout,
|
||||
}
|
||||
|
||||
setupSignalHandlers(env)
|
||||
|
||||
exitCode, err := env.Cli(args)
|
||||
exitCode, err := cli.Run()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
|
||||
fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -220,20 +241,44 @@ func loadConfig() (*config, error) {
|
|||
return &config, nil
|
||||
}
|
||||
|
||||
// logOutput determines where we should send logs (if anywhere).
|
||||
func logOutput() (logOutput io.Writer, err error) {
|
||||
logOutput = ioutil.Discard
|
||||
if os.Getenv("PACKER_LOG") != "" {
|
||||
logOutput = os.Stderr
|
||||
// copyOutput uses output prefixes to determine whether data on stdout
|
||||
// should go to stdout or stderr. This is due to panicwrap using stderr
|
||||
// as the log and error channel.
|
||||
func copyOutput(r io.Reader, doneCh chan<- struct{}) {
|
||||
defer close(doneCh)
|
||||
|
||||
if logPath := os.Getenv("PACKER_LOG_PATH"); logPath != "" {
|
||||
var err error
|
||||
logOutput, err = os.Create(logPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
pr, err := prefixedio.NewReader(r)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
stderrR, err := pr.Prefix(ErrorPrefix)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
stdoutR, err := pr.Prefix(OutputPrefix)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defaultR, err := pr.Prefix("")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(3)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
io.Copy(os.Stderr, stderrR)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
io.Copy(os.Stdout, stdoutR)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
io.Copy(os.Stdout, defaultR)
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package packer
|
||||
|
||||
// A command is a runnable sub-command of the `packer` application.
|
||||
// When `packer` is called with the proper subcommand, this will be
|
||||
// called.
|
||||
//
|
||||
// The mapping of command names to command interfaces is in the
|
||||
// Environment struct.
|
||||
type Command interface {
|
||||
// Help should return long-form help text that includes the command-line
|
||||
// usage, a brief few sentences explaining the function of the command,
|
||||
// and the complete list of flags the command accepts.
|
||||
Help() string
|
||||
|
||||
// Run should run the actual command with the given environmet and
|
||||
// command-line arguments. It should return the exit status when it is
|
||||
// finished.
|
||||
Run(env Environment, args []string) int
|
||||
|
||||
// Synopsis should return a one-line, short synopsis of the command.
|
||||
// This should be less than 50 characters ideally.
|
||||
Synopsis() string
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package packer
|
||||
|
||||
type TestCommand struct {
|
||||
runArgs []string
|
||||
runCalled bool
|
||||
runEnv Environment
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Help() string {
|
||||
return "bar"
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Run(env Environment, args []string) int {
|
||||
tc.runCalled = true
|
||||
tc.runArgs = args
|
||||
tc.runEnv = env
|
||||
return 0
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Synopsis() string {
|
||||
return "foo"
|
||||
}
|
|
@ -4,19 +4,12 @@ package packer
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// The function type used to lookup Builder implementations.
|
||||
type BuilderFunc func(name string) (Builder, error)
|
||||
|
||||
// The function type used to lookup Command implementations.
|
||||
type CommandFunc func(name string) (Command, error)
|
||||
|
||||
// The function type used to lookup Hook implementations.
|
||||
type HookFunc func(name string) (Hook, error)
|
||||
|
||||
|
@ -31,7 +24,6 @@ type ProvisionerFunc func(name string) (Provisioner, error)
|
|||
// commands, etc.
|
||||
type ComponentFinder struct {
|
||||
Builder BuilderFunc
|
||||
Command CommandFunc
|
||||
Hook HookFunc
|
||||
PostProcessor PostProcessorFunc
|
||||
Provisioner ProvisionerFunc
|
||||
|
@ -45,7 +37,6 @@ type ComponentFinder struct {
|
|||
type Environment interface {
|
||||
Builder(string) (Builder, error)
|
||||
Cache() Cache
|
||||
Cli([]string) (int, error)
|
||||
Hook(string) (Hook, error)
|
||||
PostProcessor(string) (PostProcessor, error)
|
||||
Provisioner(string) (Provisioner, error)
|
||||
|
@ -56,7 +47,6 @@ type Environment interface {
|
|||
// environment.
|
||||
type coreEnvironment struct {
|
||||
cache Cache
|
||||
commands []string
|
||||
components ComponentFinder
|
||||
ui Ui
|
||||
}
|
||||
|
@ -64,22 +54,14 @@ type coreEnvironment struct {
|
|||
// This struct configures new environments.
|
||||
type EnvironmentConfig struct {
|
||||
Cache Cache
|
||||
Commands []string
|
||||
Components ComponentFinder
|
||||
Ui Ui
|
||||
}
|
||||
|
||||
type helpCommandEntry struct {
|
||||
i int
|
||||
key string
|
||||
synopsis string
|
||||
}
|
||||
|
||||
// DefaultEnvironmentConfig returns a default EnvironmentConfig that can
|
||||
// be used to create a new enviroment with NewEnvironment with sane defaults.
|
||||
func DefaultEnvironmentConfig() *EnvironmentConfig {
|
||||
config := &EnvironmentConfig{}
|
||||
config.Commands = make([]string, 0)
|
||||
config.Ui = &BasicUi{
|
||||
Reader: os.Stdin,
|
||||
Writer: os.Stdout,
|
||||
|
@ -98,7 +80,6 @@ func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error
|
|||
|
||||
env := &coreEnvironment{}
|
||||
env.cache = config.Cache
|
||||
env.commands = config.Commands
|
||||
env.components = config.Components
|
||||
env.ui = config.Ui
|
||||
|
||||
|
@ -109,10 +90,6 @@ func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error
|
|||
env.components.Builder = func(string) (Builder, error) { return nil, nil }
|
||||
}
|
||||
|
||||
if env.components.Command == nil {
|
||||
env.components.Command = func(string) (Command, error) { return nil, nil }
|
||||
}
|
||||
|
||||
if env.components.Hook == nil {
|
||||
env.components.Hook = func(string) (Hook, error) { return nil, nil }
|
||||
}
|
||||
|
@ -199,159 +176,6 @@ func (e *coreEnvironment) Provisioner(name string) (p Provisioner, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Executes a command as if it was typed on the command-line interface.
|
||||
// The return value is the exit code of the command.
|
||||
func (e *coreEnvironment) Cli(args []string) (result int, err error) {
|
||||
log.Printf("Environment.Cli: %#v\n", args)
|
||||
|
||||
// If we have no arguments, just short-circuit here and print the help
|
||||
if len(args) == 0 {
|
||||
e.printHelp()
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
// This variable will track whether or not we're supposed to print
|
||||
// the help or not.
|
||||
isHelp := false
|
||||
for _, arg := range args {
|
||||
if arg == "-h" || arg == "--help" {
|
||||
isHelp = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Trim up to the command name
|
||||
for i, v := range args {
|
||||
if len(v) > 0 && v[0] != '-' {
|
||||
args = args[i:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("command + args: %#v", args)
|
||||
|
||||
version := args[0] == "version"
|
||||
if !version {
|
||||
for _, arg := range args {
|
||||
if arg == "--version" || arg == "-v" {
|
||||
version = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var command Command
|
||||
if version {
|
||||
command = new(versionCommand)
|
||||
}
|
||||
|
||||
if command == nil {
|
||||
command, err = e.components.Command(args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// If we still don't have a command, show the help.
|
||||
if command == nil {
|
||||
e.ui.Error(fmt.Sprintf("Unknown command: %s\n", args[0]))
|
||||
e.printHelp()
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If we're supposed to print help, then print the help of the
|
||||
// command rather than running it.
|
||||
if isHelp {
|
||||
e.ui.Say(command.Help())
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
log.Printf("Executing command: %s\n", args[0])
|
||||
return command.Run(e, args[1:]), nil
|
||||
}
|
||||
|
||||
// Prints the CLI help to the UI.
|
||||
func (e *coreEnvironment) printHelp() {
|
||||
// Created a sorted slice of the map keys and record the longest
|
||||
// command name so we can better format the output later.
|
||||
maxKeyLen := 0
|
||||
for _, command := range e.commands {
|
||||
if len(command) > maxKeyLen {
|
||||
maxKeyLen = len(command)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the keys
|
||||
sort.Strings(e.commands)
|
||||
|
||||
// Create the communication/sync mechanisms to get the synopsis' of
|
||||
// the various commands. We do this in parallel since the overhead
|
||||
// of the subprocess underneath is very expensive and this speeds things
|
||||
// up an incredible amount.
|
||||
var wg sync.WaitGroup
|
||||
ch := make(chan *helpCommandEntry)
|
||||
|
||||
for i, key := range e.commands {
|
||||
wg.Add(1)
|
||||
|
||||
// Get the synopsis in a goroutine since it may take awhile
|
||||
// to subprocess out.
|
||||
go func(i int, key string) {
|
||||
defer wg.Done()
|
||||
var synopsis string
|
||||
command, err := e.components.Command(key)
|
||||
if err != nil {
|
||||
synopsis = fmt.Sprintf("Error loading command: %s", err.Error())
|
||||
} else if command == nil {
|
||||
return
|
||||
} else {
|
||||
synopsis = command.Synopsis()
|
||||
}
|
||||
|
||||
// Pad the key with spaces so that they're all the same width
|
||||
key = fmt.Sprintf("%s%s", key, strings.Repeat(" ", maxKeyLen-len(key)))
|
||||
|
||||
// Output the command and the synopsis
|
||||
ch <- &helpCommandEntry{
|
||||
i: i,
|
||||
key: key,
|
||||
synopsis: synopsis,
|
||||
}
|
||||
}(i, key)
|
||||
}
|
||||
|
||||
e.ui.Say("usage: packer [--version] [--help] <command> [<args>]\n")
|
||||
e.ui.Say("Available commands are:")
|
||||
|
||||
// Make a goroutine that just waits for all the synopsis gathering
|
||||
// to complete, and then output it.
|
||||
synopsisDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(synopsisDone)
|
||||
entries := make([]string, len(e.commands))
|
||||
|
||||
for entry := range ch {
|
||||
e.ui.Machine("command", entry.key, entry.synopsis)
|
||||
message := fmt.Sprintf(" %s %s", entry.key, entry.synopsis)
|
||||
entries[entry.i] = message
|
||||
}
|
||||
|
||||
for _, message := range entries {
|
||||
if message != "" {
|
||||
e.ui.Say(message)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait to complete getting the synopsis' then close the channel
|
||||
wg.Wait()
|
||||
close(ch)
|
||||
<-synopsisDone
|
||||
|
||||
e.ui.Say("\nGlobally recognized options:")
|
||||
e.ui.Say(" -machine-readable Machine-readable output format.")
|
||||
}
|
||||
|
||||
// Returns the UI for the environment. The UI is the interface that should
|
||||
// be used for all communication with the outside world.
|
||||
func (e *coreEnvironment) Ui() Ui {
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -43,13 +41,6 @@ func testEnvironment() Environment {
|
|||
return env
|
||||
}
|
||||
|
||||
func TestEnvironment_DefaultConfig_Commands(t *testing.T) {
|
||||
config := DefaultEnvironmentConfig()
|
||||
if len(config.Commands) != 0 {
|
||||
t.Fatalf("bad: %#v", config.Commands)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_DefaultConfig_Ui(t *testing.T) {
|
||||
config := DefaultEnvironmentConfig()
|
||||
if config.Ui == nil {
|
||||
|
@ -91,7 +82,6 @@ func TestEnvironment_NilComponents(t *testing.T) {
|
|||
// anything but if there is a panic in the test then yeah, something
|
||||
// went wrong.
|
||||
env.Builder("foo")
|
||||
env.Cli([]string{"foo"})
|
||||
env.Hook("foo")
|
||||
env.PostProcessor("foo")
|
||||
env.Provisioner("foo")
|
||||
|
@ -154,117 +144,6 @@ func TestEnvironment_Cache(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_Cli_Error(t *testing.T) {
|
||||
config := DefaultEnvironmentConfig()
|
||||
config.Components.Command = func(n string) (Command, error) { return nil, errors.New("foo") }
|
||||
|
||||
env, _ := NewEnvironment(config)
|
||||
_, err := env.Cli([]string{"foo"})
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
if err.Error() != "foo" {
|
||||
t.Fatalf("bad: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_Cli_CallsRun(t *testing.T) {
|
||||
command := &TestCommand{}
|
||||
commands := make(map[string]Command)
|
||||
commands["foo"] = command
|
||||
|
||||
config := &EnvironmentConfig{}
|
||||
config.Commands = []string{"foo"}
|
||||
config.Components.Command = func(n string) (Command, error) { return commands[n], nil }
|
||||
|
||||
env, _ := NewEnvironment(config)
|
||||
exitCode, err := env.Cli([]string{"foo", "bar", "baz"})
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
if !command.runCalled {
|
||||
t.Fatal("command should be run")
|
||||
}
|
||||
if command.runEnv != env {
|
||||
t.Fatalf("bad env: %#v", command.runEnv)
|
||||
}
|
||||
if !reflect.DeepEqual(command.runArgs, []string{"bar", "baz"}) {
|
||||
t.Fatalf("bad: %#v", command.runArgs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_DefaultCli_Empty(t *testing.T) {
|
||||
defaultEnv := testEnvironment()
|
||||
|
||||
// Test with no args
|
||||
exitCode, _ := defaultEnv.Cli([]string{})
|
||||
if exitCode != 1 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
|
||||
// Test with only blank args
|
||||
exitCode, _ = defaultEnv.Cli([]string{""})
|
||||
if exitCode != 1 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_DefaultCli_Help(t *testing.T) {
|
||||
defaultEnv := testEnvironment()
|
||||
|
||||
// A little lambda to help us test the output actually contains help
|
||||
testOutput := func() {
|
||||
buffer := defaultEnv.Ui().(*BasicUi).Writer.(*bytes.Buffer)
|
||||
output := buffer.String()
|
||||
buffer.Reset()
|
||||
if !strings.Contains(output, "usage: packer") {
|
||||
t.Fatalf("should contain help: %#v", output)
|
||||
}
|
||||
}
|
||||
|
||||
// Test "--help"
|
||||
exitCode, _ := defaultEnv.Cli([]string{"--help"})
|
||||
if exitCode != 1 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
testOutput()
|
||||
|
||||
// Test "-h"
|
||||
exitCode, _ = defaultEnv.Cli([]string{"--help"})
|
||||
if exitCode != 1 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
testOutput()
|
||||
}
|
||||
|
||||
func TestEnvironment_DefaultCli_Version(t *testing.T) {
|
||||
defaultEnv := testEnvironment()
|
||||
|
||||
versionCommands := []string{"version", "--version", "-v"}
|
||||
for _, command := range versionCommands {
|
||||
exitCode, _ := defaultEnv.Cli([]string{command})
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
|
||||
// Test the --version and -v can appear anywhere
|
||||
exitCode, _ = defaultEnv.Cli([]string{"bad", command})
|
||||
|
||||
if command != "version" {
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
} else {
|
||||
if exitCode != 1 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvironment_Hook(t *testing.T) {
|
||||
hook := &MockHook{}
|
||||
hooks := make(map[string]Hook)
|
||||
|
|
|
@ -138,17 +138,6 @@ func (c *Client) Builder() (packer.Builder, error) {
|
|||
return &cmdBuilder{client.Builder(), c}, nil
|
||||
}
|
||||
|
||||
// Returns a command implementation that is communicating over this
|
||||
// client. If the client hasn't been started, this will start it.
|
||||
func (c *Client) Command() (packer.Command, error) {
|
||||
client, err := c.packrpcClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cmdCommand{client.Command(), c}, nil
|
||||
}
|
||||
|
||||
// Returns a hook implementation that is communicating over this
|
||||
// client. If the client hasn't been started, this will start it.
|
||||
func (c *Client) Hook() (packer.Hook, error) {
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"log"
|
||||
)
|
||||
|
||||
type cmdCommand struct {
|
||||
command packer.Command
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (c *cmdCommand) Help() (result string) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
c.checkExit(r, func() { result = "" })
|
||||
}()
|
||||
|
||||
result = c.command.Help()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cmdCommand) Run(e packer.Environment, args []string) (exitCode int) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
c.checkExit(r, func() { exitCode = 1 })
|
||||
}()
|
||||
|
||||
exitCode = c.command.Run(e, args)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cmdCommand) Synopsis() (result string) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
c.checkExit(r, func() {
|
||||
result = ""
|
||||
})
|
||||
}()
|
||||
|
||||
result = c.command.Synopsis()
|
||||
return
|
||||
}
|
||||
|
||||
func (c *cmdCommand) checkExit(p interface{}, cb func()) {
|
||||
if c.client.Exited() {
|
||||
cb()
|
||||
} else if p != nil && !Killed {
|
||||
log.Panic(p)
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"os/exec"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type helperCommand byte
|
||||
|
||||
func (helperCommand) Help() string {
|
||||
return "2"
|
||||
}
|
||||
|
||||
func (helperCommand) Run(packer.Environment, []string) int {
|
||||
return 42
|
||||
}
|
||||
|
||||
func (helperCommand) Synopsis() string {
|
||||
return "1"
|
||||
}
|
||||
|
||||
func TestCommand_NoExist(t *testing.T) {
|
||||
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
|
||||
defer c.Kill()
|
||||
|
||||
_, err := c.Command()
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommand_Good(t *testing.T) {
|
||||
c := NewClient(&ClientConfig{Cmd: helperProcess("command")})
|
||||
defer c.Kill()
|
||||
|
||||
command, err := c.Command()
|
||||
if err != nil {
|
||||
t.Fatalf("should not have error: %s", err)
|
||||
}
|
||||
|
||||
result := command.Synopsis()
|
||||
if result != "1" {
|
||||
t.Errorf("synopsis not correct: %s", result)
|
||||
}
|
||||
|
||||
result = command.Help()
|
||||
if result != "2" {
|
||||
t.Errorf("help not correct: %s", result)
|
||||
}
|
||||
}
|
|
@ -61,14 +61,6 @@ func TestHelperProcess(*testing.T) {
|
|||
}
|
||||
server.RegisterBuilder(new(packer.MockBuilder))
|
||||
server.Serve()
|
||||
case "command":
|
||||
server, err := Server()
|
||||
if err != nil {
|
||||
log.Printf("[ERR] %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
server.RegisterCommand(new(helperCommand))
|
||||
server.Serve()
|
||||
case "hook":
|
||||
server, err := Server()
|
||||
if err != nil {
|
||||
|
|
|
@ -10,7 +10,6 @@ package plugin
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
packrpc "github.com/mitchellh/packer/packer/rpc"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -38,8 +37,6 @@ const APIVersion = "4"
|
|||
// Server waits for a connection to this plugin and returns a Packer
|
||||
// RPC server that you can use to register components and serve them.
|
||||
func Server() (*packrpc.Server, error) {
|
||||
log.Printf("Plugin build against Packer '%s'", packer.GitCommit)
|
||||
|
||||
if os.Getenv(MagicCookieKey) != MagicCookieValue {
|
||||
return nil, errors.New(
|
||||
"Please do not execute plugins directly. Packer will execute these for you.")
|
||||
|
|
|
@ -90,13 +90,6 @@ func (c *Client) Cache() packer.Cache {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) Command() packer.Command {
|
||||
return &command{
|
||||
client: c.client,
|
||||
mux: c.mux,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Communicator() packer.Communicator {
|
||||
return &communicator{
|
||||
client: c.client,
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"net/rpc"
|
||||
)
|
||||
|
||||
// A Command is an implementation of the packer.Command interface where the
|
||||
// command is actually executed over an RPC connection.
|
||||
type command struct {
|
||||
client *rpc.Client
|
||||
mux *muxBroker
|
||||
}
|
||||
|
||||
// A CommandServer wraps a packer.Command and makes it exportable as part
|
||||
// of a Golang RPC server.
|
||||
type CommandServer struct {
|
||||
command packer.Command
|
||||
mux *muxBroker
|
||||
}
|
||||
|
||||
type CommandRunArgs struct {
|
||||
Args []string
|
||||
StreamId uint32
|
||||
}
|
||||
|
||||
type CommandSynopsisArgs byte
|
||||
|
||||
func (c *command) Help() (result string) {
|
||||
err := c.client.Call("Command.Help", new(interface{}), &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *command) Run(env packer.Environment, args []string) (result int) {
|
||||
nextId := c.mux.NextId()
|
||||
server := newServerWithMux(c.mux, nextId)
|
||||
server.RegisterEnvironment(env)
|
||||
go server.Serve()
|
||||
|
||||
rpcArgs := &CommandRunArgs{
|
||||
Args: args,
|
||||
StreamId: nextId,
|
||||
}
|
||||
err := c.client.Call("Command.Run", rpcArgs, &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *command) Synopsis() (result string) {
|
||||
err := c.client.Call("Command.Synopsis", CommandSynopsisArgs(0), &result)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *CommandServer) Help(args *interface{}, reply *string) error {
|
||||
*reply = c.command.Help()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommandServer) Run(args *CommandRunArgs, reply *int) error {
|
||||
client, err := newClientWithMux(c.mux, args.StreamId)
|
||||
if err != nil {
|
||||
return NewBasicError(err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
*reply = c.command.Run(client.Environment(), args.Args)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CommandServer) Synopsis(args *CommandSynopsisArgs, reply *string) error {
|
||||
*reply = c.command.Synopsis()
|
||||
return nil
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestCommand struct {
|
||||
runArgs []string
|
||||
runCalled bool
|
||||
runEnv packer.Environment
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Help() string {
|
||||
return "bar"
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Run(env packer.Environment, args []string) int {
|
||||
tc.runCalled = true
|
||||
tc.runArgs = args
|
||||
tc.runEnv = env
|
||||
return 0
|
||||
}
|
||||
|
||||
func (tc *TestCommand) Synopsis() string {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
func TestRPCCommand(t *testing.T) {
|
||||
// Create the command
|
||||
command := new(TestCommand)
|
||||
|
||||
// Start the server
|
||||
client, server := testClientServer(t)
|
||||
defer client.Close()
|
||||
defer server.Close()
|
||||
server.RegisterCommand(command)
|
||||
commClient := client.Command()
|
||||
|
||||
//Test Help
|
||||
help := commClient.Help()
|
||||
if help != "bar" {
|
||||
t.Fatalf("bad: %s", help)
|
||||
}
|
||||
|
||||
// Test run
|
||||
runArgs := []string{"foo", "bar"}
|
||||
testEnv := &testEnvironment{}
|
||||
exitCode := commClient.Run(testEnv, runArgs)
|
||||
if !reflect.DeepEqual(command.runArgs, runArgs) {
|
||||
t.Fatalf("bad: %#v", command.runArgs)
|
||||
}
|
||||
if exitCode != 0 {
|
||||
t.Fatalf("bad: %d", exitCode)
|
||||
}
|
||||
|
||||
if command.runEnv == nil {
|
||||
t.Fatal("runEnv should not be nil")
|
||||
}
|
||||
|
||||
// Test Synopsis
|
||||
synopsis := commClient.Synopsis()
|
||||
if synopsis != "foo" {
|
||||
t.Fatalf("bad: %#v", synopsis)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCommand_Implements(t *testing.T) {
|
||||
var _ packer.Command = new(command)
|
||||
}
|
|
@ -20,10 +20,6 @@ type EnvironmentServer struct {
|
|||
mux *muxBroker
|
||||
}
|
||||
|
||||
type EnvironmentCliArgs struct {
|
||||
Args []string
|
||||
}
|
||||
|
||||
func (e *Environment) Builder(name string) (b packer.Builder, err error) {
|
||||
var streamId uint32
|
||||
err = e.client.Call("Environment.Builder", name, &streamId)
|
||||
|
@ -53,12 +49,6 @@ func (e *Environment) Cache() packer.Cache {
|
|||
return client.Cache()
|
||||
}
|
||||
|
||||
func (e *Environment) Cli(args []string) (result int, err error) {
|
||||
rpcArgs := &EnvironmentCliArgs{args}
|
||||
err = e.client.Call("Environment.Cli", rpcArgs, &result)
|
||||
return
|
||||
}
|
||||
|
||||
func (e *Environment) Hook(name string) (h packer.Hook, err error) {
|
||||
var streamId uint32
|
||||
err = e.client.Call("Environment.Hook", name, &streamId)
|
||||
|
@ -138,11 +128,6 @@ func (e *EnvironmentServer) Cache(args *interface{}, reply *uint32) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (e *EnvironmentServer) Cli(args *EnvironmentCliArgs, reply *int) (err error) {
|
||||
*reply, err = e.env.Cli(args.Args)
|
||||
return
|
||||
}
|
||||
|
||||
func (e *EnvironmentServer) Hook(name string, reply *uint32) error {
|
||||
hook, err := e.env.Hook(name)
|
||||
if err != nil {
|
||||
|
|
|
@ -2,7 +2,6 @@ package rpc
|
|||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -95,19 +94,6 @@ func TestEnvironmentRPC(t *testing.T) {
|
|||
t.Fatal("should be called")
|
||||
}
|
||||
|
||||
// Test Cli
|
||||
cliArgs := []string{"foo", "bar"}
|
||||
result, _ := eClient.Cli(cliArgs)
|
||||
if !e.cliCalled {
|
||||
t.Fatal("should be called")
|
||||
}
|
||||
if !reflect.DeepEqual(e.cliArgs, cliArgs) {
|
||||
t.Fatalf("bad: %#v", e.cliArgs)
|
||||
}
|
||||
if result != 42 {
|
||||
t.Fatalf("bad: %#v", result)
|
||||
}
|
||||
|
||||
// Test Provisioner
|
||||
_, _ = eClient.Provisioner("foo")
|
||||
if !e.provCalled {
|
||||
|
|
|
@ -88,13 +88,6 @@ func (s *Server) RegisterCache(c packer.Cache) {
|
|||
})
|
||||
}
|
||||
|
||||
func (s *Server) RegisterCommand(c packer.Command) {
|
||||
s.server.RegisterName(DefaultCommandEndpoint, &CommandServer{
|
||||
command: c,
|
||||
mux: s.mux,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) RegisterCommunicator(c packer.Communicator) {
|
||||
s.server.RegisterName(DefaultCommunicatorEndpoint, &CommunicatorServer{
|
||||
c: c,
|
||||
|
|
|
@ -119,6 +119,8 @@ func ParseTemplate(data []byte, vars map[string]string) (t *Template, err error)
|
|||
}
|
||||
|
||||
if rawTpl.MinimumPackerVersion != "" {
|
||||
// TODO: NOPE! Replace this
|
||||
Version := "1.0"
|
||||
vCur, err := version.NewVersion(Version)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
package packer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// The git commit that is being compiled. This will be filled in by the
|
||||
// compiler for source builds.
|
||||
var GitCommit string
|
||||
|
||||
// This should be check to a callback to check for the latest version.
|
||||
//
|
||||
// The global nature of this variable is dirty, but a version checker
|
||||
// really shouldn't change anyways.
|
||||
var VersionChecker VersionCheckFunc
|
||||
|
||||
// The version of packer.
|
||||
const Version = "0.7.1"
|
||||
|
||||
// Any pre-release marker for the version. If this is "" (empty string),
|
||||
// then it means that it is a final release. Otherwise, this is the
|
||||
// pre-release marker.
|
||||
const VersionPrerelease = ""
|
||||
|
||||
// VersionCheckFunc is the callback that is called to check the latest
|
||||
// version of Packer.
|
||||
type VersionCheckFunc func(string) (VersionCheckInfo, error)
|
||||
|
||||
// VersionCheckInfo is the return value for the VersionCheckFunc that
|
||||
// contains the latest version information.
|
||||
type VersionCheckInfo struct {
|
||||
Outdated bool
|
||||
Latest string
|
||||
Alerts []string
|
||||
}
|
||||
|
||||
type versionCommand byte
|
||||
|
||||
func (versionCommand) Help() string {
|
||||
return `usage: packer version
|
||||
|
||||
Outputs the version of Packer that is running. There are no additional
|
||||
command-line flags for this command.`
|
||||
}
|
||||
|
||||
func (versionCommand) Run(env Environment, args []string) int {
|
||||
env.Ui().Machine("version", Version)
|
||||
env.Ui().Machine("version-prelease", VersionPrerelease)
|
||||
env.Ui().Machine("version-commit", GitCommit)
|
||||
env.Ui().Say(VersionString())
|
||||
|
||||
if VersionChecker != nil {
|
||||
current := Version
|
||||
if VersionPrerelease != "" {
|
||||
current += fmt.Sprintf(".%s", VersionPrerelease)
|
||||
}
|
||||
|
||||
info, err := VersionChecker(current)
|
||||
if err != nil {
|
||||
env.Ui().Say(fmt.Sprintf("\nError checking latest version: %s", err))
|
||||
}
|
||||
if info.Outdated {
|
||||
env.Ui().Say(fmt.Sprintf(
|
||||
"\nYour version of Packer is out of date! The latest version\n"+
|
||||
"is %s. You can update by downloading from www.packer.io.",
|
||||
info.Latest))
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (versionCommand) Synopsis() string {
|
||||
return "print Packer version"
|
||||
}
|
||||
|
||||
// VersionString returns the Packer version in human-readable
|
||||
// form complete with pre-release and git commit info if it is
|
||||
// available.
|
||||
func VersionString() string {
|
||||
var versionString bytes.Buffer
|
||||
fmt.Fprintf(&versionString, "Packer v%s", Version)
|
||||
if VersionPrerelease != "" {
|
||||
fmt.Fprintf(&versionString, ".%s", VersionPrerelease)
|
||||
|
||||
if GitCommit != "" {
|
||||
fmt.Fprintf(&versionString, " (%s)", GitCommit)
|
||||
}
|
||||
}
|
||||
|
||||
return versionString.String()
|
||||
}
|
3
panic.go
3
panic.go
|
@ -2,10 +2,11 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/panicwrap"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/panicwrap"
|
||||
)
|
||||
|
||||
// This is output if a panic happens.
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/command/build"
|
||||
"github.com/mitchellh/packer/packer/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server, err := plugin.Server()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.RegisterCommand(new(build.Command))
|
||||
server.Serve()
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package main
|
|
@ -1,15 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/command/fix"
|
||||
"github.com/mitchellh/packer/packer/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server, err := plugin.Server()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.RegisterCommand(new(fix.Command))
|
||||
server.Serve()
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package main
|
|
@ -1,15 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/command/inspect"
|
||||
"github.com/mitchellh/packer/packer/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server, err := plugin.Server()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.RegisterCommand(new(inspect.Command))
|
||||
server.Serve()
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package main
|
|
@ -1,15 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/command/validate"
|
||||
"github.com/mitchellh/packer/packer/plugin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server, err := plugin.Server()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
server.RegisterCommand(new(validate.Command))
|
||||
server.Serve()
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
package main
|
|
@ -0,0 +1,12 @@
|
|||
package main
|
||||
|
||||
// The git commit that was compiled. This will be filled in by the compiler.
|
||||
var GitCommit string
|
||||
|
||||
// The main version number that is being run at the moment.
|
||||
const Version = "0.8.0"
|
||||
|
||||
// A pre-release marker for the version. If this is "" (empty string)
|
||||
// then it means that it is a final release. Otherwise, this is a pre-release
|
||||
// such as "dev" (in development), "beta", "rc1", etc.
|
||||
const VersionPrerelease = "dev"
|
Loading…
Reference in New Issue