2013-03-24 17:03:53 -04:00
|
|
|
package packer
|
|
|
|
|
2013-05-21 02:43:37 -04:00
|
|
|
import (
|
2013-07-02 15:28:25 -04:00
|
|
|
"bytes"
|
2013-06-15 21:24:38 -04:00
|
|
|
"errors"
|
2013-05-21 02:43:37 -04:00
|
|
|
"fmt"
|
|
|
|
"io"
|
2013-05-21 14:40:07 -04:00
|
|
|
"log"
|
2013-06-14 18:59:54 -04:00
|
|
|
"os"
|
2013-07-31 17:43:34 -04:00
|
|
|
"runtime"
|
2013-07-02 15:28:25 -04:00
|
|
|
"strings"
|
2014-02-21 20:43:45 -05:00
|
|
|
"syscall"
|
2013-08-11 22:05:07 -04:00
|
|
|
"time"
|
2013-07-09 14:21:42 -04:00
|
|
|
"unicode"
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
|
2020-02-06 11:07:58 -05:00
|
|
|
getter "github.com/hashicorp/go-getter/v2"
|
2020-11-19 14:54:31 -05:00
|
|
|
packersdk "github.com/hashicorp/packer/packer-plugin-sdk/packer"
|
2013-05-21 02:43:37 -04:00
|
|
|
)
|
2013-03-24 17:03:53 -04:00
|
|
|
|
2019-06-04 17:17:50 -04:00
|
|
|
var ErrInterrupted = errors.New("interrupted")
|
|
|
|
|
2013-06-03 16:35:43 -04:00
|
|
|
type UiColor uint
|
|
|
|
|
|
|
|
const (
|
|
|
|
UiColorRed UiColor = 31
|
|
|
|
UiColorGreen = 32
|
|
|
|
UiColorYellow = 33
|
|
|
|
UiColorBlue = 34
|
|
|
|
UiColorMagenta = 35
|
|
|
|
UiColorCyan = 36
|
|
|
|
)
|
|
|
|
|
|
|
|
// ColoredUi is a UI that is colored using terminal colors.
|
|
|
|
type ColoredUi struct {
|
2013-06-12 13:41:58 -04:00
|
|
|
Color UiColor
|
|
|
|
ErrorColor UiColor
|
2020-11-19 14:54:31 -05:00
|
|
|
Ui packersdk.Ui
|
2020-09-21 19:05:14 -04:00
|
|
|
PB getter.ProgressTracker
|
2013-06-03 16:35:43 -04:00
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
var _ packersdk.Ui = new(ColoredUi)
|
2018-09-04 11:57:21 -04:00
|
|
|
|
2013-06-15 21:24:38 -04:00
|
|
|
func (u *ColoredUi) Ask(query string) (string, error) {
|
2013-06-14 18:17:03 -04:00
|
|
|
return u.Ui.Ask(u.colorize(query, u.Color, true))
|
2013-03-24 17:03:53 -04:00
|
|
|
}
|
|
|
|
|
2013-06-03 16:35:43 -04:00
|
|
|
func (u *ColoredUi) Say(message string) {
|
2013-06-12 13:41:58 -04:00
|
|
|
u.Ui.Say(u.colorize(message, u.Color, true))
|
2013-06-03 16:35:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *ColoredUi) Message(message string) {
|
2013-06-12 13:41:58 -04:00
|
|
|
u.Ui.Message(u.colorize(message, u.Color, false))
|
2013-06-03 16:35:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (u *ColoredUi) Error(message string) {
|
2013-06-12 13:41:58 -04:00
|
|
|
color := u.ErrorColor
|
|
|
|
if color == 0 {
|
|
|
|
color = UiColorRed
|
|
|
|
}
|
|
|
|
|
|
|
|
u.Ui.Error(u.colorize(message, color, true))
|
2013-06-03 16:35:43 -04:00
|
|
|
}
|
|
|
|
|
2013-08-11 21:16:00 -04:00
|
|
|
func (u *ColoredUi) Machine(t string, args ...string) {
|
|
|
|
// Don't colorize machine-readable output
|
|
|
|
u.Ui.Machine(t, args...)
|
|
|
|
}
|
|
|
|
|
2020-08-17 14:32:13 -04:00
|
|
|
func (u *ColoredUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) io.ReadCloser {
|
|
|
|
return u.Ui.TrackProgress(u.colorize(src, u.Color, false), currentSize, totalSize, stream)
|
|
|
|
}
|
|
|
|
|
2013-06-12 13:41:58 -04:00
|
|
|
func (u *ColoredUi) colorize(message string, color UiColor, bold bool) string {
|
2013-07-31 17:06:01 -04:00
|
|
|
if !u.supportsColors() {
|
|
|
|
return message
|
|
|
|
}
|
|
|
|
|
2013-06-03 16:49:59 -04:00
|
|
|
attr := 0
|
|
|
|
if bold {
|
|
|
|
attr = 1
|
|
|
|
}
|
|
|
|
|
2013-11-20 00:31:54 -05:00
|
|
|
return fmt.Sprintf("\033[%d;%dm%s\033[0m", attr, color, message)
|
2013-06-03 16:35:43 -04:00
|
|
|
}
|
|
|
|
|
2013-07-31 17:06:01 -04:00
|
|
|
func (u *ColoredUi) supportsColors() bool {
|
2013-12-16 17:10:28 -05:00
|
|
|
// Never use colors if we have this environmental variable
|
|
|
|
if os.Getenv("PACKER_NO_COLOR") != "" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2013-07-31 17:06:01 -04:00
|
|
|
// For now, on non-Windows machine, just assume it does
|
|
|
|
if runtime.GOOS != "windows" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// On Windows, if we appear to be in Cygwin, then it does
|
|
|
|
cygwin := os.Getenv("CYGWIN") != "" ||
|
|
|
|
os.Getenv("OSTYPE") == "cygwin" ||
|
|
|
|
os.Getenv("TERM") == "cygwin"
|
|
|
|
|
|
|
|
return cygwin
|
|
|
|
}
|
|
|
|
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
// TargetedUI is a UI that wraps another UI implementation and modifies
|
|
|
|
// the output to indicate a specific target. Specifically, all Say output
|
|
|
|
// is prefixed with the target name. Message output is not prefixed but
|
|
|
|
// is offset by the length of the target so that output is lined up properly
|
|
|
|
// with Say output. Machine-readable output has the proper target set.
|
|
|
|
type TargetedUI struct {
|
|
|
|
Target string
|
2020-11-19 14:54:31 -05:00
|
|
|
Ui packersdk.Ui
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
var _ packersdk.Ui = new(TargetedUI)
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) Ask(query string) (string, error) {
|
2013-08-11 21:31:28 -04:00
|
|
|
return u.Ui.Ask(u.prefixLines(true, query))
|
2013-06-14 18:17:03 -04:00
|
|
|
}
|
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) Say(message string) {
|
2013-08-11 21:31:28 -04:00
|
|
|
u.Ui.Say(u.prefixLines(true, message))
|
2013-06-03 14:30:38 -04:00
|
|
|
}
|
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) Message(message string) {
|
2013-08-11 21:31:28 -04:00
|
|
|
u.Ui.Message(u.prefixLines(false, message))
|
2013-05-21 16:20:51 -04:00
|
|
|
}
|
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) Error(message string) {
|
2013-08-11 21:31:28 -04:00
|
|
|
u.Ui.Error(u.prefixLines(true, message))
|
2013-07-02 15:28:25 -04:00
|
|
|
}
|
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) Machine(t string, args ...string) {
|
2013-08-11 22:08:08 -04:00
|
|
|
// Prefix in the target, then pass through
|
|
|
|
u.Ui.Machine(fmt.Sprintf("%s,%s", u.Target, t), args...)
|
2013-08-11 21:16:00 -04:00
|
|
|
}
|
|
|
|
|
2017-03-29 15:44:42 -04:00
|
|
|
func (u *TargetedUI) prefixLines(arrow bool, message string) string {
|
2013-08-11 21:31:28 -04:00
|
|
|
arrowText := "==>"
|
|
|
|
if !arrow {
|
|
|
|
arrowText = strings.Repeat(" ", len(arrowText))
|
|
|
|
}
|
|
|
|
|
2013-07-02 15:28:25 -04:00
|
|
|
var result bytes.Buffer
|
|
|
|
|
|
|
|
for _, line := range strings.Split(message, "\n") {
|
2013-08-11 21:31:28 -04:00
|
|
|
result.WriteString(fmt.Sprintf("%s %s: %s\n", arrowText, u.Target, line))
|
2013-07-02 15:28:25 -04:00
|
|
|
}
|
|
|
|
|
2013-07-09 14:21:42 -04:00
|
|
|
return strings.TrimRightFunc(result.String(), unicode.IsSpace)
|
2013-05-21 16:20:51 -04:00
|
|
|
}
|
|
|
|
|
2020-06-17 14:57:12 -04:00
|
|
|
func (u *TargetedUI) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) io.ReadCloser {
|
2020-08-17 14:32:13 -04:00
|
|
|
return u.Ui.TrackProgress(u.prefixLines(false, src), currentSize, totalSize, stream)
|
2020-06-17 14:57:12 -04:00
|
|
|
}
|
|
|
|
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
// MachineReadableUi is a UI that only outputs machine-readable output
|
|
|
|
// to the given Writer.
|
|
|
|
type MachineReadableUi struct {
|
|
|
|
Writer io.Writer
|
2020-12-03 17:58:07 -05:00
|
|
|
PB packersdk.NoopProgressTracker
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
var _ packersdk.Ui = new(MachineReadableUi)
|
Use the hashicorp/go-getter to download files
* removed packer.Cache and references since packer.Cache is never used except in the download step. The download step now uses the new func packer.CachePath(targetPath) for this, the behavior is the same.
* removed download code from packer that was reimplemented into the go-getter library: progress bar, http download restart, checksuming from file, skip already downloaded files, symlinking, make a download cancellable by context.
* on windows if packer is running without symlinking rights and we are getting a local file, the file will be copied instead to avoid errors.
* added unit tests for step_download that are now CI tested on windows, mac & linux.
* files are now downloaded under cache dir `sha1(filename + "?checksum=" + checksum) + file_extension`
* since the output dir is based on the source url and the checksum, when the checksum fails, the file is auto deleted.
* a download file is protected and locked by a file lock,
* updated docs
* updated go modules and vendors
2019-03-13 07:11:58 -04:00
|
|
|
|
2013-08-11 22:05:07 -04:00
|
|
|
func (u *MachineReadableUi) Ask(query string) (string, error) {
|
|
|
|
return "", errors.New("machine-readable UI can't ask")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *MachineReadableUi) Say(message string) {
|
|
|
|
u.Machine("ui", "say", message)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *MachineReadableUi) Message(message string) {
|
|
|
|
u.Machine("ui", "message", message)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *MachineReadableUi) Error(message string) {
|
|
|
|
u.Machine("ui", "error", message)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *MachineReadableUi) Machine(category string, args ...string) {
|
|
|
|
now := time.Now().UTC()
|
|
|
|
|
|
|
|
// Determine if we have a target, and set it
|
|
|
|
target := ""
|
|
|
|
commaIdx := strings.Index(category, ",")
|
|
|
|
if commaIdx > -1 {
|
|
|
|
target = category[0:commaIdx]
|
|
|
|
category = category[commaIdx+1:]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prepare the args
|
|
|
|
for i, v := range args {
|
2020-11-19 17:03:11 -05:00
|
|
|
// Use packersdk.LogSecretFilter to scrub out sensitive variables
|
|
|
|
args[i] = packersdk.LogSecretFilter.FilterString(args[i])
|
2019-08-15 19:16:11 -04:00
|
|
|
args[i] = strings.Replace(v, ",", "%!(PACKER_COMMA)", -1)
|
|
|
|
args[i] = strings.Replace(args[i], "\r", "\\r", -1)
|
|
|
|
args[i] = strings.Replace(args[i], "\n", "\\n", -1)
|
2013-08-11 22:05:07 -04:00
|
|
|
}
|
|
|
|
argsString := strings.Join(args, ",")
|
|
|
|
|
2013-08-12 02:14:42 -04:00
|
|
|
_, err := fmt.Fprintf(u.Writer, "%d,%s,%s,%s\n", now.Unix(), target, category, argsString)
|
2013-08-11 22:05:07 -04:00
|
|
|
if err != nil {
|
2014-09-04 00:31:34 -04:00
|
|
|
if err == syscall.EPIPE || strings.Contains(err.Error(), "broken pipe") {
|
2014-02-21 20:43:45 -05:00
|
|
|
// Ignore epipe errors because that just means that the file
|
|
|
|
// is probably closed or going to /dev/null or something.
|
|
|
|
} else {
|
|
|
|
panic(err)
|
|
|
|
}
|
2013-08-11 22:05:07 -04:00
|
|
|
}
|
2019-06-13 13:48:13 -04:00
|
|
|
log.Printf("%d,%s,%s,%s\n", now.Unix(), target, category, argsString)
|
2013-08-11 22:05:07 -04:00
|
|
|
}
|
2018-09-04 11:57:21 -04:00
|
|
|
|
2020-09-21 19:05:14 -04:00
|
|
|
func (u *MachineReadableUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) (body io.ReadCloser) {
|
|
|
|
return u.PB.TrackProgress(src, currentSize, totalSize, stream)
|
|
|
|
}
|
|
|
|
|
2019-02-13 16:01:50 -05:00
|
|
|
// TimestampedUi is a UI that wraps another UI implementation and
|
2018-10-02 06:30:45 -04:00
|
|
|
// prefixes each message with an RFC3339 timestamp
|
|
|
|
type TimestampedUi struct {
|
2020-11-19 14:54:31 -05:00
|
|
|
Ui packersdk.Ui
|
2020-09-21 19:05:14 -04:00
|
|
|
PB getter.ProgressTracker
|
2018-10-02 06:30:45 -04:00
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
var _ packersdk.Ui = new(TimestampedUi)
|
2018-10-02 06:30:45 -04:00
|
|
|
|
2018-09-29 09:09:24 -04:00
|
|
|
func (u *TimestampedUi) Ask(query string) (string, error) {
|
|
|
|
return u.Ui.Ask(query)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *TimestampedUi) Say(message string) {
|
|
|
|
u.Ui.Say(u.timestampLine(message))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *TimestampedUi) Message(message string) {
|
|
|
|
u.Ui.Message(u.timestampLine(message))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *TimestampedUi) Error(message string) {
|
|
|
|
u.Ui.Error(u.timestampLine(message))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (u *TimestampedUi) Machine(message string, args ...string) {
|
|
|
|
u.Ui.Machine(message, args...)
|
|
|
|
}
|
|
|
|
|
2020-09-21 19:05:14 -04:00
|
|
|
func (u *TimestampedUi) TrackProgress(src string, currentSize, totalSize int64, stream io.ReadCloser) (body io.ReadCloser) {
|
|
|
|
return u.Ui.TrackProgress(src, currentSize, totalSize, stream)
|
|
|
|
}
|
|
|
|
|
2018-09-29 09:09:24 -04:00
|
|
|
func (u *TimestampedUi) timestampLine(string string) string {
|
|
|
|
return fmt.Sprintf("%v: %v", time.Now().Format(time.RFC3339), string)
|
|
|
|
}
|