packer: min_packer_version [GH-487]

This commit is contained in:
Mitchell Hashimoto 2014-04-26 20:51:36 -07:00
parent 9ef50487fb
commit edcb8fea30
4 changed files with 95 additions and 2 deletions

View File

@ -8,6 +8,8 @@ FEATURES:
command, which talks to a Chef Server. [GH-855] command, which talks to a Chef Server. [GH-855]
* **New provisioner:** `puppet-server` - Provision using Puppet by * **New provisioner:** `puppet-server` - Provision using Puppet by
communicating to a Puppet master. [GH-796] communicating to a Puppet master. [GH-796]
* `min_packer_version` can be specified in a Packer template to force
a minimum version. [GH-487]
IMPROVEMENTS: IMPROVEMENTS:

View File

@ -3,6 +3,7 @@ package packer
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/hashicorp/go-version"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
jsonutil "github.com/mitchellh/packer/common/json" jsonutil "github.com/mitchellh/packer/common/json"
"io" "io"
@ -18,12 +19,14 @@ import (
// "interface{}" pointers since we actually don't know what their contents // "interface{}" pointers since we actually don't know what their contents
// are until we read the "type" field. // are until we read the "type" field.
type rawTemplate struct { type rawTemplate struct {
MinimumPackerVersion string `mapstructure:"min_packer_version"`
Description string Description string
Variables map[string]interface{}
Builders []map[string]interface{} Builders []map[string]interface{}
Hooks map[string][]string Hooks map[string][]string
Provisioners []map[string]interface{}
PostProcessors []interface{} `mapstructure:"post-processors"` PostProcessors []interface{} `mapstructure:"post-processors"`
Provisioners []map[string]interface{}
Variables map[string]interface{}
} }
// The Template struct represents a parsed template, parsed into the most // The Template struct represents a parsed template, parsed into the most
@ -115,6 +118,25 @@ func ParseTemplate(data []byte, vars map[string]string) (t *Template, err error)
return return
} }
if rawTpl.MinimumPackerVersion != "" {
vCur, err := version.NewVersion(Version)
if err != nil {
panic(err)
}
vReq, err := version.NewVersion(rawTpl.MinimumPackerVersion)
if err != nil {
return nil, fmt.Errorf(
"'minimum_packer_version' error: %s", err)
}
if vCur.LessThan(vReq) {
return nil, fmt.Errorf(
"Template requires Packer version %s. " +
"Running version is %s.",
vReq, vCur)
}
}
errors := make([]error, 0) errors := make([]error, 0)
if len(md.Unused) > 0 { if len(md.Unused) > 0 {

View File

@ -60,6 +60,69 @@ func TestParseTemplateFile_basic(t *testing.T) {
} }
} }
func TestParseTemplateFile_minPackerVersionBad(t *testing.T) {
data := `
{
"min_packer_version": "27.0.0",
"builders": [{"type": "something"}]
}
`
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
tf.Write([]byte(data))
tf.Close()
_, err = ParseTemplateFile(tf.Name(), nil)
if err == nil {
t.Fatal("expects error")
}
}
func TestParseTemplateFile_minPackerVersionFormat(t *testing.T) {
data := `
{
"min_packer_version": "NOPE NOPE NOPE",
"builders": [{"type": "something"}]
}
`
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
tf.Write([]byte(data))
tf.Close()
_, err = ParseTemplateFile(tf.Name(), nil)
if err == nil {
t.Fatal("expects error")
}
}
func TestParseTemplateFile_minPackerVersionGood(t *testing.T) {
data := `
{
"min_packer_version": "0.1",
"builders": [{"type": "something"}]
}
`
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("err: %s", err)
}
tf.Write([]byte(data))
tf.Close()
_, err = ParseTemplateFile(tf.Name(), nil)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestParseTemplateFile_stdin(t *testing.T) { func TestParseTemplateFile_stdin(t *testing.T) {
data := ` data := `
{ {

View File

@ -43,6 +43,12 @@ Along with each key, it is noted whether it is required or not.
information on what post-processors do and how they're defined, read the information on what post-processors do and how they're defined, read the
sub-section on [configuring post-processors in templates](/docs/templates/post-processors.html). sub-section on [configuring post-processors in templates](/docs/templates/post-processors.html).
* `min_packer_version` (optional) is a string that has a minimum Packer
version that is required to parse the template. This can be used to
ensure that proper versions of Packer are used with the template. A
max version can't be specified because Packer retains backwards
compatibility with `packer fix`.
## Example Template ## Example Template
Below is an example of a basic template that is nearly fully functional. It is just Below is an example of a basic template that is nearly fully functional. It is just