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

88 lines
1.9 KiB
Go

package terraform
import (
"context"
"encoding/json"
"errors"
"io"
"os"
"path/filepath"
"github.com/databricks/cli/bundle"
tfjson "github.com/hashicorp/terraform-json"
)
// Partial representation of the Terraform state file format.
// We are only interested global version and serial numbers,
// plus resource types, names, modes, and ids.
type resourcesState struct {
Version int `json:"version"`
Resources []stateResource `json:"resources"`
}
const SupportedStateVersion = 4
type serialState struct {
Serial int `json:"serial"`
}
type stateResource struct {
Type string `json:"type"`
Name string `json:"name"`
Mode tfjson.ResourceMode `json:"mode"`
Instances []stateResourceInstance `json:"instances"`
}
type stateResourceInstance struct {
Attributes stateInstanceAttributes `json:"attributes"`
}
type stateInstanceAttributes struct {
ID string `json:"id"`
}
func IsLocalStateStale(local io.Reader, remote io.Reader) bool {
localState, err := loadState(local)
if err != nil {
return true
}
remoteState, err := loadState(remote)
if err != nil {
return false
}
return localState.Serial < remoteState.Serial
}
func loadState(input io.Reader) (*serialState, error) {
content, err := io.ReadAll(input)
if err != nil {
return nil, err
}
var s serialState
err = json.Unmarshal(content, &s)
if err != nil {
return nil, err
}
return &s, nil
}
func ParseResourcesState(ctx context.Context, b *bundle.Bundle) (*resourcesState, error) {
cacheDir, err := Dir(ctx, b)
if err != nil {
return nil, err
}
rawState, err := os.ReadFile(filepath.Join(cacheDir, TerraformStateFileName))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return &resourcesState{Version: SupportedStateVersion}, nil
}
return nil, err
}
var state resourcesState
err = json.Unmarshal(rawState, &state)
return &state, err
}