backend/consul: build your own backend
This commit is contained in:
parent
73006a243a
commit
3db55cf747
|
@ -6,67 +6,78 @@ import (
|
|||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/backend/remote-state"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
// New creates a new backend for Consul remote state.
|
||||
func New() backend.Backend {
|
||||
return &remotestate.Backend{
|
||||
ConfigureFunc: configure,
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Path to store state in Consul",
|
||||
},
|
||||
|
||||
// Set the schema
|
||||
Backend: &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Path to store state in Consul",
|
||||
},
|
||||
"access_token": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Access token for a Consul ACL",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
|
||||
"access_token": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Access token for a Consul ACL",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
"address": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Address to the Consul Cluster",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
|
||||
"address": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Address to the Consul Cluster",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
"scheme": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Scheme to communicate to Consul with",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
|
||||
"scheme": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Scheme to communicate to Consul with",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
"datacenter": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Datacenter to communicate with",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
|
||||
"datacenter": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Datacenter to communicate with",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
|
||||
"http_auth": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "HTTP Auth in the format of 'username:password'",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
"http_auth": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "HTTP Auth in the format of 'username:password'",
|
||||
Default: "", // To prevent input
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
func configure(ctx context.Context) (remote.Client, error) {
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
|
||||
configData *schema.ResourceData
|
||||
}
|
||||
|
||||
func (b *Backend) configure(ctx context.Context) error {
|
||||
// Grab the resource data
|
||||
data := schema.FromContextBackendConfig(ctx)
|
||||
b.configData = schema.FromContextBackendConfig(ctx)
|
||||
|
||||
// Initialize a client to test config
|
||||
_, err := b.clientRaw()
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Backend) clientRaw() (*consulapi.Client, error) {
|
||||
data := b.configData
|
||||
|
||||
// Configure the client
|
||||
config := consulapi.DefaultConfig()
|
||||
|
@ -100,13 +111,5 @@ func configure(ctx context.Context) (remote.Client, error) {
|
|||
}
|
||||
}
|
||||
|
||||
client, err := consulapi.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &RemoteClient{
|
||||
Client: client,
|
||||
Path: data.Get("path").(string),
|
||||
}, nil
|
||||
return consulapi.NewClient(config)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
func (b *Backend) States() ([]string, error) {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) DeleteState(name string) error {
|
||||
return backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) State(name string) (state.State, error) {
|
||||
if name != backend.DefaultStateName {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
// Get the Consul API client
|
||||
client, err := b.clientRaw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Determine the path of the data
|
||||
path := b.configData.Get("path").(string)
|
||||
|
||||
// Build the remote state client
|
||||
return &remote.State{
|
||||
Client: &RemoteClient{
|
||||
Client: client,
|
||||
Path: path,
|
||||
},
|
||||
}, nil
|
||||
}
|
|
@ -7,7 +7,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/backend/remote-state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
|
@ -29,8 +28,14 @@ func TestRemoteClient(t *testing.T) {
|
|||
"path": fmt.Sprintf("tf-unit/%s", time.Now().String()),
|
||||
})
|
||||
|
||||
// Grab the client
|
||||
state, err := b.State(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test
|
||||
remotestate.TestClient(t, b)
|
||||
remote.TestClient(t, state.(*remote.State).Client)
|
||||
}
|
||||
|
||||
func TestConsul_stateLock(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue