provisioner/salt-masterless: Wait for operations to complete
Previously the provisioner did not wait until the Salt operation had completed before returning, causing some operations not to be applied, and causing the output to get swallowed. Now we wait until the remote work is complete, and copy output into the Terraform log in a similar way as is done for other provisioners.
This commit is contained in:
parent
fe33661b59
commit
44cb98e04f
|
@ -10,6 +10,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/communicator/remote"
|
"github.com/hashicorp/terraform/communicator/remote"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
linereader "github.com/mitchellh/go-linereader"
|
||||||
)
|
)
|
||||||
|
|
||||||
type provisionFn func(terraform.UIOutput, communicator.Communicator) error
|
type provisionFn func(terraform.UIOutput, communicator.Communicator) error
|
||||||
|
@ -139,14 +141,46 @@ func applyFn(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
o.Output(fmt.Sprintf("Downloading saltstack bootstrap to /tmp/install_salt.sh"))
|
o.Output(fmt.Sprintf("Downloading saltstack bootstrap to /tmp/install_salt.sh"))
|
||||||
if err = comm.Start(cmd); err != nil {
|
if err = comm.Start(cmd); err != nil {
|
||||||
return fmt.Errorf("Unable to download Salt: %s", err)
|
err = fmt.Errorf("Unable to download Salt: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
cmd.Wait()
|
||||||
|
if cmd.ExitStatus != 0 {
|
||||||
|
err = fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outR, outW := io.Pipe()
|
||||||
|
errR, errW := io.Pipe()
|
||||||
|
outDoneCh := make(chan struct{})
|
||||||
|
errDoneCh := make(chan struct{})
|
||||||
|
go copyOutput(o, outR, outDoneCh)
|
||||||
|
go copyOutput(o, errR, errDoneCh)
|
||||||
cmd = &remote.Cmd{
|
cmd = &remote.Cmd{
|
||||||
Command: fmt.Sprintf("%s /tmp/install_salt.sh %s", p.sudo("sh"), p.BootstrapArgs),
|
Command: fmt.Sprintf("%s /tmp/install_salt.sh %s", p.sudo("sh"), p.BootstrapArgs),
|
||||||
|
Stdout: outW,
|
||||||
|
Stderr: errW,
|
||||||
}
|
}
|
||||||
|
|
||||||
o.Output(fmt.Sprintf("Installing Salt with command %s", cmd.Command))
|
o.Output(fmt.Sprintf("Installing Salt with command %s", cmd.Command))
|
||||||
if err = comm.Start(cmd); err != nil {
|
if err = comm.Start(cmd); err != nil {
|
||||||
return fmt.Errorf("Unable to install Salt: %s", err)
|
err = fmt.Errorf("Unable to install Salt: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
cmd.Wait()
|
||||||
|
if cmd.ExitStatus != 0 {
|
||||||
|
err = fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait for output to clean up
|
||||||
|
outW.Close()
|
||||||
|
errW.Close()
|
||||||
|
<-outDoneCh
|
||||||
|
<-errDoneCh
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,17 +246,39 @@ func applyFn(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
outR, outW := io.Pipe()
|
||||||
|
errR, errW := io.Pipe()
|
||||||
|
outDoneCh := make(chan struct{})
|
||||||
|
errDoneCh := make(chan struct{})
|
||||||
|
|
||||||
|
go copyOutput(o, outR, outDoneCh)
|
||||||
|
go copyOutput(o, errR, errDoneCh)
|
||||||
o.Output(fmt.Sprintf("Running: salt-call --local %s", p.CmdArgs))
|
o.Output(fmt.Sprintf("Running: salt-call --local %s", p.CmdArgs))
|
||||||
cmd := &remote.Cmd{Command: p.sudo(fmt.Sprintf("salt-call --local %s", p.CmdArgs))}
|
cmd := &remote.Cmd{
|
||||||
|
Command: p.sudo(fmt.Sprintf("salt-call --local %s", p.CmdArgs)),
|
||||||
|
Stdout: outW,
|
||||||
|
Stderr: errW,
|
||||||
|
}
|
||||||
if err = comm.Start(cmd); err != nil || cmd.ExitStatus != 0 {
|
if err = comm.Start(cmd); err != nil || cmd.ExitStatus != 0 {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = fmt.Errorf("Bad exit status: %d", cmd.ExitStatus)
|
err = fmt.Errorf("Bad exit status: %d", cmd.ExitStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Error executing salt-call: %s", err)
|
err = fmt.Errorf("Error executing salt-call: %s", err)
|
||||||
}
|
}
|
||||||
|
if err == nil {
|
||||||
|
cmd.Wait()
|
||||||
|
if cmd.ExitStatus != 0 {
|
||||||
|
err = fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wait for output to clean up
|
||||||
|
outW.Close()
|
||||||
|
errW.Close()
|
||||||
|
<-outDoneCh
|
||||||
|
<-errDoneCh
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepends sudo to supplied command if config says to
|
// Prepends sudo to supplied command if config says to
|
||||||
|
@ -466,3 +522,12 @@ func decodeConfig(d *schema.ResourceData) (*provisioner, error) {
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyOutput(
|
||||||
|
o terraform.UIOutput, r io.Reader, doneCh chan<- struct{}) {
|
||||||
|
defer close(doneCh)
|
||||||
|
lr := linereader.New(r)
|
||||||
|
for line := range lr.Ch {
|
||||||
|
o.Output(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue