Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: hashicorp/terraform
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.5
Choose a base ref
...
head repository: hashicorp/terraform
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.0.6
Choose a head ref
  • 18 commits
  • 7 files changed
  • 4 contributors

Commits on Aug 18, 2021

  1. Verified

    This commit was signed with the committer’s verified signature.
    AVVS Vitaly Aminev
    Copy the full SHA
    c0afdf9 View commit details

Commits on Aug 20, 2021

  1. Bumping AWS GO SDK to 1.38.42 to fix error when an AWS profile uses b…

    …oth SSO config and credential_process at the same time
    Dominik Keil authored and jbardin committed Aug 20, 2021

    Verified

    This commit was signed with the committer’s verified signature.
    AVVS Vitaly Aminev
    Copy the full SHA
    8e389e3 View commit details
  2. Merge pull request #29426 from hashicorp/jbardin/backport-29017

    v1.0 backport: Bumping AWS GO SDK to 1.38.42
    jbardin authored Aug 20, 2021
    Copy the full SHA
    0fd9ef7 View commit details
  3. Copy the full SHA
    9db2bcc View commit details
  4. Merge pull request #29427 from hashicorp/jbardin/backport-29420

    v1.0 backport: github.com/hashicorp/aws-sdk-go-base 0.7.1
    jbardin authored Aug 20, 2021
    Copy the full SHA
    08ba02d View commit details
  5. update CHANGELOG.md

    jbardin committed Aug 20, 2021
    Copy the full SHA
    cb754ec View commit details
  6. backport of commit 2762a94

    alisdair committed Aug 20, 2021
    Copy the full SHA
    c91c22b View commit details
  7. Merge pull request #29439 from hashicorp/backport/alisdair/init-force…

    …-copy-multiple-workspaces/partially-pumped-chow
    
    Backport of command: Suppress prompt for init -force-copy into v1.0
    alisdair authored Aug 20, 2021
    Copy the full SHA
    4f76f5d View commit details
  8. Update CHANGELOG.md

    alisdair authored Aug 20, 2021
    Copy the full SHA
    15d2ed6 View commit details

Commits on Aug 30, 2021

  1. v1.0 backport #29445

    jbardin committed Aug 30, 2021
    Copy the full SHA
    7066932 View commit details
  2. Copy the full SHA
    7b2c793 View commit details
  3. backport of commit 7ca6be8

    jbardin committed Aug 30, 2021
    Copy the full SHA
    e4a3e55 View commit details
  4. backport of commit 9037970

    jbardin committed Aug 30, 2021
    Copy the full SHA
    94ad788 View commit details
  5. backport of commit ea68d79

    jbardin committed Aug 30, 2021
    Copy the full SHA
    4b15ed3 View commit details

Commits on Aug 31, 2021

  1. backport of commit f195ce7

    jbardin committed Aug 31, 2021
    Copy the full SHA
    3028bc5 View commit details
  2. Merge pull request #29489 from hashicorp/backport/jbardin/computed-ob…

    …j-attrs/reliably-suited-hamster
    
    Backport of Computed values within nested object types in `AssertPlanValid` into v1.0
    jbardin authored Aug 31, 2021
    Copy the full SHA
    169d013 View commit details
  3. update CHANGELOG.md

    jbardin committed Aug 31, 2021
    Copy the full SHA
    ce7ae8b View commit details

Commits on Sep 3, 2021

  1. Copy the full SHA
    b46e2d2 View commit details
Showing with 332 additions and 117 deletions.
  1. +12 −0 CHANGELOG.md
  2. +7 −6 go.mod
  3. +16 −10 go.sum
  4. +17 −13 internal/command/meta_backend_migrate.go
  5. +49 −87 internal/plans/objchange/plan_valid.go
  6. +230 −0 internal/plans/objchange/plan_valid_test.go
  7. +1 −1 version/version.go
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 1.0.6 (September 03, 2021)

ENHANCEMENTS:

