Files
mgmt/etcd/client.go
James Shubin b19583e7d3 lang: Initial implementation of the mgmt language
This is an initial implementation of the mgmt language. It is a
declarative (immutable) functional, reactive, domain specific
programming language. It is intended to be a language that is:

* safe
* powerful
* easy to reason about

With these properties, we hope this language, and the mgmt engine will
allow you to model the real-time systems that you'd like to automate.

This also includes a number of other associated changes. Sorry for the
large size of this patch.
2018-01-20 08:09:29 -05:00

95 lines
3.0 KiB
Go

// Mgmt
// Copyright (C) 2013-2018+ James Shubin and the project contributors
// Written by James Shubin <james@shubin.ca> and the project contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package etcd
import (
"time"
etcd "github.com/coreos/etcd/clientv3" // "clientv3"
errwrap "github.com/pkg/errors"
context "golang.org/x/net/context"
)
// ClientEtcd provides a simple etcd client for deploy and status operations.
type ClientEtcd struct {
Seeds []string // list of endpoints to try to connect
client *etcd.Client
}
// GetClient returns a handle to the raw etcd client object.
func (obj *ClientEtcd) GetClient() *etcd.Client {
return obj.client
}
// GetConfig returns the config struct to be used for the etcd client connect.
func (obj *ClientEtcd) GetConfig() etcd.Config {
cfg := etcd.Config{
Endpoints: obj.Seeds,
// RetryDialer chooses the next endpoint to use
// it comes with a default dialer if unspecified
DialTimeout: 5 * time.Second,
}
return cfg
}
// Connect connects the client to a server, and then builds the *API structs.
// If reconnect is true, it will force a reconnect with new config endpoints.
func (obj *ClientEtcd) Connect() error {
if obj.client != nil { // memoize
return nil
}
var err error
cfg := obj.GetConfig()
obj.client, err = etcd.New(cfg) // connect!
if err != nil {
return errwrap.Wrapf(err, "client connect error")
}
return nil
}
// Destroy cleans up the entire etcd client connection.
func (obj *ClientEtcd) Destroy() error {
err := obj.client.Close()
//obj.wg.Wait()
return err
}
// Get runs a get on the client connection. This has the same signature as our
// EmbdEtcd Get function.
func (obj *ClientEtcd) Get(path string, opts ...etcd.OpOption) (map[string]string, error) {
resp, err := obj.client.Get(context.TODO(), path, opts...)
if err != nil || resp == nil {
return nil, err
}
// TODO: write a resp.ToMap() function on https://godoc.org/github.com/coreos/etcd/etcdserver/etcdserverpb#RangeResponse
result := make(map[string]string)
for _, x := range resp.Kvs {
result[string(x.Key)] = string(x.Value)
}
return result, nil
}
// Txn runs a transaction on the client connection. This has the same signature
// as our EmbdEtcd Txn function.
func (obj *ClientEtcd) Txn(ifcmps []etcd.Cmp, thenops, elseops []etcd.Op) (*etcd.TxnResponse, error) {
return obj.client.KV.Txn(context.TODO()).If(ifcmps...).Then(thenops...).Else(elseops...).Commit()
}