github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/consul/resource_consul_catalog_entry.go (about)

     1  package consul
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  
     9  	consulapi "github.com/hashicorp/consul/api"
    10  	"github.com/hashicorp/terraform/helper/hashcode"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceConsulCatalogEntry() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceConsulCatalogEntryCreate,
    17  		Update: resourceConsulCatalogEntryCreate,
    18  		Read:   resourceConsulCatalogEntryRead,
    19  		Delete: resourceConsulCatalogEntryDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"address": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  				ForceNew: true,
    26  			},
    27  
    28  			"datacenter": &schema.Schema{
    29  				Type:     schema.TypeString,
    30  				Optional: true,
    31  				Computed: true,
    32  				ForceNew: true,
    33  			},
    34  
    35  			"node": &schema.Schema{
    36  				Type:     schema.TypeString,
    37  				Required: true,
    38  				ForceNew: true,
    39  			},
    40  
    41  			"service": &schema.Schema{
    42  				Type:     schema.TypeSet,
    43  				Optional: true,
    44  				ForceNew: true,
    45  				Elem: &schema.Resource{
    46  					Schema: map[string]*schema.Schema{
    47  						"address": &schema.Schema{
    48  							Type:     schema.TypeString,
    49  							Optional: true,
    50  							ForceNew: true,
    51  						},
    52  
    53  						"id": &schema.Schema{
    54  							Type:     schema.TypeString,
    55  							Optional: true,
    56  							Computed: true,
    57  							ForceNew: true,
    58  						},
    59  
    60  						"name": &schema.Schema{
    61  							Type:     schema.TypeString,
    62  							Required: true,
    63  							ForceNew: true,
    64  						},
    65  
    66  						"port": &schema.Schema{
    67  							Type:     schema.TypeInt,
    68  							Optional: true,
    69  							ForceNew: true,
    70  						},
    71  
    72  						"tags": &schema.Schema{
    73  							Type:     schema.TypeSet,
    74  							Optional: true,
    75  							ForceNew: true,
    76  							Elem:     &schema.Schema{Type: schema.TypeString},
    77  							Set:      resourceConsulCatalogEntryServiceTagsHash,
    78  						},
    79  					},
    80  				},
    81  				Set: resourceConsulCatalogEntryServicesHash,
    82  			},
    83  
    84  			"token": &schema.Schema{
    85  				Type:     schema.TypeString,
    86  				Optional: true,
    87  			},
    88  		},
    89  	}
    90  }
    91  
    92  func resourceConsulCatalogEntryServiceTagsHash(v interface{}) int {
    93  	return hashcode.String(v.(string))
    94  }
    95  
    96  func resourceConsulCatalogEntryServicesHash(v interface{}) int {
    97  	var buf bytes.Buffer
    98  	m := v.(map[string]interface{})
    99  	buf.WriteString(fmt.Sprintf("%s-", m["id"].(string)))
   100  	buf.WriteString(fmt.Sprintf("%s-", m["name"].(string)))
   101  	buf.WriteString(fmt.Sprintf("%s-", m["address"].(string)))
   102  	buf.WriteString(fmt.Sprintf("%d-", m["port"].(int)))
   103  	if v, ok := m["tags"]; ok {
   104  		vs := v.(*schema.Set).List()
   105  		s := make([]string, len(vs))
   106  		for i, raw := range vs {
   107  			s[i] = raw.(string)
   108  		}
   109  		sort.Strings(s)
   110  
   111  		for _, v := range s {
   112  			buf.WriteString(fmt.Sprintf("%s-", v))
   113  		}
   114  	}
   115  	return hashcode.String(buf.String())
   116  }
   117  
   118  func resourceConsulCatalogEntryCreate(d *schema.ResourceData, meta interface{}) error {
   119  	client := meta.(*consulapi.Client)
   120  	catalog := client.Catalog()
   121  
   122  	var dc string
   123  	if v, ok := d.GetOk("datacenter"); ok {
   124  		dc = v.(string)
   125  	} else {
   126  		var err error
   127  		if dc, err = getDC(d, client); err != nil {
   128  			return err
   129  		}
   130  	}
   131  
   132  	var token string
   133  	if v, ok := d.GetOk("token"); ok {
   134  		token = v.(string)
   135  	}
   136  
   137  	// Setup the operations using the datacenter
   138  	wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token}
   139  
   140  	address := d.Get("address").(string)
   141  	node := d.Get("node").(string)
   142  
   143  	var serviceIDs []string
   144  	if service, ok := d.GetOk("service"); ok {
   145  		serviceList := service.(*schema.Set).List()
   146  		serviceIDs = make([]string, len(serviceList))
   147  		for i, rawService := range serviceList {
   148  			serviceData := rawService.(map[string]interface{})
   149  
   150  			serviceID := serviceData["id"].(string)
   151  			serviceIDs[i] = serviceID
   152  
   153  			var tags []string
   154  			if v := serviceData["tags"].(*schema.Set).List(); len(v) > 0 {
   155  				tags = make([]string, len(v))
   156  				for i, raw := range v {
   157  					tags[i] = raw.(string)
   158  				}
   159  			}
   160  
   161  			registration := &consulapi.CatalogRegistration{
   162  				Address:    address,
   163  				Datacenter: dc,
   164  				Node:       node,
   165  				Service: &consulapi.AgentService{
   166  					Address: serviceData["address"].(string),
   167  					ID:      serviceID,
   168  					Service: serviceData["name"].(string),
   169  					Port:    serviceData["port"].(int),
   170  					Tags:    tags,
   171  				},
   172  			}
   173  
   174  			if _, err := catalog.Register(registration, &wOpts); err != nil {
   175  				return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' in %s: %v",
   176  					node, address, dc, err)
   177  			}
   178  		}
   179  	} else {
   180  		registration := &consulapi.CatalogRegistration{
   181  			Address:    address,
   182  			Datacenter: dc,
   183  			Node:       node,
   184  		}
   185  
   186  		if _, err := catalog.Register(registration, &wOpts); err != nil {
   187  			return fmt.Errorf("Failed to register Consul catalog entry with node '%s' at address '%s' in %s: %v",
   188  				node, address, dc, err)
   189  		}
   190  	}
   191  
   192  	// Update the resource
   193  	qOpts := consulapi.QueryOptions{Datacenter: dc}
   194  	if _, _, err := catalog.Node(node, &qOpts); err != nil {
   195  		return fmt.Errorf("Failed to read Consul catalog entry for node '%s' at address '%s' in %s: %v",
   196  			node, address, dc, err)
   197  	} else {
   198  		d.Set("datacenter", dc)
   199  	}
   200  
   201  	sort.Strings(serviceIDs)
   202  	serviceIDsJoined := strings.Join(serviceIDs, ",")
   203  
   204  	d.SetId(fmt.Sprintf("%s-%s-[%s]", node, address, serviceIDsJoined))
   205  
   206  	return nil
   207  }
   208  
   209  func resourceConsulCatalogEntryRead(d *schema.ResourceData, meta interface{}) error {
   210  	client := meta.(*consulapi.Client)
   211  	catalog := client.Catalog()
   212  
   213  	// Get the DC, error if not available.
   214  	var dc string
   215  	if v, ok := d.GetOk("datacenter"); ok {
   216  		dc = v.(string)
   217  	}
   218  
   219  	node := d.Get("node").(string)
   220  
   221  	// Setup the operations using the datacenter
   222  	qOpts := consulapi.QueryOptions{Datacenter: dc}
   223  
   224  	if _, _, err := catalog.Node(node, &qOpts); err != nil {
   225  		return fmt.Errorf("Failed to get node '%s' from Consul catalog: %v", node, err)
   226  	}
   227  
   228  	return nil
   229  }
   230  
   231  func resourceConsulCatalogEntryDelete(d *schema.ResourceData, meta interface{}) error {
   232  	client := meta.(*consulapi.Client)
   233  	catalog := client.Catalog()
   234  
   235  	var dc string
   236  	if v, ok := d.GetOk("datacenter"); ok {
   237  		dc = v.(string)
   238  	} else {
   239  		var err error
   240  		if dc, err = getDC(d, client); err != nil {
   241  			return err
   242  		}
   243  	}
   244  
   245  	var token string
   246  	if v, ok := d.GetOk("token"); ok {
   247  		token = v.(string)
   248  	}
   249  
   250  	// Setup the operations using the datacenter
   251  	wOpts := consulapi.WriteOptions{Datacenter: dc, Token: token}
   252  
   253  	address := d.Get("address").(string)
   254  	node := d.Get("node").(string)
   255  
   256  	deregistration := consulapi.CatalogDeregistration{
   257  		Address:    address,
   258  		Datacenter: dc,
   259  		Node:       node,
   260  	}
   261  
   262  	if _, err := catalog.Deregister(&deregistration, &wOpts); err != nil {
   263  		return fmt.Errorf("Failed to deregister Consul catalog entry with node '%s' at address '%s' in %s: %v",
   264  			node, address, dc, err)
   265  	}
   266  
   267  	// Clear the ID
   268  	d.SetId("")
   269  	return nil
   270  }