Compare commits

..

1 Commits

Author SHA1 Message Date
Mitchell Hashimoto 9907933bf8 v0.3.2 2013-08-18 09:47:14 -06:00
21 changed files with 97 additions and 139 deletions
-21
View File
@@ -1,24 +1,3 @@
## 0.3.3 (August 19, 2013)
FEATURES:
* builder/virtualbox: support exporting in OVA format. [GH-309]
IMPROVEMENTS:
* core: All HTTP downloads across Packer now support the standard
proxy environmental variables (`HTTP_PROXY`, `NO_PROXY`, etc.) [GH-252]
* builder/amazon: API requests will use HTTP proxy if specified by
enviromental variables.
* builder/digitalocean: API requests will use HTTP proxy if specified
by environmental variables.
BUG FIXES:
* core: TCP connection between plugin processes will keep-alive. [GH-312]
* core: No more "unused key keep_input_artifact" for post processors [GH-310]
* post-processor/vagrant: `output_path` templates now work again.
## 0.3.2 (August 18, 2013)
FEATURES:
+1 -5
View File
@@ -43,11 +43,7 @@ type DigitalOceanClient struct {
// Creates a new client for communicating with DO
func (d DigitalOceanClient) New(client string, key string) *DigitalOceanClient {
c := &DigitalOceanClient{
client: &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
},
client: http.DefaultClient,
BaseURL: DIGITALOCEAN_API_URL,
ClientID: client,
APIKey: key,
-11
View File
@@ -27,7 +27,6 @@ type config struct {
BootCommand []string `mapstructure:"boot_command"`
DiskSize uint `mapstructure:"disk_size"`
FloppyFiles []string `mapstructure:"floppy_files"`
Format string `mapstructure:"format"`
GuestAdditionsPath string `mapstructure:"guest_additions_path"`
GuestAdditionsURL string `mapstructure:"guest_additions_url"`
GuestAdditionsSHA256 string `mapstructure:"guest_additions_sha256"`
@@ -132,10 +131,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
}
if b.config.Format == "" {
b.config.Format = "ovf"
}
// Errors
templates := map[string]*string{
"guest_additions_sha256": &b.config.GuestAdditionsSHA256,
@@ -150,7 +145,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
"ssh_username": &b.config.SSHUser,
"virtualbox_version_file": &b.config.VBoxVersionFile,
"vm_name": &b.config.VMName,
"format": &b.config.Format,
"boot_wait": &b.config.RawBootWait,
"shutdown_timeout": &b.config.RawShutdownTimeout,
"ssh_wait_timeout": &b.config.RawSSHWaitTimeout,
@@ -203,11 +197,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
}
if !(b.config.Format == "ovf" || b.config.Format == "ova") {
errs = packer.MultiErrorAppend(
errs, errors.New("invalid format, only 'ovf' or 'ova' are allowed"))
}
if b.config.HTTPPortMin > b.config.HTTPPortMax {
errs = packer.MultiErrorAppend(
errs, errors.New("http_port_min must be less than http_port_max"))
-32
View File
@@ -58,10 +58,6 @@ func TestBuilderPrepare_Defaults(t *testing.T) {
if b.config.VMName != "packer-foo" {
t.Errorf("bad vm name: %s", b.config.VMName)
}
if b.config.Format != "ovf" {
t.Errorf("bad format: %s", b.config.Format)
}
}
func TestBuilderPrepare_BootWait(t *testing.T) {
@@ -252,34 +248,6 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
}
}
func TestBuilderPrepare_Format(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["format"] = "illegal value"
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
// Good
config["format"] = "ova"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
// Good
config["format"] = "ovf"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_InvalidKey(t *testing.T) {
var b Builder
config := testConfig()
+1 -1
View File
@@ -50,7 +50,7 @@ func (s *stepExport) Run(state map[string]interface{}) multistep.StepAction {
}
// Export the VM to an OVF
outputPath := filepath.Join(config.OutputDir, "packer."+config.Format)
outputPath := filepath.Join(config.OutputDir, "packer.ovf")
command = []string{
"export",
+1 -12
View File
@@ -188,18 +188,7 @@ func (*HTTPDownloader) Cancel() {
func (d *HTTPDownloader) Download(dst io.Writer, src *url.URL) error {
log.Printf("Starting download: %s", src.String())
req, err := http.NewRequest("GET", src.String(), nil)
if err != nil {
return err
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
},
}
resp, err := httpClient.Do(req)
resp, err := http.Get(src.String())
if err != nil {
return err
}
+1 -1
View File
@@ -90,7 +90,7 @@ type coreBuild struct {
type coreBuildPostProcessor struct {
processor PostProcessor
processorType string
config map[string]interface{}
config interface{}
keepInputArtifact bool
}
+10 -10
View File
@@ -20,7 +20,7 @@ func testBuild() *coreBuild {
},
postProcessors: [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "testPP", make(map[string]interface{}), true},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "testPP", 42, true},
},
},
variables: make(map[string]string),
@@ -66,7 +66,7 @@ func TestBuild_Prepare(t *testing.T) {
corePP := build.postProcessors[0][0]
pp := corePP.processor.(*TestPostProcessor)
assert.True(pp.configCalled, "config should be called")
assert.Equal(pp.configVal, []interface{}{make(map[string]interface{}), packerConfig}, "config should have right value")
assert.Equal(pp.configVal, []interface{}{42, packerConfig}, "config should have right value")
}
func TestBuild_Prepare_Twice(t *testing.T) {
@@ -231,7 +231,7 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "pp", 42, false},
},
}
@@ -256,10 +256,10 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1"}, "pp", 42, false},
},
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2"}, "pp", make(map[string]interface{}), true},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2"}, "pp", 42, true},
},
}
@@ -284,12 +284,12 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1a"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1b"}, "pp", make(map[string]interface{}), true},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1a"}, "pp", 42, false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1b"}, "pp", 42, true},
},
[]coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2a"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2b"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2a"}, "pp", 42, false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2b"}, "pp", 42, false},
},
}
@@ -315,7 +315,7 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{
coreBuildPostProcessor{
&TestPostProcessor{artifactId: "pp", keep: true}, "pp", make(map[string]interface{}), false,
&TestPostProcessor{artifactId: "pp", keep: true}, "pp", 42, false,
},
},
}
+2 -7
View File
@@ -10,7 +10,6 @@ import (
"io"
"io/ioutil"
"log"
"net"
"net/rpc"
"os"
"os/exec"
@@ -329,14 +328,10 @@ func (c *Client) rpcClient() (*rpc.Client, error) {
return nil, err
}
conn, err := net.Dial("tcp", address)
client, err := rpc.Dial("tcp", address)
if err != nil {
return nil, err
}
// Make sure to set keep alive so that the connection doesn't die
tcpConn := conn.(*net.TCPConn)
tcpConn.SetKeepAlive(true)
return rpc.NewClient(tcpConn), nil
return client, nil
}
+3 -6
View File
@@ -50,7 +50,7 @@ type RawBuilderConfig struct {
type RawPostProcessorConfig struct {
Type string
KeepInputArtifact bool `mapstructure:"keep_input_artifact"`
RawConfig map[string]interface{}
RawConfig interface{}
}
// RawProvisionerConfig represents a raw, unprocessed provisioner configuration.
@@ -162,7 +162,7 @@ func ParseTemplate(data []byte) (t *Template, err error) {
// are actually three different formats that the user can use to define
// a post-processor.
for i, rawV := range rawTpl.PostProcessors {
rawPP, err := parsePostProcessor(i, rawV)
rawPP, err := parsePostProvisioner(i, rawV)
if err != nil {
errors = append(errors, err...)
continue
@@ -189,9 +189,6 @@ func ParseTemplate(data []byte) (t *Template, err error) {
continue
}
// Remove the input keep_input_artifact option
delete(pp, "keep_input_artifact")
config.RawConfig = pp
}
}
@@ -263,7 +260,7 @@ func ParseTemplateFile(path string) (*Template, error) {
return ParseTemplate(data)
}
func parsePostProcessor(i int, rawV interface{}) (result []map[string]interface{}, errors []error) {
func parsePostProvisioner(i int, rawV interface{}) (result []map[string]interface{}, errors []error) {
switch v := rawV.(type) {
case string:
result = []map[string]interface{}{
-5
View File
@@ -623,11 +623,6 @@ func TestTemplate_Build(t *testing.T) {
assert.Equal(len(coreBuild.postProcessors[1]), 2, "should have correct number")
assert.False(coreBuild.postProcessors[1][0].keepInputArtifact, "shoule be correct")
assert.True(coreBuild.postProcessors[1][1].keepInputArtifact, "shoule be correct")
config := coreBuild.postProcessors[1][1].config
if _, ok := config["keep_input_artifact"]; ok {
t.Fatal("should not have keep_input_artifact")
}
}
func TestTemplate_Build_ProvisionerOverride(t *testing.T) {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
var GitCommit string
// The version of packer.
const Version = "0.3.3"
const Version = "0.3.2"
// 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
+15 -6
View File
@@ -43,8 +43,20 @@ func (p *AWSBoxPostProcessor) Configure(raws ...interface{}) error {
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"output": &p.config.OutputPath,
}
for n, ptr := range templates {
var err error
*ptr, err = p.config.tpl.Process(*ptr, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
validates := map[string]*string{
"output": &p.config.OutputPath,
"vagrantfile_template": &p.config.VagrantfileTemplate,
}
@@ -78,11 +90,8 @@ func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact
}
// Compile the output path
outputPath, err := p.config.tpl.Process(p.config.OutputPath, &OutputPathTemplate{
ArtifactId: artifact.Id(),
BuildName: p.config.PackerBuildName,
Provider: "aws",
})
outputPath, err := ProcessOutputPath(p.config.OutputPath,
p.config.PackerBuildName, "aws", artifact)
if err != nil {
return nil, false, err
}
+23
View File
@@ -2,12 +2,15 @@ package vagrant
import (
"archive/tar"
"bytes"
"compress/gzip"
"encoding/json"
"github.com/mitchellh/packer/packer"
"io"
"log"
"os"
"path/filepath"
"text/template"
)
// OutputPathTemplate is the structure that is availalable within the
@@ -105,6 +108,26 @@ func DirToBox(dst, dir string) error {
return filepath.Walk(dir, tarWalk)
}
// ProcessOutputPath takes an output path template and executes it,
// replacing variables with their respective values.
func ProcessOutputPath(path string, buildName string, provider string, artifact packer.Artifact) (string, error) {
var buf bytes.Buffer
tplData := &OutputPathTemplate{
ArtifactId: artifact.Id(),
BuildName: buildName,
Provider: provider,
}
t, err := template.New("output").Parse(path)
if err != nil {
return "", err
}
err = t.Execute(&buf, tplData)
return buf.String(), err
}
// 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"))
+15 -6
View File
@@ -45,8 +45,20 @@ func (p *VBoxBoxPostProcessor) Configure(raws ...interface{}) error {
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"output": &p.config.OutputPath,
}
for n, ptr := range templates {
var err error
*ptr, err = p.config.tpl.Process(*ptr, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
validates := map[string]*string{
"output": &p.config.OutputPath,
"vagrantfile_template": &p.config.VagrantfileTemplate,
}
@@ -73,11 +85,8 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
}
// Compile the output path
outputPath, err := p.config.tpl.Process(p.config.OutputPath, &OutputPathTemplate{
ArtifactId: artifact.Id(),
BuildName: p.config.PackerBuildName,
Provider: "virtualbox",
})
outputPath, err := ProcessOutputPath(p.config.OutputPath,
p.config.PackerBuildName, "virtualbox", artifact)
if err != nil {
return nil, false, err
}
+15 -6
View File
@@ -37,8 +37,20 @@ func (p *VMwareBoxPostProcessor) Configure(raws ...interface{}) error {
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"output": &p.config.OutputPath,
}
for n, ptr := range templates {
var err error
*ptr, err = p.config.tpl.Process(*ptr, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
validates := map[string]*string{
"output": &p.config.OutputPath,
"vagrantfile_template": &p.config.VagrantfileTemplate,
}
@@ -58,11 +70,8 @@ func (p *VMwareBoxPostProcessor) Configure(raws ...interface{}) error {
func (p *VMwareBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
// Compile the output path
outputPath, err := p.config.tpl.Process(p.config.OutputPath, &OutputPathTemplate{
ArtifactId: artifact.Id(),
BuildName: p.config.PackerBuildName,
Provider: "vmware",
})
outputPath, err := ProcessOutputPath(p.config.OutputPath,
p.config.PackerBuildName, "vmware", artifact)
if err != nil {
return nil, false, err
}
+8 -1
View File
@@ -60,11 +60,15 @@ waitAll() {
trap "kill 0" SIGINT SIGTERM EXIT
# Build our root project
xc
xc &
# Build all the plugins
for PLUGIN in $(find ./plugin -mindepth 1 -maxdepth 1 -type d); do
PLUGIN_NAME=$(basename ${PLUGIN})
(
pushd ${PLUGIN}
xc
popd
find ./pkg \
-type f \
-name ${PLUGIN_NAME} \
@@ -73,8 +77,11 @@ for PLUGIN in $(find ./plugin -mindepth 1 -maxdepth 1 -type d); do
-type f \
-name ${PLUGIN_NAME}.exe \
-execdir mv ${PLUGIN_NAME}.exe packer-${PLUGIN_NAME}.exe ';'
) &
done
waitAll
# Zip all the packages
mkdir -p ./pkg/${VERSIONDIR}/dist
for PLATFORM in $(find ./pkg/${VERSIONDIR} -mindepth 1 -maxdepth 1 -type d); do
+1 -3
View File
@@ -45,9 +45,7 @@ set :images_dir, 'images'
# Use the RedCarpet Markdown engine
set :markdown_engine, :redcarpet
set :markdown,
:fenced_code_blocks => true,
:with_toc_data => true
set :markdown, :fenced_code_blocks => true
# Build-specific configuration
configure :build do
@@ -82,9 +82,6 @@ Optional:
be attached. The files listed in this configuration will all be put
into the root directory of the floppy disk; sub-directories are not supported.
* `format` (string) - Either "ovf" or "ova", this specifies the output
format of the exported virtual machine. This defaults to "ovf".
* `guest_additions_path` (string) - The path on the guest virtual machine
where the VirtualBox guest additions ISO will be uploaded. By default this
is "VBoxGuestAdditions.iso" which should upload into the login directory
@@ -1,6 +1,5 @@
---
layout: "docs"
page_title: "Custom Builder - Extend Packer"
---
# Custom Builder Development
@@ -1,6 +1,5 @@
---
layout: "docs"
page_title: "Packer Plugins - Extend Packer"
---
# Packer Plugins