packer-cn/packer/environment.go

142 lines
3.3 KiB
Go
Raw Normal View History

// The packer package contains the core components of Packer.
package packer
2013-03-24 19:28:35 -04:00
import (
"errors"
2013-03-24 19:28:35 -04:00
"fmt"
"os"
"sort"
"strings"
)
2013-05-05 17:47:17 -04:00
type BuilderFunc func(name string) Builder
type CommandFunc func(name string) Command
2013-05-02 17:03:55 -04:00
// The environment interface provides access to the configuration and
// state of a single Packer run.
//
2013-05-02 17:03:55 -04:00
// It allows for things such as executing CLI commands, getting the
// list of available builders, and more.
type Environment interface {
Cli(args []string) int
Ui() Ui
}
// An implementation of an Environment that represents the Packer core
// environment.
type coreEnvironment struct {
2013-05-05 17:47:17 -04:00
builderFunc BuilderFunc
commands []string
commandFunc CommandFunc
ui Ui
}
2013-04-15 23:26:38 -04:00
// This struct configures new environments.
type EnvironmentConfig struct {
2013-05-05 17:47:17 -04:00
BuilderFunc BuilderFunc
CommandFunc CommandFunc
Commands []string
Ui Ui
2013-04-15 23:26:38 -04:00
}
// DefaultEnvironmentConfig returns a default EnvironmentConfig that can
// be used to create a new enviroment with NewEnvironment with sane defaults.
func DefaultEnvironmentConfig() *EnvironmentConfig {
config := &EnvironmentConfig{}
2013-05-05 17:47:17 -04:00
config.BuilderFunc = func(string) Builder { return nil }
config.CommandFunc = func(string) Command { return nil }
config.Commands = make([]string, 0)
config.Ui = &ReaderWriterUi{os.Stdin, os.Stdout}
return config
}
2013-04-15 23:26:38 -04:00
// This creates a new environment
2013-05-02 17:03:55 -04:00
func NewEnvironment(config *EnvironmentConfig) (resultEnv Environment, err error) {
if config == nil {
err = errors.New("config must be given to initialize environment")
return
2013-04-15 23:26:38 -04:00
}
2013-05-02 17:03:55 -04:00
env := &coreEnvironment{}
2013-05-05 17:47:17 -04:00
env.builderFunc = config.BuilderFunc
env.commandFunc = config.CommandFunc
env.commands = config.Commands
env.ui = config.Ui
2013-05-02 17:03:55 -04:00
resultEnv = env
return
}
// Executes a command as if it was typed on the command-line interface.
// The return value is the exit code of the command.
2013-05-02 17:03:55 -04:00
func (e *coreEnvironment) Cli(args []string) int {
if len(args) == 0 || args[0] == "--help" || args[0] == "-h" {
2013-05-02 17:03:55 -04:00
e.printHelp()
return 1
}
2013-05-05 17:47:17 -04:00
version := args[0] == "version"
if !version {
for _, arg := range args {
if arg == "--version" || arg == "-v" {
2013-05-05 17:47:17 -04:00
version = true
break
}
}
2013-05-05 17:47:17 -04:00
}
var command Command
if version {
command = new(versionCommand)
}
if command == nil {
command = e.commandFunc(args[0])
// If we still don't have a command, show the help.
if command == nil {
2013-05-02 17:03:55 -04:00
e.printHelp()
return 1
}
}
return command.Run(e, args[1:])
}
// Prints the CLI help to the UI.
2013-05-02 17:03:55 -04:00
func (e *coreEnvironment) printHelp() {
2013-03-24 19:28:35 -04:00
// Created a sorted slice of the map keys and record the longest
// command name so we can better format the output later.
i := 0
maxKeyLen := 0
2013-05-05 17:47:17 -04:00
for _, command := range e.commands {
if len(command) > maxKeyLen {
maxKeyLen = len(command)
2013-03-24 19:28:35 -04:00
}
i++
}
// Sort the keys
2013-05-05 17:47:17 -04:00
sort.Strings(e.commands)
2013-03-24 19:28:35 -04:00
e.ui.Say("usage: packer [--version] [--help] <command> [<args>]\n\n")
e.ui.Say("Available commands are:\n")
2013-05-05 17:47:17 -04:00
for _, key := range e.commands {
command := e.commandFunc(key)
2013-03-24 19:28:35 -04:00
// Pad the key with spaces so that they're all the same width
2013-03-24 19:36:02 -04:00
key = fmt.Sprintf("%v%v", key, strings.Repeat(" ", maxKeyLen-len(key)))
2013-03-24 19:28:35 -04:00
// Output the command and the synopsis
e.ui.Say(" %v %v\n", key, command.Synopsis())
}
}
2013-03-24 19:41:58 -04:00
// Returns the UI for the environment. The UI is the interface that should
// be used for all communication with the outside world.
2013-05-02 17:03:55 -04:00
func (e *coreEnvironment) Ui() Ui {
2013-03-24 19:41:58 -04:00
return e.ui
}