diff --git a/examples/kms/key.tf b/examples/kms/key.tf index bf36393670c..f273ba3ef81 100644 --- a/examples/kms/key.tf +++ b/examples/kms/key.tf @@ -3,9 +3,10 @@ resource "oci_kms_key" "test_key" { #Required - compartment_id = var.compartment_id - display_name = var.key_display_name - management_endpoint = data.oci_kms_vault.test_vault.management_endpoint + compartment_id = var.compartment_id + display_name = var.key_display_name + management_endpoint = data.oci_kms_vault.test_vault.management_endpoint + schedule_deletion_days = var.schedule_deletion_days key_shape { #Required diff --git a/examples/kms/keyVersion.tf b/examples/kms/keyVersion.tf index d5d731aa7d4..9461f902570 100644 --- a/examples/kms/keyVersion.tf +++ b/examples/kms/keyVersion.tf @@ -2,4 +2,5 @@ resource "oci_kms_key_version" "test_key_version" { #Required key_id = oci_kms_key.test_key.id management_endpoint = data.oci_kms_vault.test_vault.management_endpoint + schedule_deletion_days = var.schedule_deletion_days } \ No newline at end of file diff --git a/examples/kms/variables.tf b/examples/kms/variables.tf index 08f284e9f12..4c29066eddd 100644 --- a/examples/kms/variables.tf +++ b/examples/kms/variables.tf @@ -107,3 +107,8 @@ variable "key_restore_trigger" { variable "vault_restore_trigger" { default = false } + +variable "schedule_deletion_days" { + type = number + default = 30 +} diff --git a/examples/kms/vault.tf b/examples/kms/vault.tf index 01ad035d8b0..4bf731c9e3c 100644 --- a/examples/kms/vault.tf +++ b/examples/kms/vault.tf @@ -4,6 +4,6 @@ resource "oci_kms_vault" "private-vault-kms" { display_name = var.vault_display_name vault_type = var.vault_type[0] -} - + schedule_deletion_days = var.schedule_deletion_days +} diff --git a/examples/vault_secret/main.tf b/examples/vault_secret/main.tf index 4b8859a2193..819a71d9c9f 100644 --- a/examples/vault_secret/main.tf +++ b/examples/vault_secret/main.tf @@ -52,6 +52,7 @@ resource "oci_vault_secret" "test_secret" { key_id = var.kms_key_ocid secret_name = "TFsample1" vault_id = var.kms_vault_ocid + schedule_deletion_days = 30 } diff --git a/go.mod b/go.mod index 9941522660e..783060fcdeb 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/hcl2 v0.0.0-20190618163856-0b64543c968c - github.com/hashicorp/terraform-exec v0.14.0 + github.com/hashicorp/terraform-exec v0.15.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 github.com/stretchr/testify v1.8.4 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 @@ -38,7 +38,7 @@ require ( github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/hcl/v2 v2.8.2 // indirect github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-json v0.12.0 // indirect + github.com/hashicorp/terraform-json v0.13.0 // indirect github.com/hashicorp/terraform-plugin-go v0.3.0 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -58,7 +58,7 @@ require ( github.com/sony/gobreaker v0.5.0 // indirect github.com/ulikunitz/xz v0.5.8 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - github.com/zclconf/go-cty v1.8.4 // indirect + github.com/zclconf/go-cty v1.9.1 // indirect go.opencensus.io v0.22.4 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect diff --git a/go.sum b/go.sum index 080c496c417..23948af1cc8 100644 --- a/go.sum +++ b/go.sum @@ -206,8 +206,14 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/terraform-exec v0.14.0 h1:UQoUcxKTZZXhyyK68Cwn4mApT4mnFPmEXPiqaHL9r+w= github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA= +github.com/hashicorp/terraform-exec v0.15.0 h1:cqjh4d8HYNQrDoEmlSGelHmg2DYDh5yayckvJ5bV18E= +github.com/hashicorp/terraform-exec v0.15.0/go.mod h1:H4IG8ZxanU+NW0ZpDRNsvh9f0ul7C0nHP+rUR/CHs7I= +github.com/hashicorp/terraform-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw= github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI= +github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY= +github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk= github.com/hashicorp/terraform-plugin-go v0.3.0 h1:AJqYzP52JFYl9NABRI7smXI1pNjgR5Q/y2WyVJ/BOZA= github.com/hashicorp/terraform-plugin-go v0.3.0/go.mod h1:dFHsQMaTLpON2gWhVWT96fvtlc/MF1vSy3OdMhWBzdM= github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 h1:SuI59MqNjYDrL7EfqHX9V6P/24isgqYx/FdglwVs9bg= @@ -340,6 +346,8 @@ 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.8.4 h1:pwhhz5P+Fjxse7S7UriBrMu6AUJSZM5pKqGem1PjGAs= github.com/zclconf/go-cty v1.8.4/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.9.1 h1:viqrgQwFl5UpSxc046qblj78wZXVDFnSOufaOTER+cc= +github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= diff --git a/internal/service/kms/kms_key_resource.go b/internal/service/kms/kms_key_resource.go index 55ff5bfc0f5..45f00325046 100644 --- a/internal/service/kms/kms_key_resource.go +++ b/internal/service/kms/kms_key_resource.go @@ -141,6 +141,11 @@ func KmsKeyResource() *schema.Resource { Computed: true, Optional: true, }, + "schedule_deletion_days": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(7, 30), + }, "restore_from_object_store": { Type: schema.TypeList, Optional: true, @@ -622,6 +627,14 @@ func (s *KmsKeyResourceCrud) Delete() error { return err } request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } else { + if scheduleDeletionDays, ok := s.D.Get("schedule_deletion_days").(int); ok { + // Not setting TimeOfDeletion is the same as specifying 30 days, so skip it on 30 days + if scheduleDeletionDays < 30 { + tmpTime := time.Now().AddDate(0, 0, scheduleDeletionDays) + request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } + } } request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms") diff --git a/internal/service/kms/kms_key_version_resource.go b/internal/service/kms/kms_key_version_resource.go index 7a8b32cf8cb..95aae8773b0 100644 --- a/internal/service/kms/kms_key_version_resource.go +++ b/internal/service/kms/kms_key_version_resource.go @@ -6,6 +6,7 @@ package kms import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "strconv" "strings" "time" @@ -59,6 +60,12 @@ func KmsKeyVersionResource() *schema.Resource { Optional: true, Computed: true, }, + "schedule_deletion_days": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validation.IntBetween(7, 30), + }, // Computed "compartment_id": { @@ -319,6 +326,14 @@ func (s *KmsKeyVersionResourceCrud) Delete() error { return err } request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } else { + if scheduleDeletionDays, ok := s.D.Get("schedule_deletion_days").(int); ok { + // Not setting TimeOfDeletion is the same as specifying 30 days, so skip it on 30 days + if scheduleDeletionDays < 30 { + tmpTime := time.Now().AddDate(0, 0, scheduleDeletionDays) + request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } + } } request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms") diff --git a/internal/service/kms/kms_vault_resource.go b/internal/service/kms/kms_vault_resource.go index 142690645e0..d7a88cac4ae 100644 --- a/internal/service/kms/kms_vault_resource.go +++ b/internal/service/kms/kms_vault_resource.go @@ -127,6 +127,11 @@ func KmsVaultResource() *schema.Resource { Optional: true, Computed: true, }, + "schedule_deletion_days": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(7, 30), + }, "restore_from_object_store": { Type: schema.TypeList, Optional: true, @@ -518,6 +523,14 @@ func (s *KmsVaultResourceCrud) Delete() error { return err } request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } else { + if scheduleDeletionDays, ok := s.D.Get("schedule_deletion_days").(int); ok { + // Not setting TimeOfDeletion is the same as specifying 30 days, so skip it on 30 days + if scheduleDeletionDays < 30 { + tmpTime := time.Now().AddDate(0, 0, scheduleDeletionDays) + request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } + } } request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "kms") diff --git a/internal/service/vault/vault_secret_resource.go b/internal/service/vault/vault_secret_resource.go index cdaf31f1173..7dc1d2b519d 100644 --- a/internal/service/vault/vault_secret_resource.go +++ b/internal/service/vault/vault_secret_resource.go @@ -119,6 +119,11 @@ func VaultSecretResource() *schema.Resource { Computed: true, Elem: schema.TypeString, }, + "schedule_deletion_days": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(1, 30), + }, "secret_rules": { Type: schema.TypeList, Optional: true, @@ -452,6 +457,14 @@ func (s *VaultSecretResourceCrud) Delete() error { tmp := s.D.Id() request.SecretId = &tmp + if scheduleDeletionDays, ok := s.D.Get("schedule_deletion_days").(int); ok { + // Not setting TimeOfDeletion is the same as specifying 30 days, so skip it on 30 days + if scheduleDeletionDays < 30 { + tmpTime := time.Now().AddDate(0, 0, scheduleDeletionDays) + request.TimeOfDeletion = &oci_common.SDKTime{Time: tmpTime} + } + } + request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "vault") _, err := s.Client.ScheduleSecretDeletion(context.Background(), request) diff --git a/vendor/github.com/hashicorp/terraform-exec/internal/version/version.go b/vendor/github.com/hashicorp/terraform-exec/internal/version/version.go index 4d43e000bbb..cf2c1a1f322 100644 --- a/vendor/github.com/hashicorp/terraform-exec/internal/version/version.go +++ b/vendor/github.com/hashicorp/terraform-exec/internal/version/version.go @@ -1,6 +1,6 @@ package version -const version = "0.14.0" +const version = "0.15.0" // ModuleVersion returns the current version of the github.com/hashicorp/terraform-exec Go module. // This is a function to allow for future possible enhancement using debug.BuildInfo. diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/add.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/add.go new file mode 100644 index 00000000000..0e60034e493 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/add.go @@ -0,0 +1,101 @@ +package tfexec + +import ( + "context" + "fmt" + "os/exec" + "strconv" + "strings" +) + +type addConfig struct { + fromState bool + out string + includeOptional bool + provider string + reattachInfo ReattachInfo +} + +var defaultAddOptions = addConfig{} + +type AddOption interface { + configureAdd(*addConfig) +} + +func (opt *FromStateOption) configureAdd(conf *addConfig) { + conf.fromState = opt.fromState +} + +func (opt *OutOption) configureAdd(conf *addConfig) { + conf.out = opt.path +} + +func (opt *IncludeOptionalOption) configureAdd(conf *addConfig) { + conf.includeOptional = opt.includeOptional +} + +func (opt *ProviderOption) configureAdd(conf *addConfig) { + conf.provider = opt.provider +} + +func (opt *ReattachOption) configureAdd(conf *addConfig) { + conf.reattachInfo = opt.info +} + +// Add represents the `terraform add` subcommand (added in 1.1.0). +// +// Note that this function signature and behaviour is subject +// to breaking changes including removal of that function +// until final 1.1.0 Terraform version (with this command) is released. +func (tf *Terraform) Add(ctx context.Context, address string, opts ...AddOption) (string, error) { + cmd, err := tf.addCmd(ctx, address, opts...) + if err != nil { + return "", err + } + + var outBuf strings.Builder + cmd.Stdout = mergeWriters(cmd.Stdout, &outBuf) + + if err := tf.runTerraformCmd(ctx, cmd); err != nil { + return "", err + } + + return outBuf.String(), nil +} + +func (tf *Terraform) addCmd(ctx context.Context, address string, opts ...AddOption) (*exec.Cmd, error) { + err := tf.compatible(ctx, tf1_1_0, nil) + if err != nil { + return nil, fmt.Errorf("terraform add was added in 1.1.0: %w", err) + } + + c := defaultAddOptions + + for _, o := range opts { + o.configureAdd(&c) + } + + args := []string{"add"} + + args = append(args, "-from-state="+strconv.FormatBool(c.fromState)) + if c.out != "" { + args = append(args, "-out="+c.out) + } + args = append(args, "-optional="+strconv.FormatBool(c.includeOptional)) + if c.provider != "" { + args = append(args, "-provider="+c.provider) + } + + args = append(args, address) + + mergeEnv := map[string]string{} + if c.reattachInfo != nil { + reattachStr, err := c.reattachInfo.marshalString() + if err != nil { + return nil, err + } + mergeEnv[reattachEnvVar] = reattachStr + } + + return tf.buildTerraformCmd(ctx, mergeEnv, args...), nil +} diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/apply.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/apply.go index 82d09d5fc75..40d9e69b9f7 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/apply.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/apply.go @@ -17,6 +17,7 @@ type applyConfig struct { parallelism int reattachInfo ReattachInfo refresh bool + replaceAddrs []string state string stateOut string targets []string @@ -73,6 +74,10 @@ func (opt *RefreshOption) configureApply(conf *applyConfig) { conf.refresh = opt.refresh } +func (opt *ReplaceOption) configureApply(conf *applyConfig) { + conf.replaceAddrs = append(conf.replaceAddrs, opt.address) +} + func (opt *VarOption) configureApply(conf *applyConfig) { conf.vars = append(conf.vars, opt.assignment) } @@ -126,6 +131,15 @@ func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) (*exec.C args = append(args, "-refresh="+strconv.FormatBool(c.refresh)) // string slice opts: split into separate args + if c.replaceAddrs != nil { + err := tf.compatible(ctx, tf0_15_2, nil) + if err != nil { + return nil, fmt.Errorf("replace option was introduced in Terraform 0.15.2: %w", err) + } + for _, addr := range c.replaceAddrs { + args = append(args, "-replace="+addr) + } + } if c.targets != nil { for _, ta := range c.targets { args = append(args, "-target="+ta) diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/exit_errors.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/exit_errors.go index 359e6ad0e17..b2b0ada62bc 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/exit_errors.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/exit_errors.go @@ -6,6 +6,7 @@ import ( "os/exec" "regexp" "strings" + "text/template" ) // this file contains errors parsed from stderr @@ -17,8 +18,10 @@ var ( usageRegexp = regexp.MustCompile(`Too many command line arguments|^Usage: .*Options:.*|Error: Invalid -\d+ option`) - // "Could not load plugin" is present in 0.13 - noInitErrRegexp = regexp.MustCompile(`Error: Could not satisfy plugin requirements|Error: Could not load plugin`) + noInitErrRegexp = regexp.MustCompile(`Error: Could not satisfy plugin requirements|` + + `Error: Could not load plugin|` + // v0.13 + `Please run \"terraform init\"|` + // v1.1.0 early alpha versions (ref 89b05050) + `run:\s+terraform init`) // v1.1.0 (ref df578afd) noConfigErrRegexp = regexp.MustCompile(`Error: No configuration files`) @@ -29,6 +32,9 @@ var ( tfVersionMismatchErrRegexp = regexp.MustCompile(`Error: The currently running version of Terraform doesn't meet the|Error: Unsupported Terraform Core version`) tfVersionMismatchConstraintRegexp = regexp.MustCompile(`required_version = "(.+)"|Required version: (.+)\b`) configInvalidErrRegexp = regexp.MustCompile(`There are some problems with the configuration, described below.`) + + stateLockErrRegexp = regexp.MustCompile(`Error acquiring the state lock`) + stateLockInfoRegexp = regexp.MustCompile(`Lock Info:\n\s*ID:\s*([^\n]+)\n\s*Path:\s*([^\n]+)\n\s*Operation:\s*([^\n]+)\n\s*Who:\s*([^\n]+)\n\s*Version:\s*([^\n]+)\n\s*Created:\s*([^\n]+)\n`) ) func (tf *Terraform) wrapExitError(ctx context.Context, err error, stderr string) error { @@ -127,6 +133,20 @@ func (tf *Terraform) wrapExitError(ctx context.Context, err error, stderr string } case configInvalidErrRegexp.MatchString(stderr): return &ErrConfigInvalid{stderr: stderr} + case stateLockErrRegexp.MatchString(stderr): + submatches := stateLockInfoRegexp.FindStringSubmatch(stderr) + if len(submatches) == 7 { + return &ErrStateLocked{ + unwrapper: unwrapper{exitErr, ctxErr}, + + ID: submatches[1], + Path: submatches[2], + Operation: submatches[3], + Who: submatches[4], + Version: submatches[5], + Created: submatches[6], + } + } } return fmt.Errorf("%w\n%s", &unwrapper{exitErr, ctxErr}, stderr) @@ -256,3 +276,33 @@ func (e *ErrTFVersionMismatch) Error() string { return fmt.Sprintf("terraform %s not supported by configuration%s", version, requirement) } + +// ErrStateLocked is returned when the state lock is already held by another process. +type ErrStateLocked struct { + unwrapper + + ID string + Path string + Operation string + Who string + Version string + Created string +} + +func (e *ErrStateLocked) Error() string { + tmpl := `Lock Info: + ID: {{.ID}} + Path: {{.Path}} + Operation: {{.Operation}} + Who: {{.Who}} + Version: {{.Version}} + Created: {{.Created}} +` + + t := template.Must(template.New("LockInfo").Parse(tmpl)) + var out strings.Builder + if err := t.Execute(&out, e); err != nil { + return "error acquiring the state lock" + } + return fmt.Sprintf("error acquiring the state lock: %v", out.String()) +} diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/fmt.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/fmt.go index 10f6cb4cf42..2234c79fa7e 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/fmt.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/fmt.go @@ -1,7 +1,6 @@ package tfexec import ( - "bytes" "context" "fmt" "io" @@ -44,7 +43,7 @@ func FormatString(ctx context.Context, execPath string, content string) (string, // FormatString formats a passed string. func (tf *Terraform) FormatString(ctx context.Context, content string) (string, error) { in := strings.NewReader(content) - var outBuf bytes.Buffer + var outBuf strings.Builder err := tf.Format(ctx, in, &outBuf) if err != nil { return "", err @@ -101,7 +100,7 @@ func (tf *Terraform) FormatCheck(ctx context.Context, opts ...FormatOption) (boo return false, nil, err } - var outBuf bytes.Buffer + var outBuf strings.Builder cmd.Stdout = mergeWriters(cmd.Stdout, &outBuf) err = tf.runTerraformCmd(ctx, cmd) diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/options.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/options.go index d78901071b8..fb2d5bd74b8 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/options.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/options.go @@ -117,6 +117,15 @@ func DryRun(dryRun bool) *DryRunOption { return &DryRunOption{dryRun} } +type FSMirrorOption struct { + fsMirror string +} + +// FSMirror represents the -fs-mirror option (path to filesystem mirror directory) +func FSMirror(fsMirror string) *FSMirrorOption { + return &FSMirrorOption{fsMirror} +} + type ForceOption struct { force bool } @@ -178,6 +187,15 @@ func LockTimeout(lockTimeout string) *LockTimeoutOption { return &LockTimeoutOption{lockTimeout} } +type NetMirrorOption struct { + netMirror string +} + +// NetMirror represents the -net-mirror option (base URL of a network mirror) +func NetMirror(netMirror string) *NetMirrorOption { + return &NetMirrorOption{netMirror} +} + type OutOption struct { path string } @@ -194,6 +212,15 @@ func Parallelism(n int) *ParallelismOption { return &ParallelismOption{n} } +type PlatformOption struct { + platform string +} + +// Platform represents the -platform flag which is an os_arch string +func Platform(platform string) *PlatformOption { + return &PlatformOption{platform} +} + type PluginDirOption struct { pluginDir string } @@ -202,6 +229,15 @@ func PluginDir(pluginDir string) *PluginDirOption { return &PluginDirOption{pluginDir} } +type ProviderOption struct { + provider string +} + +// Provider represents the positional argument (provider source address) +func Provider(providers string) *ProviderOption { + return &ProviderOption{providers} +} + type ReattachInfo map[string]ReattachConfig // ReattachConfig holds the information Terraform needs to be able to attach @@ -260,6 +296,14 @@ func Refresh(refresh bool) *RefreshOption { return &RefreshOption{refresh} } +type ReplaceOption struct { + address string +} + +func Replace(address string) *ReplaceOption { + return &ReplaceOption{address} +} + type StateOption struct { path string } @@ -329,3 +373,21 @@ type VerifyPluginsOption struct { func VerifyPlugins(verifyPlugins bool) *VerifyPluginsOption { return &VerifyPluginsOption{verifyPlugins} } + +// FromStateOption represents the -from-state option of the "terraform add" command. +type FromStateOption struct { + fromState bool +} + +func FromState(fromState bool) *FromStateOption { + return &FromStateOption{fromState} +} + +// IncludeOptionalOption represents the -optional option of the "terraform add" command. +type IncludeOptionalOption struct { + includeOptional bool +} + +func IncludeOptional(includeOptional bool) *IncludeOptionalOption { + return &IncludeOptionalOption{includeOptional} +} diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/plan.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/plan.go index bfe77db73ff..bf41094bb84 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/plan.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/plan.go @@ -16,6 +16,7 @@ type planConfig struct { parallelism int reattachInfo ReattachInfo refresh bool + replaceAddrs []string state string targets []string vars []string @@ -63,6 +64,10 @@ func (opt *RefreshOption) configurePlan(conf *planConfig) { conf.refresh = opt.refresh } +func (opt *ReplaceOption) configurePlan(conf *planConfig) { + conf.replaceAddrs = append(conf.replaceAddrs, opt.address) +} + func (opt *ParallelismOption) configurePlan(conf *planConfig) { conf.parallelism = opt.parallelism } @@ -132,6 +137,15 @@ func (tf *Terraform) planCmd(ctx context.Context, opts ...PlanOption) (*exec.Cmd args = append(args, "-refresh="+strconv.FormatBool(c.refresh)) // unary flags: pass if true + if c.replaceAddrs != nil { + err := tf.compatible(ctx, tf0_15_2, nil) + if err != nil { + return nil, fmt.Errorf("replace option was introduced in Terraform 0.15.2: %w", err) + } + for _, addr := range c.replaceAddrs { + args = append(args, "-replace="+addr) + } + } if c.destroy { args = append(args, "-destroy") } diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/providers_lock.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/providers_lock.go new file mode 100644 index 00000000000..b3a20216d23 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/providers_lock.go @@ -0,0 +1,82 @@ +package tfexec + +import ( + "context" + "fmt" + "os/exec" +) + +type providersLockConfig struct { + fsMirror string + netMirror string + platforms []string + providers []string +} + +var defaultProvidersLockOptions = providersLockConfig{} + +type ProvidersLockOption interface { + configureProvidersLock(*providersLockConfig) +} + +func (opt *FSMirrorOption) configureProvidersLock(conf *providersLockConfig) { + conf.fsMirror = opt.fsMirror +} + +func (opt *NetMirrorOption) configureProvidersLock(conf *providersLockConfig) { + conf.netMirror = opt.netMirror +} + +func (opt *PlatformOption) configureProvidersLock(conf *providersLockConfig) { + conf.platforms = append(conf.platforms, opt.platform) +} + +func (opt *ProviderOption) configureProvidersLock(conf *providersLockConfig) { + conf.providers = append(conf.providers, opt.provider) +} + +// ProvidersLock represents the `terraform providers lock` command +func (tf *Terraform) ProvidersLock(ctx context.Context, opts ...ProvidersLockOption) error { + err := tf.compatible(ctx, tf0_14_0, nil) + if err != nil { + return fmt.Errorf("terraform providers lock was added in 0.14.0: %w", err) + } + + lockCmd := tf.providersLockCmd(ctx, opts...) + + err = tf.runTerraformCmd(ctx, lockCmd) + if err != nil { + return err + } + + return err +} + +func (tf *Terraform) providersLockCmd(ctx context.Context, opts ...ProvidersLockOption) *exec.Cmd { + c := defaultProvidersLockOptions + + for _, o := range opts { + o.configureProvidersLock(&c) + } + args := []string{"providers", "lock"} + + // string options, only pass if set + if c.fsMirror != "" { + args = append(args, "-fs-mirror="+c.fsMirror) + } + + if c.netMirror != "" { + args = append(args, "-net-mirror="+c.netMirror) + } + + for _, p := range c.platforms { + args = append(args, "-platform="+p) + } + + // positional providers argument + for _, p := range c.providers { + args = append(args, p) + } + + return tf.buildTerraformCmd(ctx, nil, args...) +} diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/show.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/show.go index a8d67f1a4cf..61e660ac991 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/show.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/show.go @@ -1,10 +1,10 @@ package tfexec import ( - "bytes" "context" "fmt" "os/exec" + "strings" tfjson "github.com/hashicorp/terraform-json" ) @@ -173,14 +173,14 @@ func (tf *Terraform) ShowPlanFileRaw(ctx context.Context, planPath string, opts showCmd := tf.showCmd(ctx, false, mergeEnv, planPath) - var ret bytes.Buffer - showCmd.Stdout = &ret + var outBuf strings.Builder + showCmd.Stdout = &outBuf err := tf.runTerraformCmd(ctx, showCmd) if err != nil { return "", err } - return ret.String(), nil + return outBuf.String(), nil } diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/validate.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/validate.go index 756eccd75c6..320011df19a 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/validate.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/validate.go @@ -19,8 +19,8 @@ func (tf *Terraform) Validate(ctx context.Context) (*tfjson.ValidateOutput, erro cmd := tf.buildTerraformCmd(ctx, nil, "validate", "-no-color", "-json") - var outbuf = bytes.Buffer{} - cmd.Stdout = &outbuf + var outBuf = bytes.Buffer{} + cmd.Stdout = &outBuf err = tf.runTerraformCmd(ctx, cmd) // TODO: this command should not exit 1 if you pass -json as its hard to differentiate other errors @@ -30,7 +30,7 @@ func (tf *Terraform) Validate(ctx context.Context) (*tfjson.ValidateOutput, erro var ret tfjson.ValidateOutput // TODO: ret.UseJSONNumber(true) validate output should support JSON numbers - jsonErr := json.Unmarshal(outbuf.Bytes(), &ret) + jsonErr := json.Unmarshal(outBuf.Bytes(), &ret) if jsonErr != nil { // the original call was possibly bad, if it has an error, actually just return that if err != nil { diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/version.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/version.go index 2e842a8758f..d9c57cd07a8 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/version.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/version.go @@ -19,6 +19,8 @@ var ( tf0_13_0 = version.Must(version.NewVersion("0.13.0")) tf0_14_0 = version.Must(version.NewVersion("0.14.0")) tf0_15_0 = version.Must(version.NewVersion("0.15.0")) + tf0_15_2 = version.Must(version.NewVersion("0.15.2")) + tf1_1_0 = version.Must(version.NewVersion("1.1.0")) ) // Version returns structured output from the terraform version command including both the Terraform CLI version @@ -88,7 +90,7 @@ func parseJsonVersionOutput(stdout []byte) (*version.Version, map[string]*versio func (tf *Terraform) versionFromPlaintext(ctx context.Context) (*version.Version, map[string]*version.Version, error) { versionCmd := tf.buildTerraformCmd(ctx, nil, "version") - var outBuf bytes.Buffer + var outBuf strings.Builder versionCmd.Stdout = &outBuf err := tf.runTerraformCmd(ctx, versionCmd) diff --git a/vendor/github.com/hashicorp/terraform-exec/tfexec/workspace_list.go b/vendor/github.com/hashicorp/terraform-exec/tfexec/workspace_list.go index b8d0309454d..33c0d779b39 100644 --- a/vendor/github.com/hashicorp/terraform-exec/tfexec/workspace_list.go +++ b/vendor/github.com/hashicorp/terraform-exec/tfexec/workspace_list.go @@ -1,7 +1,6 @@ package tfexec import ( - "bytes" "context" "strings" ) @@ -11,7 +10,7 @@ func (tf *Terraform) WorkspaceList(ctx context.Context) ([]string, string, error // TODO: [DIR] param option wlCmd := tf.buildTerraformCmd(ctx, nil, "workspace", "list", "-no-color") - var outBuf bytes.Buffer + var outBuf strings.Builder wlCmd.Stdout = &outBuf err := tf.runTerraformCmd(ctx, wlCmd) diff --git a/vendor/github.com/hashicorp/terraform-json/plan.go b/vendor/github.com/hashicorp/terraform-json/plan.go index 97635bd4733..1de5bc82a09 100644 --- a/vendor/github.com/hashicorp/terraform-json/plan.go +++ b/vendor/github.com/hashicorp/terraform-json/plan.go @@ -4,11 +4,13 @@ import ( "encoding/json" "errors" "fmt" + + "github.com/hashicorp/go-version" ) -// PlanFormatVersions represents versions of the JSON plan format that -// are supported by this package. -var PlanFormatVersions = []string{"0.1", "0.2"} +// PlanFormatVersionConstraints defines the versions of the JSON plan format +// that are supported by this package. +var PlanFormatVersionConstraints = ">= 0.1, < 2.0" // ResourceMode is a string representation of the resource type found // in certain fields in the plan. @@ -66,9 +68,19 @@ func (p *Plan) Validate() error { return errors.New("unexpected plan input, format version is missing") } - if !isStringInSlice(PlanFormatVersions, p.FormatVersion) { - return fmt.Errorf("unsupported plan format version: expected %q, got %q", - PlanFormatVersions, p.FormatVersion) + constraint, err := version.NewConstraint(PlanFormatVersionConstraints) + if err != nil { + return fmt.Errorf("invalid version constraint: %w", err) + } + + version, err := version.NewVersion(p.FormatVersion) + if err != nil { + return fmt.Errorf("invalid format version %q: %w", p.FormatVersion, err) + } + + if !constraint.Check(version) { + return fmt.Errorf("unsupported plan format version: %q does not satisfy %q", + version, constraint) } return nil diff --git a/vendor/github.com/hashicorp/terraform-json/schemas.go b/vendor/github.com/hashicorp/terraform-json/schemas.go index 88c2c94bb43..2360231d00f 100644 --- a/vendor/github.com/hashicorp/terraform-json/schemas.go +++ b/vendor/github.com/hashicorp/terraform-json/schemas.go @@ -5,12 +5,13 @@ import ( "errors" "fmt" + "github.com/hashicorp/go-version" "github.com/zclconf/go-cty/cty" ) -// ProviderSchemasFormatVersions represents the versions of -// the JSON provider schema format that are supported by this package. -var ProviderSchemasFormatVersions = []string{"0.1", "0.2"} +// ProviderSchemasFormatVersionConstraints defines the versions of the JSON +// provider schema format that are supported by this package. +var ProviderSchemasFormatVersionConstraints = ">= 0.1, < 2.0" // ProviderSchemas represents the schemas of all providers and // resources in use by the configuration. @@ -38,9 +39,19 @@ func (p *ProviderSchemas) Validate() error { return errors.New("unexpected provider schema data, format version is missing") } - if !isStringInSlice(ProviderSchemasFormatVersions, p.FormatVersion) { - return fmt.Errorf("unsupported provider schema data format version: expected %q, got %q", - ProviderSchemasFormatVersions, p.FormatVersion) + constraint, err := version.NewConstraint(PlanFormatVersionConstraints) + if err != nil { + return fmt.Errorf("invalid version constraint: %w", err) + } + + version, err := version.NewVersion(p.FormatVersion) + if err != nil { + return fmt.Errorf("invalid format version %q: %w", p.FormatVersion, err) + } + + if !constraint.Check(version) { + return fmt.Errorf("unsupported provider schema format version: %q does not satisfy %q", + version, constraint) } return nil @@ -212,6 +223,36 @@ type SchemaAttribute struct { Sensitive bool `json:"sensitive,omitempty"` } +type jsonSchemaAttribute struct { + AttributeType json.RawMessage `json:"type,omitempty"` + AttributeNestedType *SchemaNestedAttributeType `json:"nested_type,omitempty"` + Description string `json:"description,omitempty"` + DescriptionKind SchemaDescriptionKind `json:"description_kind,omitempty"` + Deprecated bool `json:"deprecated,omitempty"` + Required bool `json:"required,omitempty"` + Optional bool `json:"optional,omitempty"` + Computed bool `json:"computed,omitempty"` + Sensitive bool `json:"sensitive,omitempty"` +} + +func (as *SchemaAttribute) MarshalJSON() ([]byte, error) { + jsonSa := &jsonSchemaAttribute{ + AttributeNestedType: as.AttributeNestedType, + Description: as.Description, + DescriptionKind: as.DescriptionKind, + Deprecated: as.Deprecated, + Required: as.Required, + Optional: as.Optional, + Computed: as.Computed, + Sensitive: as.Sensitive, + } + if as.AttributeType != cty.NilType { + attrTy, _ := as.AttributeType.MarshalJSON() + jsonSa.AttributeType = attrTy + } + return json.Marshal(jsonSa) +} + // SchemaNestedAttributeType describes a nested attribute // which could also be just expressed simply as cty.Object(...), // cty.List(cty.Object(...)) etc. but this allows tracking additional diff --git a/vendor/github.com/hashicorp/terraform-json/state.go b/vendor/github.com/hashicorp/terraform-json/state.go index ad632e49d5c..bece5c22021 100644 --- a/vendor/github.com/hashicorp/terraform-json/state.go +++ b/vendor/github.com/hashicorp/terraform-json/state.go @@ -5,11 +5,13 @@ import ( "encoding/json" "errors" "fmt" + + "github.com/hashicorp/go-version" ) -// StateFormatVersions represents the versions of the JSON state format +// StateFormatVersionConstraints defines the versions of the JSON state format // that are supported by this package. -var StateFormatVersions = []string{"0.1", "0.2"} +var StateFormatVersionConstraints = ">= 0.1, < 2.0" // State is the top-level representation of a Terraform state. type State struct { @@ -50,9 +52,19 @@ func (s *State) Validate() error { return errors.New("unexpected state input, format version is missing") } - if !isStringInSlice(StateFormatVersions, s.FormatVersion) { - return fmt.Errorf("unsupported state format version: expected %q, got %q", - StateFormatVersions, s.FormatVersion) + constraint, err := version.NewConstraint(StateFormatVersionConstraints) + if err != nil { + return fmt.Errorf("invalid version constraint: %w", err) + } + + version, err := version.NewVersion(s.FormatVersion) + if err != nil { + return fmt.Errorf("invalid format version %q: %w", s.FormatVersion, err) + } + + if !constraint.Check(version) { + return fmt.Errorf("unsupported state format version: %q does not satisfy %q", + version, constraint) } return nil diff --git a/vendor/github.com/hashicorp/terraform-json/validate.go b/vendor/github.com/hashicorp/terraform-json/validate.go index db9db1919ce..97b82d0a979 100644 --- a/vendor/github.com/hashicorp/terraform-json/validate.go +++ b/vendor/github.com/hashicorp/terraform-json/validate.go @@ -4,8 +4,14 @@ import ( "encoding/json" "errors" "fmt" + + "github.com/hashicorp/go-version" ) +// ValidateFormatVersionConstraints defines the versions of the JSON +// validate format that are supported by this package. +var ValidateFormatVersionConstraints = ">= 0.1, < 2.0" + // Pos represents a position in a config file type Pos struct { Line int `json:"line"` @@ -110,10 +116,19 @@ func (vo *ValidateOutput) Validate() error { return nil } - supportedVersion := "0.1" - if vo.FormatVersion != supportedVersion { - return fmt.Errorf("unsupported validation output format version: expected %q, got %q", - supportedVersion, vo.FormatVersion) + constraint, err := version.NewConstraint(ValidateFormatVersionConstraints) + if err != nil { + return fmt.Errorf("invalid version constraint: %w", err) + } + + version, err := version.NewVersion(vo.FormatVersion) + if err != nil { + return fmt.Errorf("invalid format version %q: %w", vo.FormatVersion, err) + } + + if !constraint.Check(version) { + return fmt.Errorf("unsupported validation output format version: %q does not satisfy %q", + version, constraint) } return nil diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go index f50f196e2ca..279a20ee535 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/collection.go @@ -538,7 +538,7 @@ func flattener(flattenList cty.Value) ([]cty.Value, []cty.ValueMarks, bool) { // Any dynamic types could result in more collections that need to be // flattened, so the type cannot be known. - if val.Type().Equals(cty.DynamicPseudoType) { + if val == cty.DynamicVal { isKnown = false } diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go index 5070a5adf57..339d04dbdbd 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/csv.go @@ -30,7 +30,7 @@ var CSVDecodeFunc = function.New(&function.Spec{ return cty.DynamicPseudoType, fmt.Errorf("missing header line") } if err != nil { - return cty.DynamicPseudoType, err + return cty.DynamicPseudoType, csvError(err) } atys := make(map[string]cty.Type, len(headers)) @@ -64,7 +64,7 @@ var CSVDecodeFunc = function.New(&function.Spec{ break } if err != nil { - return cty.DynamicVal, err + return cty.DynamicVal, csvError(err) } vals := make(map[string]cty.Value, len(cols)) @@ -91,3 +91,12 @@ var CSVDecodeFunc = function.New(&function.Spec{ func CSVDecode(str cty.Value) (cty.Value, error) { return CSVDecodeFunc.Call([]cty.Value{str}) } + +func csvError(err error) error { + switch err := err.(type) { + case *csv.ParseError: + return fmt.Errorf("CSV parse error on line %d: %w", err.Line, err.Err) + default: + return err + } +} diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go index 63881f58531..8b17758950c 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/format.go @@ -114,6 +114,8 @@ var FormatListFunc = function.New(&function.Spec{ continue } iterators[i] = arg.ElementIterator() + case arg == cty.DynamicVal: + unknowns[i] = true default: singleVals[i] = arg } diff --git a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go index 7bbe584b0a1..4effeb7bb8d 100644 --- a/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go +++ b/vendor/github.com/zclconf/go-cty/cty/function/stdlib/number.go @@ -371,14 +371,21 @@ var CeilFunc = function.New(&function.Spec{ }, Type: function.StaticReturnType(cty.Number), Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - var val float64 - if err := gocty.FromCtyValue(args[0], &val); err != nil { - return cty.UnknownVal(cty.String), err + f := args[0].AsBigFloat() + + if f.IsInf() { + return cty.NumberVal(f), nil } - if math.IsInf(val, 0) { - return cty.NumberFloatVal(val), nil + + i, acc := f.Int(nil) + switch acc { + case big.Exact, big.Above: + // Done. + case big.Below: + i.Add(i, big.NewInt(1)) } - return cty.NumberIntVal(int64(math.Ceil(val))), nil + + return cty.NumberVal(f.SetInt(i)), nil }, }) @@ -393,14 +400,21 @@ var FloorFunc = function.New(&function.Spec{ }, Type: function.StaticReturnType(cty.Number), Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { - var val float64 - if err := gocty.FromCtyValue(args[0], &val); err != nil { - return cty.UnknownVal(cty.String), err + f := args[0].AsBigFloat() + + if f.IsInf() { + return cty.NumberVal(f), nil } - if math.IsInf(val, 0) { - return cty.NumberFloatVal(val), nil + + i, acc := f.Int(nil) + switch acc { + case big.Exact, big.Below: + // Done. + case big.Above: + i.Sub(i, big.NewInt(1)) } - return cty.NumberIntVal(int64(math.Floor(val))), nil + + return cty.NumberVal(f.SetInt(i)), nil }, }) diff --git a/vendor/github.com/zclconf/go-cty/cty/value_ops.go b/vendor/github.com/zclconf/go-cty/cty/value_ops.go index 8c37535c885..55bebe0365a 100644 --- a/vendor/github.com/zclconf/go-cty/cty/value_ops.go +++ b/vendor/github.com/zclconf/go-cty/cty/value_ops.go @@ -116,9 +116,9 @@ func (val Value) GoString() string { // Use RawEquals to compare if two values are equal *ignoring* the // short-circuit rules and the exception for null values. func (val Value) Equals(other Value) Value { - if val.IsMarked() || other.IsMarked() { - val, valMarks := val.Unmark() - other, otherMarks := other.Unmark() + if val.ContainsMarked() || other.ContainsMarked() { + val, valMarks := val.UnmarkDeep() + other, otherMarks := other.UnmarkDeep() return val.Equals(other).WithMarks(valMarks, otherMarks) } @@ -1283,9 +1283,7 @@ func (val Value) AsBigFloat() *big.Float { } // Copy the float so that callers can't mutate our internal state - ret := *(val.v.(*big.Float)) - - return &ret + return new(big.Float).Copy(val.v.(*big.Float)) } // AsValueSlice returns a []cty.Value representation of a non-null, non-unknown diff --git a/vendor/github.com/zclconf/go-cty/cty/walk.go b/vendor/github.com/zclconf/go-cty/cty/walk.go index d17f48ccd1e..87ba32e796b 100644 --- a/vendor/github.com/zclconf/go-cty/cty/walk.go +++ b/vendor/github.com/zclconf/go-cty/cty/walk.go @@ -33,10 +33,15 @@ func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error { return nil } + // The callback already got a chance to see the mark in our + // call above, so can safely strip it off here in order to + // visit the child elements, which might still have their own marks. + rawVal, _ := val.Unmark() + ty := val.Type() switch { case ty.IsObjectType(): - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { nameVal, av := it.Element() path := append(path, GetAttrStep{ Name: nameVal.AsString(), @@ -46,8 +51,8 @@ func walk(path Path, val Value, cb func(Path, Value) (bool, error)) error { return err } } - case val.CanIterateElements(): - for it := val.ElementIterator(); it.Next(); { + case rawVal.CanIterateElements(): + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -134,6 +139,12 @@ func transform(path Path, val Value, t Transformer) (Value, error) { ty := val.Type() var newVal Value + // We need to peel off any marks here so that we can dig around + // inside any collection values. We'll reapply these to any + // new collections we construct, but the transformer's Exit + // method gets the final say on what to do with those. + rawVal, marks := val.Unmark() + switch { case val.IsNull() || !val.IsKnown(): @@ -141,14 +152,14 @@ func transform(path Path, val Value, t Transformer) (Value, error) { newVal = val case ty.IsListType() || ty.IsSetType() || ty.IsTupleType(): - l := val.LengthInt() + l := rawVal.LengthInt() switch l { case 0: // No deep transform for an empty sequence newVal = val default: elems := make([]Value, 0, l) - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -161,25 +172,25 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } switch { case ty.IsListType(): - newVal = ListVal(elems) + newVal = ListVal(elems).WithMarks(marks) case ty.IsSetType(): - newVal = SetVal(elems) + newVal = SetVal(elems).WithMarks(marks) case ty.IsTupleType(): - newVal = TupleVal(elems) + newVal = TupleVal(elems).WithMarks(marks) default: panic("unknown sequence type") // should never happen because of the case we are in } } case ty.IsMapType(): - l := val.LengthInt() + l := rawVal.LengthInt() switch l { case 0: // No deep transform for an empty map newVal = val default: elems := make(map[string]Value) - for it := val.ElementIterator(); it.Next(); { + for it := rawVal.ElementIterator(); it.Next(); { kv, ev := it.Element() path := append(path, IndexStep{ Key: kv, @@ -190,7 +201,7 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } elems[kv.AsString()] = newEv } - newVal = MapVal(elems) + newVal = MapVal(elems).WithMarks(marks) } case ty.IsObjectType(): @@ -212,7 +223,7 @@ func transform(path Path, val Value, t Transformer) (Value, error) { } newAVs[name] = newAV } - newVal = ObjectVal(newAVs) + newVal = ObjectVal(newAVs).WithMarks(marks) } default: diff --git a/vendor/modules.txt b/vendor/modules.txt index 28f4c18a0eb..0f3845d675d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -162,12 +162,12 @@ github.com/hashicorp/hcl2/hclwrite # github.com/hashicorp/logutils v1.0.0 ## explicit github.com/hashicorp/logutils -# github.com/hashicorp/terraform-exec v0.14.0 +# github.com/hashicorp/terraform-exec v0.15.0 ## explicit; go 1.14 github.com/hashicorp/terraform-exec/internal/version github.com/hashicorp/terraform-exec/tfexec github.com/hashicorp/terraform-exec/tfinstall -# github.com/hashicorp/terraform-json v0.12.0 +# github.com/hashicorp/terraform-json v0.13.0 ## explicit; go 1.13 github.com/hashicorp/terraform-json # github.com/hashicorp/terraform-plugin-go v0.3.0 @@ -385,7 +385,7 @@ github.com/ulikunitz/xz/lzma ## explicit github.com/vmihailenco/msgpack github.com/vmihailenco/msgpack/codes -# github.com/zclconf/go-cty v1.8.4 +# github.com/zclconf/go-cty v1.9.1 ## explicit; go 1.12 github.com/zclconf/go-cty/cty github.com/zclconf/go-cty/cty/convert diff --git a/website/docs/r/kms_key.html.markdown b/website/docs/r/kms_key.html.markdown index 925585f89b3..b7a93604091 100644 --- a/website/docs/r/kms_key.html.markdown +++ b/website/docs/r/kms_key.html.markdown @@ -78,6 +78,7 @@ The following arguments are supported: * `uri` - (Optional) (Updatable) Pre-authenticated-request-uri of the backup * `restore_trigger` - (Optional) (Updatable) An optional property when flipped triggers restore from restore option provided in config file. * `time_of_deletion` - (Optional) (Updatable) An optional property for the deletion time of the key, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2019-04-03T21:10:29.600Z` +* `schedule_deletion_days` - (Optional) (Updatable) An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. ** IMPORTANT ** Any change to a property that does not support update will force the destruction and recreation of the resource with the new property values @@ -107,6 +108,7 @@ The following attributes are exported: * `replica_details` - Key replica details * `replication_id` - ReplicationId associated with a key operation * `restored_from_key_id` - The OCID of the key from which this key was restored. +* `schedule_deletion_days` - An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. * `state` - The key's current lifecycle state. Example: `ENABLED` * `time_created` - The date and time the key was created, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2018-04-03T21:10:29.600Z` * `time_of_deletion` - An optional property indicating when to delete the key, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2019-04-03T21:10:29.600Z` diff --git a/website/docs/r/kms_key_version.html.markdown b/website/docs/r/kms_key_version.html.markdown index 49e2892f59d..2d809adfbc9 100644 --- a/website/docs/r/kms_key_version.html.markdown +++ b/website/docs/r/kms_key_version.html.markdown @@ -40,6 +40,7 @@ The following arguments are supported: * `key_id` - (Required) The OCID of the key. * `management_endpoint` - (Required) The service endpoint to perform management operations against. Management operations include 'Create,' 'Update,' 'List,' 'Get,' and 'Delete' operations. See Vault Management endpoint. * `time_of_deletion` - (Optional) (Updatable) An optional property for the deletion time of the key version, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2019-04-03T21:10:29.600Z` +* `schedule_deletion_days` - (Optional) (Updatable) An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. ** IMPORTANT ** Any change to a property that does not support update will force the destruction and recreation of the resource with the new property values @@ -59,6 +60,7 @@ The following attributes are exported: * `replica_details` - KeyVersion replica details * `replication_id` - ReplicationId associated with a key version operation * `restored_from_key_version_id` - The OCID of the key version from which this key version was restored. +* `schedule_deletion_days` - An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. * `state` - The key version's current lifecycle state. Example: `ENABLED` * `time_created` - The date and time this key version was created, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: "2018-04-03T21:10:29.600Z" * `time_of_deletion` - An optional property to indicate when to delete the key version, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2019-04-03T21:10:29.600Z` diff --git a/website/docs/r/kms_vault.html.markdown b/website/docs/r/kms_vault.html.markdown index 4ad45367b5d..7e70aff5019 100644 --- a/website/docs/r/kms_vault.html.markdown +++ b/website/docs/r/kms_vault.html.markdown @@ -74,6 +74,7 @@ The following arguments are supported: * `uri` - (Optional) (Updatable) Pre-authenticated-request-uri of the backup* `restore_trigger` - (Optional) (Updatable) An optional property when flipped triggers restore from restore option provided in config file. * `vault_type` - (Required) The type of vault to create. Each type of vault stores the key with different degrees of isolation and has different options and pricing. * `time_of_deletion` - (Optional) (Updatable) An optional property for the deletion time of the vault, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2019-04-03T21:10:29.600Z` +* `schedule_deletion_days` - (Optional) (Updatable) An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. ** IMPORTANT ** Any change to a property that does not support update will force the destruction and recreation of the resource with the new property values @@ -99,7 +100,8 @@ The following attributes are exported: * `management_endpoint` - The service endpoint to perform management operations against. Management operations include "Create," "Update," "List," "Get," and "Delete" operations. * `replica_details` - Vault replica details * `replication_id` - ReplicationId associated with a vault operation -* `restored_from_vault_id` - The OCID of the vault from which this vault was restored, if it was restored from a backup file. If you restore a vault to the same region, the vault retains the same OCID that it had when you backed up the vault. +* `restored_from_vault_id` - The OCID of the vault from which this vault was restored, if it was restored from a backup file. If you restore a vault to the same region, the vault retains the same OCID that it had when you backed up the vault. +* `schedule_deletion_days` - An optional property used to define the number of days a deletion will be scheduled for. `time_of_deletion` takes precedence if set. Must be between 7 and 30 days. Default: `30`. * `state` - The vault's current lifecycle state. Example: `DELETED` * `time_created` - The date and time this vault was created, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2018-04-03T21:10:29.600Z` * `time_of_deletion` - An optional property to indicate when to delete the vault, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. Example: `2018-04-03T21:10:29.600Z` diff --git a/website/docs/r/vault_secret.html.markdown b/website/docs/r/vault_secret.html.markdown index b53437f6039..0f6f2409ba8 100644 --- a/website/docs/r/vault_secret.html.markdown +++ b/website/docs/r/vault_secret.html.markdown @@ -73,6 +73,7 @@ The following arguments are supported: * `secret_version_expiry_interval` - (Applicable when rule_type=SECRET_EXPIRY_RULE) (Updatable) A property indicating how long the secret contents will be considered valid, expressed in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Time_intervals) format. The secret needs to be updated when the secret content expires. No enforcement mechanism exists at this time, but audit logs record the expiration on the appropriate date, according to the time interval specified in the rule. The timer resets after you update the secret contents. The minimum value is 1 day and the maximum value is 90 days for this property. Currently, only intervals expressed in days are supported. For example, pass `P3D` to have the secret version expire every 3 days. * `time_of_absolute_expiry` - (Applicable when rule_type=SECRET_EXPIRY_RULE) (Updatable) An optional property indicating the absolute time when this secret will expire, expressed in [RFC 3339](https://tools.ietf.org/html/rfc3339) timestamp format. The minimum number of days from current time is 1 day and the maximum number of days from current time is 365 days. Example: `2019-04-03T21:10:29.600Z` * `vault_id` - (Required) The OCID of the vault where you want to create the secret. +* `schedule_deletion_days` - (Optional) (Updatable) An optional property used to define the number of days a deletion will be scheduled for. Must be between 1 and 30 days. Default: `30`. ** IMPORTANT ** @@ -91,6 +92,7 @@ The following attributes are exported: * `key_id` - The OCID of the master encryption key that is used to encrypt the secret. * `lifecycle_details` - Additional information about the current lifecycle state of the secret. * `metadata` - Additional metadata that you can use to provide context about how to use the secret or during rotation or other administrative tasks. For example, for a secret that you use to connect to a database, the additional metadata might specify the connection endpoint and the connection string. Provide additional metadata as key-value pairs. +* `schedule_deletion_days` - An optional property used to define the number of days a deletion will be scheduled for. Must be between 1 and 30 days. Default: `30`. * `secret_name` - The user-friendly name of the secret. Avoid entering confidential information. * `secret_rules` - A list of rules that control how the secret is used and managed. * `is_enforced_on_deleted_secret_versions` - A property indicating whether the rule is applied even if the secret version with the content you are trying to reuse was deleted.