Lots of stuff, too early for meaningful commit messages
UI, command dispatch
This commit is contained in:
parent
817822abab
commit
db1c11fff5
|
@ -1,2 +1 @@
|
||||||
/bin
|
/bin
|
||||||
/packer
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
||||||
all:
|
all:
|
||||||
@mkdir -p bin/
|
@mkdir -p bin/
|
||||||
go get -a
|
go get -d
|
||||||
go build -a -o bin/packer
|
go build -a -o bin/packer
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
|
@ -11,11 +11,12 @@ type Builder struct {
|
||||||
config config
|
config config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Builder) ConfigInterface() interface{} {
|
||||||
|
return &b.config
|
||||||
|
}
|
||||||
|
|
||||||
func (*Builder) Prepare() {
|
func (*Builder) Prepare() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Builder) Build() {
|
func (b *Builder) Build() {
|
||||||
}
|
|
||||||
|
|
||||||
func (*Builder) Destroy() {
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "my-custom-image",
|
||||||
|
|
||||||
|
"builders": [
|
||||||
|
{
|
||||||
|
"type": "amazon-ebs",
|
||||||
|
"region": "us-east-1",
|
||||||
|
"source": "ami-de0d9eb7"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"provisioners": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"path": "script.sh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"type": "vagrant"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
56
packer.go
56
packer.go
|
@ -1,44 +1,40 @@
|
||||||
// This is the main package for the `packer` application.
|
// This is the main package for the `packer` application.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/mitchellh/packer/builder/amazon"
|
import "github.com/mitchellh/packer/packer"
|
||||||
|
import "os"
|
||||||
|
|
||||||
// A command is a runnable sub-command of the `packer` application.
|
type RawTemplate struct {
|
||||||
// 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 {
|
|
||||||
Run(args []string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The environment struct contains all the state necessary for a single
|
|
||||||
// instance of Packer.
|
|
||||||
//
|
|
||||||
// It is *not* a singleton, but generally a single environment is created
|
|
||||||
// when Packer starts running to represent that Packer run. Technically,
|
|
||||||
// if you're building a custom Packer binary, you could instantiate multiple
|
|
||||||
// environments and run them in parallel.
|
|
||||||
type Environment struct {
|
|
||||||
commands map[string]Command
|
|
||||||
}
|
|
||||||
|
|
||||||
type Template struct {
|
|
||||||
Name string
|
Name string
|
||||||
Builders map[string]interface{} `toml:"builder"`
|
Builders []map[string]interface{}
|
||||||
Provisioners map[string]interface{} `toml:"provision"`
|
Provisioners []map[string]interface{}
|
||||||
Outputs map[string]interface{} `toml:"output"`
|
Outputs []map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Builder interface {
|
type Builder interface {
|
||||||
|
ConfigInterface() interface{}
|
||||||
Prepare()
|
Prepare()
|
||||||
Build()
|
Build()
|
||||||
Destroy()
|
}
|
||||||
|
|
||||||
|
type Build interface {
|
||||||
|
Hook(name string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var builder Builder
|
env := packer.NewEnvironment()
|
||||||
builder = &amazon.Builder{}
|
os.Exit(env.Cli(os.Args[1:]))
|
||||||
builder.Build()
|
/*
|
||||||
|
file, _ := ioutil.ReadFile("example.json")
|
||||||
|
|
||||||
|
var tpl RawTemplate
|
||||||
|
json.Unmarshal(file, &tpl)
|
||||||
|
fmt.Printf("%#v\n", tpl)
|
||||||
|
|
||||||
|
builderType, ok := tpl.Builders[0]["type"].(Build)
|
||||||
|
if !ok {
|
||||||
|
panic("OH NOES")
|
||||||
|
}
|
||||||
|
fmt.Printf("TYPE: %v\n", builderType)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
// The packer package contains the core components of Packer.
|
||||||
|
package packer
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
Run(env *Environment, args []string) int
|
||||||
|
}
|
||||||
|
|
||||||
|
// The environment struct contains all the state necessary for a single
|
||||||
|
// instance of Packer.
|
||||||
|
//
|
||||||
|
// It is *not* a singleton, but generally a single environment is created
|
||||||
|
// when Packer starts running to represent that Packer run. Technically,
|
||||||
|
// if you're building a custom Packer binary, you could instantiate multiple
|
||||||
|
// environments and run them in parallel.
|
||||||
|
type Environment struct {
|
||||||
|
command map[string]Command
|
||||||
|
ui Ui
|
||||||
|
}
|
||||||
|
|
||||||
|
// This creates a new environment
|
||||||
|
func NewEnvironment() *Environment {
|
||||||
|
env := &Environment{}
|
||||||
|
env.command = make(map[string]Command)
|
||||||
|
env.command["version"] = new(versionCommand)
|
||||||
|
env.ui = &ReaderWriterUi{ os.Stdin, os.Stdout }
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 *Environment) Cli(args []string) int {
|
||||||
|
if len(args) == 0 {
|
||||||
|
e.PrintHelp()
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command, ok := e.command[args[0]]
|
||||||
|
if !ok {
|
||||||
|
// The command was not found. In this case, let's go through
|
||||||
|
// the arguments and see if the user is requesting the version.
|
||||||
|
for _, arg := range args {
|
||||||
|
if arg == "--version" || arg == "-v" {
|
||||||
|
command = e.command["version"]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we still don't have a command, show the help.
|
||||||
|
if command == nil {
|
||||||
|
e.PrintHelp()
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command.Run(e, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the UI for the environment. The UI is the interface that should
|
||||||
|
// be used for all communication with the outside world.
|
||||||
|
func (e *Environment) Ui() Ui {
|
||||||
|
return e.ui
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prints the CLI help to the UI.
|
||||||
|
func (e *Environment) PrintHelp() {
|
||||||
|
e.ui.Say("Bad.\n")
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package packer
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
// The Ui interface handles all communication for Packer with the outside
|
||||||
|
// world. This sort of control allows us to strictly control how output
|
||||||
|
// is formatted and various levels of output.
|
||||||
|
type Ui interface {
|
||||||
|
Say(format string, a ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ReaderWriterUi is a UI that writes and reads from standard Go
|
||||||
|
// io.Reader and io.Writer.
|
||||||
|
type ReaderWriterUi struct {
|
||||||
|
Reader io.Reader
|
||||||
|
Writer io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rw *ReaderWriterUi) Say(format string, a ...interface{}) {
|
||||||
|
fmt.Fprintf(rw.Writer, format, a...)
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package packer
|
||||||
|
|
||||||
|
// The version of packer.
|
||||||
|
const Version = "0.1.0.dev"
|
||||||
|
|
||||||
|
type versionCommand byte
|
||||||
|
|
||||||
|
// Implement the Command interface by simply showing the version
|
||||||
|
func (versionCommand) Run(env *Environment, args[] string) int {
|
||||||
|
env.Ui().Say("Packer v%v\n", Version)
|
||||||
|
return 0
|
||||||
|
}
|
Loading…
Reference in New Issue