github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/terraform/state_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"path"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/go-test/deep"
    10  	"github.com/golang/mock/gomock"
    11  	"github.com/hashicorp/terraform/terraform"
    12  	"github.com/replicatedhq/ship/pkg/state"
    13  	state2 "github.com/replicatedhq/ship/pkg/test-mocks/state"
    14  	"github.com/replicatedhq/ship/pkg/testing/logger"
    15  	"github.com/replicatedhq/ship/pkg/testing/matchers"
    16  	"github.com/spf13/afero"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestPersistState(t *testing.T) {
    21  	tests := []struct {
    22  		name     string
    23  		state    string
    24  		instate  state.State
    25  		outstate state.State
    26  	}{
    27  		{
    28  			name: "post-delete state, mostly empty",
    29  			state: `{
    30      "version": 3,
    31      "terraform_version": "0.11.9",
    32      "serial": 3,
    33      "lineage": "3218b0ca-45de-2227-e420-f0d948f91e86",
    34      "modules": [
    35          {
    36              "path": [
    37                  "root"
    38              ],
    39              "outputs": {},
    40              "resources": {},
    41              "depends_on": []
    42          }
    43      ]
    44  }
    45  `,
    46  			instate: state.State{
    47  				V1: &state.V1{},
    48  			},
    49  			outstate: state.State{
    50  				V1: &state.V1{
    51  					Terraform: &state.Terraform{
    52  						RawState: `{
    53      "version": 3,
    54      "terraform_version": "0.11.9",
    55      "serial": 3,
    56      "lineage": "3218b0ca-45de-2227-e420-f0d948f91e86",
    57      "modules": [
    58          {
    59              "path": [
    60                  "root"
    61              ],
    62              "outputs": {},
    63              "resources": {},
    64              "depends_on": []
    65          }
    66      ]
    67  }
    68  `,
    69  						State: &terraform.State{
    70  							Version:   3,
    71  							TFVersion: "0.11.9",
    72  							Serial:    3,
    73  							Lineage:   "3218b0ca-45de-2227-e420-f0d948f91e86",
    74  							Modules: []*terraform.ModuleState{
    75  								{
    76  									Path: []string{
    77  										"root",
    78  									},
    79  									Outputs:      map[string]*terraform.OutputState{},
    80  									Resources:    map[string]*terraform.ResourceState{},
    81  									Dependencies: []string{},
    82  								},
    83  							},
    84  						},
    85  					},
    86  				},
    87  			},
    88  		},
    89  	}
    90  	for _, test := range tests {
    91  		t.Run(test.name, func(t *testing.T) {
    92  			mc := gomock.NewController(t)
    93  			req := require.New(t)
    94  			debug := &logger.TestLogger{T: t}
    95  			mockFs := afero.Afero{Fs: afero.NewMemMapFs()}
    96  			statemanager := state2.NewMockManager(mc)
    97  
    98  			err := mockFs.WriteFile("installer/terraform.tfstate", []byte(test.state), 0644)
    99  			req.NoError(err)
   100  
   101  			statemanager.EXPECT().CachedState().Return(test.instate, nil)
   102  			statemanager.EXPECT().Save(&matchers.Is{
   103  				Test: func(v interface{}) bool {
   104  					vstate := v.(state.State)
   105  					diff := deep.Equal(*vstate.V1.Terraform, *test.outstate.V1.Terraform)
   106  					t.Log(strings.Join(diff, "\n"))
   107  					return len(diff) == 0
   108  				},
   109  				Describe: fmt.Sprintf("equal to %+v", *test.outstate.V1.Terraform),
   110  			}).Return(nil)
   111  
   112  			err = persistState(debug, mockFs, statemanager, "installer")
   113  			req.NoError(err)
   114  
   115  			mc.Finish()
   116  
   117  		})
   118  	}
   119  }
   120  
   121  func TestRestoreState(t *testing.T) {
   122  	tests := []struct {
   123  		name       string
   124  		instate    state.State
   125  		expectFile string
   126  	}{
   127  		{
   128  			name: "post-delete state, mostly empty",
   129  			expectFile: `{
   130      "version": 3,
   131      "terraform_version": "0.11.9",
   132      "serial": 3,
   133      "lineage": "3218b0ca-45de-2227-e420-f0d948f91e86",
   134      "modules": [
   135          {
   136              "path": [
   137                  "root"
   138              ],
   139              "outputs": {},
   140              "resources": {},
   141              "depends_on": []
   142          }
   143      ]
   144  }
   145  `,
   146  			instate: state.State{
   147  				V1: &state.V1{
   148  					Terraform: &state.Terraform{
   149  						RawState: `{
   150      "version": 3,
   151      "terraform_version": "0.11.9",
   152      "serial": 3,
   153      "lineage": "3218b0ca-45de-2227-e420-f0d948f91e86",
   154      "modules": [
   155          {
   156              "path": [
   157                  "root"
   158              ],
   159              "outputs": {},
   160              "resources": {},
   161              "depends_on": []
   162          }
   163      ]
   164  }
   165  `,
   166  						State: &terraform.State{
   167  							Version:   3,
   168  							TFVersion: "0.11.9",
   169  							Serial:    3,
   170  							Lineage:   "3218b0ca-45de-2227-e420-f0d948f91e86",
   171  							Modules: []*terraform.ModuleState{
   172  								{
   173  									Path: []string{
   174  										"root",
   175  									},
   176  									Outputs:      map[string]*terraform.OutputState{},
   177  									Resources:    map[string]*terraform.ResourceState{},
   178  									Dependencies: []string{},
   179  								},
   180  							},
   181  						},
   182  					},
   183  				},
   184  			},
   185  		},
   186  	}
   187  	for _, test := range tests {
   188  		t.Run(test.name, func(t *testing.T) {
   189  			mc := gomock.NewController(t)
   190  			req := require.New(t)
   191  			debug := &logger.TestLogger{T: t}
   192  			mockFs := afero.Afero{Fs: afero.NewMemMapFs()}
   193  			statemanager := state2.NewMockManager(mc)
   194  
   195  			statemanager.EXPECT().CachedState().Return(test.instate, nil)
   196  
   197  			err := restoreState(debug, mockFs, statemanager, "installer")
   198  			req.NoError(err)
   199  
   200  			contents, err := mockFs.ReadFile(path.Join("installer", "terraform.tfstate"))
   201  			req.NoError(err)
   202  
   203  			req.Equal(test.expectFile, string(contents))
   204  
   205  			mc.Finish()
   206  
   207  		})
   208  	}
   209  }