refactored env var code and tests so that I don't have to set env vars during tests to check logic

This commit is contained in:
Megan Marsh 2018-06-29 16:33:26 -07:00
parent 14166fdd99
commit f657ca39c9
3 changed files with 75 additions and 53 deletions

View File

@ -242,38 +242,77 @@ func WaitForImageToBeImported(c *ec2.EC2, ctx aws.Context, input *ec2.DescribeIm
// if AWS_MAX_ATTEMPTS is set but AWS_POLL_DELAY_SECONDS is not, then we will
// use waiter-specific defaults.
type envInfo struct {
envKey string
Val int
overridden bool
}
type overridableWaitVars struct {
awsPollDelaySeconds envInfo
awsMaxAttempts envInfo
awsTimeoutSeconds envInfo
}
func getWaiterOptions() []request.WaiterOption {
envOverrides := getEnvOverrides()
waitOpts := applyEnvOverrides(envOverrides)
return waitOpts
}
func getEnvOverrides() overridableWaitVars {
// Load env vars from environment, and use them to override defaults
envValues := overridableWaitVars{
envInfo{"AWS_POLL_DELAY_SECONDS", 2, false},
envInfo{"AWS_MAX_ATTEMPTS", 0, false},
envInfo{"AWS_TIMEOUT_SECONDS", 300, false},
}
for _, varInfo := range []envInfo{envValues.awsPollDelaySeconds, envValues.awsMaxAttempts, envValues.awsTimeoutSeconds} {
override := os.Getenv(varInfo.envKey)
if override != "" {
n, err := strconv.Atoi(override)
if err != nil {
log.Printf("Invalid %s '%s', using default", varInfo.envKey, override)
} else {
varInfo.overridden = true
varInfo.Val = n
}
}
}
return envValues
}
func applyEnvOverrides(envOverrides overridableWaitVars) []request.WaiterOption {
waitOpts := make([]request.WaiterOption, 0)
// If user has set poll delay seconds, overwrite it. If user has NOT,
// default to a poll delay of 2 seconds
delayOverridden, delay := getEnvOverrides(2, "AWS_POLL_DELAY_SECONDS")
if delayOverridden {
delaySeconds := request.ConstantWaiterDelay(time.Duration(delay) * time.Second)
if envOverrides.awsPollDelaySeconds.overridden {
delaySeconds := request.ConstantWaiterDelay(time.Duration(envOverrides.awsPollDelaySeconds.Val) * time.Second)
waitOpts = append(waitOpts, request.WithWaiterDelay(delaySeconds))
}
// If user has set max attempts, overwrite it. If user hasn't set max
// attempts, default to whatever the waiter has set as a default.
maxAttemptsOverridden, maxAttempts := getEnvOverrides(0, "AWS_MAX_ATTEMPTS")
if maxAttemptsOverridden {
waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(maxAttempts))
if envOverrides.awsMaxAttempts.overridden {
waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(envOverrides.awsMaxAttempts.Val))
}
timeoutOverridden, timeoutSeconds := getEnvOverrides(300, "AWS_TIMEOUT_SECONDS")
if maxAttemptsOverridden {
if envOverrides.awsMaxAttempts.overridden && envOverrides.awsTimeoutSeconds.overridden {
log.Printf("WARNING: AWS_MAX_ATTEMPTS and AWS_TIMEOUT_SECONDS are" +
" both set. Packer will be using AWS_MAX_ATTEMPTS and discarding " +
"AWS_TIMEOUT_SECONDS. If you have not set AWS_POLL_DELAY_SECONDS, " +
"Packer will default to a 2 second poll delay.")
} else if timeoutOverridden {
} else if envOverrides.awsTimeoutSeconds.overridden {
log.Printf("DEPRECATION WARNING: env var AWS_TIMEOUT_SECONDS is " +
"deprecated in favor of AWS_MAX_ATTEMPTS. If you have not " +
"explicitly set AWS_POLL_DELAY_SECONDS, we are defaulting to a " +
"poll delay of 2 seconds, regardless of the AWS waiter's default.")
maxAttempts := timeoutSeconds / delay
maxAttempts := envOverrides.awsTimeoutSeconds.Val / envOverrides.awsPollDelaySeconds.Val
// override the delay so we can get the timeout right
if !delayOverridden {
delaySeconds := request.ConstantWaiterDelay(time.Duration(delay) * time.Second)
if !envOverrides.awsPollDelaySeconds.overridden {
delaySeconds := request.ConstantWaiterDelay(time.Duration(envOverrides.awsPollDelaySeconds.Val) * time.Second)
waitOpts = append(waitOpts, request.WithWaiterDelay(delaySeconds))
}
waitOpts = append(waitOpts, request.WithWaiterMaxAttempts(maxAttempts))
@ -289,22 +328,3 @@ func getWaiterOptions() []request.WaiterOption {
return waitOpts
}
func getEnvOverrides(defaultValue int, envVarName string) (bool, int) {
// "AWS_POLL_DELAY_SECONDS"
retVal := defaultValue
overridden := false
override := os.Getenv(envVarName)
if override != "" {
n, err := strconv.Atoi(override)
if err != nil {
log.Printf("Invalid %s '%s', using default", envVarName, override)
} else {
overridden = true
retVal = n
}
}
log.Printf("Using %ds for %s", retVal, envVarName)
return overridden, retVal
}

View File

@ -1,7 +1,6 @@
package common
import (
"os"
"reflect"
"testing"
"time"
@ -9,26 +8,25 @@ import (
"github.com/aws/aws-sdk-go/aws/request"
)
func clearEnvVars() {
os.Unsetenv("AWS_POLL_DELAY_SECONDS")
os.Unsetenv("AWS_MAX_ATTEMPTS")
os.Unsetenv("AWS_TIMEOUT_SECONDS")
}
func testGetWaiterOptions(t *testing.T) {
clearEnvVars()
// no vars are set
options := getWaiterOptions()
envValues := overridableWaitVars{
envInfo{"AWS_POLL_DELAY_SECONDS", 2, false},
envInfo{"AWS_MAX_ATTEMPTS", 0, false},
envInfo{"AWS_TIMEOUT_SECONDS", 300, false},
}
options := applyEnvOverrides(envValues)
if len(options) > 0 {
t.Fatalf("Did not expect any waiter options to be generated; actual: %#v", options)
}
// all vars are set
os.Setenv("AWS_MAX_ATTEMPTS", "800")
os.Setenv("AWS_TIMEOUT_SECONDS", "20")
os.Setenv("AWS_POLL_DELAY_SECONDS", "1")
options = getWaiterOptions()
envValues = overridableWaitVars{
envInfo{"AWS_POLL_DELAY_SECONDS", 1, true},
envInfo{"AWS_MAX_ATTEMPTS", 800, true},
envInfo{"AWS_TIMEOUT_SECONDS", 20, true},
}
options = applyEnvOverrides(envValues)
expected := []request.WaiterOption{
request.WithWaiterDelay(request.ConstantWaiterDelay(time.Duration(1) * time.Second)),
request.WithWaiterMaxAttempts(800),
@ -36,22 +34,28 @@ func testGetWaiterOptions(t *testing.T) {
if !reflect.DeepEqual(options, expected) {
t.Fatalf("expected != actual!! Expected: %#v; Actual: %#v.", expected, options)
}
clearEnvVars()
// poll delay is not set
os.Setenv("AWS_MAX_ATTEMPTS", "800")
options = getWaiterOptions()
envValues = overridableWaitVars{
envInfo{"AWS_POLL_DELAY_SECONDS", 2, false},
envInfo{"AWS_MAX_ATTEMPTS", 800, true},
envInfo{"AWS_TIMEOUT_SECONDS", 300, false},
}
options = applyEnvOverrides(envValues)
expected = []request.WaiterOption{
request.WithWaiterMaxAttempts(800),
}
if !reflect.DeepEqual(options, expected) {
t.Fatalf("expected != actual!! Expected: %#v; Actual: %#v.", expected, options)
}
clearEnvVars()
// poll delay is not set but timeout seconds is
os.Setenv("AWS_TIMEOUT_SECONDS", "20")
options = getWaiterOptions()
envValues = overridableWaitVars{
envInfo{"AWS_POLL_DELAY_SECONDS", 2, false},
envInfo{"AWS_MAX_ATTEMPTS", 0, false},
envInfo{"AWS_TIMEOUT_SECONDS", 20, true},
}
options = applyEnvOverrides(envValues)
expected = []request.WaiterOption{
request.WithWaiterDelay(request.ConstantWaiterDelay(time.Duration(2) * time.Second)),
request.WithWaiterMaxAttempts(10),
@ -59,5 +63,4 @@ func testGetWaiterOptions(t *testing.T) {
if !reflect.DeepEqual(options, expected) {
t.Fatalf("expected != actual!! Expected: %#v; Actual: %#v.", expected, options)
}
clearEnvVars()
}

View File

@ -203,7 +203,6 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
}
// Check it was actually completed
log.Printf("MEGAN result was %s", *import_result.ImportImageTasks[0].Status)
if *import_result.ImportImageTasks[0].Status != "completed" {
// The most useful error message is from the job itself
return nil, false, fmt.Errorf("Import task %s failed: %s", *import_start.ImportTaskId, *import_result.ImportImageTasks[0].StatusMessage)