config: parse "when" and "on_failure" on provisioners
This commit is contained in:
parent
570af34f0f
commit
928fce71f7
|
@ -136,6 +136,9 @@ type Provisioner struct {
|
||||||
Type string
|
Type string
|
||||||
RawConfig *RawConfig
|
RawConfig *RawConfig
|
||||||
ConnInfo *RawConfig
|
ConnInfo *RawConfig
|
||||||
|
|
||||||
|
When ProvisionerWhen
|
||||||
|
OnFailure ProvisionerOnFailure
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of this Provisioner
|
// Copy returns a copy of this Provisioner
|
||||||
|
@ -144,6 +147,8 @@ func (p *Provisioner) Copy() *Provisioner {
|
||||||
Type: p.Type,
|
Type: p.Type,
|
||||||
RawConfig: p.RawConfig.Copy(),
|
RawConfig: p.RawConfig.Copy(),
|
||||||
ConnInfo: p.ConnInfo.Copy(),
|
ConnInfo: p.ConnInfo.Copy(),
|
||||||
|
When: p.When,
|
||||||
|
OnFailure: p.OnFailure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,7 +558,7 @@ func (c *Config) Validate() error {
|
||||||
// Validate DependsOn
|
// Validate DependsOn
|
||||||
errs = append(errs, c.validateDependsOn(n, r.DependsOn, resources, modules)...)
|
errs = append(errs, c.validateDependsOn(n, r.DependsOn, resources, modules)...)
|
||||||
|
|
||||||
// Verify provisioners don't contain any splats
|
// Verify provisioners
|
||||||
for _, p := range r.Provisioners {
|
for _, p := range r.Provisioners {
|
||||||
// This validation checks that there are now splat variables
|
// This validation checks that there are now splat variables
|
||||||
// referencing ourself. This currently is not allowed.
|
// referencing ourself. This currently is not allowed.
|
||||||
|
@ -585,6 +590,17 @@ func (c *Config) Validate() error {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for invalid when/onFailure values, though this should be
|
||||||
|
// picked up by the loader we check here just in case.
|
||||||
|
if p.When == ProvisionerWhenInvalid {
|
||||||
|
errs = append(errs, fmt.Errorf(
|
||||||
|
"%s: provisioner 'when' value is invalid", n))
|
||||||
|
}
|
||||||
|
if p.OnFailure == ProvisionerOnFailureInvalid {
|
||||||
|
errs = append(errs, fmt.Errorf(
|
||||||
|
"%s: provisioner 'on_failure' value is invalid", n))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify ignore_changes contains valid entries
|
// Verify ignore_changes contains valid entries
|
||||||
|
|
|
@ -214,7 +214,16 @@ func resourcesStr(rs []*Resource) string {
|
||||||
if len(r.Provisioners) > 0 {
|
if len(r.Provisioners) > 0 {
|
||||||
result += fmt.Sprintf(" provisioners\n")
|
result += fmt.Sprintf(" provisioners\n")
|
||||||
for _, p := range r.Provisioners {
|
for _, p := range r.Provisioners {
|
||||||
result += fmt.Sprintf(" %s\n", p.Type)
|
when := ""
|
||||||
|
if p.When != ProvisionerWhenCreate {
|
||||||
|
when = fmt.Sprintf(" (%s)", p.When.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
result += fmt.Sprintf(" %s%s\n", p.Type, when)
|
||||||
|
|
||||||
|
if p.OnFailure != ProvisionerOnFailureFail {
|
||||||
|
result += fmt.Sprintf(" on_failure = %s\n", p.OnFailure.String())
|
||||||
|
}
|
||||||
|
|
||||||
ks := make([]string, 0, len(p.RawConfig.Raw))
|
ks := make([]string, 0, len(p.RawConfig.Raw))
|
||||||
for k, _ := range p.RawConfig.Raw {
|
for k, _ := range p.RawConfig.Raw {
|
||||||
|
|
|
@ -168,6 +168,13 @@ func TestConfigValidate_table(t *testing.T) {
|
||||||
true,
|
true,
|
||||||
"data sources cannot have",
|
"data sources cannot have",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"basic provisioners",
|
||||||
|
"validate-basic-provisioners",
|
||||||
|
false,
|
||||||
|
"",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range cases {
|
for i, tc := range cases {
|
||||||
|
|
|
@ -849,8 +849,40 @@ func loadProvisionersHcl(list *ast.ObjectList, connInfo map[string]interface{})
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the "connection" section, handle separately
|
// Parse the "when" value
|
||||||
|
when := ProvisionerWhenCreate
|
||||||
|
if v, ok := config["when"]; ok {
|
||||||
|
switch v {
|
||||||
|
case "create":
|
||||||
|
when = ProvisionerWhenCreate
|
||||||
|
case "destroy":
|
||||||
|
when = ProvisionerWhenDestroy
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"position %s: 'provisioner' when must be 'create' or 'destroy'",
|
||||||
|
item.Pos())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the "on_failure" value
|
||||||
|
onFailure := ProvisionerOnFailureFail
|
||||||
|
if v, ok := config["on_failure"]; ok {
|
||||||
|
switch v {
|
||||||
|
case "continue":
|
||||||
|
onFailure = ProvisionerOnFailureContinue
|
||||||
|
case "fail":
|
||||||
|
onFailure = ProvisionerOnFailureFail
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"position %s: 'provisioner' on_failure must be 'continue' or 'fail'",
|
||||||
|
item.Pos())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete fields we special case
|
||||||
delete(config, "connection")
|
delete(config, "connection")
|
||||||
|
delete(config, "when")
|
||||||
|
delete(config, "on_failure")
|
||||||
|
|
||||||
rawConfig, err := NewRawConfig(config)
|
rawConfig, err := NewRawConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -889,6 +921,8 @@ func loadProvisionersHcl(list *ast.ObjectList, connInfo map[string]interface{})
|
||||||
Type: n,
|
Type: n,
|
||||||
RawConfig: rawConfig,
|
RawConfig: rawConfig,
|
||||||
ConnInfo: connRaw,
|
ConnInfo: connRaw,
|
||||||
|
When: when,
|
||||||
|
OnFailure: onFailure,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -629,6 +629,22 @@ func TestLoadFile_provisioners(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadFile_provisionersDestroy(t *testing.T) {
|
||||||
|
c, err := LoadFile(filepath.Join(fixtureDir, "provisioners-destroy.tf"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == nil {
|
||||||
|
t.Fatal("config should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := resourcesStr(c.Resources)
|
||||||
|
if actual != strings.TrimSpace(provisionerDestroyResourcesStr) {
|
||||||
|
t.Fatalf("bad:\n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadFile_unnamedOutput(t *testing.T) {
|
func TestLoadFile_unnamedOutput(t *testing.T) {
|
||||||
_, err := LoadFile(filepath.Join(fixtureDir, "output-unnamed.tf"))
|
_, err := LoadFile(filepath.Join(fixtureDir, "output-unnamed.tf"))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -1126,6 +1142,17 @@ aws_instance.web (x1)
|
||||||
user: var.foo
|
user: var.foo
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const provisionerDestroyResourcesStr = `
|
||||||
|
aws_instance.web (x1)
|
||||||
|
provisioners
|
||||||
|
shell
|
||||||
|
shell (destroy)
|
||||||
|
path
|
||||||
|
shell (destroy)
|
||||||
|
on_failure = continue
|
||||||
|
path
|
||||||
|
`
|
||||||
|
|
||||||
const connectionResourcesStr = `
|
const connectionResourcesStr = `
|
||||||
aws_instance.web (x1)
|
aws_instance.web (x1)
|
||||||
ami
|
ami
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
// ProvisionerWhen is an enum for valid values for when to run provisioners.
|
||||||
|
type ProvisionerWhen int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProvisionerWhenInvalid ProvisionerWhen = iota
|
||||||
|
ProvisionerWhenCreate
|
||||||
|
ProvisionerWhenDestroy
|
||||||
|
)
|
||||||
|
|
||||||
|
var provisionerWhenStrs = map[ProvisionerWhen]string{
|
||||||
|
ProvisionerWhenInvalid: "invalid",
|
||||||
|
ProvisionerWhenCreate: "create",
|
||||||
|
ProvisionerWhenDestroy: "destroy",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v ProvisionerWhen) String() string {
|
||||||
|
return provisionerWhenStrs[v]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProvisionerOnFailure is an enum for valid values for on_failure options
|
||||||
|
// for provisioners.
|
||||||
|
type ProvisionerOnFailure int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProvisionerOnFailureInvalid ProvisionerOnFailure = iota
|
||||||
|
ProvisionerOnFailureContinue
|
||||||
|
ProvisionerOnFailureFail
|
||||||
|
)
|
||||||
|
|
||||||
|
var provisionerOnFailureStrs = map[ProvisionerOnFailure]string{
|
||||||
|
ProvisionerOnFailureInvalid: "invalid",
|
||||||
|
ProvisionerOnFailureContinue: "continue",
|
||||||
|
ProvisionerOnFailureFail: "fail",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v ProvisionerOnFailure) String() string {
|
||||||
|
return provisionerOnFailureStrs[v]
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
resource "aws_instance" "web" {
|
||||||
|
provisioner "shell" {}
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
path = "foo"
|
||||||
|
when = "destroy"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
path = "foo"
|
||||||
|
when = "destroy"
|
||||||
|
on_failure = "continue"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
resource "aws_instance" "web" {
|
||||||
|
provisioner "shell" {}
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
path = "foo"
|
||||||
|
when = "destroy"
|
||||||
|
}
|
||||||
|
|
||||||
|
provisioner "shell" {
|
||||||
|
path = "foo"
|
||||||
|
when = "destroy"
|
||||||
|
on_failure = "continue"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue