github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/legacy/terraform/upgrade_state_v2_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package terraform
     5  
     6  import (
     7  	"bytes"
     8  	"strings"
     9  	"testing"
    10  )
    11  
    12  // TestReadUpgradeStateV2toV3 tests the state upgrade process from the V2 state
    13  // to the current version, and needs editing each time. This means it tests the
    14  // entire pipeline of upgrades (which migrate version to version).
    15  func TestReadUpgradeStateV2toV3(t *testing.T) {
    16  	// ReadState should transparently detect the old version but will upgrade
    17  	// it on Write.
    18  	upgraded, err := ReadState(strings.NewReader(testV2State))
    19  	if err != nil {
    20  		t.Fatalf("err: %s", err)
    21  	}
    22  
    23  	buf := new(bytes.Buffer)
    24  	if err := WriteState(upgraded, buf); err != nil {
    25  		t.Fatalf("err: %s", err)
    26  	}
    27  
    28  	if upgraded.Version != 3 {
    29  		t.Fatalf("bad: State version not incremented; is %d", upgraded.Version)
    30  	}
    31  
    32  	// For this test we cannot assert that we match the round trip because an
    33  	// empty map has been removed from state. Instead we make assertions against
    34  	// some of the key fields in the _upgraded_ state.
    35  	instanceState, ok := upgraded.RootModule().Resources["test_resource.main"]
    36  	if !ok {
    37  		t.Fatalf("Instance state for test_resource.main was removed from state during upgrade")
    38  	}
    39  
    40  	primary := instanceState.Primary
    41  	if primary == nil {
    42  		t.Fatalf("Primary instance was removed from state for test_resource.main")
    43  	}
    44  
    45  	// Non-empty computed map is moved from .# to .%
    46  	if _, ok := primary.Attributes["computed_map.#"]; ok {
    47  		t.Fatalf("Count was not upgraded from .# to .%% for computed_map")
    48  	}
    49  	if count, ok := primary.Attributes["computed_map.%"]; !ok || count != "1" {
    50  		t.Fatalf("Count was not in .%% or was not 2 for computed_map")
    51  	}
    52  
    53  	// list_of_map top level retains .#
    54  	if count, ok := primary.Attributes["list_of_map.#"]; !ok || count != "2" {
    55  		t.Fatal("Count for list_of_map was migrated incorrectly")
    56  	}
    57  
    58  	// list_of_map.0 is moved from .# to .%
    59  	if _, ok := primary.Attributes["list_of_map.0.#"]; ok {
    60  		t.Fatalf("Count was not upgraded from .# to .%% for list_of_map.0")
    61  	}
    62  	if count, ok := primary.Attributes["list_of_map.0.%"]; !ok || count != "2" {
    63  		t.Fatalf("Count was not in .%% or was not 2 for list_of_map.0")
    64  	}
    65  
    66  	// list_of_map.1 is moved from .# to .%
    67  	if _, ok := primary.Attributes["list_of_map.1.#"]; ok {
    68  		t.Fatalf("Count was not upgraded from .# to .%% for list_of_map.1")
    69  	}
    70  	if count, ok := primary.Attributes["list_of_map.1.%"]; !ok || count != "2" {
    71  		t.Fatalf("Count was not in .%% or was not 2 for list_of_map.1")
    72  	}
    73  
    74  	// map is moved from .# to .%
    75  	if _, ok := primary.Attributes["map.#"]; ok {
    76  		t.Fatalf("Count was not upgraded from .# to .%% for map")
    77  	}
    78  	if count, ok := primary.Attributes["map.%"]; !ok || count != "2" {
    79  		t.Fatalf("Count was not in .%% or was not 2 for map")
    80  	}
    81  
    82  	// optional_computed_map should be removed from state
    83  	if _, ok := primary.Attributes["optional_computed_map"]; ok {
    84  		t.Fatal("optional_computed_map was not removed from state")
    85  	}
    86  
    87  	// required_map is moved from .# to .%
    88  	if _, ok := primary.Attributes["required_map.#"]; ok {
    89  		t.Fatalf("Count was not upgraded from .# to .%% for required_map")
    90  	}
    91  	if count, ok := primary.Attributes["required_map.%"]; !ok || count != "3" {
    92  		t.Fatalf("Count was not in .%% or was not 3 for map")
    93  	}
    94  
    95  	// computed_list keeps .#
    96  	if count, ok := primary.Attributes["computed_list.#"]; !ok || count != "2" {
    97  		t.Fatal("Count was migrated incorrectly for computed_list")
    98  	}
    99  
   100  	// computed_set keeps .#
   101  	if count, ok := primary.Attributes["computed_set.#"]; !ok || count != "2" {
   102  		t.Fatal("Count was migrated incorrectly for computed_set")
   103  	}
   104  	if val, ok := primary.Attributes["computed_set.2337322984"]; !ok || val != "setval1" {
   105  		t.Fatal("Set item for computed_set.2337322984 changed or moved")
   106  	}
   107  	if val, ok := primary.Attributes["computed_set.307881554"]; !ok || val != "setval2" {
   108  		t.Fatal("Set item for computed_set.307881554 changed or moved")
   109  	}
   110  
   111  	// string properties are unaffected
   112  	if val, ok := primary.Attributes["id"]; !ok || val != "testId" {
   113  		t.Fatal("id was not set correctly after migration")
   114  	}
   115  }
   116  
   117  const testV2State = `{
   118      "version": 2,
   119      "terraform_version": "0.7.0",
   120      "serial": 2,
   121      "modules": [
   122          {
   123              "path": [
   124                  "root"
   125              ],
   126              "outputs": {
   127                  "computed_map": {
   128                      "sensitive": false,
   129                      "type": "map",
   130                      "value": {
   131                          "key1": "value1"
   132                      }
   133                  },
   134                  "computed_set": {
   135                      "sensitive": false,
   136                      "type": "list",
   137                      "value": [
   138                          "setval1",
   139                          "setval2"
   140                      ]
   141                  },
   142                  "map": {
   143                      "sensitive": false,
   144                      "type": "map",
   145                      "value": {
   146                          "key": "test",
   147                          "test": "test"
   148                      }
   149                  },
   150                  "set": {
   151                      "sensitive": false,
   152                      "type": "list",
   153                      "value": [
   154                          "test1",
   155                          "test2"
   156                      ]
   157                  }
   158              },
   159              "resources": {
   160                  "test_resource.main": {
   161                      "type": "test_resource",
   162                      "primary": {
   163                          "id": "testId",
   164                          "attributes": {
   165                              "computed_list.#": "2",
   166                              "computed_list.0": "listval1",
   167                              "computed_list.1": "listval2",
   168                              "computed_map.#": "1",
   169                              "computed_map.key1": "value1",
   170                              "computed_read_only": "value_from_api",
   171                              "computed_read_only_force_new": "value_from_api",
   172                              "computed_set.#": "2",
   173                              "computed_set.2337322984": "setval1",
   174                              "computed_set.307881554": "setval2",
   175                              "id": "testId",
   176                              "list_of_map.#": "2",
   177                              "list_of_map.0.#": "2",
   178                              "list_of_map.0.key1": "value1",
   179                              "list_of_map.0.key2": "value2",
   180                              "list_of_map.1.#": "2",
   181                              "list_of_map.1.key3": "value3",
   182                              "list_of_map.1.key4": "value4",
   183                              "map.#": "2",
   184                              "map.key": "test",
   185                              "map.test": "test",
   186                              "map_that_look_like_set.#": "2",
   187                              "map_that_look_like_set.12352223": "hello",
   188                              "map_that_look_like_set.36234341": "world",
   189                              "optional_computed_map.#": "0",
   190                              "required": "Hello World",
   191                              "required_map.#": "3",
   192                              "required_map.key1": "value1",
   193                              "required_map.key2": "value2",
   194                              "required_map.key3": "value3",
   195                              "set.#": "2",
   196                              "set.2326977762": "test1",
   197                              "set.331058520": "test2"
   198                          }
   199                      }
   200                  }
   201              }
   202          }
   203      ]
   204  }
   205  `