databricks-cli/bundle/deploy/terraform/state_pull_test.go

129 lines
3.3 KiB
Go

package terraform
import (
"bytes"
"context"
"encoding/json"
"io"
"io/fs"
"os"
"testing"
"github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/config"
mock "github.com/databricks/cli/internal/mocks/libs/filer"
"github.com/databricks/cli/libs/filer"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
func mockStateFilerForPull(t *testing.T, contents map[string]int, merr error) filer.Filer {
buf, err := json.Marshal(contents)
require.NoError(t, err)
ctrl := gomock.NewController(t)
mock := mock.NewMockFiler(ctrl)
mock.
EXPECT().
Read(gomock.Any(), gomock.Eq(TerraformStateFileName)).
Return(io.NopCloser(bytes.NewReader(buf)), merr).
Times(1)
return mock
}
func statePullTestBundle(t *testing.T) *bundle.Bundle {
return &bundle.Bundle{
Config: config.Root{
Bundle: config.Bundle{
Target: "default",
},
Path: t.TempDir(),
},
}
}
func TestStatePullLocalMissingRemoteMissing(t *testing.T) {
m := &statePull{
identityFiler(mockStateFilerForPull(t, nil, os.ErrNotExist)),
}
ctx := context.Background()
b := statePullTestBundle(t)
err := bundle.Apply(ctx, b, m)
assert.NoError(t, err)
// Confirm that no local state file has been written.
_, err = os.Stat(localStateFile(t, ctx, b))
assert.ErrorIs(t, err, fs.ErrNotExist)
}
func TestStatePullLocalMissingRemotePresent(t *testing.T) {
m := &statePull{
identityFiler(mockStateFilerForPull(t, map[string]int{"serial": 5}, nil)),
}
ctx := context.Background()
b := statePullTestBundle(t)
err := bundle.Apply(ctx, b, m)
assert.NoError(t, err)
// Confirm that the local state file has been updated.
localState := readLocalState(t, ctx, b)
assert.Equal(t, map[string]int{"serial": 5}, localState)
}
func TestStatePullLocalStale(t *testing.T) {
m := &statePull{
identityFiler(mockStateFilerForPull(t, map[string]int{"serial": 5}, nil)),
}
ctx := context.Background()
b := statePullTestBundle(t)
// Write a stale local state file.
writeLocalState(t, ctx, b, map[string]int{"serial": 4})
err := bundle.Apply(ctx, b, m)
assert.NoError(t, err)
// Confirm that the local state file has been updated.
localState := readLocalState(t, ctx, b)
assert.Equal(t, map[string]int{"serial": 5}, localState)
}
func TestStatePullLocalEqual(t *testing.T) {
m := &statePull{
identityFiler(mockStateFilerForPull(t, map[string]int{"serial": 5, "some_other_key": 123}, nil)),
}
ctx := context.Background()
b := statePullTestBundle(t)
// Write a local state file with the same serial as the remote.
writeLocalState(t, ctx, b, map[string]int{"serial": 5})
err := bundle.Apply(ctx, b, m)
assert.NoError(t, err)
// Confirm that the local state file has not been updated.
localState := readLocalState(t, ctx, b)
assert.Equal(t, map[string]int{"serial": 5}, localState)
}
func TestStatePullLocalNewer(t *testing.T) {
m := &statePull{
identityFiler(mockStateFilerForPull(t, map[string]int{"serial": 5, "some_other_key": 123}, nil)),
}
ctx := context.Background()
b := statePullTestBundle(t)
// Write a local state file with a newer serial as the remote.
writeLocalState(t, ctx, b, map[string]int{"serial": 6})
err := bundle.Apply(ctx, b, m)
assert.NoError(t, err)
// Confirm that the local state file has not been updated.
localState := readLocalState(t, ctx, b)
assert.Equal(t, map[string]int{"serial": 6}, localState)
}