#2087: consul_catalog_entry can set a service

This commit is contained in:
Max Englander 2015-10-15 04:06:52 -04:00
parent fce89ec1ae
commit 7b9ec59258
2 changed files with 64 additions and 42 deletions

View File

@ -27,7 +27,7 @@ func (c *Config) Client() (*consulapi.Client, error) {
config.Scheme = c.Scheme config.Scheme = c.Scheme
} }
if c.Token != "" { if c.Token != "" {
config.Token = c.Token config.Token = c.Token
} }
client, err := consulapi.NewClient(config) client, err := consulapi.NewClient(config)

View File

@ -3,7 +3,6 @@ package consul
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"log"
consulapi "github.com/hashicorp/consul/api" consulapi "github.com/hashicorp/consul/api"
"github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/hashcode"
@ -19,38 +18,60 @@ func resourceConsulCatalogEntry() *schema.Resource {
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"address": &schema.Schema{ "address": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
"datacenter": &schema.Schema{ "datacenter": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"node": &schema.Schema{ "node": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
"service": &schema.Schema{ "service": &schema.Schema{
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
Elem: &schema.Resource { Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"service": &schema.Schema{ "address": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true,
},
"id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true, Required: true,
}, },
"port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
},
"tags": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
}, },
}, },
Set: resourceConsulCatalogEntryServicesHash, Set: resourceConsulCatalogEntryServicesHash,
}, },
"token": &schema.Schema{ "token": &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
}, },
}, },
@ -60,7 +81,7 @@ func resourceConsulCatalogEntry() *schema.Resource {
func resourceConsulCatalogEntryServicesHash(v interface{}) int { func resourceConsulCatalogEntryServicesHash(v interface{}) int {
var buf bytes.Buffer var buf bytes.Buffer
m := v.(map[string]interface{}) m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["service"].(string))) buf.WriteString(fmt.Sprintf("%s-", m["id"].(string)))
return hashcode.String(buf.String()) return hashcode.String(buf.String())
} }
@ -68,16 +89,12 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{})
client := meta.(*consulapi.Client) client := meta.(*consulapi.Client)
catalog := client.Catalog() catalog := client.Catalog()
// Resolve the datacenter first, all the other keys are dependent on this
var dc string var dc string
if v, ok := d.GetOk("datacenter"); ok { if v, ok := d.GetOk("datacenter"); ok {
dc = v.(string) dc = v.(string)
log.Printf("[DEBUG] Consul datacenter: %s", dc)
} else { } else {
log.Printf("[DEBUG] Resolving Consul datacenter...")
var err error var err error
dc, err = getDC(client) if dc, err = getDC(client); err != nil {
if err != nil {
return err return err
} }
} }
@ -93,30 +110,39 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{})
address := d.Get("address").(string) address := d.Get("address").(string)
node := d.Get("node").(string) node := d.Get("node").(string)
if rawServiceDefinition, ok := d.GetOk("service"); ok { if services, ok := d.GetOk("service"); ok {
rawServiceList := rawServiceDefinition.(*schema.Set).List() for _, rawService := range services.(*schema.Set).List() {
for _, rawService := range rawServiceList { serviceData := rawService.(map[string]interface{})
service, ok := rawService.(map[string]interface{})
if !ok { rawTags := serviceData["tags"].([]interface{})
return fmt.Errorf("Failed to unroll: %#v", rawService) tags := make([]string, len(rawTags))
for i, v := range rawTags {
tags[i] = v.(string)
} }
serviceName := service["service"].(string)
registration := consulapi.CatalogRegistration{ registration := consulapi.CatalogRegistration{
Node: node, Address: address, Datacenter: dc, Address: address,
Service: &consulapi.AgentService{Service: serviceName}, Datacenter: dc,
Node: node,
Service: &consulapi.AgentService{
Address: serviceData["address"].(string),
ID: serviceData["id"].(string),
Service: serviceData["name"].(string),
Port: serviceData["port"].(int),
Tags: tags,
},
} }
if _, err := catalog.Register(&registration, &wOpts); err != nil { if _, err := catalog.Register(&registration, &wOpts); err != nil {
return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' with service %s in %s: %v", return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' in %s: %v",
node, address, serviceName, dc, err) node, address, dc, err)
} }
} }
} else { } else {
registration := consulapi.CatalogRegistration{ registration := consulapi.CatalogRegistration{
Node: node, Address: address, Datacenter: dc, Address: address,
Datacenter: dc,
Node: node,
} }
if _, err := catalog.Register(&registration, &wOpts); err != nil { if _, err := catalog.Register(&registration, &wOpts); err != nil {
@ -126,8 +152,14 @@ func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{})
} }
// Update the resource // Update the resource
qOpts := consulapi.QueryOptions{Datacenter: dc}
if _, _, err := catalog.Node(node, &qOpts); err != nil {
return fmt.Errorf("Failed to read Consul catalog entry for node '%s' at address '%s' in %s: %v",
node, address, dc, err)
} else {
d.Set("datacenter", dc)
}
d.SetId(fmt.Sprintf("consul-catalog-node-%s-%s", node, address)) d.SetId(fmt.Sprintf("consul-catalog-node-%s-%s", node, address))
d.Set("datacenter", dc)
return nil return nil
} }
@ -139,19 +171,12 @@ func resourceConsulCatalogEntryRead(d *schema.ResourceData, meta interface{}) er
var dc string var dc string
if v, ok := d.GetOk("datacenter"); ok { if v, ok := d.GetOk("datacenter"); ok {
dc = v.(string) dc = v.(string)
log.Printf("[DEBUG] Consul datacenter: %s", dc)
} else {
return fmt.Errorf("Missing datacenter configuration")
}
var token string
if v, ok := d.GetOk("token"); ok {
token = v.(string)
} }
node := d.Get("node").(string) node := d.Get("node").(string)
// Setup the operations using the datacenter // Setup the operations using the datacenter
qOpts := consulapi.QueryOptions{Datacenter: dc, Token: token} qOpts := consulapi.QueryOptions{Datacenter: dc}
if _, _, err := catalog.Node(node, &qOpts); err != nil { if _, _, err := catalog.Node(node, &qOpts); err != nil {
return fmt.Errorf("Failed to get node '%s' from Consul catalog: %v", node, err) return fmt.Errorf("Failed to get node '%s' from Consul catalog: %v", node, err)
@ -168,10 +193,8 @@ func resourceConsulCatalogEntryDelete(d *schema.ResourceData, meta interface{})
var dc string var dc string
if v, ok := d.GetOk("datacenter"); ok { if v, ok := d.GetOk("datacenter"); ok {
dc = v.(string) dc = v.(string)
log.Printf("[DEBUG] Consul datacenter: %s", dc)
} else {
return fmt.Errorf("Missing datacenter configuration")
} }
var token string var token string
if v, ok := d.GetOk("token"); ok { if v, ok := d.GetOk("token"); ok {
token = v.(string) token = v.(string)
@ -196,4 +219,3 @@ func resourceConsulCatalogEntryDelete(d *schema.ResourceData, meta interface{})
d.SetId("") d.SetId("")
return nil return nil
} }