Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7db468f55e | |||
| e4ad595c90 | |||
| 1ffae8ad93 | |||
| 0691bf7657 | |||
| dfc88064a7 | |||
| 0c20949ed9 | |||
| b34c95af04 | |||
| a1c0ff0c90 | |||
| 6ed3f77951 | |||
| 686e418bbc | |||
| 17f2ea4c5d | |||
| 5d4abf8280 | |||
| 68d9d4be7c | |||
| 9163c25ef7 | |||
| df352702b5 | |||
| 0faa87b311 | |||
| 6903d11800 | |||
| 5786f6ad5a | |||
| e920c49e8f | |||
| b69e983474 | |||
| 69883d1abe | |||
| e8535e7f6a | |||
| 43bb20d05f | |||
| 871785ddfd | |||
| da8648114a | |||
| 8201b7f6e1 | |||
| adae75402f | |||
| 848f324515 | |||
| 02d67fd34d | |||
| 3682b30ee0 | |||
| 84e8dd806d | |||
| 7fff56657e | |||
| 9202878107 | |||
| 33635caf8c | |||
| 90829dcc19 |
@@ -1,3 +1,17 @@
|
||||
## 0.1.1 (June 28, 2013)
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* core: plugins listen explicitly on 127.0.0.1, fixing odd hangs. [GH-37]
|
||||
* core: fix race condition on verifying checksum of large ISOs which
|
||||
could cause panics [GH-52]
|
||||
* virtualbox: `boot_wait` defaults to "10s" rather than 0. [GH-44]
|
||||
* virtualbox: if `http_port_min` and max are the same, it will no longer
|
||||
panic [GH-53]
|
||||
* vmware: `boot_wait` defaults to "10s" rather than 0. [GH-44]
|
||||
* vmware: if `http_port_min` and max are the same, it will no longer
|
||||
panic [GH-53]
|
||||
|
||||
## 0.1.0 (June 28, 2013)
|
||||
|
||||
* Initial release
|
||||
|
||||
@@ -17,12 +17,12 @@ plugins. The images that Packer creates an easily be turned into
|
||||
## Quick Start
|
||||
|
||||
**Note:** There is a great
|
||||
[introduction and getting started guide](http://localhost:4567/intro)
|
||||
[introduction and getting started guide](http://www.packer.io/intro)
|
||||
for those with a bit more patience. Otherwise, the quick start below
|
||||
will get you up and running quickly, at the sacrifice of not explaining some
|
||||
key points.
|
||||
|
||||
First, [downloada pre-built Packer binary](http://localhost:4567/downloads.html)
|
||||
First, [download a pre-built Packer binary](http://www.packer.io/downloads.html)
|
||||
for your operating system or [compile Packer yourself](#developing-packer).
|
||||
|
||||
After Packer is installed, create your first template, which tells Packer
|
||||
|
||||
@@ -48,7 +48,7 @@ func (a *artifact) Destroy() error {
|
||||
errors := make([]error, 0)
|
||||
|
||||
for _, imageId := range a.amis {
|
||||
log.Printf("Degistering image ID: %s", imageId)
|
||||
log.Printf("Deregistering image ID: %s", imageId)
|
||||
if _, err := a.conn.DeregisterImage(imageId); err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -73,6 +74,7 @@ func (d *DownloadClient) Cancel() {
|
||||
func (d *DownloadClient) Get() (string, error) {
|
||||
// If we already have the file and it matches, then just return the target path.
|
||||
if verify, _ := d.VerifyChecksum(d.config.TargetPath); verify {
|
||||
log.Println("Initial checksum matched, no download needed.")
|
||||
return d.config.TargetPath, nil
|
||||
}
|
||||
|
||||
@@ -81,6 +83,8 @@ func (d *DownloadClient) Get() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
log.Printf("Parsed URL: %#v", url)
|
||||
|
||||
// Files when we don't copy the file are special cased.
|
||||
var finalPath string
|
||||
if url.Scheme == "file" && !d.config.CopyFile {
|
||||
@@ -101,6 +105,7 @@ func (d *DownloadClient) Get() (string, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
log.Printf("Downloading: %s", url.String())
|
||||
err = d.downloader.Download(f, url)
|
||||
}
|
||||
|
||||
@@ -117,6 +122,10 @@ func (d *DownloadClient) Get() (string, error) {
|
||||
|
||||
// PercentProgress returns the download progress as a percentage.
|
||||
func (d *DownloadClient) PercentProgress() uint {
|
||||
if d.downloader == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return uint((float64(d.downloader.Progress()) / float64(d.downloader.Total())) * 100)
|
||||
}
|
||||
|
||||
@@ -133,6 +142,7 @@ func (d *DownloadClient) VerifyChecksum(path string) (bool, error) {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
log.Printf("Verifying checksum of %s", path)
|
||||
d.config.Hash.Reset()
|
||||
io.Copy(d.config.Hash, f)
|
||||
return bytes.Compare(d.config.Hash.Sum(nil), d.config.Checksum) == 0, nil
|
||||
|
||||
@@ -89,6 +89,10 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||
b.config.OutputDir = "virtualbox"
|
||||
}
|
||||
|
||||
if b.config.RawBootWait == "" {
|
||||
b.config.RawBootWait = "10s"
|
||||
}
|
||||
|
||||
if b.config.SSHHostPortMin == 0 {
|
||||
b.config.SSHHostPortMin = 2222
|
||||
}
|
||||
@@ -168,17 +172,19 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||
errs = append(errs, errors.New("Output directory already exists. It must not exist."))
|
||||
}
|
||||
|
||||
if b.config.RawBootWait != "" {
|
||||
b.config.BootWait, err = time.ParseDuration(b.config.RawBootWait)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
||||
}
|
||||
b.config.BootWait, err = time.ParseDuration(b.config.RawBootWait)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing boot_wait: %s", err))
|
||||
}
|
||||
|
||||
if b.config.RawShutdownTimeout == "" {
|
||||
b.config.RawShutdownTimeout = "5m"
|
||||
}
|
||||
|
||||
if b.config.RawSSHWaitTimeout == "" {
|
||||
b.config.RawSSHWaitTimeout = "20m"
|
||||
}
|
||||
|
||||
b.config.ShutdownTimeout, err = time.ParseDuration(b.config.RawShutdownTimeout)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing shutdown_timeout: %s", err))
|
||||
@@ -192,10 +198,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||
errs = append(errs, errors.New("An ssh_username must be specified."))
|
||||
}
|
||||
|
||||
if b.config.RawSSHWaitTimeout == "" {
|
||||
b.config.RawSSHWaitTimeout = "20m"
|
||||
}
|
||||
|
||||
b.config.SSHWaitTimeout, err = time.ParseDuration(b.config.RawSSHWaitTimeout)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed parsing ssh_wait_timeout: %s", err))
|
||||
|
||||
@@ -61,9 +61,20 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test a default boot_wait
|
||||
delete(config, "boot_wait")
|
||||
err := b.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if b.config.RawBootWait != "10s" {
|
||||
t.Fatalf("bad value: %s", b.config.RawBootWait)
|
||||
}
|
||||
|
||||
// Test with a bad boot_wait
|
||||
config["boot_wait"] = "this is not good"
|
||||
err := b.Prepare(config)
|
||||
err = b.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
@@ -317,9 +328,20 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test a default boot_wait
|
||||
delete(config, "ssh_wait_timeout")
|
||||
err := b.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if b.config.RawSSHWaitTimeout != "20m" {
|
||||
t.Fatalf("bad value: %s", b.config.RawSSHWaitTimeout)
|
||||
}
|
||||
|
||||
// Test with a bad value
|
||||
config["ssh_wait_timeout"] = "this is not good"
|
||||
err := b.Prepare(config)
|
||||
err = b.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
@@ -35,9 +35,7 @@ func (s *stepDownloadISO) Run(state map[string]interface{}) multistep.StepAction
|
||||
|
||||
checksum, err := hex.DecodeString(config.ISOMD5)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error parsing checksum: %s", err)
|
||||
state["error"] = err
|
||||
ui.Error(err.Error())
|
||||
state["error"] = fmt.Errorf("Error parsing checksum: %s", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
@@ -111,6 +109,7 @@ DownloadWaitLoop:
|
||||
}
|
||||
defer sourceF.Close()
|
||||
|
||||
log.Printf("Copying ISO to temp location: %s", tempdir)
|
||||
if _, err := io.Copy(f, sourceF); err != nil {
|
||||
state["error"] = fmt.Errorf("Error copying ISO: %s", err)
|
||||
return multistep.ActionHalt
|
||||
|
||||
@@ -38,7 +38,14 @@ func (s *stepHTTPServer) Run(state map[string]interface{}) multistep.StepAction
|
||||
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
|
||||
for {
|
||||
var err error
|
||||
httpPort = uint(rand.Intn(portRange)) + config.HTTPPortMin
|
||||
var offset uint = 0
|
||||
|
||||
if portRange > 0 {
|
||||
// Intn will panic if portRange == 0, so we do a check.
|
||||
offset = uint(rand.Intn(portRange))
|
||||
}
|
||||
|
||||
httpPort = offset + config.HTTPPortMin
|
||||
httpAddr = fmt.Sprintf(":%d", httpPort)
|
||||
log.Printf("Trying port: %d", httpPort)
|
||||
s.l, err = net.Listen("tcp", httpAddr)
|
||||
|
||||
@@ -86,6 +86,10 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||
b.config.HTTPPortMax = 9000
|
||||
}
|
||||
|
||||
if b.config.RawBootWait == "" {
|
||||
b.config.RawBootWait = "10s"
|
||||
}
|
||||
|
||||
if b.config.VNCPortMin == 0 {
|
||||
b.config.VNCPortMin = 5900
|
||||
}
|
||||
|
||||
@@ -28,9 +28,20 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
|
||||
var b Builder
|
||||
config := testConfig()
|
||||
|
||||
// Test a default boot_wait
|
||||
delete(config, "boot_wait")
|
||||
err := b.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if b.config.RawBootWait != "10s" {
|
||||
t.Fatalf("bad value: %s", b.config.RawBootWait)
|
||||
}
|
||||
|
||||
// Test with a bad boot_wait
|
||||
config["boot_wait"] = "this is not good"
|
||||
err := b.Prepare(config)
|
||||
err = b.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have error")
|
||||
}
|
||||
|
||||
@@ -38,7 +38,14 @@ func (s *stepHTTPServer) Run(state map[string]interface{}) multistep.StepAction
|
||||
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
|
||||
for {
|
||||
var err error
|
||||
httpPort = uint(rand.Intn(portRange)) + config.HTTPPortMin
|
||||
var offset uint = 0
|
||||
|
||||
if portRange > 0 {
|
||||
// Intn will panic if portRange == 0, so we do a check.
|
||||
offset = uint(rand.Intn(portRange))
|
||||
}
|
||||
|
||||
httpPort = offset + config.HTTPPortMin
|
||||
httpAddr = fmt.Sprintf(":%d", httpPort)
|
||||
log.Printf("Trying port: %d", httpPort)
|
||||
s.l, err = net.Listen("tcp", httpAddr)
|
||||
|
||||
@@ -218,6 +218,8 @@ func (c *Client) Start() (address string, err error) {
|
||||
cmd.Env = append(cmd.Env, env...)
|
||||
cmd.Stderr = stderr
|
||||
cmd.Stdout = stdout
|
||||
|
||||
log.Printf("Starting plugin: %s %#v", cmd.Path, cmd.Args)
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return
|
||||
@@ -250,6 +252,7 @@ func (c *Client) Start() (address string, err error) {
|
||||
timeout := time.After(c.config.StartTimeout)
|
||||
|
||||
// Start looking for the address
|
||||
log.Println("Waiting for RPC address for: %s", cmd.Path)
|
||||
for done := false; !done; {
|
||||
select {
|
||||
case <-timeout:
|
||||
|
||||
@@ -56,7 +56,7 @@ func serve(server *rpc.Server) (err error) {
|
||||
var address string
|
||||
var listener net.Listener
|
||||
for port := minPort; port <= maxPort; port++ {
|
||||
address = fmt.Sprintf(":%d", port)
|
||||
address = fmt.Sprintf("127.0.0.1:%d", port)
|
||||
listener, err = net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "address already in use") {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import (
|
||||
)
|
||||
|
||||
// The version of packer.
|
||||
const Version = "0.1.0"
|
||||
const Version = "0.1.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
|
||||
|
||||
+11
-4
@@ -13,7 +13,7 @@ cd $DIR
|
||||
# of packer/version.go.
|
||||
VERSION=$(grep "const Version " packer/version.go | sed -E 's/.*"(.+)"$/\1/')
|
||||
VERSIONDIR="${VERSION}"
|
||||
PREVERSION=$(grep "const VersionPrerelease " packer/version.go | sed -E 's/.*"(.+)"$/\1/')
|
||||
PREVERSION=$(grep "const VersionPrerelease " packer/version.go | sed -E 's/.*"(.*)"$/\1/')
|
||||
if [ ! -z $PREVERSION ]; then
|
||||
PREVERSION="${PREVERSION}.$(date -u +%s)"
|
||||
VERSIONDIR="${VERSIONDIR}-${PREVERSION}"
|
||||
@@ -61,7 +61,14 @@ for PLUGIN in $(find ./plugin -mindepth 1 -maxdepth 1 -type d); do
|
||||
pushd ${PLUGIN}
|
||||
xc
|
||||
popd
|
||||
find ./pkg -type f -name ${PLUGIN_NAME} -execdir mv ${PLUGIN_NAME} packer-${PLUGIN_NAME} ';'
|
||||
find ./pkg \
|
||||
-type f \
|
||||
-name ${PLUGIN_NAME} \
|
||||
-execdir mv ${PLUGIN_NAME} packer-${PLUGIN_NAME} ';'
|
||||
find ./pkg \
|
||||
-type f \
|
||||
-name ${PLUGIN_NAME}.exe \
|
||||
-execdir mv ${PLUGIN_NAME}.exe packer-${PLUGIN_NAME}.exe ';'
|
||||
) &
|
||||
done
|
||||
|
||||
@@ -79,7 +86,7 @@ for PLATFORM in $(find ./pkg/${VERSIONDIR} -mindepth 1 -maxdepth 1 -type d); do
|
||||
|
||||
(
|
||||
pushd ${PLATFORM}
|
||||
zip -P hashipacker ${DIR}/pkg/${VERSIONDIR}/dist/${ARCHIVE_NAME}.zip ./*
|
||||
zip ${DIR}/pkg/${VERSIONDIR}/dist/${ARCHIVE_NAME}.zip ./*
|
||||
popd
|
||||
) &
|
||||
done
|
||||
@@ -88,7 +95,7 @@ waitAll
|
||||
|
||||
# Make the checksums
|
||||
pushd ./pkg/${VERSIONDIR}/dist
|
||||
shasum -a256 * > ./${VERSION}_SHA256SUMS
|
||||
shasum -a256 * > ./${VERSIONDIR}_SHA256SUMS
|
||||
popd
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Packer Website
|
||||
|
||||
This subdirectory contains the entire source for the [Packer website](http://www.packer.io).
|
||||
T
|
||||
This is a [Middleman](http://middlemanapp.com) project, which builds a static
|
||||
site from these source files.
|
||||
|
||||
|
||||
+5
-2
@@ -18,8 +18,9 @@ if !ENV["PACKER_DISABLE_DOWNLOAD_FETCH"]
|
||||
|
||||
response.body.split("\n").each do |line|
|
||||
next if line !~ /\/mitchellh\/packer\/(#{ENV["PACKER_VERSION"]}.+?)\?/
|
||||
filename = $1.to_s
|
||||
filename = $1.to_s
|
||||
os = filename.split("_")[1]
|
||||
next if os == "SHA256SUMS"
|
||||
|
||||
$packer_files[os] ||= []
|
||||
$packer_files[os] << filename
|
||||
@@ -59,7 +60,9 @@ end
|
||||
#-------------------------------------------------------------------------
|
||||
helpers do
|
||||
def download_arch(file)
|
||||
file.split("_")[2].split(".")[0]
|
||||
parts = file.split("_")
|
||||
return "" if parts.length != 3
|
||||
parts[2].split(".")[0]
|
||||
end
|
||||
|
||||
def download_os_human(os)
|
||||
|
||||
@@ -39,7 +39,7 @@ the `type` key. This key specifies the name of the provisioner to use.
|
||||
Additional keys within the object are used to configure the provisioner,
|
||||
with the exception of a handful of special keys, covered later.
|
||||
|
||||
As an example, the "shell" provisioner requires at least the `path` key,
|
||||
As an example, the "shell" provisioner requires at least the `script` key,
|
||||
which specifies a path to a shell script to execute within the machines
|
||||
being created.
|
||||
|
||||
@@ -49,7 +49,7 @@ provisioner to run a local script within the machines:
|
||||
<pre class="prettyprint">
|
||||
{
|
||||
"type": "shell",
|
||||
"path": "script.sh"
|
||||
"script": "script.sh"
|
||||
}
|
||||
</pre>
|
||||
|
||||
@@ -73,7 +73,7 @@ This example is shown below:
|
||||
<pre class="prettyprint">
|
||||
{
|
||||
"type": "shell",
|
||||
"path": "script.sh",
|
||||
"script": "script.sh",
|
||||
|
||||
"override": {
|
||||
"vmware": {
|
||||
|
||||
@@ -16,7 +16,8 @@ page_title: "Downloads"
|
||||
<p>
|
||||
Below are all available downloads for the latest version of Packer
|
||||
(<%= latest_version %>). Please download the proper package for your
|
||||
operating system and architecture.
|
||||
operating system and architecture. You can find SHA256 checksums
|
||||
for packages <a href="http://dl.bintray.com/mitchellh/packer/<%= latest_version %>_SHA256SUMS?direct">here</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -17,14 +17,6 @@
|
||||
<div class="row download-row">
|
||||
<div class="download-container">
|
||||
<h2 class="uppercase"><a href="/downloads.html">Download v<%= latest_version %></a></h2>
|
||||
<div class="small">
|
||||
<small class="uppercase mono">
|
||||
<a href="#">
|
||||
Release Notes
|
||||
<!-- {{releasedate}} -->
|
||||
<span>06/17/13</span>
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@ for your system and download it. Packer is packaged as a "zip" file.
|
||||
Next, unzip the downloaded package into a directory where Packer will be
|
||||
installed. On Unix systems, `~/packer` or `/usr/local/packer` is generally good,
|
||||
depending on whether you want to restrict the install to just your user
|
||||
or install it system-wide. On Windows systems, you can put it whereever you'd
|
||||
or install it system-wide. On Windows systems, you can put it wherever you'd
|
||||
like.
|
||||
|
||||
After unzipping the package, the directory should contain a set of binary
|
||||
@@ -49,7 +49,7 @@ Available commands are:
|
||||
```
|
||||
|
||||
If you get an error that `packer` could not be found, then your PATH
|
||||
environmental variable was not setup properly. Please go back and ensure
|
||||
that yoru PATH variable contains the directory which has Packer installed.
|
||||
environment variable was not setup properly. Please go back and ensure
|
||||
that your PATH variable contains the directory which has Packer installed.
|
||||
|
||||
Otherwise, Packer is installed and you're ready to go!
|
||||
|
||||
@@ -8,7 +8,7 @@ next_title: "Getting Started: Install Packer"
|
||||
|
||||
# Supported Platforms
|
||||
|
||||
Packer can creates machine images for any platform. Packer ships with
|
||||
Packer can create machine images for any platform. Packer ships with
|
||||
support for a set of platforms, but can be [extend through plugins](/docs/extend/builder.html)
|
||||
to support any platform. This page documents the list of supported image
|
||||
types that Packer supports creating.
|
||||
|
||||
@@ -10,7 +10,7 @@ next_title: "Packer Use Cases"
|
||||
|
||||
Pre-baked machine images have a lot of advantages, but most have been unable
|
||||
to benefit from them because images have been too tedious to create and manage.
|
||||
There were ether no existing tools to automate the creation of machine images or
|
||||
There were either no existing tools to automate the creation of machine images or
|
||||
they had too high of a learning curve. The result is that, prior to Packer,
|
||||
creating machine images threatened the agility of operations teams, and therefore
|
||||
aren't used, despite the massive benefits.
|
||||
|
||||
@@ -47,7 +47,7 @@ header .header {
|
||||
|
||||
h2 {
|
||||
font-family: $serif;
|
||||
font-size: 38px;
|
||||
font-size: 44px;
|
||||
color: #7bc6b1;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
||||
Reference in New Issue
Block a user