mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Migration of null resource to terraform data (#2481)
Signed-off-by: Ilia Gogotchuri <ilia.gogotchuri0@gmail.com>
This commit is contained in:
parent
7ad0af1f4c
commit
ec4e0cf0e2
@ -17,6 +17,7 @@ ENHANCEMENTS:
|
|||||||
* State encryption now supports using external programs as key providers. Additionally, the PBKDF2 key provider now supports chaining via the `chain` parameter. ([#2023](https://github.com/opentofu/opentofu/pull/2023))
|
* State encryption now supports using external programs as key providers. Additionally, the PBKDF2 key provider now supports chaining via the `chain` parameter. ([#2023](https://github.com/opentofu/opentofu/pull/2023))
|
||||||
* The `element` function now accepts negative indices, which extends the existing "wrapping" model into the negative direction. In particular, choosing element `-1` selects the final element in the sequence. ([#2371](https://github.com/opentofu/opentofu/pull/2371))
|
* The `element` function now accepts negative indices, which extends the existing "wrapping" model into the negative direction. In particular, choosing element `-1` selects the final element in the sequence. ([#2371](https://github.com/opentofu/opentofu/pull/2371))
|
||||||
* `moved` now supports moving between different types ([#2370](https://github.com/opentofu/opentofu/pull/2370))
|
* `moved` now supports moving between different types ([#2370](https://github.com/opentofu/opentofu/pull/2370))
|
||||||
|
* `moved` block can now be used to migrate from the `null_resource` to the `terraform_data` resource. ([#2481](https://github.com/opentofu/opentofu/pull/2481))
|
||||||
|
|
||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
|
@ -169,11 +169,14 @@ func (p *Provider) ImportResourceState(req providers.ImportResourceStateRequest)
|
|||||||
panic("unimplemented - terraform_remote_state has no resources")
|
panic("unimplemented - terraform_remote_state has no resources")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MoveResourceState is called when the state loader encounters an instance state
|
||||||
|
// that has been moved to a new type, and the state should be updated to reflect the change.
|
||||||
|
// This is used to move the old state to the new schema.
|
||||||
func (p *Provider) MoveResourceState(r providers.MoveResourceStateRequest) (resp providers.MoveResourceStateResponse) {
|
func (p *Provider) MoveResourceState(r providers.MoveResourceStateRequest) (resp providers.MoveResourceStateResponse) {
|
||||||
panic("unimplmented")
|
return moveDataStoreResourceState(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateResourceConfig is used to to validate the resource configuration values.
|
// ValidateResourceConfig is used to validate the resource configuration values.
|
||||||
func (p *Provider) ValidateResourceConfig(req providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse {
|
func (p *Provider) ValidateResourceConfig(req providers.ValidateResourceConfigRequest) providers.ValidateResourceConfigResponse {
|
||||||
return validateDataStoreResourceConfig(req)
|
return validateDataStoreResourceConfig(req)
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,54 @@ func upgradeDataStoreResourceState(req providers.UpgradeResourceStateRequest) (r
|
|||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nullResourceSchema returns a schema for a null_resource with relevant attributes for type migration.
|
||||||
|
func nullResourceSchema() providers.Schema {
|
||||||
|
return providers.Schema{
|
||||||
|
Block: &configschema.Block{
|
||||||
|
Attributes: map[string]*configschema.Attribute{
|
||||||
|
"triggers": {Type: cty.Map(cty.String), Optional: true},
|
||||||
|
"id": {Type: cty.String, Computed: true},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func moveDataStoreResourceState(req providers.MoveResourceStateRequest) providers.MoveResourceStateResponse {
|
||||||
|
var resp providers.MoveResourceStateResponse
|
||||||
|
if req.SourceTypeName != "null_resource" || req.TargetTypeName != "terraform_data" {
|
||||||
|
resp.Diagnostics = resp.Diagnostics.Append(
|
||||||
|
fmt.Errorf("unsupported move: %s -> %s; only move from null_resource to terraform_data is supported",
|
||||||
|
req.SourceTypeName, req.TargetTypeName))
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
nullTy := nullResourceSchema().Block.ImpliedType()
|
||||||
|
oldState, err := ctyjson.Unmarshal(req.SourceStateJSON, nullTy)
|
||||||
|
if err != nil {
|
||||||
|
resp.Diagnostics = resp.Diagnostics.Append(err)
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
oldStateMap := oldState.AsValueMap()
|
||||||
|
newStateMap := map[string]cty.Value{}
|
||||||
|
|
||||||
|
if trigger, ok := oldStateMap["triggers"]; ok && !trigger.IsNull() {
|
||||||
|
newStateMap["triggers_replace"] = cty.ObjectVal(trigger.AsValueMap())
|
||||||
|
}
|
||||||
|
if id, ok := oldStateMap["id"]; ok && !id.IsNull() {
|
||||||
|
newStateMap["id"] = id
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSchema := dataStoreResourceSchema()
|
||||||
|
newState, err := currentSchema.Block.CoerceValue(cty.ObjectVal(newStateMap))
|
||||||
|
if err != nil {
|
||||||
|
resp.Diagnostics = resp.Diagnostics.Append(err)
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
resp.TargetState = newState
|
||||||
|
resp.TargetPrivate = req.SourcePrivate
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
func readDataStoreResourceState(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
|
func readDataStoreResourceState(req providers.ReadResourceRequest) (resp providers.ReadResourceResponse) {
|
||||||
resp.NewState = req.PriorState
|
resp.NewState = req.PriorState
|
||||||
return resp
|
return resp
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package tf
|
package tf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -82,6 +83,57 @@ func TestManagedDataUpgradeState(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestManagedDataMovedState(t *testing.T) {
|
||||||
|
nullSchema := nullResourceSchema()
|
||||||
|
nullTy := nullSchema.Block.ImpliedType()
|
||||||
|
|
||||||
|
state := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"triggers": cty.MapVal(map[string]cty.Value{
|
||||||
|
"examplekey": cty.StringVal("value"),
|
||||||
|
}),
|
||||||
|
"id": cty.StringVal("not-quite-unique"),
|
||||||
|
})
|
||||||
|
|
||||||
|
jsState, err := ctyjson.Marshal(state, nullTy)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty request should fail
|
||||||
|
req := providers.MoveResourceStateRequest{}
|
||||||
|
|
||||||
|
resp := moveDataStoreResourceState(req)
|
||||||
|
if !resp.Diagnostics.HasErrors() {
|
||||||
|
t.Fatalf("expected error, got %#v", resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// valid request
|
||||||
|
req = providers.MoveResourceStateRequest{
|
||||||
|
TargetTypeName: "terraform_data",
|
||||||
|
SourceTypeName: "null_resource",
|
||||||
|
SourcePrivate: []byte("PRIVATE"),
|
||||||
|
SourceStateJSON: jsState,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = moveDataStoreResourceState(req)
|
||||||
|
|
||||||
|
expectedState := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"triggers_replace": cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"examplekey": cty.StringVal("value"),
|
||||||
|
}),
|
||||||
|
"id": cty.StringVal("not-quite-unique"),
|
||||||
|
"input": cty.NullVal(cty.DynamicPseudoType),
|
||||||
|
"output": cty.NullVal(cty.DynamicPseudoType),
|
||||||
|
})
|
||||||
|
if !resp.TargetState.RawEquals(expectedState) {
|
||||||
|
t.Errorf("prior state was:\n%#v\nmoved state is:\n%#v\n", expectedState, resp.TargetState)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(resp.TargetPrivate, req.SourcePrivate) {
|
||||||
|
t.Error("expected private data to be copied")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
func TestManagedDataRead(t *testing.T) {
|
func TestManagedDataRead(t *testing.T) {
|
||||||
req := providers.ReadResourceRequest{
|
req := providers.ReadResourceRequest{
|
||||||
TypeName: "terraform_data",
|
TypeName: "terraform_data",
|
||||||
|
@ -11,6 +11,7 @@ This page will run you through the most important changes in OpenTofu 1.10:
|
|||||||
|
|
||||||
- [New features](#new-features)
|
- [New features](#new-features)
|
||||||
- [New built-in functions](#new-built-in-functions)
|
- [New built-in functions](#new-built-in-functions)
|
||||||
|
- [Moved for different resource types](#moved-for-different-resource-types)
|
||||||
- [Improvements to existing features](#improvements-to-existing-features)
|
- [Improvements to existing features](#improvements-to-existing-features)
|
||||||
- [External programs as encryption key providers (experimental)](#external-programs-as-encryption-key-providers-experimental)
|
- [External programs as encryption key providers (experimental)](#external-programs-as-encryption-key-providers-experimental)
|
||||||
- [Smaller improvements](#smaller-improvements)
|
- [Smaller improvements](#smaller-improvements)
|
||||||
@ -28,6 +29,11 @@ New builtin provider functions added ([#2306](https://github.com/opentofu/opento
|
|||||||
- `provider::terraform::encode_tfvars` - Encode an object into a string with the same format as a TFVars file.
|
- `provider::terraform::encode_tfvars` - Encode an object into a string with the same format as a TFVars file.
|
||||||
- `provider::terraform::encode_expr` - Encode an arbitrary expression into a string with valid OpenTofu syntax.
|
- `provider::terraform::encode_expr` - Encode an arbitrary expression into a string with valid OpenTofu syntax.
|
||||||
|
|
||||||
|
### Moved for different resource types
|
||||||
|
|
||||||
|
- `moved` block can now be used to migrate between different types of resources ([docs](../language/modules/develop/refactoring.mdx#changing-a-resource-type)).
|
||||||
|
- Builtin provider now supports migration from `null_resource` to `terraform_data` resource.
|
||||||
|
|
||||||
## Improvements to existing features
|
## Improvements to existing features
|
||||||
|
|
||||||
### External programs as encryption key providers (experimental)
|
### External programs as encryption key providers (experimental)
|
||||||
|
@ -63,6 +63,7 @@ resource "terraform_data" "bootstrap" {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`moved` block can be used to migrate from the `null_resource` to the `terraform_data` resource. [Migration guide](https://search.opentofu.org/provider/hashicorp/null/latest/docs/guides/terraform-migration)
|
||||||
|
|
||||||
## Argument Reference
|
## Argument Reference
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user