Merge pull request #9649 from hashicorp/clean_up_vsphere_ui

Clean up vsphere ui
This commit is contained in:
Megan Marsh 2020-07-28 10:45:47 -07:00 committed by GitHub
commit 3b297f4937
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 22 deletions

View File

@ -48,7 +48,7 @@ func (s *StepExport) generateArgs(c *DriverConfig, displayName string, hidePassw
password := c.RemotePassword
if hidePassword {
password = "<password_redacted>"
password = "<password>"
}
u.User = url.UserPassword(c.RemoteUser, password)

View File

@ -6,17 +6,17 @@ import (
"bytes"
"context"
"fmt"
"io"
"log"
"net/url"
"os"
"os/exec"
"regexp"
"runtime"
"strings"
"time"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer/common"
shelllocal "github.com/hashicorp/packer/common/shell-local"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
@ -144,6 +144,16 @@ func (p *PostProcessor) generateURI() (*url.URL, error) {
return u, nil
}
func getEncodedPassword(u *url.URL) (string, bool) {
// filter password from all logging
password, passwordSet := u.User.Password()
if passwordSet && password != "" {
encodedPassword := strings.Split(u.User.String(), ":")[1]
return encodedPassword, true
}
return password, false
}
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
source := ""
for _, path := range artifact.Files() {
@ -161,6 +171,10 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
if err != nil {
return nil, false, false, err
}
encodedPassword, isSet := getEncodedPassword(ovftool_uri)
if isSet {
packer.LogSecretFilter.Set(encodedPassword)
}
args, err := p.BuildArgs(source, ovftool_uri.String())
if err != nil {
@ -169,35 +183,61 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
ui.Message(fmt.Sprintf("Uploading %s to vSphere", source))
log.Printf("Starting ovftool with parameters: %s",
filterLog(strings.Join(args, " "), ovftool_uri))
log.Printf("Starting ovftool with parameters: %s", strings.Join(args, " "))
var errWriter io.Writer
var errOut bytes.Buffer
cmd := exec.Command(ovftool, args...)
errWriter = io.MultiWriter(os.Stderr, &errOut)
cmd.Stdout = os.Stdout
cmd.Stderr = errWriter
if err := cmd.Run(); err != nil {
err := fmt.Errorf("Error uploading virtual machine: %s\n%s\n", err, filterLog(errOut.String(), ovftool_uri))
ui.Message("Validating Username and Password with dry-run")
err = p.ValidateOvfTool(args, ovftool)
if err != nil {
return nil, false, false, err
}
ui.Message(filterLog(errOut.String(), ovftool_uri))
// Validation has passed, so run for real.
ui.Message("Calling OVFtool to upload vm")
commandAndArgs := []string{ovftool}
commandAndArgs = append(commandAndArgs, args...)
comm := &shelllocal.Communicator{
ExecuteCommand: commandAndArgs,
}
flattenedCmd := strings.Join(commandAndArgs, " ")
cmd := &packer.RemoteCmd{Command: flattenedCmd}
log.Printf("[INFO] (vsphere): starting ovftool command: %s", flattenedCmd)
if err := cmd.RunWithUi(ctx, comm, ui); err != nil {
return nil, false, false, fmt.Errorf(
"Error uploading virtual machine: Please see output above for more information.")
}
artifact = NewArtifact(p.config.Datastore, p.config.VMFolder, p.config.VMName, artifact.Files())
return artifact, false, false, nil
}
func filterLog(s string, u *url.URL) string {
password, passwordSet := u.User.Password()
if passwordSet && password != "" {
return strings.Replace(s, password, "<password>", -1)
}
func (p *PostProcessor) ValidateOvfTool(args []string, ofvtool string) error {
args = append([]string{"--verifyOnly"}, args...)
var out bytes.Buffer
cmdCtx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
cmd := exec.CommandContext(cmdCtx, ovftool, args...)
cmd.Stdout = &out
return s
// Need to manually close stdin or else the ofvtool call will hang
// forever in a situation where the user has provided an invalid
// password or username
stdin, err := cmd.StdinPipe()
if err != nil {
return err
}
defer stdin.Close()
if err := cmd.Run(); err != nil {
outString := out.String()
if strings.Contains(outString, "Enter login information for") {
err = fmt.Errorf("Error performing OVFtool dry run; the username " +
"or password you provided to ovftool is likely invalid.")
return err
}
return nil
}
return nil
}
func (p *PostProcessor) BuildArgs(source, ovftool_uri string) ([]string, error) {

View File

@ -101,3 +101,30 @@ func TestGenerateURI_PasswordEscapes(t *testing.T) {
}
}
}
func TestGetEncodedPassword(t *testing.T) {
// Password is encoded, and contains a colon
ovftool_uri := fmt.Sprintf("vi://hostname/Datacenter/host/cluster")
u, _ := url.Parse(ovftool_uri)
u.User = url.UserPassword("us:ername", "P@ssW:rd")
encoded, isSet := getEncodedPassword(u)
expected := "P%40ssW%3Ard"
if !isSet {
t.Fatalf("Password is set but test said it is not")
}
if encoded != expected {
t.Fatalf("Should have successfully gotten encoded password. Expected: %s; recieved: %s", expected, encoded)
}
// There is no password
u.User = url.UserPassword("us:ername", "")
_, isSet = getEncodedPassword(u)
if isSet {
t.Fatalf("Should have determined that password was not set")
}
}

View File

@ -22,7 +22,9 @@ each category, the available configuration keys are alphabetized.
Required:
- `cluster` (string) - The cluster to upload the VM to.
- `cluster` (string) - The cluster to upload the VM to. If you do not have a
cluster defined, you can instead provide the IP address of the esx host
that you want to upload to.
- `datacenter` (string) - The name of the datacenter within vSphere to add
the VM to.