provider/consul: Vast simplification
This commit is contained in:
parent
229e477413
commit
e4450fcd51
|
@ -1,394 +0,0 @@
|
||||||
package consul
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/armon/consul-api"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
)
|
|
||||||
|
|
||||||
type consulKeys map[string]*consulKey
|
|
||||||
|
|
||||||
type consulKey struct {
|
|
||||||
Key string
|
|
||||||
Value string
|
|
||||||
Default string
|
|
||||||
Delete bool
|
|
||||||
|
|
||||||
SetValue bool `mapstructure:"-"`
|
|
||||||
SetDefault bool `mapstructure:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_validate(c *terraform.ResourceConfig) (ws []string, es []error) {
|
|
||||||
conf := c.Raw
|
|
||||||
for k, v := range conf {
|
|
||||||
// datacenter is special and can be ignored
|
|
||||||
if k == "datacenter" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
keyList, ok := v.([]map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("Field '%s' must be map containing a key", k))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(keyList) > 1 {
|
|
||||||
es = append(es, fmt.Errorf("Field '%s' is defined more than once", k))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := keyList[0]
|
|
||||||
|
|
||||||
for sub, val := range key {
|
|
||||||
// Verify the sub-key is supported
|
|
||||||
switch sub {
|
|
||||||
case "key":
|
|
||||||
case "value":
|
|
||||||
case "default":
|
|
||||||
case "delete":
|
|
||||||
default:
|
|
||||||
es = append(es, fmt.Errorf("Field '%s' has unsupported config '%s'", k, sub))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify value is of the correct type
|
|
||||||
_, isStr := val.(string)
|
|
||||||
_, isBool := val.(bool)
|
|
||||||
if !isStr && sub != "delete" {
|
|
||||||
es = append(es, fmt.Errorf("Field '%s' must set '%s' as a string", key, sub))
|
|
||||||
}
|
|
||||||
if !isBool && sub == "delete" {
|
|
||||||
es = append(es, fmt.Errorf("Field '%s' must set '%s' as a bool", key, sub))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_create(
|
|
||||||
s *terraform.ResourceState,
|
|
||||||
d *terraform.ResourceDiff,
|
|
||||||
meta interface{}) (*terraform.ResourceState, error) {
|
|
||||||
p := meta.(*ResourceProvider)
|
|
||||||
if s.Attributes == nil {
|
|
||||||
s.Attributes = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the configuration
|
|
||||||
var config map[string]interface{}
|
|
||||||
for _, attr := range d.Attributes {
|
|
||||||
if attr.NewExtra != nil {
|
|
||||||
config = attr.NewExtra.(map[string]interface{})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config == nil {
|
|
||||||
return s, fmt.Errorf("Missing configuration state")
|
|
||||||
}
|
|
||||||
dc, keys, err := partsFromConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we are missing a datacenter
|
|
||||||
if dc == "" {
|
|
||||||
dc, err = get_dc(p.client)
|
|
||||||
}
|
|
||||||
s.Attributes["datacenter"] = dc
|
|
||||||
|
|
||||||
// Handle each of the keys
|
|
||||||
kv := p.client.KV()
|
|
||||||
qOpts := consulapi.QueryOptions{Datacenter: dc}
|
|
||||||
wOpts := consulapi.WriteOptions{Datacenter: dc}
|
|
||||||
for name, conf := range keys {
|
|
||||||
if conf.SetValue {
|
|
||||||
log.Printf("[DEBUG] Setting key '%s' to '%v' in %s", conf.Key, conf.Value, dc)
|
|
||||||
pair := consulapi.KVPair{Key: conf.Key, Value: []byte(conf.Value)}
|
|
||||||
if _, err := kv.Put(&pair, &wOpts); err != nil {
|
|
||||||
return s, fmt.Errorf("Failed to set Consul key '%s': %v", conf.Key, err)
|
|
||||||
}
|
|
||||||
s.Attributes[name] = conf.Value
|
|
||||||
} else {
|
|
||||||
log.Printf("[DEBUG] Getting key '%s' in %s", conf.Key, dc)
|
|
||||||
pair, _, err := kv.Get(conf.Key, &qOpts)
|
|
||||||
if err != nil {
|
|
||||||
return s, fmt.Errorf("Failed to get Consul key '%s': %v", conf.Key, err)
|
|
||||||
}
|
|
||||||
if pair == nil && conf.SetDefault {
|
|
||||||
s.Attributes[name] = conf.Default
|
|
||||||
} else if pair == nil {
|
|
||||||
s.Attributes[name] = ""
|
|
||||||
} else {
|
|
||||||
s.Attributes[name] = string(pair.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set an ID, store the config
|
|
||||||
s.ID = "consul"
|
|
||||||
s.Extra = config
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_destroy(
|
|
||||||
s *terraform.ResourceState,
|
|
||||||
meta interface{}) error {
|
|
||||||
p := meta.(*ResourceProvider)
|
|
||||||
client := p.client
|
|
||||||
kv := client.KV()
|
|
||||||
|
|
||||||
// Restore our configuration
|
|
||||||
dc, keys, err := partsFromConfig(s.Extra)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the DC if not given
|
|
||||||
if dc == "" {
|
|
||||||
dc = s.Attributes["datacenter"]
|
|
||||||
}
|
|
||||||
opts := consulapi.WriteOptions{Datacenter: dc}
|
|
||||||
for _, key := range keys {
|
|
||||||
// Skip any non-managed keys
|
|
||||||
if !key.Delete {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Printf("[DEBUG] Deleting key '%s' in %s", key.Key, dc)
|
|
||||||
if _, err := kv.Delete(key.Key, &opts); err != nil {
|
|
||||||
return fmt.Errorf("Failed to delete Consul key '%s': %v", key.Key, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_update(
|
|
||||||
s *terraform.ResourceState,
|
|
||||||
d *terraform.ResourceDiff,
|
|
||||||
meta interface{}) (*terraform.ResourceState, error) {
|
|
||||||
p := meta.(*ResourceProvider)
|
|
||||||
|
|
||||||
// Load the configuration
|
|
||||||
var config map[string]interface{}
|
|
||||||
for _, attr := range d.Attributes {
|
|
||||||
if attr.NewExtra != nil {
|
|
||||||
config = attr.NewExtra.(map[string]interface{})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if config == nil {
|
|
||||||
return s, fmt.Errorf("Missing configuration state")
|
|
||||||
}
|
|
||||||
dc, keys, err := partsFromConfig(config)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we are missing a datacenter
|
|
||||||
if dc == "" {
|
|
||||||
dc, err = get_dc(p.client)
|
|
||||||
}
|
|
||||||
s.Attributes["datacenter"] = dc
|
|
||||||
|
|
||||||
// Handle each of the updated keys
|
|
||||||
kv := p.client.KV()
|
|
||||||
qOpts := consulapi.QueryOptions{Datacenter: dc}
|
|
||||||
wOpts := consulapi.WriteOptions{Datacenter: dc}
|
|
||||||
for name := range d.Attributes {
|
|
||||||
if name == "datacenter" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
conf := keys[name]
|
|
||||||
if conf.SetValue {
|
|
||||||
log.Printf("[DEBUG] Setting key '%s' to '%v' in %s", conf.Key, conf.Value, dc)
|
|
||||||
pair := consulapi.KVPair{Key: conf.Key, Value: []byte(conf.Value)}
|
|
||||||
if _, err := kv.Put(&pair, &wOpts); err != nil {
|
|
||||||
return s, fmt.Errorf("Failed to set Consul key '%s': %v", conf.Key, err)
|
|
||||||
}
|
|
||||||
s.Attributes[name] = conf.Value
|
|
||||||
} else {
|
|
||||||
log.Printf("[DEBUG] Getting key '%s' in %s", conf.Key, dc)
|
|
||||||
pair, _, err := kv.Get(conf.Key, &qOpts)
|
|
||||||
if err != nil {
|
|
||||||
return s, fmt.Errorf("Failed to get Consul key '%s': %v", conf.Key, err)
|
|
||||||
}
|
|
||||||
if pair == nil && conf.SetDefault {
|
|
||||||
s.Attributes[name] = conf.Default
|
|
||||||
} else if pair == nil {
|
|
||||||
s.Attributes[name] = ""
|
|
||||||
} else {
|
|
||||||
s.Attributes[name] = string(pair.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the config
|
|
||||||
s.Extra = config
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_diff(
|
|
||||||
s *terraform.ResourceState,
|
|
||||||
c *terraform.ResourceConfig,
|
|
||||||
meta interface{}) (*terraform.ResourceDiff, error) {
|
|
||||||
// Parse the configuration
|
|
||||||
dc, keys, err := partsFromConfig(c.Config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the old values
|
|
||||||
oldValues := s.Attributes
|
|
||||||
|
|
||||||
// Initialize the diff set
|
|
||||||
attrs := make(map[string]*terraform.ResourceAttrDiff)
|
|
||||||
diff := &terraform.ResourceDiff{Attributes: attrs}
|
|
||||||
|
|
||||||
// Handle removed attributes
|
|
||||||
for key, oldVal := range oldValues {
|
|
||||||
if key == "datacenter" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, keep := keys[key]; !keep {
|
|
||||||
attrs[key] = &terraform.ResourceAttrDiff{
|
|
||||||
Old: oldVal,
|
|
||||||
NewRemoved: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle added or changed attributes
|
|
||||||
for key, conf := range keys {
|
|
||||||
aDiff := &terraform.ResourceAttrDiff{
|
|
||||||
Type: terraform.DiffAttrInput,
|
|
||||||
}
|
|
||||||
oldVal, ok := oldValues[key]
|
|
||||||
if conf.SetValue {
|
|
||||||
aDiff.New = conf.Value
|
|
||||||
} else {
|
|
||||||
aDiff.NewComputed = true
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
aDiff.Old = oldVal
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this is new or changed we need to refresh
|
|
||||||
if !ok || (conf.SetValue && oldVal != conf.Value) {
|
|
||||||
attrs[key] = aDiff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the DC has changed, require a destroy!
|
|
||||||
if old := oldValues["datacenter"]; dc != old {
|
|
||||||
aDiff := &terraform.ResourceAttrDiff{
|
|
||||||
Old: old,
|
|
||||||
New: dc,
|
|
||||||
RequiresNew: true,
|
|
||||||
Type: terraform.DiffAttrInput,
|
|
||||||
}
|
|
||||||
if aDiff.New == "" {
|
|
||||||
aDiff.NewComputed = true
|
|
||||||
}
|
|
||||||
attrs["datacenter"] = aDiff
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure one of the attributes contains the configuration
|
|
||||||
if len(attrs) > 0 {
|
|
||||||
for _, aDiff := range attrs {
|
|
||||||
aDiff.NewExtra = c.Config
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return diff, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func resource_consul_keys_refresh(
|
|
||||||
s *terraform.ResourceState,
|
|
||||||
meta interface{}) (*terraform.ResourceState, error) {
|
|
||||||
p := meta.(*ResourceProvider)
|
|
||||||
client := p.client
|
|
||||||
kv := client.KV()
|
|
||||||
|
|
||||||
// Restore our configuration
|
|
||||||
dc, keys, err := partsFromConfig(s.Extra)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we are missing a datacenter
|
|
||||||
if dc == "" {
|
|
||||||
dc, err = get_dc(p.client)
|
|
||||||
if err != nil {
|
|
||||||
return s, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the attributes
|
|
||||||
s.Attributes["datacenter"] = dc
|
|
||||||
opts := consulapi.QueryOptions{Datacenter: dc}
|
|
||||||
for name, key := range keys {
|
|
||||||
pair, _, err := kv.Get(key.Key, &opts)
|
|
||||||
if err != nil {
|
|
||||||
return s, fmt.Errorf("Failed to get key '%s' from Consul: %v", key.Key, err)
|
|
||||||
}
|
|
||||||
if pair == nil && key.SetDefault {
|
|
||||||
s.Attributes[name] = key.Default
|
|
||||||
} else if pair == nil {
|
|
||||||
s.Attributes[name] = ""
|
|
||||||
} else {
|
|
||||||
s.Attributes[name] = string(pair.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// partsFromConfig extracts the relevant configuration from the raw format
|
|
||||||
func partsFromConfig(raw map[string]interface{}) (string, consulKeys, error) {
|
|
||||||
var dc string
|
|
||||||
keys := make(map[string]*consulKey)
|
|
||||||
for k, v := range raw {
|
|
||||||
// datacenter is special and can be ignored
|
|
||||||
if k == "datacenter" {
|
|
||||||
vStr, ok := v.(string)
|
|
||||||
if !ok {
|
|
||||||
return "", nil, fmt.Errorf("datacenter must be a string")
|
|
||||||
}
|
|
||||||
dc = vStr
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
confs, ok := v.([]map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return "", nil, fmt.Errorf("Field '%s' must be map containing a key", k)
|
|
||||||
}
|
|
||||||
if len(confs) > 1 {
|
|
||||||
return "", nil, fmt.Errorf("Field '%s' has duplicate definitions", k)
|
|
||||||
}
|
|
||||||
conf := confs[0]
|
|
||||||
|
|
||||||
key := &consulKey{}
|
|
||||||
if err := mapstructure.WeakDecode(conf, key); err != nil {
|
|
||||||
return "", nil, fmt.Errorf("Field '%s' failed to decode: %v", k, err)
|
|
||||||
}
|
|
||||||
for sub := range conf {
|
|
||||||
switch sub {
|
|
||||||
case "value":
|
|
||||||
key.SetValue = true
|
|
||||||
case "default":
|
|
||||||
key.SetDefault = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keys[k] = key
|
|
||||||
}
|
|
||||||
return dc, keys, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// get_dc is used to get the datacenter of the local agent
|
|
||||||
func get_dc(client *consulapi.Client) (string, error) {
|
|
||||||
info, err := client.Agent().Self()
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Failed to get datacenter from Consul agent: %v", err)
|
|
||||||
}
|
|
||||||
dc := info["Config"]["Datacenter"].(string)
|
|
||||||
return dc, nil
|
|
||||||
}
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
package consul
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/armon/consul-api"
|
||||||
|
"github.com/hashicorp/terraform/flatmap"
|
||||||
|
"github.com/hashicorp/terraform/helper/config"
|
||||||
|
"github.com/hashicorp/terraform/helper/diff"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resource_consul_keys_validation() *config.Validator {
|
||||||
|
return &config.Validator{
|
||||||
|
Required: []string{
|
||||||
|
"key.*.name",
|
||||||
|
"key.*.path",
|
||||||
|
},
|
||||||
|
Optional: []string{
|
||||||
|
"datacenter",
|
||||||
|
"key.*.value",
|
||||||
|
"key.*.default",
|
||||||
|
"key.*.delete",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resource_consul_keys_create(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
d *terraform.ResourceDiff,
|
||||||
|
meta interface{}) (*terraform.ResourceState, error) {
|
||||||
|
p := meta.(*ResourceProvider)
|
||||||
|
|
||||||
|
// Merge the diff into the state so that we have all the attributes
|
||||||
|
// properly.
|
||||||
|
rs := s.MergeDiff(d)
|
||||||
|
|
||||||
|
// Check if the datacenter should be computed
|
||||||
|
dc := rs.Attributes["datacenter"]
|
||||||
|
if aDiff, ok := d.Attributes["datacenter"]; ok && aDiff.NewComputed {
|
||||||
|
var err error
|
||||||
|
dc, err = get_dc(p.client)
|
||||||
|
if err != nil {
|
||||||
|
return rs, fmt.Errorf("Failed to get agent datacenter: %v", err)
|
||||||
|
}
|
||||||
|
rs.Attributes["datacenter"] = dc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the keys
|
||||||
|
keys, ok := flatmap.Expand(rs.Attributes, "key").([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to unroll keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
kv := p.client.KV()
|
||||||
|
qOpts := consulapi.QueryOptions{Datacenter: dc}
|
||||||
|
wOpts := consulapi.WriteOptions{Datacenter: dc}
|
||||||
|
for _, raw := range keys {
|
||||||
|
sub := raw.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to unroll: %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, ok := sub["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to expand key '%#v'", sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
path, ok := sub["path"].(string)
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to get path for key '%s'", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
valueRaw, shouldSet := sub["value"]
|
||||||
|
if shouldSet {
|
||||||
|
value, ok := valueRaw.(string)
|
||||||
|
if !ok {
|
||||||
|
return rs, fmt.Errorf("Failed to get value for key '%s'", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Setting key '%s' to '%v' in %s", path, value, dc)
|
||||||
|
pair := consulapi.KVPair{Key: path, Value: []byte(value)}
|
||||||
|
if _, err := kv.Put(&pair, &wOpts); err != nil {
|
||||||
|
return rs, fmt.Errorf("Failed to set Consul key '%s': %v", path, err)
|
||||||
|
}
|
||||||
|
rs.Attributes[fmt.Sprintf("var.%s", key)] = value
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Getting key '%s' in %s", path, dc)
|
||||||
|
pair, _, err := kv.Get(path, &qOpts)
|
||||||
|
if err != nil {
|
||||||
|
return rs, fmt.Errorf("Failed to get Consul key '%s': %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a default value
|
||||||
|
var defaultVal string
|
||||||
|
setDefault := false
|
||||||
|
if raw, ok := sub["default"]; ok {
|
||||||
|
switch def := raw.(type) {
|
||||||
|
case string:
|
||||||
|
setDefault = true
|
||||||
|
defaultVal = def
|
||||||
|
case bool:
|
||||||
|
setDefault = true
|
||||||
|
defaultVal = strconv.FormatBool(def)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pair == nil && setDefault {
|
||||||
|
rs.Attributes[fmt.Sprintf("var.%s", key)] = defaultVal
|
||||||
|
} else if pair == nil {
|
||||||
|
rs.Attributes[fmt.Sprintf("var.%s", key)] = ""
|
||||||
|
} else {
|
||||||
|
rs.Attributes[fmt.Sprintf("var.%s", key)] = string(pair.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set an ID
|
||||||
|
rs.ID = "consul"
|
||||||
|
return rs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resource_consul_keys_destroy(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
meta interface{}) error {
|
||||||
|
p := meta.(*ResourceProvider)
|
||||||
|
client := p.client
|
||||||
|
kv := client.KV()
|
||||||
|
|
||||||
|
// Get the keys
|
||||||
|
keys, ok := flatmap.Expand(s.Attributes, "key").([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Failed to unroll keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
dc := s.Attributes["datacenter"]
|
||||||
|
wOpts := consulapi.WriteOptions{Datacenter: dc}
|
||||||
|
for _, raw := range keys {
|
||||||
|
sub := raw.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Failed to unroll: %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore if the key is non-managed
|
||||||
|
shouldDelete, ok := sub["delete"].(bool)
|
||||||
|
if !ok || !shouldDelete {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
key, ok := sub["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Failed to expand key '%#v'", sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
path, ok := sub["path"].(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Failed to get path for key '%s'", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Deleting key '%s' in %s", path, dc)
|
||||||
|
_, err := kv.Delete(path, &wOpts)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to delete Consul key '%s': %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resource_consul_keys_update(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
d *terraform.ResourceDiff,
|
||||||
|
meta interface{}) (*terraform.ResourceState, error) {
|
||||||
|
panic("cannot update")
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resource_consul_keys_diff(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
c *terraform.ResourceConfig,
|
||||||
|
meta interface{}) (*terraform.ResourceDiff, error) {
|
||||||
|
|
||||||
|
// Get the list of keys
|
||||||
|
var computed []string
|
||||||
|
keys, ok := flatmap.Expand(flatmap.Flatten(c.Config), "key").([]interface{})
|
||||||
|
if !ok {
|
||||||
|
goto AFTER
|
||||||
|
}
|
||||||
|
for _, sub := range keys {
|
||||||
|
subMap, ok := sub.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nameRaw, ok := subMap["name"]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name, ok := nameRaw.(string)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
computed = append(computed, "var."+name)
|
||||||
|
}
|
||||||
|
|
||||||
|
AFTER:
|
||||||
|
b := &diff.ResourceBuilder{
|
||||||
|
Attrs: map[string]diff.AttrType{
|
||||||
|
"datacenter": diff.AttrTypeCreate,
|
||||||
|
"key": diff.AttrTypeUpdate,
|
||||||
|
},
|
||||||
|
ComputedAttrs: computed,
|
||||||
|
}
|
||||||
|
return b.Diff(s, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resource_consul_keys_refresh(
|
||||||
|
s *terraform.ResourceState,
|
||||||
|
meta interface{}) (*terraform.ResourceState, error) {
|
||||||
|
p := meta.(*ResourceProvider)
|
||||||
|
client := p.client
|
||||||
|
kv := client.KV()
|
||||||
|
|
||||||
|
// Get the list of keys
|
||||||
|
keys, ok := flatmap.Expand(s.Attributes, "key").([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to unroll keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update each key
|
||||||
|
dc := s.Attributes["datacenter"]
|
||||||
|
opts := consulapi.QueryOptions{Datacenter: dc}
|
||||||
|
for _, raw := range keys {
|
||||||
|
sub := raw.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to unroll: %#v", raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
key, ok := sub["name"].(string)
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to expand key '%#v'", sub)
|
||||||
|
}
|
||||||
|
|
||||||
|
path, ok := sub["path"].(string)
|
||||||
|
if !ok {
|
||||||
|
return s, fmt.Errorf("Failed to get path for key '%s'", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Refreshing value of key '%s' in %s", path, dc)
|
||||||
|
pair, _, err := kv.Get(path, &opts)
|
||||||
|
if err != nil {
|
||||||
|
return s, fmt.Errorf("Failed to get value for path '%s' from Consul: %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for a default value
|
||||||
|
var defaultVal string
|
||||||
|
setDefault := false
|
||||||
|
if raw, ok := sub["default"]; ok {
|
||||||
|
switch def := raw.(type) {
|
||||||
|
case string:
|
||||||
|
setDefault = true
|
||||||
|
defaultVal = def
|
||||||
|
case bool:
|
||||||
|
setDefault = true
|
||||||
|
defaultVal = strconv.FormatBool(def)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pair == nil && setDefault {
|
||||||
|
s.Attributes[fmt.Sprintf("var.%s", key)] = defaultVal
|
||||||
|
} else if pair == nil {
|
||||||
|
s.Attributes[fmt.Sprintf("var.%s", key)] = ""
|
||||||
|
} else {
|
||||||
|
s.Attributes[fmt.Sprintf("var.%s", key)] = string(pair.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_dc is used to get the datacenter of the local agent
|
||||||
|
func get_dc(client *consulapi.Client) (string, error) {
|
||||||
|
info, err := client.Agent().Self()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Failed to get datacenter from Consul agent: %v", err)
|
||||||
|
}
|
||||||
|
dc := info["Config"]["Datacenter"].(string)
|
||||||
|
return dc, nil
|
||||||
|
}
|
|
@ -62,7 +62,7 @@ func testAccCheckConsulKeysValue(n, attr, val string) resource.TestCheckFunc {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Resource not found")
|
return fmt.Errorf("Resource not found")
|
||||||
}
|
}
|
||||||
out, ok := rn.Attributes[attr]
|
out, ok := rn.Attributes["var."+attr]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Attribute '%s' not found: %#v", attr, rn.Attributes)
|
return fmt.Errorf("Attribute '%s' not found: %#v", attr, rn.Attributes)
|
||||||
}
|
}
|
||||||
|
@ -79,15 +79,18 @@ func testAccCheckConsulKeysValue(n, attr, val string) resource.TestCheckFunc {
|
||||||
const testAccConsulKeysConfig = `
|
const testAccConsulKeysConfig = `
|
||||||
resource "consul_keys" "app" {
|
resource "consul_keys" "app" {
|
||||||
datacenter = "nyc1"
|
datacenter = "nyc1"
|
||||||
time {
|
key {
|
||||||
key = "global/time"
|
name = "time"
|
||||||
|
path = "global/time"
|
||||||
}
|
}
|
||||||
enabled {
|
key {
|
||||||
key = "test/enabled"
|
name = "enabled"
|
||||||
|
path = "test/enabled"
|
||||||
default = "true"
|
default = "true"
|
||||||
}
|
}
|
||||||
set {
|
key {
|
||||||
key = "test/set"
|
name = "set"
|
||||||
|
path = "test/set"
|
||||||
value = "acceptance"
|
value = "acceptance"
|
||||||
delete = true
|
delete = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,7 @@ func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []er
|
||||||
|
|
||||||
func (p *ResourceProvider) ValidateResource(
|
func (p *ResourceProvider) ValidateResource(
|
||||||
t string, c *terraform.ResourceConfig) ([]string, []error) {
|
t string, c *terraform.ResourceConfig) ([]string, []error) {
|
||||||
switch t {
|
return resourceMap.Validate(t, c)
|
||||||
case "consul_keys":
|
|
||||||
return resource_consul_keys_validate(c)
|
|
||||||
default:
|
|
||||||
return resourceMap.Validate(t, c)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
|
func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error {
|
||||||
|
|
|
@ -13,7 +13,7 @@ var testAccProvider *ResourceProvider
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
testAccProvider = new(ResourceProvider)
|
testAccProvider = new(ResourceProvider)
|
||||||
testAccProvider.Config.Address = "demo.consul.io:80"
|
//testAccProvider.Config.Address = "demo.consul.io:80"
|
||||||
testAccProviders = map[string]terraform.ResourceProvider{
|
testAccProviders = map[string]terraform.ResourceProvider{
|
||||||
"consul": testAccProvider,
|
"consul": testAccProvider,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,12 @@ func init() {
|
||||||
resourceMap = &resource.Map{
|
resourceMap = &resource.Map{
|
||||||
Mapping: map[string]resource.Resource{
|
Mapping: map[string]resource.Resource{
|
||||||
"consul_keys": resource.Resource{
|
"consul_keys": resource.Resource{
|
||||||
Create: resource_consul_keys_create,
|
ConfigValidator: resource_consul_keys_validation(),
|
||||||
Destroy: resource_consul_keys_destroy,
|
Create: resource_consul_keys_create,
|
||||||
Update: resource_consul_keys_update,
|
Destroy: resource_consul_keys_destroy,
|
||||||
Diff: resource_consul_keys_diff,
|
Update: resource_consul_keys_update,
|
||||||
Refresh: resource_consul_keys_refresh,
|
Diff: resource_consul_keys_diff,
|
||||||
|
Refresh: resource_consul_keys_refresh,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue