2015-01-06 18:40:00 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
crand "crypto/rand"
|
|
|
|
"fmt"
|
2015-01-06 23:26:50 +00:00
|
|
|
"io/ioutil"
|
2015-01-06 18:40:00 +00:00
|
|
|
"net/http"
|
2015-01-06 23:26:50 +00:00
|
|
|
"os"
|
2015-01-16 18:56:47 +00:00
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
2015-01-06 18:40:00 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
2015-01-07 00:48:54 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/consul/testutil"
|
2015-01-06 18:40:00 +00:00
|
|
|
)
|
|
|
|
|
2015-01-16 01:24:15 +00:00
|
|
|
type configCallback func(c *Config)
|
2015-01-06 23:26:50 +00:00
|
|
|
|
2015-03-03 02:18:38 +00:00
|
|
|
func makeClient(t *testing.T) (*Client, *testutil.TestServer) {
|
2015-03-03 03:20:13 +00:00
|
|
|
return makeClientWithConfig(t, nil, nil)
|
2015-01-14 19:30:43 +00:00
|
|
|
}
|
|
|
|
|
2015-03-03 02:18:38 +00:00
|
|
|
func makeClientWithConfig(
|
|
|
|
t *testing.T,
|
|
|
|
cb1 configCallback,
|
|
|
|
cb2 testutil.ServerConfigCallback) (*Client, *testutil.TestServer) {
|
|
|
|
|
2015-01-16 01:24:15 +00:00
|
|
|
// Make client config
|
2015-01-14 19:30:43 +00:00
|
|
|
conf := DefaultConfig()
|
2015-03-03 02:18:38 +00:00
|
|
|
if cb1 != nil {
|
|
|
|
cb1(conf)
|
|
|
|
}
|
2015-01-16 01:24:15 +00:00
|
|
|
|
2015-03-03 03:20:13 +00:00
|
|
|
// Create server
|
|
|
|
server := testutil.NewTestServerConfig(t, cb2)
|
2015-03-11 16:47:47 +00:00
|
|
|
conf.Address = server.HTTPAddr
|
2015-03-03 03:20:13 +00:00
|
|
|
|
2015-01-16 01:24:15 +00:00
|
|
|
// Create client
|
2015-01-14 19:30:43 +00:00
|
|
|
client, err := NewClient(conf)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
2015-01-06 23:26:50 +00:00
|
|
|
return client, server
|
2015-01-06 18:40:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testKey() string {
|
|
|
|
buf := make([]byte, 16)
|
|
|
|
if _, err := crand.Read(buf); err != nil {
|
|
|
|
panic(fmt.Errorf("Failed to read random bytes: %v", err))
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Sprintf("%08x-%04x-%04x-%04x-%12x",
|
|
|
|
buf[0:4],
|
|
|
|
buf[4:6],
|
|
|
|
buf[6:8],
|
|
|
|
buf[8:10],
|
|
|
|
buf[10:16])
|
|
|
|
}
|
|
|
|
|
2015-03-18 14:41:00 +00:00
|
|
|
func TestDefaultConfig_env(t *testing.T) {
|
|
|
|
addr := "1.2.3.4:5678"
|
|
|
|
token := "abcd1234"
|
|
|
|
auth := "username:password"
|
|
|
|
|
|
|
|
os.Setenv("CONSUL_HTTP_ADDR", addr)
|
|
|
|
defer os.Setenv("CONSUL_HTTP_ADDR", "")
|
|
|
|
os.Setenv("CONSUL_HTTP_TOKEN", token)
|
|
|
|
defer os.Setenv("CONSUL_HTTP_TOKEN", "")
|
|
|
|
os.Setenv("CONSUL_HTTP_AUTH", auth)
|
|
|
|
defer os.Setenv("CONSUL_HTTP_AUTH", "")
|
|
|
|
os.Setenv("CONSUL_HTTP_SSL", "1")
|
|
|
|
defer os.Setenv("CONSUL_HTTP_SSL", "")
|
|
|
|
os.Setenv("CONSUL_HTTP_SSL_VERIFY", "0")
|
|
|
|
defer os.Setenv("CONSUL_HTTP_SSL_VERIFY", "")
|
|
|
|
|
|
|
|
config := DefaultConfig()
|
|
|
|
|
|
|
|
if config.Address != addr {
|
|
|
|
t.Errorf("expected %q to be %q", config.Address, addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.Token != token {
|
|
|
|
t.Errorf("expected %q to be %q", config.Token, token)
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.HttpAuth == nil {
|
|
|
|
t.Fatalf("expected HttpAuth to be enabled")
|
|
|
|
}
|
|
|
|
if config.HttpAuth.Username != "username" {
|
|
|
|
t.Errorf("expected %q to be %q", config.HttpAuth.Username, "username")
|
|
|
|
}
|
|
|
|
if config.HttpAuth.Password != "password" {
|
|
|
|
t.Errorf("expected %q to be %q", config.HttpAuth.Password, "password")
|
|
|
|
}
|
|
|
|
|
|
|
|
if config.Scheme != "https" {
|
|
|
|
t.Errorf("expected %q to be %q", config.Scheme, "https")
|
|
|
|
}
|
|
|
|
|
|
|
|
if !config.HttpClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify {
|
|
|
|
t.Errorf("expected SSL verification to be off")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-06 18:40:00 +00:00
|
|
|
func TestSetQueryOptions(t *testing.T) {
|
2015-01-06 23:26:50 +00:00
|
|
|
c, s := makeClient(t)
|
2015-03-03 02:18:38 +00:00
|
|
|
defer s.Stop()
|
2015-01-06 23:26:50 +00:00
|
|
|
|
2015-01-06 18:40:00 +00:00
|
|
|
r := c.newRequest("GET", "/v1/kv/foo")
|
|
|
|
q := &QueryOptions{
|
|
|
|
Datacenter: "foo",
|
|
|
|
AllowStale: true,
|
|
|
|
RequireConsistent: true,
|
|
|
|
WaitIndex: 1000,
|
|
|
|
WaitTime: 100 * time.Second,
|
|
|
|
Token: "12345",
|
|
|
|
}
|
|
|
|
r.setQueryOptions(q)
|
|
|
|
|
|
|
|
if r.params.Get("dc") != "foo" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if _, ok := r.params["stale"]; !ok {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if _, ok := r.params["consistent"]; !ok {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if r.params.Get("index") != "1000" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if r.params.Get("wait") != "100000ms" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if r.params.Get("token") != "12345" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetWriteOptions(t *testing.T) {
|
2015-01-06 23:26:50 +00:00
|
|
|
c, s := makeClient(t)
|
2015-03-03 02:18:38 +00:00
|
|
|
defer s.Stop()
|
2015-01-06 23:26:50 +00:00
|
|
|
|
2015-01-06 18:40:00 +00:00
|
|
|
r := c.newRequest("GET", "/v1/kv/foo")
|
|
|
|
q := &WriteOptions{
|
|
|
|
Datacenter: "foo",
|
|
|
|
Token: "23456",
|
|
|
|
}
|
|
|
|
r.setWriteOptions(q)
|
|
|
|
|
|
|
|
if r.params.Get("dc") != "foo" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
if r.params.Get("token") != "23456" {
|
|
|
|
t.Fatalf("bad: %v", r.params)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRequestToHTTP(t *testing.T) {
|
2015-01-06 23:26:50 +00:00
|
|
|
c, s := makeClient(t)
|
2015-03-03 02:18:38 +00:00
|
|
|
defer s.Stop()
|
2015-01-06 23:26:50 +00:00
|
|
|
|
2015-01-06 18:40:00 +00:00
|
|
|
r := c.newRequest("DELETE", "/v1/kv/foo")
|
|
|
|
q := &QueryOptions{
|
|
|
|
Datacenter: "foo",
|
|
|
|
}
|
|
|
|
r.setQueryOptions(q)
|
|
|
|
req, err := r.toHTTP()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if req.Method != "DELETE" {
|
|
|
|
t.Fatalf("bad: %v", req)
|
|
|
|
}
|
2015-01-14 19:30:43 +00:00
|
|
|
if req.URL.RequestURI() != "/v1/kv/foo?dc=foo" {
|
2015-01-06 18:40:00 +00:00
|
|
|
t.Fatalf("bad: %v", req)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestParseQueryMeta(t *testing.T) {
|
|
|
|
resp := &http.Response{
|
|
|
|
Header: make(map[string][]string),
|
|
|
|
}
|
|
|
|
resp.Header.Set("X-Consul-Index", "12345")
|
|
|
|
resp.Header.Set("X-Consul-LastContact", "80")
|
|
|
|
resp.Header.Set("X-Consul-KnownLeader", "true")
|
|
|
|
|
|
|
|
qm := &QueryMeta{}
|
|
|
|
if err := parseQueryMeta(resp, qm); err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if qm.LastIndex != 12345 {
|
|
|
|
t.Fatalf("Bad: %v", qm)
|
|
|
|
}
|
|
|
|
if qm.LastContact != 80*time.Millisecond {
|
|
|
|
t.Fatalf("Bad: %v", qm)
|
|
|
|
}
|
|
|
|
if !qm.KnownLeader {
|
|
|
|
t.Fatalf("Bad: %v", qm)
|
|
|
|
}
|
|
|
|
}
|
2015-01-16 18:56:47 +00:00
|
|
|
|
|
|
|
func TestAPI_UnixSocket(t *testing.T) {
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
t.SkipNow()
|
|
|
|
}
|
|
|
|
|
|
|
|
tempDir, err := ioutil.TempDir("", "consul")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
socket := filepath.Join(tempDir, "test.sock")
|
|
|
|
|
|
|
|
c, s := makeClientWithConfig(t, func(c *Config) {
|
|
|
|
c.Address = "unix://" + socket
|
2015-03-03 02:18:38 +00:00
|
|
|
}, func(c *testutil.TestServerConfig) {
|
|
|
|
c.Addresses = &testutil.TestAddressConfig{
|
2015-01-16 18:56:47 +00:00
|
|
|
HTTP: "unix://" + socket,
|
|
|
|
}
|
|
|
|
})
|
2015-03-03 02:18:38 +00:00
|
|
|
defer s.Stop()
|
2015-01-16 18:56:47 +00:00
|
|
|
|
|
|
|
agent := c.Agent()
|
|
|
|
|
|
|
|
info, err := agent.Self()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
if info["Config"]["NodeName"] == "" {
|
|
|
|
t.Fatalf("bad: %v", info)
|
|
|
|
}
|
|
|
|
}
|