post-processor/vagrant: Can make AWS boxes!
This commit is contained in:
parent
8a609b67c1
commit
f4c9f96085
|
@ -0,0 +1,40 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
const BuilderId = "mitchellh.post-processor.vagrant"
|
||||
|
||||
type Artifact struct {
|
||||
Path string
|
||||
Provider string
|
||||
}
|
||||
|
||||
func NewArtifact(provider, path string) *Artifact {
|
||||
return &Artifact{
|
||||
Path: path,
|
||||
Provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
return BuilderId
|
||||
}
|
||||
|
||||
func (a *Artifact) Files() []string {
|
||||
return []string{a.Path}
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return fmt.Sprintf("'%s' provider box: %s", a.Provider, a.Path)
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
return os.Remove(a.Path)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArtifact_ImplementsArtifact(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Artifact{}
|
||||
if _, ok := raw.(packer.Artifact); !ok {
|
||||
t.Fatalf("Artifact should be a Artifact")
|
||||
}
|
||||
}
|
|
@ -1,16 +1,90 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type AWSBoxConfig struct {
|
||||
OutputPath string `mapstructure:"output"`
|
||||
}
|
||||
|
||||
type AWSVagrantfileTemplate struct {
|
||||
Images map[string]string
|
||||
}
|
||||
|
||||
type AWSBoxPostProcessor struct {
|
||||
config AWSBoxConfig
|
||||
}
|
||||
|
||||
func (p *AWSBoxPostProcessor) Configure(raw interface{}) error {
|
||||
err := mapstructure.Decode(raw, &p.config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) {
|
||||
return nil, nil
|
||||
// Determine the regions...
|
||||
tplData := &AWSVagrantfileTemplate{
|
||||
Images: make(map[string]string),
|
||||
}
|
||||
|
||||
for _, regions := range strings.Split(artifact.Id(), ",") {
|
||||
parts := strings.Split(regions, ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("Poorly formatted artifact ID: %s", artifact.Id())
|
||||
}
|
||||
|
||||
tplData.Images[parts[0]] = parts[1]
|
||||
}
|
||||
|
||||
// Create a temporary directory for us to build the contents of the box in
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create the Vagrantfile from the template
|
||||
vf, err := os.Create(filepath.Join(dir, "Vagrantfile"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer vf.Close()
|
||||
|
||||
t := template.Must(template.New("vagrantfile").Parse(defaultVagrantfile))
|
||||
t.Execute(vf, tplData)
|
||||
vf.Close()
|
||||
|
||||
// Create the metadata
|
||||
metadata := map[string]string{"provider": "aws"}
|
||||
if err := WriteMetadata(dir, metadata); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Compress the directory to the given output path
|
||||
if err := DirToBox(p.config.OutputPath, dir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewArtifact("aws", p.config.OutputPath), nil
|
||||
}
|
||||
|
||||
var defaultVagrantfile = `
|
||||
Vagrant.configure("2") do |config|
|
||||
config.vm.provider "aws" do |aws|
|
||||
{{ range $region, $ami := .Images }}
|
||||
aws.region_config "{{ $region }}", ami: "{{ $ami }}"
|
||||
{{ end }}
|
||||
end
|
||||
end
|
||||
`
|
||||
|
|
|
@ -12,4 +12,3 @@ func TestPostProcessor_ImplementsPostProcessor(t *testing.T) {
|
|||
t.Fatalf("AWS PostProcessor should be a PostProcessor")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ var builtins = map[string]string{
|
|||
"mitchellh.amazonebs": "aws",
|
||||
}
|
||||
|
||||
type Config struct {}
|
||||
type Config struct{}
|
||||
|
||||
type PostProcessor struct {
|
||||
config Config
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package vagrant
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// DirToBox takes the directory and compresses it into a Vagrant-compatible
|
||||
// box. This function does not perform checks to verify that dir is
|
||||
// actually a proper box. This is an expected precondition.
|
||||
func DirToBox(dst, dir string) error {
|
||||
dstF, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstF.Close()
|
||||
|
||||
gzipWriter := gzip.NewWriter(dstF)
|
||||
defer gzipWriter.Close()
|
||||
|
||||
tarWriter := tar.NewWriter(gzipWriter)
|
||||
defer tarWriter.Close()
|
||||
|
||||
// This is the walk func that tars each of the files in the dir
|
||||
tarWalk := func(path string, info os.FileInfo, prevErr error) error {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
header, err := tar.FileInfoHeader(info, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We have to set the Name explicitly because it is supposed to
|
||||
// be a relative path to the root. Otherwise, the tar ends up
|
||||
// being a bunch of files in the root, even if they're actually
|
||||
// nested in a dir in the original "dir" param.
|
||||
header.Name, err = filepath.Rel(dir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := tarWriter.WriteHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(tarWriter, f); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Tar.gz everything up
|
||||
return filepath.Walk(dir, tarWalk)
|
||||
}
|
||||
|
||||
// WriteMetadata writes the "metadata.json" file for a Vagrant box.
|
||||
func WriteMetadata(dir string, contents interface{}) error {
|
||||
f, err := os.Create(filepath.Join(dir, "metadata.json"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
enc := json.NewEncoder(f)
|
||||
return enc.Encode(contents)
|
||||
}
|
Loading…
Reference in New Issue