* backend/s3: Improve SSO handling and add new endpoints in the AWS SDK ([#29017](https://github.com/hashicorp/terraform/issues/29017))

BUG FIXES:

* cli: Suppress confirmation prompt when initializing with the `-force-copy` flag and migrating state between multiple workspaces. ([#29438](https://github.com/hashicorp/terraform/issues/29438))
* cli: Update tencentcount dependency versions to fix errors when building from source ([#29445](https://github.com/hashicorp/terraform/issues/29445))
* core: Fix panic while handling computed attributes within nested objects, and improve plan validation for unknown values ([#29482](https://github.com/hashicorp/terraform/issues/29482))

## 1.0.5 (August 18, 2021)

BUG FIXES:
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ require (
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.37.0
github.com/aws/aws-sdk-go v1.40.25
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/bgentry/speakeasy v0.1.0
github.com/bmatcuk/doublestar v1.1.5
@@ -95,8 +95,9 @@ require (
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect
github.com/spf13/afero v1.2.2
github.com/tencentcloud/tencentcloud-sdk-go v3.0.82+incompatible
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190808065407-f07404cefc8c
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.232
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233
github.com/tencentyun/cos-go-sdk-v5 v0.7.29
github.com/tombuildsstuff/giovanni v0.15.1
github.com/xanzy/ssh-agent v0.2.1
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
@@ -106,11 +107,11 @@ require (
go.etcd.io/etcd v0.5.0-alpha.5.0.20210428180535-15715dcf1ace
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/mod v0.4.2
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
golang.org/x/sys v0.0.0-20210423082822-04245dca01da
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf
golang.org/x/text v0.3.5
golang.org/x/text v0.3.6
golang.org/x/tools v0.1.0
google.golang.org/api v0.44.0-impersonate-preview
google.golang.org/grpc v1.36.0
26 changes: 16 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
@@ -130,8 +130,8 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.37.0 h1:GzFnhOIsrGyQ69s7VgqtrG2BG8v7X7vwB3Xpbd/DBBk=
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.25 h1:Depnx7O86HWgOCLD5nMto6F9Ju85Q1QuFDnbpZYQWno=
github.com/aws/aws-sdk-go v1.40.25/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
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=
@@ -589,10 +589,14 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tencentcloud/tencentcloud-sdk-go v3.0.82+incompatible h1:5Td2b0yfaOvw9M9nZ5Oav6Li9bxUNxt4DgxMfIPpsa0=
github.com/tencentcloud/tencentcloud-sdk-go v3.0.82+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190808065407-f07404cefc8c h1:iRD1CqtWUjgEVEmjwTMbP1DMzz1HRytOsgx/rlw/vNs=
github.com/tencentyun/cos-go-sdk-v5 v0.0.0-20190808065407-f07404cefc8c/go.mod h1:wk2XFUg6egk4tSDNZtXeKfe2G6690UVyt163PuUxBZk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.232 h1:kwsWbh4rEw42ZDe9/812ebhbwNZxlQyZ2sTmxBOKhN4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.232/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233 h1:5Tbi+jyZ2MojC6GK8V6hchwtnkP2IuENUTqSisbYOlA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233/go.mod h1:sX14+NSvMjOhNFaMtP2aDy6Bss8PyFXij21gpY6+DAs=
github.com/tencentyun/cos-go-sdk-v5 v0.7.29 h1:uwRBzc70Wgtc5iQQCowqecfRT0OpCXUOZzodZHOOEDs=
github.com/tencentyun/cos-go-sdk-v5 v0.7.29/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o=
github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966 h1:j6JEOq5QWFker+d7mFQYOhjTZonQ7YkLTHm56dbn+yM=
github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tombuildsstuff/giovanni v0.15.1 h1:CVRaLOJ7C/eercCrKIsarfJ4SZoGMdBL9Q2deFDUXco=
@@ -738,8 +742,9 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -813,8 +818,8 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
@@ -827,8 +832,9 @@ golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5f
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/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/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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=
30 changes: 17 additions & 13 deletions internal/command/meta_backend_migrate.go
Original file line number Diff line number Diff line change
@@ -146,19 +146,23 @@ func (m *Meta) backendMigrateState(opts *backendMigrateOpts) error {
func (m *Meta) backendMigrateState_S_S(opts *backendMigrateOpts) error {
log.Print("[TRACE] backendMigrateState: migrating all named workspaces")

// Ask the user if they want to migrate their existing remote state
migrate, err := m.confirm(&terraform.InputOpts{
Id: "backend-migrate-multistate-to-multistate",
Query: fmt.Sprintf(
"Do you want to migrate all workspaces to %q?",
opts.TwoType),
Description: fmt.Sprintf(
strings.TrimSpace(inputBackendMigrateMultiToMulti),
opts.OneType, opts.TwoType),
})
if err != nil {
return fmt.Errorf(
"Error asking for state migration action: %s", err)
migrate := opts.force
if !migrate {
var err error
// Ask the user if they want to migrate their existing remote state
migrate, err = m.confirm(&terraform.InputOpts{
Id: "backend-migrate-multistate-to-multistate",
Query: fmt.Sprintf(
"Do you want to migrate all workspaces to %q?",
opts.TwoType),
Description: fmt.Sprintf(
strings.TrimSpace(inputBackendMigrateMultiToMulti),
opts.OneType, opts.TwoType),
})
if err != nil {
return fmt.Errorf(
"Error asking for state migration action: %s", err)
}
}
if !migrate {
return fmt.Errorf("Migration aborted by user.")
136 changes: 49 additions & 87 deletions internal/plans/objchange/plan_valid.go
Original file line number Diff line number Diff line change
@@ -39,11 +39,11 @@ func AssertPlanValid(schema *configschema.Block, priorState, config, plannedStat
func assertPlanValid(schema *configschema.Block, priorState, config, plannedState cty.Value, path cty.Path) []error {
var errs []error
if plannedState.IsNull() && !config.IsNull() {
errs = append(errs, path.NewErrorf("planned for absense but config wants existence"))
errs = append(errs, path.NewErrorf("planned for absence but config wants existence"))
return errs
}
if config.IsNull() && !plannedState.IsNull() {
errs = append(errs, path.NewErrorf("planned for existence but config wants absense"))
errs = append(errs, path.NewErrorf("planned for existence but config wants absence"))
return errs
}
if plannedState.IsNull() {
@@ -286,6 +286,11 @@ func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, pla
}
return errs
}
} else {
if attrS.Computed {
errs = append(errs, path.NewErrorf("configuration present for computed attribute"))
return errs
}
}

// If this attribute has a NestedType, validate the nested object
@@ -317,11 +322,11 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
var errs []error

if planned.IsNull() && !config.IsNull() {
errs = append(errs, path.NewErrorf("planned for absense but config wants existence"))
errs = append(errs, path.NewErrorf("planned for absence but config wants existence"))
return errs
}
if config.IsNull() && !planned.IsNull() {
errs = append(errs, path.NewErrorf("planned for existence but config wants absense"))
errs = append(errs, path.NewErrorf("planned for existence but config wants absence"))
return errs
}
if planned.IsNull() {
@@ -349,10 +354,6 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
for it := planned.ElementIterator(); it.Next(); {
idx, plannedEV := it.Element()
path := append(path, cty.IndexStep{Key: idx})
if !plannedEV.IsKnown() {
errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
continue
}
if !config.HasIndex(idx).True() {
continue // should never happen since we checked the lengths above
}
@@ -368,94 +369,55 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne

case configschema.NestingMap:
// A NestingMap might either be a map or an object, depending on
// whether there are dynamically-typed attributes inside, but
// that's decided statically and so all values will have the same
// kind.
if planned.Type().IsObjectType() {
plannedAtys := planned.Type().AttributeTypes()
configAtys := config.Type().AttributeTypes()
for k := range plannedAtys {
if _, ok := configAtys[k]; !ok {
errs = append(errs, path.NewErrorf("block key %q from plan is not present in config", k))
continue
}
path := append(path, cty.GetAttrStep{Name: k})
// whether there are dynamically-typed attributes inside, so we will
// break these down to maps to handle them both in the same manner.
plannedVals := map[string]cty.Value{}
configVals := map[string]cty.Value{}
priorVals := map[string]cty.Value{}

if !planned.IsNull() {
plannedVals = planned.AsValueMap()
}
if !config.IsNull() {
configVals = config.AsValueMap()
}
if !prior.IsNull() {
priorVals = prior.AsValueMap()
}

plannedEV := planned.GetAttr(k)
if !plannedEV.IsKnown() {
errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
continue
}
configEV := config.GetAttr(k)
priorEV := cty.NullVal(schema.ImpliedType())
if !prior.IsNull() && prior.Type().HasAttribute(k) {
priorEV = prior.GetAttr(k)
}
moreErrs := assertPlannedAttrsValid(schema.Attributes, priorEV, configEV, plannedEV, path)
errs = append(errs, moreErrs...)
}
for k := range configAtys {
if _, ok := plannedAtys[k]; !ok {
errs = append(errs, path.NewErrorf("block key %q from config is not present in plan", k))
continue
}
}
} else {
plannedL := planned.LengthInt()
configL := config.LengthInt()
if plannedL != configL {
errs = append(errs, path.NewErrorf("block count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
return errs
for k, plannedEV := range plannedVals {
configEV, ok := configVals[k]
if !ok {
errs = append(errs, path.NewErrorf("map key %q from plan is not present in config", k))
continue
}
for it := planned.ElementIterator(); it.Next(); {
idx, plannedEV := it.Element()
path := append(path, cty.IndexStep{Key: idx})
if !plannedEV.IsKnown() {
errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
continue
}
k := idx.AsString()
if !config.HasIndex(idx).True() {
errs = append(errs, path.NewErrorf("block key %q from plan is not present in config", k))
continue
}
configEV := config.Index(idx)
priorEV := cty.NullVal(schema.ImpliedType())
if !prior.IsNull() && prior.HasIndex(idx).True() {
priorEV = prior.Index(idx)
}
moreErrs := assertPlannedObjectValid(schema, priorEV, configEV, plannedEV, path)
errs = append(errs, moreErrs...)
path := append(path, cty.GetAttrStep{Name: k})

priorEV, ok := priorVals[k]
if !ok {
priorEV = cty.NullVal(schema.ImpliedType())
}
for it := config.ElementIterator(); it.Next(); {
idx, _ := it.Element()
if !planned.HasIndex(idx).True() {
errs = append(errs, path.NewErrorf("block key %q from config is not present in plan", idx.AsString()))
continue
}
moreErrs := assertPlannedAttrsValid(schema.Attributes, priorEV, configEV, plannedEV, path)
errs = append(errs, moreErrs...)
}
for k := range configVals {
if _, ok := plannedVals[k]; !ok {
errs = append(errs, path.NewErrorf("map key %q from config is not present in plan", k))
continue
}
}

case configschema.NestingSet:
plannedL := planned.LengthInt()
configL := config.LengthInt()
if plannedL != configL {
errs = append(errs, path.NewErrorf("count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
return errs
}
// Because set elements have no identifier with which to correlate
// them, we can't robustly validate the plan for a nested block
// them, we can't robustly validate the plan for a nested object
// backed by a set, and so unfortunately we need to just trust the
// provider to do the right thing. :(
//
// (In principle we could correlate elements by matching the
// subset of attributes explicitly set in config, except for the
// special diff suppression rule which allows for there to be a
// planned value that is constructed by mixing part of a prior
// value with part of a config value, creating an entirely new
// element that is not present in either prior nor config.)
for it := planned.ElementIterator(); it.Next(); {
idx, plannedEV := it.Element()
path := append(path, cty.IndexStep{Key: idx})
if !plannedEV.IsKnown() {
errs = append(errs, path.NewErrorf("element representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
continue
}
}
// provider to do the right thing.
}

return errs
230 changes: 230 additions & 0 deletions internal/plans/objchange/plan_valid_test.go
Original file line number Diff line number Diff line change
@@ -1222,6 +1222,236 @@ func TestAssertPlanValid(t *testing.T) {
}),
[]string{`.bloop: planned value cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"blop":cty.StringVal("ok")})}) for a non-computed attribute`},
},
"computed within nested objects": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"map": {
NestedType: &configschema.Object{
Nesting: configschema.NestingMap,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
Computed: true,
},
},
},
},
// When an object has dynamic attrs, the map may be
// handled as an object.
"map_as_obj": {
NestedType: &configschema.Object{
Nesting: configschema.NestingMap,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
Computed: true,
},
},
},
},
"list": {
NestedType: &configschema.Object{
Nesting: configschema.NestingList,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
Computed: true,
},
},
},
},
"set": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSet,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
Computed: true,
},
},
},
},
"single": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSingle,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.DynamicPseudoType,
Computed: true,
},
},
},
},
},
},
cty.NullVal(cty.Object(map[string]cty.Type{
"map": cty.Map(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"map_as_obj": cty.Map(cty.Object(map[string]cty.Type{
"name": cty.DynamicPseudoType,
})),
"list": cty.List(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"set": cty.Set(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"single": cty.Object(map[string]cty.Type{
"name": cty.String,
}),
})),
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"map_as_obj": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.DynamicPseudoType),
}),
}),
"list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"single": cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"map_as_obj": cty.ObjectVal(map[string]cty.Value{
"one": cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("computed"),
}),
}),
"list": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
"single": cty.ObjectVal(map[string]cty.Value{
"name": cty.NullVal(cty.String),
}),
}),
nil,
},
"computed nested objects": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"map": {
NestedType: &configschema.Object{
Nesting: configschema.NestingMap,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
},
},
},
Computed: true,
},
"list": {
NestedType: &configschema.Object{
Nesting: configschema.NestingList,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
},
},
},
Computed: true,
},
"set": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSet,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.String,
},
},
},
Computed: true,
},
"single": {
NestedType: &configschema.Object{
Nesting: configschema.NestingSingle,
Attributes: map[string]*configschema.Attribute{
"name": {
Type: cty.DynamicPseudoType,
},
},
},
Computed: true,
},
},
},
cty.NullVal(cty.Object(map[string]cty.Type{
"map": cty.Map(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"list": cty.List(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"set": cty.Set(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
"single": cty.Object(map[string]cty.Type{
"name": cty.String,
}),
})),
cty.ObjectVal(map[string]cty.Value{
"map": cty.NullVal(cty.Map(cty.Object(map[string]cty.Type{
"name": cty.String,
}))),
"list": cty.NullVal(cty.List(cty.Object(map[string]cty.Type{
"name": cty.String,
}))),
"set": cty.NullVal(cty.Set(cty.Object(map[string]cty.Type{
"name": cty.String,
}))),
"single": cty.NullVal(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
}),
cty.ObjectVal(map[string]cty.Value{
"map": cty.MapVal(map[string]cty.Value{
"one": cty.UnknownVal(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
}),
"list": cty.ListVal([]cty.Value{
cty.UnknownVal(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
}),
"set": cty.SetVal([]cty.Value{
cty.UnknownVal(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
}),
"single": cty.UnknownVal(cty.Object(map[string]cty.Type{
"name": cty.String,
})),
}),
nil,
},
}

for name, test := range tests {
2 changes: 1 addition & 1 deletion version/version.go
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ import (
)

// The main version number that is being run at the moment.
var Version = "1.0.5"
var Version = "1.0.6"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release