forked from hashicorp/consul
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
api: initial import from armon/consul-api
- Loading branch information
Showing
28 changed files
with
3,050 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Compiled Object files, Static and Dynamic libs (Shared Objects) | ||
*.o | ||
*.a | ||
*.so | ||
|
||
# Folders | ||
_obj | ||
_test | ||
|
||
# Architecture specific extensions/prefixes | ||
*.[568vq] | ||
[568vq].out | ||
|
||
*.cgo1.go | ||
*.cgo2.c | ||
_cgo_defun.c | ||
_cgo_gotypes.go | ||
_cgo_export.* | ||
|
||
_testmain.go | ||
|
||
*.exe | ||
*.test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
Consul API client | ||
================= | ||
|
||
This package provides the `api` package which attempts to | ||
provide programmatic access to the full Consul API. | ||
|
||
Currently, all of the Consul APIs included in version 0.3 are supported. | ||
|
||
Documentation | ||
============= | ||
|
||
The full documentation is available on [Godoc](http://godoc.org/github.com/hashicorp/consul/api) | ||
|
||
Usage | ||
===== | ||
|
||
Below is an example of using the Consul client: | ||
|
||
```go | ||
// Get a new client, with KV endpoints | ||
client, _ := api.NewClient(api.DefaultConfig()) | ||
kv := client.KV() | ||
|
||
// PUT a new KV pair | ||
p := &api.KVPair{Key: "foo", Value: []byte("test")} | ||
_, err := kv.Put(p, nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
// Lookup the pair | ||
pair, _, err := kv.Get("foo", nil) | ||
if err != nil { | ||
panic(err) | ||
} | ||
fmt.Printf("KV: %v", pair) | ||
|
||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package api | ||
|
||
const ( | ||
// ACLCLientType is the client type token | ||
ACLClientType = "client" | ||
|
||
// ACLManagementType is the management type token | ||
ACLManagementType = "management" | ||
) | ||
|
||
// ACLEntry is used to represent an ACL entry | ||
type ACLEntry struct { | ||
CreateIndex uint64 | ||
ModifyIndex uint64 | ||
ID string | ||
Name string | ||
Type string | ||
Rules string | ||
} | ||
|
||
// ACL can be used to query the ACL endpoints | ||
type ACL struct { | ||
c *Client | ||
} | ||
|
||
// ACL returns a handle to the ACL endpoints | ||
func (c *Client) ACL() *ACL { | ||
return &ACL{c} | ||
} | ||
|
||
// Create is used to generate a new token with the given parameters | ||
func (a *ACL) Create(acl *ACLEntry, q *WriteOptions) (string, *WriteMeta, error) { | ||
r := a.c.newRequest("PUT", "/v1/acl/create") | ||
r.setWriteOptions(q) | ||
r.obj = acl | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
wm := &WriteMeta{RequestTime: rtt} | ||
var out struct{ ID string } | ||
if err := decodeBody(resp, &out); err != nil { | ||
return "", nil, err | ||
} | ||
return out.ID, wm, nil | ||
} | ||
|
||
// Update is used to update the rules of an existing token | ||
func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { | ||
r := a.c.newRequest("PUT", "/v1/acl/update") | ||
r.setWriteOptions(q) | ||
r.obj = acl | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
wm := &WriteMeta{RequestTime: rtt} | ||
return wm, nil | ||
} | ||
|
||
// Destroy is used to destroy a given ACL token ID | ||
func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { | ||
r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) | ||
r.setWriteOptions(q) | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return nil, err | ||
} | ||
resp.Body.Close() | ||
|
||
wm := &WriteMeta{RequestTime: rtt} | ||
return wm, nil | ||
} | ||
|
||
// Clone is used to return a new token cloned from an existing one | ||
func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { | ||
r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) | ||
r.setWriteOptions(q) | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return "", nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
wm := &WriteMeta{RequestTime: rtt} | ||
var out struct{ ID string } | ||
if err := decodeBody(resp, &out); err != nil { | ||
return "", nil, err | ||
} | ||
return out.ID, wm, nil | ||
} | ||
|
||
// Info is used to query for information about an ACL token | ||
func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { | ||
r := a.c.newRequest("GET", "/v1/acl/info/"+id) | ||
r.setQueryOptions(q) | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
qm := &QueryMeta{} | ||
parseQueryMeta(resp, qm) | ||
qm.RequestTime = rtt | ||
|
||
var entries []*ACLEntry | ||
if err := decodeBody(resp, &entries); err != nil { | ||
return nil, nil, err | ||
} | ||
if len(entries) > 0 { | ||
return entries[0], qm, nil | ||
} | ||
return nil, qm, nil | ||
} | ||
|
||
// List is used to get all the ACL tokens | ||
func (a *ACL) List(q *QueryOptions) ([]*ACLEntry, *QueryMeta, error) { | ||
r := a.c.newRequest("GET", "/v1/acl/list") | ||
r.setQueryOptions(q) | ||
rtt, resp, err := requireOK(a.c.doRequest(r)) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
qm := &QueryMeta{} | ||
parseQueryMeta(resp, qm) | ||
qm.RequestTime = rtt | ||
|
||
var entries []*ACLEntry | ||
if err := decodeBody(resp, &entries); err != nil { | ||
return nil, nil, err | ||
} | ||
return entries, qm, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package api | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
) | ||
|
||
// ROOT is a management token for the tests | ||
var CONSUL_ROOT string | ||
|
||
func init() { | ||
CONSUL_ROOT = os.Getenv("CONSUL_ROOT") | ||
} | ||
|
||
func TestACL_CreateDestroy(t *testing.T) { | ||
if CONSUL_ROOT == "" { | ||
t.SkipNow() | ||
} | ||
c := makeClient(t) | ||
c.config.Token = CONSUL_ROOT | ||
acl := c.ACL() | ||
|
||
ae := ACLEntry{ | ||
Name: "API test", | ||
Type: ACLClientType, | ||
Rules: `key "" { policy = "deny" }`, | ||
} | ||
|
||
id, wm, err := acl.Create(&ae, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if wm.RequestTime == 0 { | ||
t.Fatalf("bad: %v", wm) | ||
} | ||
|
||
if id == "" { | ||
t.Fatalf("invalid: %v", id) | ||
} | ||
|
||
ae2, _, err := acl.Info(id, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if ae2.Name != ae.Name || ae2.Type != ae.Type || ae2.Rules != ae.Rules { | ||
t.Fatalf("Bad: %#v", ae2) | ||
} | ||
|
||
wm, err = acl.Destroy(id, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if wm.RequestTime == 0 { | ||
t.Fatalf("bad: %v", wm) | ||
} | ||
} | ||
|
||
func TestACL_CloneDestroy(t *testing.T) { | ||
if CONSUL_ROOT == "" { | ||
t.SkipNow() | ||
} | ||
c := makeClient(t) | ||
c.config.Token = CONSUL_ROOT | ||
acl := c.ACL() | ||
|
||
id, wm, err := acl.Clone(CONSUL_ROOT, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if wm.RequestTime == 0 { | ||
t.Fatalf("bad: %v", wm) | ||
} | ||
|
||
if id == "" { | ||
t.Fatalf("invalid: %v", id) | ||
} | ||
|
||
wm, err = acl.Destroy(id, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if wm.RequestTime == 0 { | ||
t.Fatalf("bad: %v", wm) | ||
} | ||
} | ||
|
||
func TestACL_Info(t *testing.T) { | ||
if CONSUL_ROOT == "" { | ||
t.SkipNow() | ||
} | ||
c := makeClient(t) | ||
c.config.Token = CONSUL_ROOT | ||
acl := c.ACL() | ||
|
||
ae, qm, err := acl.Info(CONSUL_ROOT, nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if qm.LastIndex == 0 { | ||
t.Fatalf("bad: %v", qm) | ||
} | ||
if !qm.KnownLeader { | ||
t.Fatalf("bad: %v", qm) | ||
} | ||
|
||
if ae == nil || ae.ID != CONSUL_ROOT || ae.Type != ACLManagementType { | ||
t.Fatalf("bad: %#v", ae) | ||
} | ||
} | ||
|
||
func TestACL_List(t *testing.T) { | ||
if CONSUL_ROOT == "" { | ||
t.SkipNow() | ||
} | ||
c := makeClient(t) | ||
c.config.Token = CONSUL_ROOT | ||
acl := c.ACL() | ||
|
||
acls, qm, err := acl.List(nil) | ||
if err != nil { | ||
t.Fatalf("err: %v", err) | ||
} | ||
|
||
if len(acls) < 2 { | ||
t.Fatalf("bad: %v", acls) | ||
} | ||
|
||
if qm.LastIndex == 0 { | ||
t.Fatalf("bad: %v", qm) | ||
} | ||
if !qm.KnownLeader { | ||
t.Fatalf("bad: %v", qm) | ||
} | ||
} |
Oops, something went wrong.