mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-05-11 09:00:56 -04:00
Both differing serials and lineage protections should be bypassed with the -force flag (in addition to resources). Compared to other backends we aren’t just shipping over the state bytes in a simple payload during the persistence phase of the push command and the force flag added to the Go TFE client needs to be specified at that time. To prevent changing every method signature of PersistState of the remote client I added an optional interface that provides a hook to flag the Client as operating in a force push context. Changing the method signature would be more explicit at the cost of not being used anywhere else currently or the optional interface pattern could be applied to the state itself so it could be upgraded to support PersistState(force bool) only when needed. Prior to this only the resources of the state were checked for changes not the lineage or the serial. To bring this in line with documented behavior noted above those attributes also have a “read” counterpart just like state has. These are now checked along with state to determine if the state as a whole is unchanged. Tests were altered to table driven test format and testing was expanded to include WriteStateForMigration and its interaction with a ClientForcePusher type.
56 lines
1.4 KiB
Go
56 lines
1.4 KiB
Go
package remote
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/state"
|
|
)
|
|
|
|
// Client is the interface that must be implemented for a remote state
|
|
// driver. It supports dumb put/get/delete, and the higher level structs
|
|
// handle persisting the state properly here.
|
|
type Client interface {
|
|
Get() (*Payload, error)
|
|
Put([]byte) error
|
|
Delete() error
|
|
}
|
|
|
|
// ClientForcePusher is an optional interface that allows a remote
|
|
// state to force push by managing a flag on the client that is
|
|
// toggled on by a call to EnableForcePush.
|
|
type ClientForcePusher interface {
|
|
Client
|
|
EnableForcePush()
|
|
}
|
|
|
|
// ClientLocker is an optional interface that allows a remote state
|
|
// backend to enable state lock/unlock.
|
|
type ClientLocker interface {
|
|
Client
|
|
state.Locker
|
|
}
|
|
|
|
// Payload is the return value from the remote state storage.
|
|
type Payload struct {
|
|
MD5 []byte
|
|
Data []byte
|
|
}
|
|
|
|
// Factory is the factory function to create a remote client.
|
|
type Factory func(map[string]string) (Client, error)
|
|
|
|
// NewClient returns a new Client with the given type and configuration.
|
|
// The client is looked up in the BuiltinClients variable.
|
|
func NewClient(t string, conf map[string]string) (Client, error) {
|
|
f, ok := BuiltinClients[t]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unknown remote client type: %s", t)
|
|
}
|
|
|
|
return f(conf)
|
|
}
|
|
|
|
// BuiltinClients is the list of built-in clients that can be used with
|
|
// NewClient.
|
|
var BuiltinClients = map[string]Factory{}
|