diff --git a/.circleci/config.yml b/.circleci/config.yml index 84c7b92c98..4d46699ff5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,7 @@ defaults: &defaults docker: - - image: 087285199408.dkr.ecr.us-east-1.amazonaws.com/circle-ci-test-image-base:tf14.4 + - image: 087285199408.dkr.ecr.us-east-1.amazonaws.com/circle-ci-test-image-base:go1.16-tf14.4-tg28.8 + version: 2 jobs: # We're running unit tests separately from integration tests - with no parallelization. @@ -58,16 +59,12 @@ jobs: <<: *defaults steps: - checkout - # Build amd64 and 386 separately, as darwin/386 is no longer supported in later versions of go - - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" --arch 'amd64' - - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" --os 'linux windows' --arch 386 + - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" deploy: <<: *defaults steps: - checkout - # Build amd64 and 386 separately, as darwin/386 is no longer supported in later versions of go - - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" --arch 'amd64' - - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" --os 'linux windows' --arch 386 + - run: build-go-binaries --app-name terragrunt --dest-path bin --ld-flags "-X main.VERSION=$CIRCLE_TAG" - run: cd bin && sha256sum * > SHA256SUMS - run: upload-github-release-assets bin/* workflows: diff --git a/aws_helper/config.go b/aws_helper/config.go index 254e52a0e7..dc5177ff2f 100644 --- a/aws_helper/config.go +++ b/aws_helper/config.go @@ -17,6 +17,7 @@ import ( type AwsSessionConfig struct { Region string CustomS3Endpoint string + CustomDynamoDBEndpoint string Profile string RoleArn string CredsFilename string @@ -36,6 +37,11 @@ func CreateAwsSession(config *AwsSessionConfig, terragruntOptions *options.Terra URL: config.CustomS3Endpoint, SigningRegion: config.Region, }, nil + } else if service == "dynamodb" && config.CustomDynamoDBEndpoint != "" { + return endpoints.ResolvedEndpoint{ + URL: config.CustomDynamoDBEndpoint, + SigningRegion: config.Region, + }, nil } return defaultResolver.EndpointFor(service, region, optFns...) diff --git a/cli/args.go b/cli/args.go index 2938860b74..dcf3dde379 100644 --- a/cli/args.go +++ b/cli/args.go @@ -220,23 +220,9 @@ func filterTerraformExtraArgs(terragruntOptions *options.TerragruntOptions, terr } if !skipVars { - // If RequiredVarFiles is specified, add -var-file= for each specified files - if arg.RequiredVarFiles != nil { - for _, file := range util.RemoveDuplicatesFromListKeepLast(*arg.RequiredVarFiles) { - out = append(out, fmt.Sprintf("-var-file=%s", file)) - } - } - - // If OptionalVarFiles is specified, check for each file if it exists and if so, add -var-file= - // It is possible that many files resolve to the same path, so we remove duplicates. - if arg.OptionalVarFiles != nil { - for _, file := range util.RemoveDuplicatesFromListKeepLast(*arg.OptionalVarFiles) { - if util.FileExists(file) { - out = append(out, fmt.Sprintf("-var-file=%s", file)) - } else { - terragruntOptions.Logger.Debugf("Skipping var-file %s as it does not exist", file) - } - } + varFiles := arg.GetVarFiles(terragruntOptions.Logger) + for _, file := range varFiles { + out = append(out, fmt.Sprintf("-var-file=%s", file)) } } } @@ -434,7 +420,7 @@ func toTerraformEnvVars(vars map[string]interface{}) (map[string]string, error) out := map[string]string{} for varName, varValue := range vars { - envVarName := fmt.Sprintf("TF_VAR_%s", varName) + envVarName := fmt.Sprintf("%s_%s", TFVarPrefix, varName) envVarValue, err := asTerraformEnvVarJsonValue(varValue) if err != nil { diff --git a/cli/cli_app.go b/cli/cli_app.go index 6262a3e690..3a055eb4e3 100644 --- a/cli/cli_app.go +++ b/cli/cli_app.go @@ -81,6 +81,7 @@ const CMD_INIT_FROM_MODULE = "init-from-module" const CMD_PROVIDERS = "providers" const CMD_LOCK = "lock" const CMD_TERRAGRUNT_INFO = "terragrunt-info" +const CMD_TERRAGRUNT_VALIDATE_INPUTS = "validate-inputs" const CMD_TERRAGRUNT_GRAPH_DEPENDENCIES = "graph-dependencies" const CMD_TERRAGRUNT_READ_CONFIG = "terragrunt-read-config" const CMD_HCLFMT = "hclfmt" @@ -197,12 +198,13 @@ USAGE: {{.Usage}} COMMANDS: - run-all Run a terraform command against a 'stack' by running the specified command in each subfolder. E.g., to run 'terragrunt apply' in each subfolder, use 'terragrunt run-all apply'. - terragrunt-info Emits limited terragrunt state on stdout and exits - graph-dependencies Prints the terragrunt dependency graph to stdout - hclfmt Recursively find terragrunt.hcl files and rewrite them into a canonical format. - aws-provider-patch Overwrite settings on nested AWS providers to work around a Terraform bug (issue #13018) - * Terragrunt forwards all other commands directly to Terraform + run-all Run a terraform command against a 'stack' by running the specified command in each subfolder. E.g., to run 'terragrunt apply' in each subfolder, use 'terragrunt run-all apply'. + terragrunt-info Emits limited terragrunt state on stdout and exits + validate-inputs Checks if the terragrunt configured inputs align with the terraform defined variables. + graph-dependencies Prints the terragrunt dependency graph to stdout + hclfmt Recursively find terragrunt.hcl files and rewrite them into a canonical format. + aws-provider-patch Overwrite settings on nested AWS providers to work around a Terraform bug (issue #13018) + * Terragrunt forwards all other commands directly to Terraform GLOBAL OPTIONS: terragrunt-config Path to the Terragrunt config file. Default is terragrunt.hcl. @@ -244,6 +246,9 @@ const DEFAULT_TERRAFORM_VERSION_CONSTRAINT = ">= v0.12.0" const TERRAFORM_EXTENSION_GLOB = "*.tf" +// Prefix to use for terraform variables set with environment variables. +const TFVarPrefix = "TF_VAR" + // The supported flags to show help of terraform commands var TERRAFORM_HELP_FLAGS = []string{ "--help", @@ -437,6 +442,12 @@ func RunTerragrunt(terragruntOptions *options.TerragruntOptions) error { } } + // We do the terragrunt input validation here, after all the terragrunt generated terraform files are created so + // that we can ensure the necessary information is available. + if shouldValidateTerragruntInputs(updatedTerragruntOptions) { + return validateTerragruntInputs(updatedTerragruntOptions, terragruntConfig) + } + // We do the debug file generation here, after all the terragrunt generated terraform files are created so that we // can ensure the tfvars json file only includes the vars that are defined in the module. if updatedTerragruntOptions.Debug { @@ -519,6 +530,10 @@ func shouldPrintTerragruntInfo(terragruntOptions *options.TerragruntOptions) boo return util.ListContainsElement(terragruntOptions.TerraformCliArgs, CMD_TERRAGRUNT_INFO) } +func shouldValidateTerragruntInputs(terragruntOptions *options.TerragruntOptions) bool { + return util.ListContainsElement(terragruntOptions.TerraformCliArgs, CMD_TERRAGRUNT_VALIDATE_INPUTS) +} + func shouldRunHCLFmt(terragruntOptions *options.TerragruntOptions) bool { return util.ListContainsElement(terragruntOptions.TerraformCliArgs, CMD_HCLFMT) } @@ -540,10 +555,20 @@ func processHooks(hooks []config.Hook, terragruntOptions *options.TerragruntOpti allPreviousErrors := append(previousExecError, errorsOccurred...) if shouldRunHook(curHook, terragruntOptions, allPreviousErrors...) { terragruntOptions.Logger.Infof("Executing hook: %s", curHook.Name) + workingDir := "" + if curHook.WorkingDir != nil { + workingDir = *curHook.WorkingDir + } + actionToExecute := curHook.Execute[0] actionParams := curHook.Execute[1:] - possibleError := shell.RunShellCommand(terragruntOptions, actionToExecute, actionParams...) - + _, possibleError := shell.RunShellCommandWithOutput( + terragruntOptions, + workingDir, + false, + false, + actionToExecute, actionParams..., + ) if possibleError != nil { terragruntOptions.Logger.Errorf("Error running hook %s with message: %s", curHook.Name, possibleError.Error()) errorsOccurred = append(errorsOccurred, possibleError) diff --git a/cli/debug.go b/cli/debug.go index e8a62786ee..d22bd258e9 100644 --- a/cli/debug.go +++ b/cli/debug.go @@ -27,10 +27,12 @@ func writeTerragruntDebugFile(terragruntOptions *options.TerragruntOptions, terr terragruntOptions.WorkingDir, ) - variables, err := terraformModuleVariables(terragruntOptions) + required, optional, err := terraformModuleVariables(terragruntOptions) if err != nil { return err } + variables := append(required, optional...) + terragruntOptions.Logger.Debugf("The following variables were detected in the terraform module:") terragruntOptions.Logger.Debugf("%v", variables) @@ -71,7 +73,7 @@ func terragruntDebugFileContents( jsonValuesByKey := make(map[string]interface{}) for varName, varValue := range terragruntConfig.Inputs { - nameAsEnvVar := fmt.Sprintf("TF_VAR_%s", varName) + nameAsEnvVar := fmt.Sprintf("%s_%s", TFVarPrefix, varName) _, varIsInEnv := envVars[nameAsEnvVar] varIsDefined := util.ListContainsElement(moduleVariables, varName) @@ -100,17 +102,22 @@ func terragruntDebugFileContents( } // terraformModuleVariables will return all the variables defined in the downloaded terraform modules, taking into -// account all the generated sources. -func terraformModuleVariables(terragruntOptions *options.TerragruntOptions) ([]string, error) { +// account all the generated sources. This function will return the required and optional variables separately. +func terraformModuleVariables(terragruntOptions *options.TerragruntOptions) ([]string, []string, error) { modulePath := terragruntOptions.WorkingDir module, diags := tfconfig.LoadModule(modulePath) if diags.HasErrors() { - return nil, errors.WithStackTrace(diags) + return nil, nil, errors.WithStackTrace(diags) } - variables := []string{} + required := []string{} + optional := []string{} for _, variable := range module.Variables { - variables = append(variables, variable.Name) + if variable.Required { + required = append(required, variable.Name) + } else { + optional = append(optional, variable.Name) + } } - return variables, nil + return required, optional, nil } diff --git a/cli/tfsource/types.go b/cli/tfsource/types.go index fd27e46f6c..745738f558 100644 --- a/cli/tfsource/types.go +++ b/cli/tfsource/types.go @@ -142,7 +142,15 @@ func toSourceUrl(source string, workingDir string) (*url.URL, error) { // Parse the given source URL into a URL struct. This method can handle source URLs that include go-getter's "forced // getter" prefixes, such as git::. func parseSourceUrl(source string) (*url.URL, error) { + forcedGetters := []string{} + // Continuously strip the forced getters until there is no more. This is to handle complex URL schemes like the + // git-remote-codecommit style URL. forcedGetter, rawSourceUrl := getForcedGetter(source) + for forcedGetter != "" { + // Prepend like a stack, so that we prepend to the URL scheme in the right order. + forcedGetters = append([]string{forcedGetter}, forcedGetters...) + forcedGetter, rawSourceUrl = getForcedGetter(rawSourceUrl) + } // Parse the URL without the getter prefix canonicalSourceUrl, err := urlhelper.Parse(rawSourceUrl) @@ -151,7 +159,7 @@ func parseSourceUrl(source string) (*url.URL, error) { } // Reattach the "getter" prefix as part of the scheme - if forcedGetter != "" { + for _, forcedGetter := range forcedGetters { canonicalSourceUrl.Scheme = fmt.Sprintf("%s::%s", forcedGetter, canonicalSourceUrl.Scheme) } diff --git a/cli/tfsource/types_test.go b/cli/tfsource/types_test.go index a885147d6e..8424ac5f29 100644 --- a/cli/tfsource/types_test.go +++ b/cli/tfsource/types_test.go @@ -58,3 +58,21 @@ func TestSplitSourceUrl(t *testing.T) { }) } } + +func TestRegressionSupportForGitRemoteCodecommit(t *testing.T) { + t.Parallel() + + terragruntOptions, err := options.NewTerragruntOptionsForTest("testing") + require.NoError(t, err) + + source := "git::codecommit::ap-northeast-1://my_app_modules//my-app/modules/main-module" + sourceURL, err := toSourceUrl(source, ".") + require.NoError(t, err) + require.Equal(t, "git::codecommit::ap-northeast-1", sourceURL.Scheme) + + actualRootRepo, actualModulePath, err := splitSourceUrl(sourceURL, terragruntOptions.Logger) + require.NoError(t, err) + + require.Equal(t, "git::codecommit::ap-northeast-1://my_app_modules", actualRootRepo.String()) + require.Equal(t, "my-app/modules/main-module", actualModulePath) +} diff --git a/cli/validate_inputs.go b/cli/validate_inputs.go new file mode 100644 index 0000000000..e73d335e61 --- /dev/null +++ b/cli/validate_inputs.go @@ -0,0 +1,310 @@ +package cli + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "path/filepath" + "strings" + + "github.com/google/shlex" + + "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/util" +) + +// validateTerragruntInputs will collect all the terraform variables defined in the target module, and the terragrunt +// inputs that are configured, and compare the two to determine if there are any unused inputs or undefined required +// inputs. +func validateTerragruntInputs(terragruntOptions *options.TerragruntOptions, workingConfig *config.TerragruntConfig) error { + required, optional, err := terraformModuleVariables(terragruntOptions) + if err != nil { + return err + } + allVars := append(required, optional...) + + allInputs, err := getDefinedTerragruntInputs(terragruntOptions, workingConfig) + if err != nil { + return err + } + + // Unused variables are those that are passed in by terragrunt, but are not defined in terraform. + unusedVars := []string{} + for _, varName := range allInputs { + if !util.ListContainsElement(allVars, varName) { + unusedVars = append(unusedVars, varName) + } + } + + // Missing variables are those that are required by the terraform config, but not defined in terragrunt. + missingVars := []string{} + for _, varName := range required { + if !util.ListContainsElement(allInputs, varName) { + missingVars = append(missingVars, varName) + } + } + + // Now print out all the information + if len(unusedVars) > 0 { + terragruntOptions.Logger.Warn("The following inputs passed in by terragrunt are unused:\n") + for _, varName := range unusedVars { + terragruntOptions.Logger.Warnf("\t- %s", varName) + } + terragruntOptions.Logger.Warn("") + } else { + terragruntOptions.Logger.Info("All variables passed in by terragrunt are in use.") + } + + if len(missingVars) > 0 { + terragruntOptions.Logger.Error("The following required inputs are missing:\n") + for _, varName := range missingVars { + terragruntOptions.Logger.Errorf("\t- %s", varName) + } + terragruntOptions.Logger.Error("") + } else { + terragruntOptions.Logger.Info("All required inputs are passed in by terragrunt.") + } + + // Return an error when there are misaligned inputs. + if len(unusedVars) > 0 || len(missingVars) > 0 { + return fmt.Errorf("Terragrunt configuration has misaligned inputs") + } + return nil +} + +// getDefinedTerragruntInputs will return a list of names of all variables that are configured by terragrunt to be +// passed into terraform. Terragrunt can pass in inputs from: +// - var files defined on terraform.extra_arguments blocks. +// - -var and -var-file args passed in on extra_arguments CLI args. +// - env vars defined on terraform.extra_arguments blocks. +// - env vars from the external runtime calling terragrunt. +// - inputs blocks. +// - automatically injected terraform vars (terraform.tfvars, terraform.tfvars.json, *.auto.tfvars, *.auto.tfvars.json) +func getDefinedTerragruntInputs(terragruntOptions *options.TerragruntOptions, workingConfig *config.TerragruntConfig) ([]string, error) { + envVarTFVars := getTerraformInputNamesFromEnvVar(terragruntOptions, workingConfig) + inputsTFVars := getTerraformInputNamesFromConfig(workingConfig) + varFileTFVars, err := getTerraformInputNamesFromVarFiles(terragruntOptions, workingConfig) + if err != nil { + return nil, err + } + cliArgsTFVars, err := getTerraformInputNamesFromCLIArgs(terragruntOptions, workingConfig) + if err != nil { + return nil, err + } + autoVarFileTFVars, err := getTerraformInputNamesFromAutomaticVarFiles(terragruntOptions) + if err != nil { + return nil, err + } + + // Dedupe the input vars. We use a map as a set to accomplish this. + tmpOut := map[string]bool{} + for _, varName := range envVarTFVars { + tmpOut[varName] = true + } + for _, varName := range inputsTFVars { + tmpOut[varName] = true + } + for _, varName := range varFileTFVars { + tmpOut[varName] = true + } + for _, varName := range cliArgsTFVars { + tmpOut[varName] = true + } + for _, varName := range autoVarFileTFVars { + tmpOut[varName] = true + } + + out := []string{} + for varName, _ := range tmpOut { + out = append(out, varName) + } + return out, nil +} + +// getTerraformInputNamesFromEnvVar will check the runtime environment variables and the configured environment +// variables from extra_arguments blocks to see if there are any TF_VAR environment variables that set terraform +// variables. This will return the list of names of variables that are set in this way by the given terragrunt +// configuration. +func getTerraformInputNamesFromEnvVar(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) []string { + envVars := terragruntOptions.Env + + // Make sure to check if there are configured env vars in the parsed terragrunt config. + if terragruntConfig.Terraform != nil { + for _, arg := range terragruntConfig.Terraform.ExtraArgs { + if arg.EnvVars != nil { + for key, val := range *arg.EnvVars { + envVars[key] = val + } + } + } + } + + out := []string{} + for envName, _ := range envVars { + if strings.HasPrefix(envName, TFVarPrefix) { + out = append(out, strings.TrimPrefix(envName, fmt.Sprintf("%s_", TFVarPrefix))) + } + } + return out +} + +// getTerraformInputNamesFromConfig will return the list of names of variables configured by the inputs block in the +// terragrunt config. +func getTerraformInputNamesFromConfig(terragruntConfig *config.TerragruntConfig) []string { + out := []string{} + for inputName, _ := range terragruntConfig.Inputs { + out = append(out, inputName) + } + return out +} + +// getTerraformInputNamesFromVarFiles will return the list of names of variables configured by var files set in the +// extra_arguments block required_var_files and optional_var_files settings of the given terragrunt config. +func getTerraformInputNamesFromVarFiles(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) ([]string, error) { + if terragruntConfig.Terraform == nil { + return nil, nil + } + + varFiles := []string{} + for _, arg := range terragruntConfig.Terraform.ExtraArgs { + varFiles = append(varFiles, arg.GetVarFiles(terragruntOptions.Logger)...) + } + + return getVarNamesFromVarFiles(varFiles) +} + +// getTerraformInputNamesFromCLIArgs will return the list of names of variables configured by -var and -var-file CLI +// args that are passed in via the configured arguments attribute in the extra_arguments block of the given terragrunt +// config and those that are directly passed in via the CLI. +func getTerraformInputNamesFromCLIArgs(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) ([]string, error) { + inputNames, varFiles, err := getVarFlagsFromArgList(terragruntOptions.TerraformCliArgs) + if err != nil { + return inputNames, err + } + + if terragruntConfig.Terraform != nil { + for _, arg := range terragruntConfig.Terraform.ExtraArgs { + if arg.Arguments != nil { + vars, rawVarFiles, err := getVarFlagsFromArgList(*arg.Arguments) + if err != nil { + return inputNames, err + } + inputNames = append(inputNames, vars...) + varFiles = append(varFiles, rawVarFiles...) + } + } + } + + fileVars, err := getVarNamesFromVarFiles(varFiles) + if err != nil { + return inputNames, err + } + inputNames = append(inputNames, fileVars...) + + return inputNames, nil +} + +// getTerraformInputNamesFromAutomaticVarFiles returns all the variables names +func getTerraformInputNamesFromAutomaticVarFiles(terragruntOptions *options.TerragruntOptions) ([]string, error) { + base := terragruntOptions.WorkingDir + automaticVarFiles := []string{} + + tfTFVarsFile := filepath.Join(base, "terraform.tfvars") + if util.FileExists(tfTFVarsFile) { + automaticVarFiles = append(automaticVarFiles, tfTFVarsFile) + } + + tfTFVarsJsonFile := filepath.Join(base, "terraform.tfvars.json") + if util.FileExists(tfTFVarsJsonFile) { + automaticVarFiles = append(automaticVarFiles, tfTFVarsJsonFile) + } + + varFiles, err := filepath.Glob(filepath.Join(base, "*.auto.tfvars")) + if err != nil { + return nil, err + } + automaticVarFiles = append(automaticVarFiles, varFiles...) + jsonVarFiles, err := filepath.Glob(filepath.Join(base, "*.auto.tfvars.json")) + if err != nil { + return nil, err + } + automaticVarFiles = append(automaticVarFiles, jsonVarFiles...) + return getVarNamesFromVarFiles(automaticVarFiles) +} + +// getVarNamesFromVarFiles will parse all the given var files and returns a list of names of variables that are +// configured in all of them combined together. +func getVarNamesFromVarFiles(varFiles []string) ([]string, error) { + inputNames := []string{} + for _, varFile := range varFiles { + fileVars, err := getVarNamesFromVarFile(varFile) + if err != nil { + return inputNames, err + } + inputNames = append(inputNames, fileVars...) + } + return inputNames, nil +} + +// getVarNamesFromVarFile will parse the given terraform var file and return a list of names of variables that are +// configured in that var file. +func getVarNamesFromVarFile(varFile string) ([]string, error) { + fileContents, err := ioutil.ReadFile(varFile) + if err != nil { + return nil, err + } + + var variables map[string]interface{} + if strings.HasSuffix(varFile, "json") { + if err := json.Unmarshal(fileContents, &variables); err != nil { + return nil, err + } + } else { + if err := config.ParseAndDecodeVarFile(string(fileContents), varFile, &variables); err != nil { + return nil, err + } + } + + out := []string{} + for varName, _ := range variables { + out = append(out, varName) + } + return out, nil +} + +// Returns the CLI flags defined on the provided arguments list that correspond to -var and -var-file. Returns two +// slices, one for `-var` args (the first one) and one for `-var-file` args (the second one). +func getVarFlagsFromArgList(argList []string) ([]string, []string, error) { + vars := []string{} + varFiles := []string{} + + for _, arg := range argList { + // Use shlex to handle shell style quoting rules. This will reduce quoted args to remove quoting rules. For + // example, the string: + // -var="'"foo"'"='bar' + // becomes: + // -var='foo'=bar + shlexedArgSlice, err := shlex.Split(arg) + if err != nil { + return vars, varFiles, err + } + // Since we expect each element in extra_args.arguments to correspond to a single arg for terraform, we join + // back the shlex split slice even if it thinks there are multiple. + shlexedArg := strings.Join(shlexedArgSlice, " ") + + if strings.HasPrefix(shlexedArg, "-var=") { + // -var is passed in in the format -var=VARNAME=VALUE, so we split on '=' and take the middle value. + splitArg := strings.Split(shlexedArg, "=") + if len(splitArg) < 2 { + return vars, varFiles, fmt.Errorf("Unexpected -var arg format in terraform.extra_arguments.arguments. Expected '-var=VARNAME=VALUE', got %s.", arg) + } + vars = append(vars, splitArg[1]) + } + if strings.HasPrefix(shlexedArg, "-var-file=") { + varFiles = append(varFiles, strings.TrimPrefix(shlexedArg, "-var-file=")) + } + } + + return vars, varFiles, nil +} diff --git a/cli/validate_inputs_test.go b/cli/validate_inputs_test.go new file mode 100644 index 0000000000..ea24632706 --- /dev/null +++ b/cli/validate_inputs_test.go @@ -0,0 +1,69 @@ +package cli + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetVarFlagsFromExtraArgs(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + args []string + expectedVars []string + expectedVarFiles []string + }{ + { + "VarsWithQuotes", + []string{`-var='hello=world'`, `-var="foo=bar"`, `-var="'"enabled"'"=false`}, + []string{"'enabled'", "foo", "hello"}, + []string{}, + }, + { + "VarFilesWithQuotes", + []string{`-var-file='terraform.tfvars'`, `-var-file="other_vars.tfvars"`}, + []string{}, + []string{"other_vars.tfvars", "terraform.tfvars"}, + }, + { + "MixedWithOtherIrrelevantArgs", + []string{"-lock=true", "-var=enabled=true", "-refresh=false"}, + []string{"enabled"}, + []string{}, + }, + { + "None", + []string{"-lock=true", "-refresh=false"}, + []string{}, + []string{}, + }, + { + "SpaceInVarFileName", + []string{"-var-file='this is a test.tfvars'"}, + []string{}, + []string{"this is a test.tfvars"}, + }, + } + + for _, testCase := range testCases { + // Capture range variable so that it is brought into the scope within the for loop, so that it is stable even + // when subtests are run in parallel. + testCase := testCase + + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + vars, varFiles, err := getVarFlagsFromArgList(testCase.args) + require.NoError(t, err) + sort.Strings(vars) + sort.Strings(varFiles) + assert.Equal(t, testCase.expectedVars, vars) + assert.Equal(t, testCase.expectedVarFiles, varFiles) + }) + } + +} diff --git a/config/config.go b/config/config.go index 5336a68723..8c95389ed0 100644 --- a/config/config.go +++ b/config/config.go @@ -8,8 +8,8 @@ import ( "strings" "github.com/hashicorp/hcl/v2" - "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclparse" + "github.com/sirupsen/logrus" "github.com/zclconf/go-cty/cty" "github.com/gruntwork-io/terragrunt/codegen" @@ -181,6 +181,7 @@ type Hook struct { Commands []string `hcl:"commands,attr" cty:"commands"` Execute []string `hcl:"execute,attr" cty:"execute"` RunOnError *bool `hcl:"run_on_error,attr" cty:"run_on_error"` + WorkingDir *string `hcl:"working_dir,attr" cty:"working_dir"` } func (conf *Hook) String() string { @@ -248,6 +249,32 @@ func (conf *TerraformExtraArguments) String() string { conf.EnvVars) } +func (conf *TerraformExtraArguments) GetVarFiles(logger *logrus.Entry) []string { + varFiles := []string{} + + // Include all specified RequiredVarFiles. + if conf.RequiredVarFiles != nil { + for _, file := range util.RemoveDuplicatesFromListKeepLast(*conf.RequiredVarFiles) { + varFiles = append(varFiles, file) + } + } + + // If OptionalVarFiles is specified, check for each file if it exists and if so, include in the var + // files list. Note that it is possible that many files resolve to the same path, so we remove + // duplicates. + if conf.OptionalVarFiles != nil { + for _, file := range util.RemoveDuplicatesFromListKeepLast(*conf.OptionalVarFiles) { + if util.FileExists(file) { + varFiles = append(varFiles, file) + } else { + logger.Debugf("Skipping var-file %s as it does not exist", file) + } + } + } + + return varFiles +} + // There are two ways a user can tell Terragrunt that it needs to download Terraform configurations from a specific // URL: via a command-line option or via an entry in the Terragrunt configuration. If the user used one of these, this // method returns the source URL or an empty string if there is no source url @@ -487,59 +514,6 @@ func decodeAsTerragruntConfigFile( return &terragruntConfig, nil } -// decodeHcl uses the HCL2 parser to decode the parsed HCL into the struct specified by out. -func decodeHcl( - file *hcl.File, - filename string, - out interface{}, - terragruntOptions *options.TerragruntOptions, - extensions EvalContextExtensions, -) (err error) { - // The HCL2 parser and especially cty conversions will panic in many types of errors, so we have to recover from - // those panics here and convert them to normal errors - defer func() { - if recovered := recover(); recovered != nil { - err = errors.WithStackTrace(PanicWhileParsingConfig{RecoveredValue: recovered, ConfigFile: filename}) - } - }() - - evalContext := CreateTerragruntEvalContext(filename, terragruntOptions, extensions) - - decodeDiagnostics := gohcl.DecodeBody(file.Body, evalContext, out) - if decodeDiagnostics != nil && decodeDiagnostics.HasErrors() { - return decodeDiagnostics - } - - return nil -} - -// parseHcl uses the HCL2 parser to parse the given string into an HCL file body. -func parseHcl(parser *hclparse.Parser, hcl string, filename string) (file *hcl.File, err error) { - // The HCL2 parser and especially cty conversions will panic in many types of errors, so we have to recover from - // those panics here and convert them to normal errors - defer func() { - if recovered := recover(); recovered != nil { - err = errors.WithStackTrace(PanicWhileParsingConfig{RecoveredValue: recovered, ConfigFile: filename}) - } - }() - - if filepath.Ext(filename) == ".json" { - file, parseDiagnostics := parser.ParseJSON([]byte(hcl), filename) - if parseDiagnostics != nil && parseDiagnostics.HasErrors() { - return nil, parseDiagnostics - } - - return file, nil - } - - file, parseDiagnostics := parser.ParseHCL([]byte(hcl), filename) - if parseDiagnostics != nil && parseDiagnostics.HasErrors() { - return nil, parseDiagnostics - } - - return file, nil -} - // Merge the given config with an included config. Anything specified in the current config will override the contents // of the included config. If the included config is nil, just return the current config. func mergeConfigWithIncludedConfig(config *TerragruntConfig, includedConfig *TerragruntConfig, terragruntOptions *options.TerragruntOptions) (*TerragruntConfig, error) { diff --git a/config/config_helpers.go b/config/config_helpers.go index 9c508994d9..d61a8f8377 100644 --- a/config/config_helpers.go +++ b/config/config_helpers.go @@ -115,6 +115,7 @@ func CreateTerragruntEvalContext( "get_terraform_commands_that_need_input": wrapStaticValueToStringSliceAsFuncImpl(TERRAFORM_COMMANDS_NEED_INPUT), "get_terraform_commands_that_need_parallelism": wrapStaticValueToStringSliceAsFuncImpl(TERRAFORM_COMMANDS_NEED_PARALLELISM), "sops_decrypt_file": wrapStringSliceToStringAsFuncImpl(sopsDecryptFile, extensions.Include, terragruntOptions), + "get_terragrunt_source_cli_flag": wrapVoidToStringAsFuncImpl(getTerragruntSourceCliFlag, extensions.Include, terragruntOptions), } functions := map[string]function.Function{} @@ -332,7 +333,7 @@ func getTerraformCommand(include *IncludeConfig, terragruntOptions *options.Terr return terragruntOptions.TerraformCommand, nil } -// getTerraformCommand returns the current terraform command in execution +// getTerraformCliArgs returns cli args for terraform func getTerraformCliArgs(include *IncludeConfig, terragruntOptions *options.TerragruntOptions) ([]string, error) { return terragruntOptions.TerraformCliArgs, nil } @@ -559,6 +560,11 @@ func sopsDecryptFile(params []string, include *IncludeConfig, terragruntOptions return "", errors.WithStackTrace(InvalidSopsFormat{SourceFilePath: sourceFile}) } +// Return the location of the Terraform files provided via --terragrunt-source +func getTerragruntSourceCliFlag(include *IncludeConfig, terragruntOptions *options.TerragruntOptions) (string, error) { + return terragruntOptions.Source, nil +} + // Custom error types type WrongNumberOfParams struct { Func string diff --git a/config/dependency.go b/config/dependency.go index 9165e60187..02e262a296 100644 --- a/config/dependency.go +++ b/config/dependency.go @@ -639,7 +639,7 @@ func runTerraformInitForDependencyOutput(terragruntOptions *options.TerragruntOp initTGOptions := terragruntOptions.Clone(targetConfig) initTGOptions.WorkingDir = workingDir initTGOptions.ErrWriter = &stderr - err := shell.RunTerraformCommand(initTGOptions, "init", "-get=false", "-get-plugins=false") + err := shell.RunTerraformCommand(initTGOptions, "init", "-get=false") if err != nil { terragruntOptions.Logger.Debugf("Ignoring expected error from dependency init call") terragruntOptions.Logger.Debugf("Init call stderr:") diff --git a/config/hcl_parser.go b/config/hcl_parser.go new file mode 100644 index 0000000000..9df638f428 --- /dev/null +++ b/config/hcl_parser.go @@ -0,0 +1,115 @@ +package config + +import ( + "path/filepath" + + "github.com/gruntwork-io/terragrunt/errors" + "github.com/gruntwork-io/terragrunt/options" + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/gohcl" + "github.com/hashicorp/hcl/v2/hclparse" + "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/gocty" +) + +// parseHcl uses the HCL2 parser to parse the given string into an HCL file body. +func parseHcl(parser *hclparse.Parser, hcl string, filename string) (file *hcl.File, err error) { + // The HCL2 parser and especially cty conversions will panic in many types of errors, so we have to recover from + // those panics here and convert them to normal errors + defer func() { + if recovered := recover(); recovered != nil { + err = errors.WithStackTrace(PanicWhileParsingConfig{RecoveredValue: recovered, ConfigFile: filename}) + } + }() + + if filepath.Ext(filename) == ".json" { + file, parseDiagnostics := parser.ParseJSON([]byte(hcl), filename) + if parseDiagnostics != nil && parseDiagnostics.HasErrors() { + return nil, parseDiagnostics + } + + return file, nil + } + + file, parseDiagnostics := parser.ParseHCL([]byte(hcl), filename) + if parseDiagnostics != nil && parseDiagnostics.HasErrors() { + return nil, parseDiagnostics + } + + return file, nil +} + +// decodeHcl uses the HCL2 parser to decode the parsed HCL into the struct specified by out. +func decodeHcl( + file *hcl.File, + filename string, + out interface{}, + terragruntOptions *options.TerragruntOptions, + extensions EvalContextExtensions, +) (err error) { + // The HCL2 parser and especially cty conversions will panic in many types of errors, so we have to recover from + // those panics here and convert them to normal errors + defer func() { + if recovered := recover(); recovered != nil { + err = errors.WithStackTrace(PanicWhileParsingConfig{RecoveredValue: recovered, ConfigFile: filename}) + } + }() + + evalContext := CreateTerragruntEvalContext(filename, terragruntOptions, extensions) + + decodeDiagnostics := gohcl.DecodeBody(file.Body, evalContext, out) + if decodeDiagnostics != nil && decodeDiagnostics.HasErrors() { + return decodeDiagnostics + } + + return nil +} + +// ParseAndDecodeVarFile uses the HCL2 parser to parse the given varfile string into an HCL file body, and then decode it +// into the provided output. +func ParseAndDecodeVarFile(hclContents string, filename string, out interface{}) (err error) { + // The HCL2 parser and especially cty conversions will panic in many types of errors, so we have to recover from + // those panics here and convert them to normal errors + defer func() { + if recovered := recover(); recovered != nil { + err = PanicWhileParsingConfig{RecoveredValue: recovered, ConfigFile: filename} + } + }() + + parser := hclparse.NewParser() + file, err := parseHcl(parser, hclContents, filename) + if err != nil { + return err + } + + // VarFiles should only have attributes, so extract the attributes and decode the expressions into the return map. + attrs, hclDiags := file.Body.JustAttributes() + if hclDiags != nil && hclDiags.HasErrors() { + return hclDiags + } + + valMap := map[string]cty.Value{} + for name, attr := range attrs { + val, hclDiags := attr.Expr.Value(nil) // nil because no function calls or variable references are allowed here + if hclDiags != nil && hclDiags.HasErrors() { + return hclDiags + } + valMap[name] = val + } + + ctyVal, err := convertValuesMapToCtyVal(valMap) + if err != nil { + return err + } + + typedOut, hasType := out.(*map[string]interface{}) + if hasType { + genericMap, err := parseCtyValueToMap(ctyVal) + if err != nil { + return err + } + *typedOut = genericMap + return nil + } + return gocty.FromCtyValue(ctyVal, out) +} diff --git a/configstack/stack.go b/configstack/stack.go index db2df93c03..d0dc86b607 100644 --- a/configstack/stack.go +++ b/configstack/stack.go @@ -81,6 +81,12 @@ func (stack *Stack) Run(terragruntOptions *options.TerragruntOptions) error { func (stack *Stack) summarizePlanAllErrors(terragruntOptions *options.TerragruntOptions, errorStreams []bytes.Buffer) { for i, errorStream := range errorStreams { output := errorStream.String() + + if len(output) == 0 { + // We get empty buffer if stack execution completed without errors, so skip that to avoid logging too much + continue + } + terragruntOptions.Logger.Infoln(output) if strings.Contains(output, "Error running plan:") { if strings.Contains(output, ": Resource 'data.terraform_remote_state.") { diff --git a/docs/_docs/02_features/keep-your-cli-flags-dry.md b/docs/_docs/02_features/keep-your-cli-flags-dry.md index d092d1bd75..34a47d72c3 100644 --- a/docs/_docs/02_features/keep-your-cli-flags-dry.md +++ b/docs/_docs/02_features/keep-your-cli-flags-dry.md @@ -129,7 +129,6 @@ terraform { ] arguments = [ - "-get-plugins=false", "-plugin-dir=/my/terraform/plugin/dir", ] } diff --git a/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md b/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md index 277a6a20e5..03faee8eb3 100644 --- a/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md +++ b/docs/_docs/02_features/keep-your-remote-state-configuration-dry.md @@ -198,7 +198,9 @@ When you run `terragrunt` with `remote_state` configuration, it will automatical In addition, you can let terragrunt tag the bucket with custom tags that you specify in `remote_state.config.s3_bucket_tags`. - **DynamoDB table**: If you are using the [S3 backend](https://www.terraform.io/docs/backends/types/s3.html) for remote state storage and you specify a `dynamodb_table` (a [DynamoDB table used for locking](https://www.terraform.io/docs/backends/types/s3.html#dynamodb_table)) in `remote_state.config`, if that table doesn’t already exist, Terragrunt will create it automatically, with [server-side encryption](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html) enabled, including a primary key called `LockID`. - + + You may configure custom endpoint for the AWS DynamoDB API using `remote_state.config.dynamodb_endpoint`. + In addition, you can let terragrunt tag the DynamoDB table with custom tags that you specify in `remote_state.config.dynamodb_table_tags`. - **GCS bucket**: If you are using the [GCS backend](https://www.terraform.io/docs/backends/types/gcs.html) for remote state storage and the `bucket` you specify in `remote_state.config` doesn’t already exist, Terragrunt will create it automatically, with [versioning](https://cloud.google.com/storage/docs/object-versioning) enabled. For this to work correctly you must also specify `project` and `location` keys in `remote_state.config`, so Terragrunt knows where to create the bucket. You will also need to supply valid credentials using either `remote_state.config.credentials` or by setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. If you want to skip creating the bucket entirely, simply set `skip_bucket_creation` to `true` and Terragrunt will assume the bucket has already been created. If you don’t specify `bucket` in `remote_state` then terragrunt will assume that you will pass `bucket` through `-backend-config` in `extra_arguments`. @@ -237,6 +239,7 @@ remote_state { skip_bucket_enforced_tls = true # use only if you need to access the S3 bucket without TLS being enforced enable_lock_table_ssencryption = true # use only if non-encrypted DynamoDB Lock Table for the Terraform State is required and/or the NoSQL database service does not support server-side encryption accesslogging_bucket_name = # use only if you need server access logging to be enabled for your terraform state S3 bucket. Provide a value representing the name of the target bucket to be used for logs output. + accesslogging_target_prefix = # use only if you want to set a specific prefix for your terraform state S3 bucket access logs when Server Access Logging is enabled. Provide a value representing the TargetPrefix to be used for the logs output objects. If set to empty , then TargetPrefix will be set to empty . If attribute is not provided at all, then TargetPrefix will be set to default value `TFStateLogs/`. shared_credentials_file = "/path/to/credentials/file" skip_credentials_validation = true @@ -247,7 +250,7 @@ remote_state { If you experience an error for any of these configurations, confirm you are using Terraform v0.12.2 or greater. -Further, the config options `s3_bucket_tags`, `dynamodb_table_tags`, `skip_bucket_versioning`, `skip_bucket_ssencryption`, `skip_bucket_root_access`, `skip_bucket_enforced_tls`, `accesslogging_bucket_name`, and `enable_lock_table_ssencryption` are only valid for backend `s3`. They are used by terragrunt and are **not** passed on to terraform. See section [Create remote state and locking resources automatically](#create-remote-state-and-locking-resources-automatically). +Further, the config options `s3_bucket_tags`, `dynamodb_table_tags`, `skip_bucket_versioning`, `skip_bucket_ssencryption`, `skip_bucket_root_access`, `skip_bucket_enforced_tls`, `accesslogging_bucket_name`, `accesslogging_target_prefix`, and `enable_lock_table_ssencryption` are only valid for backend `s3`. They are used by terragrunt and are **not** passed on to terraform. See section [Create remote state and locking resources automatically](#create-remote-state-and-locking-resources-automatically). ### GCS-specific remote state settings diff --git a/docs/_docs/02_features/work-with-multiple-aws-accounts.md b/docs/_docs/02_features/work-with-multiple-aws-accounts.md index c2d9229fee..fbeb523de7 100644 --- a/docs/_docs/02_features/work-with-multiple-aws-accounts.md +++ b/docs/_docs/02_features/work-with-multiple-aws-accounts.md @@ -14,7 +14,7 @@ nav_title_link: /docs/ ### Motivation -The most secure way to manage infrastructure in AWS is to use [multiple AWS accounts](https://aws.amazon.com/answers/account-management/aws-multi-account-security-strategy/). You define all your IAM users in one account (e.g., the "security" account) and deploy all of your infrastructure into a number of other accounts (e.g., the "dev", "stage", and "prod" accounts). To access those accounts, you login to the security account and [assume an IAM role](http://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html) in the other accounts. +The most secure way to manage infrastructure in AWS is to use [multiple AWS accounts](https://aws.amazon.com/organizations/getting-started/best-practices/). You define all your IAM users in one account (e.g., the "security" account) and deploy all of your infrastructure into a number of other accounts (e.g., the "dev", "stage", and "prod" accounts). To access those accounts, you login to the security account and [assume an IAM role](http://docs.aws.amazon.com/cli/latest/userguide/cli-roles.html) in the other accounts. There are a few ways to assume IAM roles when using AWS CLI tools, such as Terraform: diff --git a/docs/_docs/03_community/contributing.md b/docs/_docs/03_community/contributing.md index 2aeadb6187..b1c3c06dd1 100644 --- a/docs/_docs/03_community/contributing.md +++ b/docs/_docs/03_community/contributing.md @@ -82,10 +82,10 @@ outlined in the guide. to include the following: 1. A description of the change, including a link to your GitHub issue. -1. The output of your automated test run, preferably in a [GitHub Gist](https://gist.github.com/). We cannot run - automated tests for pull requests automatically due to [security - concerns](https://circleci.com/docs/fork-pr-builds/#security-implications), so we need you to manually provide this - test output so we can verify that everything is working. +1. The output of your automated test run, preferably in a [GitHub Gist](https://gist.github.com/). + We cannot run automated tests for pull requests automatically due to + [security concerns](https://circleci.com/docs/2.0/oss/#pass-secrets-to-builds-from-forked-pull-requests), + so we need you to manually provide this test output so we can verify that everything is working. 1. Any notes on backwards incompatibility. ### Merge and release diff --git a/docs/_docs/04_reference/built-in-functions.md b/docs/_docs/04_reference/built-in-functions.md index 5bdba92f8d..9eff6f9258 100644 --- a/docs/_docs/04_reference/built-in-functions.md +++ b/docs/_docs/04_reference/built-in-functions.md @@ -52,6 +52,8 @@ Terragrunt allows you to use built-in functions anywhere in `terragrunt.hcl`, ju - [sops\_decrypt\_file()](#sops_decrypt_file) + - [get\_terragrunt\_source\_cli\_flag()](#get_terragrunt_source_cli_flag) + ## Terraform built-in functions All [Terraform built-in functions](https://www.terraform.io/docs/configuration/functions.html) are supported in Terragrunt config files: @@ -114,6 +116,25 @@ include { } ``` +Note that this function searches relative to the child `terragrunt.hcl` file when called from a parent config. For +example, if you had the following folder structure: + + ├── terragrunt.hcl + └── prod + ├── env.hcl + └── mysql + └── terragrunt.hcl + +And the root `terragrunt.hcl` contained the following: + + locals { + env_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) + } + +The `find_in_parent_folders` will search from the __child `terragrunt.hcl`__ (`prod/mysql/terragrunt.hcl`) config, +finding the `env.hcl` file in the `prod` directory. + + ## path\_relative\_to\_include `path_relative_to_include()` returns the relative path between the current `terragrunt.hcl` file and the `path` specified in its `include` block. For example, consider the following folder structure: @@ -610,3 +631,15 @@ inputs = merge( } ) ``` + +## get\_terragrunt\_source\_cli\_flag + +`get_terragrunt_source_cli_flag()` returns the value passed in via the CLI `--terragrunt-source` or an environment variable `TERRAGRUNT_SOURCE`. Note that this will return an empty string when either of those values are not provided. + +This is useful for constructing before and after hooks, or TF flags that only apply to local development (e.g., setting up debug flags, or adjusting the `iam_role` parameter). + +Some example use cases are: + +- Setting debug logging when doing local development. +- Adjusting the kubernetes provider configuration so that it targets minikube instead of real clusters. +- Providing special mocks pulled in from the local dev source (e.g., something like `mock_outputs = jsondecode(file("${get_terragrunt_source_cli_arg()}/dependency_mocks/vpc.json"))`). diff --git a/docs/_docs/04_reference/cli-options.md b/docs/_docs/04_reference/cli-options.md index 10336ddda9..b32cb42576 100644 --- a/docs/_docs/04_reference/cli-options.md +++ b/docs/_docs/04_reference/cli-options.md @@ -31,27 +31,28 @@ Terragrunt supports the following CLI commands: - [destroy-all (DEPRECATED: use run-all)](#destroy-all-deprecated-use-run-all) - [validate-all (DEPRECATED: use run-all)](#validate-all-deprecated-use-run-all) - [terragrunt-info](#terragrunt-info) + - [validate-inputs](#validate-inputs) - [graph-dependencies](#graph-dependencies) - [hclfmt](#hclfmt) - [aws-provider-patch](#aws-provider-patch) ### All Terraform built-in commands -Terragrunt is a thin wrapper for Terraform, so except for a few of the special commands defined in these docs, -Terragrunt forwards all other commands to Terraform. For example, when you run `terragrunt apply`, Terragrunt executes +Terragrunt is a thin wrapper for Terraform, so except for a few of the special commands defined in these docs, +Terragrunt forwards all other commands to Terraform. For example, when you run `terragrunt apply`, Terragrunt executes `terraform apply`. Examples: ```bash -terragrunt plan -terragrunt apply +terragrunt plan +terragrunt apply terragrunt output terragrunt destroy -# etc +# etc ``` -Run `terraform --help` to get the full list. +Run `terraform --help` to get the full list. ### run-all @@ -90,25 +91,25 @@ information](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment- **DEPRECATED: Use `run-all plan` instead.** -Display the plans of a 'stack' by running 'terragrunt plan' in each subfolder. Make sure to read [Execute Terraform -commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for +Display the plans of a 'stack' by running 'terragrunt plan' in each subfolder. Make sure to read [Execute Terraform +commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for context. Example: ```bash terragrunt plan-all -``` +``` This will recursively search the current working directory for any folders that contain Terragrunt modules and run -`plan` in each one, concurrently, while respecting ordering defined via +`plan` in each one, concurrently, while respecting ordering defined via [`dependency`](/docs/reference/config-blocks-and-attributes/#dependency) and -[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. +[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. -**[WARNING] `plan-all` is currently broken for certain use cases**. If you have a stack of Terragrunt modules with -dependencies between them—either via `dependency` blocks or `terraform_remote_state` data sources—and you've never -deployed them, then `plan-all` will fail as it will not be possible to resolve the `dependency` blocks or -`terraform_remote_state` data sources! Please [see here for more +**[WARNING] `plan-all` is currently broken for certain use cases**. If you have a stack of Terragrunt modules with +dependencies between them—either via `dependency` blocks or `terraform_remote_state` data sources—and you've never +deployed them, then `plan-all` will fail as it will not be possible to resolve the `dependency` blocks or +`terraform_remote_state` data sources! Please [see here for more information](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment-497888756). @@ -116,83 +117,83 @@ information](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment- **DEPRECATED: Use `run-all apply` instead.** -Apply a 'stack' by running 'terragrunt apply' in each subfolder. Make sure to read [Execute Terraform -commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for +Apply a 'stack' by running 'terragrunt apply' in each subfolder. Make sure to read [Execute Terraform +commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for context. Example: ```bash terragrunt apply-all -``` +``` This will recursively search the current working directory for any folders that contain Terragrunt modules and run -`apply` in each one, concurrently, while respecting ordering defined via +`apply` in each one, concurrently, while respecting ordering defined via [`dependency`](/docs/reference/config-blocks-and-attributes/#dependency) and -[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. +[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. ### output-all (DEPRECATED: use run-all) **DEPRECATED: Use `run-all output` instead.** -Display the outputs of a 'stack' by running 'terragrunt output' in each subfolder. Make sure to read [Execute Terraform -commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for +Display the outputs of a 'stack' by running 'terragrunt output' in each subfolder. Make sure to read [Execute Terraform +commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for context. Example: ```bash terragrunt output-all -``` +``` This will recursively search the current working directory for any folders that contain Terragrunt modules and run -`output` in each one, concurrently, while respecting ordering defined via +`output` in each one, concurrently, while respecting ordering defined via [`dependency`](/docs/reference/config-blocks-and-attributes/#dependency) and -[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. +[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. -**[WARNING] `output-all` is currently broken for certain use cases**. If you have a stack of Terragrunt modules with -dependencies between them—either via `dependency` blocks or `terraform_remote_state` data sources—and you've never -deployed them, then `output-all` will fail as it will not be possible to resolve the `dependency` blocks or -`terraform_remote_state` data sources! Please [see here for more +**[WARNING] `output-all` is currently broken for certain use cases**. If you have a stack of Terragrunt modules with +dependencies between them—either via `dependency` blocks or `terraform_remote_state` data sources—and you've never +deployed them, then `output-all` will fail as it will not be possible to resolve the `dependency` blocks or +`terraform_remote_state` data sources! Please [see here for more information](https://github.com/gruntwork-io/terragrunt/issues/720#issuecomment-497888756). ### destroy-all (DEPRECATED: use run-all) **DEPRECATED: Use `run-all destroy` instead.** -Destroy a 'stack' by running 'terragrunt destroy' in each subfolder. Make sure to read [Execute Terraform -commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for +Destroy a 'stack' by running 'terragrunt destroy' in each subfolder. Make sure to read [Execute Terraform +commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for context. Example: ```bash terragrunt destroy-all -``` +``` This will recursively search the current working directory for any folders that contain Terragrunt modules and run -`destroy` in each one, concurrently, while respecting ordering defined via +`destroy` in each one, concurrently, while respecting ordering defined via [`dependency`](/docs/reference/config-blocks-and-attributes/#dependency) and -[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. +[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. ### validate-all (DEPRECATED: use run-all) **DEPRECATED: Use `run-all validate` instead.** -Validate 'stack' by running 'terragrunt validate' in each subfolder. Make sure to read [Execute Terraform -commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for +Validate 'stack' by running 'terragrunt validate' in each subfolder. Make sure to read [Execute Terraform +commands on multiple modules at once](/docs/features/execute-terraform-commands-on-multiple-modules-at-once/) for context. Example: ```bash terragrunt validate-all -``` +``` This will recursively search the current working directory for any folders that contain Terragrunt modules and run -`validate` in each one, concurrently, while respecting ordering defined via +`validate` in each one, concurrently, while respecting ordering defined via [`dependency`](/docs/reference/config-blocks-and-attributes/#dependency) and -[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. +[`dependencies`](/docs/reference/config-blocks-and-attributes/#dependencies) blocks. ### terragrunt-info @@ -217,6 +218,51 @@ Might produce output such as: } ``` +### validate-inputs + +Emits information about the input variables that are configured with the given +terragrunt configuration. Specifically, this command will print out unused +inputs (inputs that are not defined as a terraform variable in the +corresponding module) and undefined required inputs (required terraform +variables that are not currently being passed in). + +Example: + +```bash +> terragrunt validate-inputs +The following inputs passed in by terragrunt are unused: + + - foo + - bar + + +The following required inputs are missing: + + - baz + +``` + +Note that this only checks for variables passed in in the following ways: + +- Configured `inputs` attribute. + +- var files defined on `terraform.extra_arguments` blocks using `required_var_files` and `optional_var_files`. + +- `-var-file` and `-var` CLI arguments defined on `terraform.extra_arguments` using `arguments`. + +- `-var-file` and `-var` CLI arguments passed to terragrunt. + +- Automatically loaded var files (`terraform.tfvars`, `terraform.tfvars.json`, `*.auto.tfvars`, `*.auto.tfvars.json`) + +- `TF_VAR` environment variables defined on `terraform.extra_arguments` blocks. + +- `TF_VAR` environment variables defined in the environment. + +Be aware that other ways to pass variables to `terraform` are not checked by this command. + +This command will exit with an error if terragrunt detects any unused inputs or undefined required inputs. + + ### graph-dependencies Prints the terragrunt dependency graph, in DOT format, to `stdout`. You can generate charts from DOT format using tools @@ -276,15 +322,15 @@ This will recursively search the current working directory for any folders that ### aws-provider-patch -Overwrite settings on nested AWS providers to work around several Terraform bugs. Due to +Overwrite settings on nested AWS providers to work around several Terraform bugs. Due to [issue #13018](https://github.com/hashicorp/terraform/issues/13018) and [issue #26211](https://github.com/hashicorp/terraform/issues/26211), the `import` command may fail if your Terraform -code uses a module that has a `provider` block nested within it that sets any of its attributes to computed values. -This command is a hacky attempt at working around this problem by allowing you to temporarily hard-code those -attributes so `import` can work. +code uses a module that has a `provider` block nested within it that sets any of its attributes to computed values. +This command is a hacky attempt at working around this problem by allowing you to temporarily hard-code those +attributes so `import` can work. -You specify which attributes to hard-code using the [`--terragrunt-override-attr`](#terragrunt-override-attr) option, -passing it `ATTR=VALUE`, where `ATTR` is the attribute name and `VALUE` is the new value. Note that `ATTR` can specify +You specify which attributes to hard-code using the [`--terragrunt-override-attr`](#terragrunt-override-attr) option, +passing it `ATTR=VALUE`, where `ATTR` is the attribute name and `VALUE` is the new value. Note that `ATTR` can specify attributes within a nested block by specifying `.`, where `` is the block name. For example, let's say you had a `provider` block in a module that looked like this: @@ -298,18 +344,18 @@ provider "aws" { ``` Both the `region` and `role_arn` parameters are set to dynamic values, which will trigger those Terraform bugs. To work -around it, run the following command: +around it, run the following command: ```bash terragrunt aws-provider-patch \ --terragrunt-override-attr region=eu-west-1 \ --terragrunt-override-attr assume_role.role_arn="" -``` +``` When you run the command above, Terragrunt will: 1. Run `terraform init` to download the code for all your modules into `.terraform/modules`. -1. Scan all the Terraform code in `.terraform/modules`, find AWS `provider` blocks, and for each one, hard-code: +1. Scan all the Terraform code in `.terraform/modules`, find AWS `provider` blocks, and for each one, hard-code: 1. The `region` param to `"eu-west-1"`. 1. The `role_arn` within the `assume_role` block to `""`. @@ -324,15 +370,15 @@ provider "aws" { } ``` -This should allow you to run `import` on the module and work around those Terraform bugs. When you're done running -`import`, remember to delete your overridden code! E.g., Delete the `.terraform` or `.terragrunt-cache` folders. +This should allow you to run `import` on the module and work around those Terraform bugs. When you're done running +`import`, remember to delete your overridden code! E.g., Delete the `.terraform` or `.terragrunt-cache` folders. ## CLI options -Terragrunt forwards all options to Terraform. The only exceptions are `--version` and arguments that start with the +Terragrunt forwards all options to Terraform. The only exceptions are `--version` and arguments that start with the prefix `--terragrunt-` (e.g., `--terragrunt-config`). The currently available options are: - [terragrunt-config](#terragrunt-config) @@ -407,9 +453,15 @@ When passed in, don't automatically retry commands which fail with transient err **CLI Arg**: `--terragrunt-non-interactive`
**Environment Variable**: `TF_INPUT` (set to `false`) -When passed in, don't show interactive user prompts. This will default the answer for all prompts to 'yes'. Useful if -you need to run Terragrunt in an automated setting (e.g. from a script). May also be specified with the -[TF\_INPUT](https://www.terraform.io/docs/configuration/environment-variables.html#tf_input) environment variable. +When passed in, don't show interactive user prompts. This will default the answer for all prompts to `yes` except for +the listed cases below. This is useful if you need to run Terragrunt in an automated setting (e.g. from a script). May +also be specified with the [TF\_INPUT](https://www.terraform.io/docs/configuration/environment-variables.html#tf_input) +environment variable. + +This setting will default to `no` for the following cases: + +- Prompts related to pulling in external dependencies. You can force include external dependencies using the + [--terragrunt-include-external-dependencies](#terragrunt-include-external-dependencies) option. ### terragrunt-working-dir @@ -590,7 +642,7 @@ When passed in, run `hclfmt` only on specified `*/terragrunt.hcl` file. **CLI Arg**: `--terragrunt-override-attr` **Requires an argument**: `--terragrunt-override-attr ATTR=VALUE` -Override the attribute named `ATTR` with the value `VALUE` in a `provider` block as part of the [aws-provider-patch +Override the attribute named `ATTR` with the value `VALUE` in a `provider` block as part of the [aws-provider-patch command](#aws-provider-patch). May be specified multiple times. Also, `ATTR` can specify attributes within a nested block by specifying `.`, where `` is the block name: e.g., `assume_role.role` arn will override the `role_arn` attribute of the `assume_role { ... }` block. diff --git a/docs/_docs/04_reference/config-blocks-and-attributes.md b/docs/_docs/04_reference/config-blocks-and-attributes.md index 63ca212d29..647b07a45c 100644 --- a/docs/_docs/04_reference/config-blocks-and-attributes.md +++ b/docs/_docs/04_reference/config-blocks-and-attributes.md @@ -58,6 +58,9 @@ The `terraform` block supports the following arguments: - `commands` (required) : A list of `terraform` sub commands for which the hook should run before. - `execute` (required) : A list of command and arguments that should be run as the hook. For example, if `execute` is set as `["echo", "Foo"]`, the command `echo Foo` will be run. + - `working_dir` (optional) : The path to set as the working directory of the hook. Terragrunt will switch directory + to this path prior to running the hook command. Defaults to the terragrunt configuration directory for + `terragrunt-read-config` and `init-from-module` hooks, and the terraform module directory for other command hooks. - `run_on_error` (optional) : If set to true, this hook will run even if a previous hook hit an error, or in the case of "after" hooks, if the Terraform command hit an error. Default is false. @@ -248,6 +251,7 @@ For the `s3` backend, the following additional properties are supported in the ` such as the CRC32 check for DynamoDB. This can be used to workaround https://github.com/gruntwork-io/terragrunt/issues/1059. - `accesslogging_bucket_name`: (Optional) When provided as a valid `string`, create an S3 bucket with this name to store the access logs for the S3 bucket used to store Terraform state. If not provided, or string is empty or invalid S3 bucket name, then server access logging for the S3 bucket storing the terraform state will be disabled. +- `accesslogging_target_prefix`: (Optional) When provided as a valid `string`, set the `TargetPrefix` for the access log objects in the S3 bucket used to store Terraform state. If set to **empty**`string`, then `TargetPrefix` will be set to **empty** `string`. If attribute is not provided at all, then `TargetPrefix` will be set to **default** value `TFStateLogs/`. This attribute won't take effect if the `accesslogging_bucket_name` attribute is not present. For the `gcs` backend, the following additional properties are supported in the `config` attribute: diff --git a/go.mod b/go.mod index 845bbf2d52..31d83ea6fd 100644 --- a/go.mod +++ b/go.mod @@ -4,29 +4,32 @@ go 1.13 require ( cloud.google.com/go/storage v1.10.0 - github.com/aws/aws-sdk-go v1.29.34 - github.com/creack/pty v1.1.9 - github.com/fatih/color v1.9.0 + github.com/agext/levenshtein v1.2.3 // indirect + github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect + github.com/aws/aws-sdk-go v1.37.7 + github.com/creack/pty v1.1.11 github.com/fatih/structs v1.1.0 github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 - github.com/gruntwork-io/terratest v0.30.26 + github.com/google/go-cmp v0.5.5 // indirect + github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf + github.com/gruntwork-io/terratest v0.32.6 github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02 github.com/hashicorp/go-version v1.2.0 - github.com/hashicorp/hcl/v2 v2.8.2 + github.com/hashicorp/hcl/v2 v2.9.1 github.com/hashicorp/terraform v0.12.24 - github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7 + github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34 github.com/hashicorp/vault v1.6.2 github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.2.2 github.com/sirupsen/logrus v1.6.0 github.com/stretchr/testify v1.5.1 github.com/urfave/cli v1.22.3 - github.com/zclconf/go-cty v1.3.1 + github.com/zclconf/go-cty v1.8.1 go.mozilla.org/sops/v3 v3.6.1 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f google.golang.org/api v0.35.0 - gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 3e177f02cd..6d9bace0d3 100644 --- a/go.sum +++ b/go.sum @@ -11,7 +11,6 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= @@ -21,24 +20,20 @@ cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0 h1:xE3CPsOgttP4ACBePh79zTKALtXwn/Edhcr16R5hMWU= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/spanner v1.5.1/go.mod h1:e1+8M6PF3ntV9Xr57X2Gf+UhylXXYF6gI4WRZ1kfu2A= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= @@ -62,7 +57,6 @@ github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW github.com/Azure/go-autorest/autorest v0.1.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.2/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.3 h1:OZEIaBbMdUE/Js+BQKlpO81XlISgipr6yDJ+PSwsgi4= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.10.1/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= @@ -77,7 +71,6 @@ github.com/Azure/go-autorest/autorest/adal v0.6.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S github.com/Azure/go-autorest/autorest/adal v0.7.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1-0.20191028180845-3492b2aff503/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/adal v0.8.1 h1:pZdL8o72rK+avFWl+p9nE8RWi1JInZrWJYlnpfXJwHk= github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= @@ -98,13 +91,11 @@ github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9 github.com/Azure/go-autorest/autorest/azure/cli v0.4.0 h1:Ml+UCrnlKD+cJmSzrZ/RDcDw86NjkRUpnFh7V5JUhzU= github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= @@ -115,21 +106,17 @@ github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsI github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= -github.com/Azure/go-autorest/autorest/validation v0.2.0 h1:15vMO4y76dehZSq7pAaOLQxC6dZYsSrj2GQpflyM/L4= github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/autorest/validation v0.3.0 h1:3I9AAI63HfcLtphd9g39ruUwRI+Ca+z/f36KHPFRUss= github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= -github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= @@ -164,6 +151,8 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= +github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agl/ed25519 v0.0.0-20150830182803-278e1ec8e8a6/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -189,6 +178,8 @@ github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2 github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-versions v0.0.2-0.20180815153302-64b99f7cb171/go.mod h1:JXY95WvQrPJQtudvNARshgWajS7jNNlM90altXIPNyI= github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2/go.mod h1:OMVSB21p9+xQUIqlGizHPZfjK+SHws1ht+ZytVDoz9U= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -213,13 +204,8 @@ github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.29.34 h1:yrzwfDaZFe9oT4AmQeNNunSQA7c0m2chz0B43+bJ1ok= -github.com/aws/aws-sdk-go v1.29.34/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= -github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.33.18/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk= -github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go v1.37.7 h1:vfald/ssuWaA2HgJ9DrieVVXVE9eD0Kly/9kl0hofbE= +github.com/aws/aws-sdk-go v1.37.7/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -300,8 +286,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -407,10 +393,8 @@ github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8 github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -452,9 +436,6 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -476,7 +457,6 @@ github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= @@ -497,13 +477,14 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-metrics-stackdriver v0.2.0/go.mod h1:KLcPyp3dWJAFD+yHisGlJSZktIsTjb50eB72U2YZ9K0= @@ -525,6 +506,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= @@ -566,9 +548,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/gruntwork-io/gruntwork-cli v0.7.0 h1:YgSAmfCj9c61H+zuvHwKfYUwlMhu5arnQQLM4RH+CYs= github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= -github.com/gruntwork-io/terratest v0.30.26 h1:0nNTfmYl5ohvKtPot7j5jwKhG1j7EJAO3ixi0TbVmH0= -github.com/gruntwork-io/terratest v0.30.26/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/gruntwork-io/terratest v0.32.6 h1:OEA11ZqEwKRowEdxusDnAPnMUN0w/jzeNcziuQsqkYk= +github.com/gruntwork-io/terratest v0.32.6/go.mod h1:0iy7d56CziX3R4ZUn570HMElr4WgBKoKNa8Hzex7bvo= github.com/hashicorp/aws-sdk-go-base v0.4.0/go.mod h1:eRhlz3c4nhqxFZJAahJEFL7gh6Jyj5rQmQc7F9eHFyQ= github.com/hashicorp/consul v0.0.0-20171026175957-610f3c86a089/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI= github.com/hashicorp/consul-template v0.25.1/go.mod h1:/vUsrJvDuuQHcxEw0zik+YXTS7ZKWZjQeaQhshBmfH0= @@ -611,7 +592,6 @@ github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uP github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-plugin v1.0.0/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-plugin v1.0.1-0.20190610192547-a1bc61569a26/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-raftchunking v0.6.3-0.20191002164813-7e9e8525653a/go.mod h1:xbXnmKqX9/+RhPkJ4zrEx4738HacP72aaUPlT2RZ4sU= @@ -657,10 +637,11 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T github.com/hashicorp/hcl v1.0.1-vault h1:UiJeEzCWAYdVaJr8Xo4lBkTozlW1+1yxVUnpbS1xVEk= github.com/hashicorp/hcl v1.0.1-vault/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90= -github.com/hashicorp/hcl/v2 v2.3.0 h1:iRly8YaMwTBAKhn1Ybk7VSdzbnopghktCD031P8ggUE= github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY= github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= +github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac= +github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -681,6 +662,8 @@ github.com/hashicorp/terraform v0.12.24 h1:lTTswsCcmTOhTwuUl2NdjtJBCNdGqZmRGQi0c github.com/hashicorp/terraform v0.12.24/go.mod h1:eJcloDEx5ywM4a1tetIuVrlqklM0bUVRYJBYAh4CYzA= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7 h1:Pc5TCv9mbxFN6UVX0LH6CpQrdTM5YjbVI2w15237Pjk= github.com/hashicorp/terraform-config-inspect v0.0.0-20191212124732-c6ae6269b9d7/go.mod h1:p+ivJws3dpqbp1iP84+npOyAmTTOLMgCzrXd3GSdn/A= +github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34 h1:y4kOB9aYVSsJWVqewwUZmHxPSNjkDbOeW7eb9yFIc3Q= +github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34/go.mod h1:Z0Nnk4+3Cy89smEbrq+sl1bxc9198gIP4I7wcQF6Kqs= github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596 h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg= github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= github.com/hashicorp/vault v0.10.4/go.mod h1:KfSyffbKxoVyspOdlaGVjIuwLobi07qD1bAbosPMpP0= @@ -763,11 +746,10 @@ github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f/go.mod h1:3J2 github.com/jefferai/jsonx v1.0.0/go.mod h1:OGmqmi2tTeI/PS+qQfBDToLHHJIy/RMp24fPo8vFvoQ= github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= @@ -806,12 +788,10 @@ github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -900,8 +880,8 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= @@ -1097,7 +1077,6 @@ github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -1126,6 +1105,7 @@ github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bd github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= @@ -1176,7 +1156,8 @@ github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44 github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.1+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= @@ -1199,6 +1180,10 @@ github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= github.com/zclconf/go-cty v1.3.1 h1:QIOZl+CKKdkv4l2w3lG23nNzXgLoxsWLSEdg1MlX4p0= github.com/zclconf/go-cty v1.3.1/go.mod h1:YO23e2L18AG+ZYQfSobnY4G65nvwvprPCxBHkufUH1k= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.8.1 h1:SI0LqNeNxAgv2WWqWJMlG2/Ad/6aYJ7IVYYMigmfkuI= +github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8= github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -1222,7 +1207,6 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1279,7 +1263,6 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -1293,7 +1276,6 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -1303,7 +1285,6 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -1341,7 +1322,6 @@ golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0 h1:MsuvTghUPjX762sGLnGsxC3HM0B5r83wEtYcYR8/vRs= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1354,8 +1334,9 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1364,7 +1345,6 @@ golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1374,7 +1354,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= @@ -1434,7 +1413,6 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1450,19 +1428,19 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1519,7 +1497,6 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2 h1:L/G4KZvrQn7FWLN/LlulBtBzrLUhqjiGfTWWDmrh+IQ= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= @@ -1540,7 +1517,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41Z golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1564,7 +1540,6 @@ google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= @@ -1581,7 +1556,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -1607,7 +1581,6 @@ google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt37+h7X16BWQbad7Q4S6gclTKFXM8= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1643,7 +1616,6 @@ google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRn google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= @@ -1667,7 +1639,6 @@ gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1704,7 +1675,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1723,7 +1693,6 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.0.0-20190409092523-d687e77c8ae9/go.mod h1:FQEUn50aaytlU65qqBn/w+5ugllHwrBzKm7DzbnXdzE= diff --git a/remote/remote_state_s3.go b/remote/remote_state_s3.go index 51069d14d0..21437dafb3 100644 --- a/remote/remote_state_s3.go +++ b/remote/remote_state_s3.go @@ -21,7 +21,8 @@ import ( ) const ( - lockTableDeprecationMessage = "Remote state configuration 'lock_table' attribute is deprecated; use 'dynamodb_table' instead." + lockTableDeprecationMessage = "Remote state configuration 'lock_table' attribute is deprecated; use 'dynamodb_table' instead." + DefaultS3BucketAccessLoggingTargetPrefix = "TFStateLogs/" ) /* @@ -42,6 +43,7 @@ type ExtendedRemoteStateConfigS3 struct { EnableLockTableSSEncryption bool `mapstructure:"enable_lock_table_ssencryption"` DisableAWSClientChecksums bool `mapstructure:"disable_aws_client_checksums"` AccessLoggingBucketName string `mapstructure:"accesslogging_bucket_name"` + AccessLoggingTargetPrefix string `mapstructure:"accesslogging_target_prefix"` } // These are settings that can appear in the remote_state config that are ONLY used by Terragrunt and NOT forwarded @@ -57,6 +59,7 @@ var terragruntOnlyConfigs = []string{ "enable_lock_table_ssencryption", "disable_aws_client_checksums", "accesslogging_bucket_name", + "accesslogging_target_prefix", } // A representation of the configuration options available for S3 remote state @@ -66,6 +69,7 @@ type RemoteStateConfigS3 struct { Key string `mapstructure:"key"` Region string `mapstructure:"region"` Endpoint string `mapstructure:"endpoint"` + DynamoDBEndpoint string `mapstructure:"dynamodb_endpoint"` Profile string `mapstructure:"profile"` RoleArn string `mapstructure:"role_arn"` ExternalID string `mapstructure:"external_id"` @@ -81,6 +85,7 @@ func (c *ExtendedRemoteStateConfigS3) GetAwsSessionConfig() *aws_helper.AwsSessi return &aws_helper.AwsSessionConfig{ Region: c.remoteStateConfigS3.Region, CustomS3Endpoint: c.remoteStateConfigS3.Endpoint, + CustomDynamoDBEndpoint: c.remoteStateConfigS3.DynamoDBEndpoint, Profile: c.remoteStateConfigS3.Profile, RoleArn: c.remoteStateConfigS3.RoleArn, ExternalID: c.remoteStateConfigS3.ExternalID, @@ -313,6 +318,11 @@ func parseExtendedS3Config(config map[string]interface{}) (*ExtendedRemoteStateC return nil, errors.WithStackTrace(err) } + _, targetPrefixExists := config["accesslogging_target_prefix"] + if !targetPrefixExists { + extendedConfig.AccessLoggingTargetPrefix = DefaultS3BucketAccessLoggingTargetPrefix + } + extendedConfig.remoteStateConfigS3 = s3Config return &extendedConfig, nil @@ -448,7 +458,7 @@ func CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(s3Client *s3.S3, c return err } - if err := EnableAccessLoggingForS3BucketWide(s3Client, &config.remoteStateConfigS3, terragruntOptions, config.AccessLoggingBucketName); err != nil { + if err := EnableAccessLoggingForS3BucketWide(s3Client, &config.remoteStateConfigS3, terragruntOptions, config.AccessLoggingBucketName, config.AccessLoggingTargetPrefix); err != nil { return err } } else { @@ -674,20 +684,19 @@ func EnableSSEForS3BucketWide(s3Client *s3.S3, config *RemoteStateConfigS3, terr } // Enable bucket-wide Access Logging for the AWS S3 bucket specified in the given config -func EnableAccessLoggingForS3BucketWide(s3Client *s3.S3, config *RemoteStateConfigS3, terragruntOptions *options.TerragruntOptions, logsBucket string) error { +func EnableAccessLoggingForS3BucketWide(s3Client *s3.S3, config *RemoteStateConfigS3, terragruntOptions *options.TerragruntOptions, logsBucket string, logsBucketPrefix string) error { if err := configureBucketAccessLoggingAcl(s3Client, aws.String(logsBucket), terragruntOptions); err != nil { return errors.WithStackTrace(err) } - targetPrefix := "TFStateLogs/" - terragruntOptions.Logger.Debugf("Putting bucket logging on S3 bucket %s with TargetBucket %s and TargetPrefix %s", config.Bucket, logsBucket, targetPrefix) + terragruntOptions.Logger.Debugf("Putting bucket logging on S3 bucket %s with TargetBucket %s and TargetPrefix %s", config.Bucket, logsBucket, logsBucketPrefix) loggingInput := s3.PutBucketLoggingInput{ Bucket: aws.String(config.Bucket), BucketLoggingStatus: &s3.BucketLoggingStatus{ LoggingEnabled: &s3.LoggingEnabled{ TargetBucket: aws.String(logsBucket), - TargetPrefix: aws.String(targetPrefix), + TargetPrefix: aws.String(logsBucketPrefix), }, }, } diff --git a/remote/remote_state_s3_test.go b/remote/remote_state_s3_test.go index cdab481627..e9acbc8a37 100644 --- a/remote/remote_state_s3_test.go +++ b/remote/remote_state_s3_test.go @@ -185,7 +185,7 @@ func TestGetAwsSessionConfig(t *testing.T) { }, { "extra-values", - map[string]interface{}{"something": "unexpected", "region": "foo", "endpoint": "bar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "force_path_style": false}, + map[string]interface{}{"something": "unexpected", "region": "foo", "endpoint": "bar", "dynamodb_endpoint": "foobar", "profile": "baz", "role_arn": "arn::it", "shared_credentials_file": "my-file", "force_path_style": false}, }, } @@ -203,6 +203,7 @@ func TestGetAwsSessionConfig(t *testing.T) { expected := &aws_helper.AwsSessionConfig{ Region: s3ConfigExtended.remoteStateConfigS3.Region, CustomS3Endpoint: s3ConfigExtended.remoteStateConfigS3.Endpoint, + CustomDynamoDBEndpoint: s3ConfigExtended.remoteStateConfigS3.DynamoDBEndpoint, Profile: s3ConfigExtended.remoteStateConfigS3.Profile, RoleArn: s3ConfigExtended.remoteStateConfigS3.RoleArn, CredsFilename: s3ConfigExtended.remoteStateConfigS3.CredsFilename, @@ -278,6 +279,7 @@ func TestGetTerraformInitArgs(t *testing.T) { "enable_lock_table_ssencryption": true, "disable_aws_client_checksums": false, "accesslogging_bucket_name": "test", + "accesslogging_target_prefix": "test", }, map[string]interface{}{}, true, diff --git a/test/fixture-get-terragrunt-source-cli/terraform_config_cli/main.tf b/test/fixture-get-terragrunt-source-cli/terraform_config_cli/main.tf new file mode 100644 index 0000000000..55f742016b --- /dev/null +++ b/test/fixture-get-terragrunt-source-cli/terraform_config_cli/main.tf @@ -0,0 +1,7 @@ +variable "terragrunt_source" { + type = string +} + +output "terragrunt_source" { + value = "CLI: ${var.terragrunt_source}" +} diff --git a/test/fixture-get-terragrunt-source-cli/terragrunt.hcl b/test/fixture-get-terragrunt-source-cli/terragrunt.hcl new file mode 100644 index 0000000000..cf552d3b2e --- /dev/null +++ b/test/fixture-get-terragrunt-source-cli/terragrunt.hcl @@ -0,0 +1,3 @@ +inputs = { + terragrunt_source = get_terragrunt_source_cli_flag() +} diff --git a/test/fixture-get-terragrunt-source-hcl/terraform_config_hcl/main.tf b/test/fixture-get-terragrunt-source-hcl/terraform_config_hcl/main.tf new file mode 100644 index 0000000000..6503bb265d --- /dev/null +++ b/test/fixture-get-terragrunt-source-hcl/terraform_config_hcl/main.tf @@ -0,0 +1,7 @@ +variable "terragrunt_source" { + type = string +} + +output "terragrunt_source" { + value = "HCL: ${var.terragrunt_source}" +} diff --git a/test/fixture-get-terragrunt-source-hcl/terragrunt.hcl b/test/fixture-get-terragrunt-source-hcl/terragrunt.hcl new file mode 100644 index 0000000000..f1a0962ce9 --- /dev/null +++ b/test/fixture-get-terragrunt-source-hcl/terragrunt.hcl @@ -0,0 +1,7 @@ +inputs = { + terragrunt_source = get_terragrunt_source_cli_flag() +} + +terraform { + source = "./terraform_config_hcl" +} diff --git a/test/fixture-hooks/working_dir/main.tf b/test/fixture-hooks/working_dir/main.tf new file mode 100644 index 0000000000..e87b21f0c2 --- /dev/null +++ b/test/fixture-hooks/working_dir/main.tf @@ -0,0 +1,3 @@ +output "example" { + value = "hello world" +} diff --git a/test/fixture-hooks/working_dir/mydir/hello_world b/test/fixture-hooks/working_dir/mydir/hello_world new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixture-hooks/working_dir/terragrunt.hcl b/test/fixture-hooks/working_dir/terragrunt.hcl new file mode 100644 index 0000000000..250c698b11 --- /dev/null +++ b/test/fixture-hooks/working_dir/terragrunt.hcl @@ -0,0 +1,7 @@ +terraform { + before_hook "before_hook" { + commands = ["validate"] + execute = ["ls", "hello_world"] + working_dir = "${get_terragrunt_dir()}/mydir" + } +} diff --git a/test/fixture-regressions/accesslogging-bucket-name/.gitignore b/test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/.gitignore similarity index 100% rename from test/fixture-regressions/accesslogging-bucket-name/.gitignore rename to test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/.gitignore diff --git a/test/fixture-regressions/accesslogging-bucket-name/local_terragrunt.hcl b/test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/local_terragrunt.hcl similarity index 100% rename from test/fixture-regressions/accesslogging-bucket-name/local_terragrunt.hcl rename to test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/local_terragrunt.hcl diff --git a/test/fixture-regressions/accesslogging-bucket-name/main.tf b/test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/main.tf similarity index 100% rename from test/fixture-regressions/accesslogging-bucket-name/main.tf rename to test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/main.tf diff --git a/test/fixture-regressions/accesslogging-bucket-name/remote_terragrunt.hcl b/test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/remote_terragrunt.hcl similarity index 100% rename from test/fixture-regressions/accesslogging-bucket-name/remote_terragrunt.hcl rename to test/fixture-regressions/accesslogging-bucket/no-target-prefix-input/remote_terragrunt.hcl diff --git a/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/.gitignore b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/.gitignore new file mode 100644 index 0000000000..79655ca151 --- /dev/null +++ b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/.gitignore @@ -0,0 +1 @@ +backend.tf diff --git a/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/local_terragrunt.hcl b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/local_terragrunt.hcl new file mode 100644 index 0000000000..bb7b160deb --- /dev/null +++ b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/local_terragrunt.hcl @@ -0,0 +1 @@ +# Intentionally empty diff --git a/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/main.tf b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/main.tf new file mode 100644 index 0000000000..3911a2a9b2 --- /dev/null +++ b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/main.tf @@ -0,0 +1 @@ +resource "null_resource" "foo" {} diff --git a/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/remote_terragrunt.hcl b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/remote_terragrunt.hcl new file mode 100644 index 0000000000..2ae108e2b2 --- /dev/null +++ b/test/fixture-regressions/accesslogging-bucket/with-target-prefix-input/remote_terragrunt.hcl @@ -0,0 +1,18 @@ +# Configure Terragrunt to automatically store tfstate files in an S3 bucket +remote_state { + backend = "s3" + generate = { + path = "backend.tf" + if_exists = "overwrite" + } + config = { + encrypt = true + bucket = "__FILL_IN_BUCKET_NAME__" + key = "terraform.tfstate" + region = "us-west-2" + dynamodb_table = "__FILL_IN_LOCK_TABLE_NAME__" + enable_lock_table_ssencryption = true + accesslogging_bucket_name = "__FILL_IN_LOGS_BUCKET_NAME__" + accesslogging_target_prefix = "logs/" + } +} diff --git a/test/fixture-validate-inputs/fail-generated-var/main.tf b/test/fixture-validate-inputs/fail-generated-var/main.tf new file mode 100644 index 0000000000..538cc40690 --- /dev/null +++ b/test/fixture-validate-inputs/fail-generated-var/main.tf @@ -0,0 +1,3 @@ +output "output" { + value = var.input +} diff --git a/test/fixture-validate-inputs/fail-generated-var/terragrunt.hcl b/test/fixture-validate-inputs/fail-generated-var/terragrunt.hcl new file mode 100644 index 0000000000..158d49ff87 --- /dev/null +++ b/test/fixture-validate-inputs/fail-generated-var/terragrunt.hcl @@ -0,0 +1,7 @@ +generate "variables" { + path = "variables.tf" + if_exists = "overwrite_terragrunt" + contents = <