provisioner/remote-exec: Fix panic from remote_exec provisioner
Fixes panic on `nil` values of `inline` and `scripts` from improper interface casts. Fixes: #13970
This commit is contained in:
parent
08e778c883
commit
7e5eeb2268
|
@ -22,7 +22,7 @@ import (
|
||||||
func Provisioner() terraform.ResourceProvisioner {
|
func Provisioner() terraform.ResourceProvisioner {
|
||||||
return &schema.Provisioner{
|
return &schema.Provisioner{
|
||||||
Schema: map[string]*schema.Schema{
|
Schema: map[string]*schema.Schema{
|
||||||
"inline": &schema.Schema{
|
"inline": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
PromoteSingle: true,
|
PromoteSingle: true,
|
||||||
|
@ -30,13 +30,13 @@ func Provisioner() terraform.ResourceProvisioner {
|
||||||
ConflictsWith: []string{"script", "scripts"},
|
ConflictsWith: []string{"script", "scripts"},
|
||||||
},
|
},
|
||||||
|
|
||||||
"script": &schema.Schema{
|
"script": {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ConflictsWith: []string{"inline", "scripts"},
|
ConflictsWith: []string{"inline", "scripts"},
|
||||||
},
|
},
|
||||||
|
|
||||||
"scripts": &schema.Schema{
|
"scripts": {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -81,7 +81,11 @@ func applyFn(ctx context.Context) error {
|
||||||
func generateScripts(d *schema.ResourceData) ([]string, error) {
|
func generateScripts(d *schema.ResourceData) ([]string, error) {
|
||||||
var lines []string
|
var lines []string
|
||||||
for _, l := range d.Get("inline").([]interface{}) {
|
for _, l := range d.Get("inline").([]interface{}) {
|
||||||
lines = append(lines, l.(string))
|
line, ok := l.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Error parsing %v as a string", l)
|
||||||
|
}
|
||||||
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
lines = append(lines, "")
|
lines = append(lines, "")
|
||||||
|
|
||||||
|
@ -109,12 +113,20 @@ func collectScripts(d *schema.ResourceData) ([]io.ReadCloser, error) {
|
||||||
// Collect scripts
|
// Collect scripts
|
||||||
var scripts []string
|
var scripts []string
|
||||||
if script, ok := d.GetOk("script"); ok {
|
if script, ok := d.GetOk("script"); ok {
|
||||||
scripts = append(scripts, script.(string))
|
scr, ok := script.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Error parsing script %v as string", script)
|
||||||
|
}
|
||||||
|
scripts = append(scripts, scr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if scriptList, ok := d.GetOk("scripts"); ok {
|
if scriptList, ok := d.GetOk("scripts"); ok {
|
||||||
for _, script := range scriptList.([]interface{}) {
|
for _, script := range scriptList.([]interface{}) {
|
||||||
scripts = append(scripts, script.(string))
|
scr, ok := script.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Error parsing script %v as string", script)
|
||||||
|
}
|
||||||
|
scripts = append(scripts, scr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/config"
|
"github.com/hashicorp/terraform/config"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -71,6 +73,23 @@ func TestResourceProvider_generateScript(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResourceProvider_generateScriptEmptyInline(t *testing.T) {
|
||||||
|
p := Provisioner().(*schema.Provisioner)
|
||||||
|
conf := map[string]interface{}{
|
||||||
|
"inline": []interface{}{""},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := generateScripts(schema.TestResourceDataRaw(
|
||||||
|
t, p.Schema, conf))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got none")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), "Error parsing") {
|
||||||
|
t.Fatalf("expected parsing error, got: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestResourceProvider_CollectScripts_inline(t *testing.T) {
|
func TestResourceProvider_CollectScripts_inline(t *testing.T) {
|
||||||
p := Provisioner().(*schema.Provisioner)
|
p := Provisioner().(*schema.Provisioner)
|
||||||
conf := map[string]interface{}{
|
conf := map[string]interface{}{
|
||||||
|
@ -162,6 +181,24 @@ func TestResourceProvider_CollectScripts_scripts(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestResourceProvider_CollectScripts_scriptsEmpty(t *testing.T) {
|
||||||
|
p := Provisioner().(*schema.Provisioner)
|
||||||
|
conf := map[string]interface{}{
|
||||||
|
"scripts": []interface{}{""},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := collectScripts(schema.TestResourceDataRaw(
|
||||||
|
t, p.Schema, conf))
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(err.Error(), "Error parsing") {
|
||||||
|
t.Fatalf("Expected parsing error, got: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRetryFunc(t *testing.T) {
|
func TestRetryFunc(t *testing.T) {
|
||||||
// succeed on the third try
|
// succeed on the third try
|
||||||
errs := []error{io.EOF, &net.OpError{Err: errors.New("ERROR")}, nil}
|
errs := []error{io.EOF, &net.OpError{Err: errors.New("ERROR")}, nil}
|
||||||
|
|
Loading…
Reference in New Issue