github.com/dustinrc/deis@v1.10.1-0.20150917223407-0894a5fb979e/mesos/pkg/etcd/etcd.go (about)

     1  package etcd
     2  
     3  import (
     4  	"errors"
     5  	"path"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/coreos/go-etcd/etcd"
    11  	logger "github.com/deis/deis/mesos/pkg/log"
    12  	etcdlock "github.com/leeor/etcd-sync"
    13  )
    14  
    15  // Client etcd client
    16  type Client struct {
    17  	client *etcd.Client
    18  	lock   *etcdlock.EtcdMutex
    19  }
    20  
    21  // Error etcd error
    22  type Error struct {
    23  	ErrorCode int    `json:"errorCode"`
    24  	Message   string `json:"message"`
    25  	Cause     string `json:"cause,omitempty"`
    26  	Index     uint64 `json:"index"`
    27  }
    28  
    29  var log = logger.New()
    30  
    31  // NewClient create a etcd client using the given machine list
    32  func NewClient(machines []string) *Client {
    33  	log.Debugf("connecting to %v etcd server/s", machines)
    34  	return &Client{etcd.NewClient(machines), nil}
    35  }
    36  
    37  // SetDefault sets the value of a key without expiration
    38  func SetDefault(client *Client, key, value string) {
    39  	Create(client, key, value, 0)
    40  }
    41  
    42  // Mkdir creates a directory only if does not exists
    43  func Mkdir(c *Client, path string) {
    44  	_, err := c.client.CreateDir(path, 0)
    45  	if err != nil {
    46  		log.Debug(err)
    47  	}
    48  }
    49  
    50  // WaitForKeys wait for the required keys up to the timeout or forever if is nil
    51  func WaitForKeys(c *Client, keys []string, ttl time.Duration) error {
    52  	start := time.Now()
    53  	wait := true
    54  
    55  	for {
    56  		for _, key := range keys {
    57  			_, err := c.client.Get(key, false, false)
    58  			if err != nil {
    59  				log.Debugf("key \"%s\" error %v", key, err)
    60  				wait = true
    61  			}
    62  		}
    63  
    64  		if !wait {
    65  			return nil
    66  		}
    67  
    68  		log.Debug("waiting for missing etcd keys...")
    69  		time.Sleep(1 * time.Second)
    70  		wait = false
    71  
    72  		if time.Since(start) > ttl {
    73  			return errors.New("maximum ttl reached. aborting")
    74  		}
    75  	}
    76  }
    77  
    78  // Get returns the value inside a key or an empty string
    79  func Get(c *Client, key string) string {
    80  	result, err := c.client.Get(key, false, false)
    81  	if err != nil {
    82  		log.Debugf("%v", err)
    83  		return ""
    84  	}
    85  
    86  	return result.Node.Value
    87  }
    88  
    89  // GetList returns the list of elements inside a key or an empty list
    90  func GetList(c *Client, key string) []string {
    91  	values, err := c.client.Get(key, true, false)
    92  	if err != nil {
    93  		log.Debugf("getlist %v", err)
    94  		return []string{}
    95  	}
    96  
    97  	result := []string{}
    98  	for _, node := range values.Node.Nodes {
    99  		result = append(result, path.Base(node.Key))
   100  	}
   101  
   102  	log.Debugf("getlist %s -> %v", key, result)
   103  	return result
   104  }
   105  
   106  // Set sets the value of a key.
   107  // If the ttl is bigger than 0 it will expire after the specified time
   108  func Set(c *Client, key, value string, ttl uint64) {
   109  	log.Debugf("set %s -> %s", key, value)
   110  	_, err := c.client.Set(key, value, ttl)
   111  	if err != nil {
   112  		log.Debugf("%v", err)
   113  	}
   114  }
   115  
   116  // Create set the value of a key only if it does not exits
   117  func Create(c *Client, key, value string, ttl uint64) {
   118  	log.Debugf("create %s -> %s", key, value)
   119  	_, err := c.client.Create(key, value, ttl)
   120  	if err != nil {
   121  		log.Debugf("%v", err)
   122  	}
   123  }
   124  
   125  // PublishService publish a service to etcd periodically
   126  func PublishService(
   127  	client *Client,
   128  	etcdPath string,
   129  	host string,
   130  	externalPort int,
   131  	ttl uint64,
   132  	timeout time.Duration) {
   133  
   134  	for {
   135  		Set(client, etcdPath+"/host", host, ttl)
   136  		Set(client, etcdPath+"/port", strconv.Itoa(externalPort), ttl)
   137  		time.Sleep(timeout)
   138  	}
   139  }
   140  
   141  func convertEtcdError(err error) *Error {
   142  	etcdError := err.(*etcd.EtcdError)
   143  	return &Error{
   144  		ErrorCode: etcdError.ErrorCode,
   145  		Message:   etcdError.Message,
   146  		Cause:     etcdError.Cause,
   147  		Index:     etcdError.Index,
   148  	}
   149  }
   150  
   151  // GetHTTPEtcdUrls returns an array of urls that contains at least one host
   152  func GetHTTPEtcdUrls(host, etcdPeers string) []string {
   153  	if etcdPeers != "127.0.0.1:4001" {
   154  		hosts := strings.Split(etcdPeers, ",")
   155  		result := []string{}
   156  		for _, _host := range hosts {
   157  			result = append(result, "http://"+_host+":4001")
   158  		}
   159  		return result
   160  	}
   161  
   162  	return []string{"http://" + host}
   163  }