From 8bbc4dbad7d3ad3f3d415ebbe9ca27e9a021ca4c Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 9 Oct 2013 17:36:26 -0700 Subject: [PATCH 1/5] bump(github.com/coreos/go-etcd/etcd): --- .../github.com/coreos/go-etcd/etcd/client.go | 20 +++++++++++++---- .../coreos/go-etcd/etcd/client_test.go | 22 ++++++++++++++++++- .../coreos/go-etcd/etcd/delete_test.go | 2 +- .../coreos/go-etcd/etcd/get_test.go | 2 +- .../coreos/go-etcd/etcd/list_test.go | 2 +- .../coreos/go-etcd/etcd/set_test.go | 2 +- .../coreos/go-etcd/etcd/testAndSet_test.go | 2 +- .../github.com/coreos/go-etcd/etcd/watch.go | 7 +++++- .../coreos/go-etcd/etcd/watch_test.go | 11 ++++++---- 9 files changed, 55 insertions(+), 15 deletions(-) diff --git a/third_party/github.com/coreos/go-etcd/etcd/client.go b/third_party/github.com/coreos/go-etcd/etcd/client.go index abc4574..31d3c2a 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/client.go +++ b/third_party/github.com/coreos/go-etcd/etcd/client.go @@ -36,12 +36,16 @@ type Client struct { } // Setup a basic conf and cluster -func NewClient() *Client { +func NewClient(machines []string) *Client { + // if an empty slice was sent in then just assume localhost + if len(machines) == 0 { + machines = []string{"http://127.0.0.1:4001"} + } // default leader and machines cluster := Cluster{ - Leader: "http://127.0.0.1:4001", - Machines: []string{"http://127.0.0.1:4001"}, + Leader: machines[0], + Machines: machines, } config := Config{ @@ -107,6 +111,10 @@ func (c *Client) SetCluster(machines []string) bool { return success } +func (c *Client) GetCluster() []string { + return c.cluster.Machines +} + // sycn cluster information using the existing machine list func (c *Client) SyncCluster() bool { success := c.internalSyncCluster(c.cluster.Machines) @@ -128,8 +136,9 @@ func (c *Client) internalSyncCluster(machines []string) bool { // try another machine in the cluster continue } + // update Machines List - c.cluster.Machines = strings.Split(string(b), ",") + c.cluster.Machines = strings.Split(string(b), ", ") // update leader // the first one in the machine list is the leader @@ -147,6 +156,9 @@ func (c *Client) internalSyncCluster(machines []string) bool { func (c *Client) createHttpPath(serverName string, _path string) string { u, _ := url.Parse(serverName) u.Path = path.Join(u.Path, "/", _path) + if u.Scheme == "" { + u.Scheme = "http" + } return u.String() } diff --git a/third_party/github.com/coreos/go-etcd/etcd/client_test.go b/third_party/github.com/coreos/go-etcd/etcd/client_test.go index 45a99e9..29f1381 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/client_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/client_test.go @@ -3,6 +3,8 @@ package etcd import ( "fmt" "testing" + "net/url" + "net" ) // To pass this test, we need to create a cluster of 3 machines @@ -10,13 +12,31 @@ import ( func TestSync(t *testing.T) { fmt.Println("Make sure there are three nodes at 0.0.0.0:4001-4003") - c := NewClient() + c := NewClient(nil) success := c.SyncCluster() if !success { t.Fatal("cannot sync machines") } + for _, m := range(c.GetCluster()) { + u, err := url.Parse(m) + if err != nil { + t.Fatal(err) + } + if u.Scheme != "http" { + t.Fatal("scheme must be http") + } + + host, _, err := net.SplitHostPort(u.Host) + if err != nil { + t.Fatal(err) + } + if host != "127.0.0.1" { + t.Fatal("Host must be 127.0.0.1") + } + } + badMachines := []string{"abc", "edef"} success = c.SetCluster(badMachines) diff --git a/third_party/github.com/coreos/go-etcd/etcd/delete_test.go b/third_party/github.com/coreos/go-etcd/etcd/delete_test.go index a5f9801..52756d0 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/delete_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/delete_test.go @@ -6,7 +6,7 @@ import ( func TestDelete(t *testing.T) { - c := NewClient() + c := NewClient(nil) c.Set("foo", "bar", 100) result, err := c.Delete("foo") diff --git a/third_party/github.com/coreos/go-etcd/etcd/get_test.go b/third_party/github.com/coreos/go-etcd/etcd/get_test.go index 8e3852c..ff81374 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/get_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/get_test.go @@ -7,7 +7,7 @@ import ( func TestGet(t *testing.T) { - c := NewClient() + c := NewClient(nil) c.Set("foo", "bar", 100) diff --git a/third_party/github.com/coreos/go-etcd/etcd/list_test.go b/third_party/github.com/coreos/go-etcd/etcd/list_test.go index 1e98e76..382bb35 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/list_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/list_test.go @@ -6,7 +6,7 @@ import ( ) func TestList(t *testing.T) { - c := NewClient() + c := NewClient(nil) c.Set("foo_list/foo", "bar", 100) c.Set("foo_list/fooo", "barbar", 100) diff --git a/third_party/github.com/coreos/go-etcd/etcd/set_test.go b/third_party/github.com/coreos/go-etcd/etcd/set_test.go index dc46608..3809ee9 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/set_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/set_test.go @@ -6,7 +6,7 @@ import ( ) func TestSet(t *testing.T) { - c := NewClient() + c := NewClient(nil) result, err := c.Set("foo", "bar", 100) diff --git a/third_party/github.com/coreos/go-etcd/etcd/testAndSet_test.go b/third_party/github.com/coreos/go-etcd/etcd/testAndSet_test.go index ba6d0e8..5dbd854 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/testAndSet_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/testAndSet_test.go @@ -6,7 +6,7 @@ import ( ) func TestTestAndSet(t *testing.T) { - c := NewClient() + c := NewClient(nil) c.Set("foo_testAndSet", "bar", 100) diff --git a/third_party/github.com/coreos/go-etcd/etcd/watch.go b/third_party/github.com/coreos/go-etcd/etcd/watch.go index 5da5565..7f59ed0 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/watch.go +++ b/third_party/github.com/coreos/go-etcd/etcd/watch.go @@ -16,6 +16,11 @@ type respAndErr struct { err error } +// Errors introduced by the Watch command. +var ( + ErrWatchStoppedByUser = errors.New("Watch stopped by the user via stop channel") +) + // Watch any change under the given prefix. // When a sinceIndex is given, watch will try to scan from that index to the last index // and will return any changes under the given prefix during the history @@ -66,7 +71,7 @@ func (c *Client) watchOnce(key string, sinceIndex uint64, stop chan bool) (*stor resp, err = res.resp, res.err case <-stop: - resp, err = nil, errors.New("User stoped watch") + resp, err = nil, ErrWatchStoppedByUser } } else { resp, err = c.sendWatchRequest(key, sinceIndex) diff --git a/third_party/github.com/coreos/go-etcd/etcd/watch_test.go b/third_party/github.com/coreos/go-etcd/etcd/watch_test.go index 5e18a2b..0d93485 100644 --- a/third_party/github.com/coreos/go-etcd/etcd/watch_test.go +++ b/third_party/github.com/coreos/go-etcd/etcd/watch_test.go @@ -8,7 +8,7 @@ import ( ) func TestWatch(t *testing.T) { - c := NewClient() + c := NewClient(nil) go setHelper("bar", c) @@ -35,9 +35,12 @@ func TestWatch(t *testing.T) { go setLoop("bar", c) - go reciver(ch, stop) + go receiver(ch, stop) - c.Watch("watch_foo", 0, ch, stop) + _, err = c.Watch("watch_foo", 0, ch, stop) + if err != ErrWatchStoppedByUser { + t.Fatalf("Watch returned a non-user stop error") + } } func setHelper(value string, c *Client) { @@ -54,7 +57,7 @@ func setLoop(value string, c *Client) { } } -func reciver(c chan *store.Response, stop chan bool) { +func receiver(c chan *store.Response, stop chan bool) { for i := 0; i < 10; i++ { <-c } From 450036c84bdde533f544c7540a08b94903a9b29b Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 9 Oct 2013 17:36:27 -0700 Subject: [PATCH 2/5] bump(github.com/coreos/etcd/error): --- .../github.com/coreos/etcd/error/error.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/third_party/github.com/coreos/etcd/error/error.go b/third_party/github.com/coreos/etcd/error/error.go index dc209f2..3c87055 100644 --- a/third_party/github.com/coreos/etcd/error/error.go +++ b/third_party/github.com/coreos/etcd/error/error.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package error import ( From ba287a6f99423b41446a04e2372f63ddca13dd37 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 9 Oct 2013 17:36:27 -0700 Subject: [PATCH 3/5] bump(github.com/coreos/etcd/store): --- .../coreos/etcd/store/keyword_test.go | 16 ++ .../github.com/coreos/etcd/store/keywords.go | 16 ++ .../github.com/coreos/etcd/store/stats.go | 16 ++ .../github.com/coreos/etcd/store/store.go | 187 ++++++++++-------- .../coreos/etcd/store/store_test.go | 52 +++++ .../github.com/coreos/etcd/store/test.go | 16 ++ .../github.com/coreos/etcd/store/tree.go | 16 ++ .../coreos/etcd/store/tree_store_test.go | 16 ++ .../github.com/coreos/etcd/store/watcher.go | 16 ++ .../coreos/etcd/store/watcher_test.go | 16 ++ 10 files changed, 286 insertions(+), 81 deletions(-) diff --git a/third_party/github.com/coreos/etcd/store/keyword_test.go b/third_party/github.com/coreos/etcd/store/keyword_test.go index 7c54a9f..146fe28 100644 --- a/third_party/github.com/coreos/etcd/store/keyword_test.go +++ b/third_party/github.com/coreos/etcd/store/keyword_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/keywords.go b/third_party/github.com/coreos/etcd/store/keywords.go index 2e4ceb7..f93a862 100644 --- a/third_party/github.com/coreos/etcd/store/keywords.go +++ b/third_party/github.com/coreos/etcd/store/keywords.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/stats.go b/third_party/github.com/coreos/etcd/store/stats.go index b57f4db..e85ed6b 100644 --- a/third_party/github.com/coreos/etcd/store/stats.go +++ b/third_party/github.com/coreos/etcd/store/stats.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/store.go b/third_party/github.com/coreos/etcd/store/store.go index d37345f..aeda69f 100644 --- a/third_party/github.com/coreos/etcd/store/store.go +++ b/third_party/github.com/coreos/etcd/store/store.go @@ -1,13 +1,30 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( "encoding/json" "fmt" - etcdErr "github.com/coreos/etcd/error" "path" "strconv" "sync" "time" + + etcdErr "github.com/coreos/etcd/error" ) //------------------------------------------------------------------------------ @@ -325,75 +342,81 @@ func (s *Store) Get(key string) ([]byte, error) { return json.Marshal(resps) } -func (s *Store) RawGet(key string) ([]*Response, error) { - // Update stats - s.BasicStats.Gets++ +func (s *Store) rawGetNode(key string, node *Node) ([]*Response, error) { + resps := make([]*Response, 1) - key = path.Clean("/" + key) - - nodes, keys, ok := s.Tree.list(key) + isExpire := !node.ExpireTime.Equal(PERMANENT) - if ok { + resps[0] = &Response{ + Action: "GET", + Index: s.Index, + Key: key, + Value: node.Value, + } - node, ok := nodes.(*Node) + // Update ttl + if isExpire { + TTL := int64(node.ExpireTime.Sub(time.Now()) / time.Second) + resps[0].Expiration = &node.ExpireTime + resps[0].TTL = TTL + } - if ok { - resps := make([]*Response, 1) + return resps, nil +} - isExpire := !node.ExpireTime.Equal(PERMANENT) +func (s *Store) rawGetNodeList(key string, keys []string, nodes []*Node) ([]*Response, error) { + resps := make([]*Response, len(nodes)) - resps[0] = &Response{ - Action: "GET", - Index: s.Index, - Key: key, - Value: node.Value, - } + // TODO: check if nodes and keys are the same length + for i := 0; i < len(nodes); i++ { + var TTL int64 + var isExpire bool = false - // Update ttl - if isExpire { - TTL := int64(node.ExpireTime.Sub(time.Now()) / time.Second) - resps[0].Expiration = &node.ExpireTime - resps[0].TTL = TTL - } + isExpire = !nodes[i].ExpireTime.Equal(PERMANENT) - return resps, nil + resps[i] = &Response{ + Action: "GET", + Index: s.Index, + Key: path.Join(key, keys[i]), } - nodes, _ := nodes.([]*Node) - - resps := make([]*Response, len(nodes)) - for i := 0; i < len(nodes); i++ { - - var TTL int64 - var isExpire bool = false + if len(nodes[i].Value) != 0 { + resps[i].Value = nodes[i].Value + } else { + resps[i].Dir = true + } - isExpire = !nodes[i].ExpireTime.Equal(PERMANENT) + // Update ttl + if isExpire { + TTL = int64(nodes[i].ExpireTime.Sub(time.Now()) / time.Second) + resps[i].Expiration = &nodes[i].ExpireTime + resps[i].TTL = TTL + } - resps[i] = &Response{ - Action: "GET", - Index: s.Index, - Key: path.Join(key, keys[i]), - } + } - if len(nodes[i].Value) != 0 { - resps[i].Value = nodes[i].Value - } else { - resps[i].Dir = true - } + return resps, nil +} - // Update ttl - if isExpire { - TTL = int64(nodes[i].ExpireTime.Sub(time.Now()) / time.Second) - resps[i].Expiration = &nodes[i].ExpireTime - resps[i].TTL = TTL - } +func (s *Store) RawGet(key string) ([]*Response, error) { + // Update stats + s.BasicStats.Gets++ - } + key = path.Clean("/" + key) - return resps, nil + nodes, keys, ok := s.Tree.list(key) + if !ok { + return nil, etcdErr.NewError(100, "get: "+key) } - return nil, etcdErr.NewError(100, "get: "+key) + switch node := nodes.(type) { + case *Node: + return s.rawGetNode(key, node) + case []*Node: + return s.rawGetNodeList(key, keys, node) + default: + panic("invalid cast ") + } } func (s *Store) Delete(key string, index uint64) ([]byte, error) { @@ -415,43 +438,41 @@ func (s *Store) internalDelete(key string, index uint64) ([]byte, error) { node, ok := s.Tree.get(key) - if ok { - - resp := Response{ - Action: "DELETE", - Key: key, - PrevValue: node.Value, - Index: index, - } + if !ok { + return nil, etcdErr.NewError(100, "delete: "+key) + } - if node.ExpireTime.Equal(PERMANENT) { + resp := Response{ + Action: "DELETE", + Key: key, + PrevValue: node.Value, + Index: index, + } - s.Tree.delete(key) + if node.ExpireTime.Equal(PERMANENT) { - } else { - resp.Expiration = &node.ExpireTime - // Kill the expire go routine - node.update <- PERMANENT - s.Tree.delete(key) + s.Tree.delete(key) - } + } else { + resp.Expiration = &node.ExpireTime + // Kill the expire go routine + node.update <- PERMANENT + s.Tree.delete(key) - msg, err := json.Marshal(resp) + } - s.watcher.notify(resp) + msg, err := json.Marshal(resp) - // notify the messager - if s.messager != nil && err == nil { - s.messager <- string(msg) - } + s.watcher.notify(resp) - s.addToResponseMap(index, &resp) + // notify the messager + if s.messager != nil && err == nil { + s.messager <- string(msg) + } - return msg, err + s.addToResponseMap(index, &resp) - } else { - return nil, etcdErr.NewError(100, "delete: "+key) - } + return msg, err } // Set the value of the key to the value if the given prevValue is equal to the value of the key @@ -465,12 +486,16 @@ func (s *Store) TestAndSet(key string, prevValue string, value string, expireTim resp := s.internalGet(key) if resp == nil { - return nil, etcdErr.NewError(100, "testandset: "+key) + if prevValue != "" { + errmsg := fmt.Sprintf("TestAndSet: key not found and previousValue is not empty %s:%s ", key, prevValue) + return nil, etcdErr.NewError(100, errmsg) + } + return s.internalSet(key, value, expireTime, index) } if resp.Value == prevValue { - // If test success, do set + // If test succeed, do set return s.internalSet(key, value, expireTime, index) } else { diff --git a/third_party/github.com/coreos/etcd/store/store_test.go b/third_party/github.com/coreos/etcd/store/store_test.go index 001f5dd..90335c4 100644 --- a/third_party/github.com/coreos/etcd/store/store_test.go +++ b/third_party/github.com/coreos/etcd/store/store_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( @@ -31,6 +47,42 @@ func TestStoreGetDelete(t *testing.T) { } } +func TestTestAndSet(t *testing.T) { + s := CreateStore(100) + s.Set("foo", "bar", time.Unix(0, 0), 1) + + _, err := s.TestAndSet("foo", "barbar", "barbar", time.Unix(0, 0), 2) + + if err == nil { + t.Fatalf("test bar == barbar should fail") + } + + _, err = s.TestAndSet("foo", "bar", "barbar", time.Unix(0, 0), 3) + + if err != nil { + t.Fatalf("test bar == bar should succeed") + } + + _, err = s.TestAndSet("foo", "", "barbar", time.Unix(0, 0), 4) + + if err == nil { + t.Fatalf("test empty == bar should fail") + } + + _, err = s.TestAndSet("fooo", "bar", "barbar", time.Unix(0, 0), 5) + + if err == nil { + t.Fatalf("test bar == non-existing key should fail") + } + + _, err = s.TestAndSet("fooo", "", "bar", time.Unix(0, 0), 6) + + if err != nil { + t.Fatalf("test empty == non-existing key should succeed") + } + +} + func TestSaveAndRecovery(t *testing.T) { s := CreateStore(100) diff --git a/third_party/github.com/coreos/etcd/store/test.go b/third_party/github.com/coreos/etcd/store/test.go index ac23261..5934305 100644 --- a/third_party/github.com/coreos/etcd/store/test.go +++ b/third_party/github.com/coreos/etcd/store/test.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/tree.go b/third_party/github.com/coreos/etcd/store/tree.go index 3d6d1bf..59dff62 100644 --- a/third_party/github.com/coreos/etcd/store/tree.go +++ b/third_party/github.com/coreos/etcd/store/tree.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/tree_store_test.go b/third_party/github.com/coreos/etcd/store/tree_store_test.go index ad8222f..e791471 100644 --- a/third_party/github.com/coreos/etcd/store/tree_store_test.go +++ b/third_party/github.com/coreos/etcd/store/tree_store_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/watcher.go b/third_party/github.com/coreos/etcd/store/watcher.go index 17de27b..8c4ef5e 100644 --- a/third_party/github.com/coreos/etcd/store/watcher.go +++ b/third_party/github.com/coreos/etcd/store/watcher.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( diff --git a/third_party/github.com/coreos/etcd/store/watcher_test.go b/third_party/github.com/coreos/etcd/store/watcher_test.go index b5730ed..0ac4262 100644 --- a/third_party/github.com/coreos/etcd/store/watcher_test.go +++ b/third_party/github.com/coreos/etcd/store/watcher_test.go @@ -1,3 +1,19 @@ +/* +Copyright 2013 CoreOS Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package store import ( From a12bd5734cd74011d41a9f241de4ae0127a7575b Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 9 Oct 2013 17:36:30 -0700 Subject: [PATCH 4/5] bump(github.com/coreos/go-log/log): --- .../github.com/coreos/go-log/log/commands.go | 2 +- .../github.com/coreos/go-log/log/fields.go | 2 +- .../github.com/coreos/go-log/log/logger.go | 12 ++----- .../github.com/coreos/go-log/log/priority.go | 2 +- .../github.com/coreos/go-log/log/sinks.go | 32 +++++++++---------- 5 files changed, 21 insertions(+), 29 deletions(-) diff --git a/third_party/github.com/coreos/go-log/log/commands.go b/third_party/github.com/coreos/go-log/log/commands.go index f0bf757..94dc9e1 100644 --- a/third_party/github.com/coreos/go-log/log/commands.go +++ b/third_party/github.com/coreos/go-log/log/commands.go @@ -1,5 +1,5 @@ package log -// Copyright 2013, David Fisher. All rights reserved. +// Copyright 2013, CoreOS, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/third_party/github.com/coreos/go-log/log/fields.go b/third_party/github.com/coreos/go-log/log/fields.go index c060a22..e8d9698 100644 --- a/third_party/github.com/coreos/go-log/log/fields.go +++ b/third_party/github.com/coreos/go-log/log/fields.go @@ -1,5 +1,5 @@ package log -// Copyright 2013, David Fisher. All rights reserved. +// Copyright 2013, CoreOS, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/third_party/github.com/coreos/go-log/log/logger.go b/third_party/github.com/coreos/go-log/log/logger.go index 341340e..2089a11 100644 --- a/third_party/github.com/coreos/go-log/log/logger.go +++ b/third_party/github.com/coreos/go-log/log/logger.go @@ -1,5 +1,5 @@ package log -// Copyright 2013, David Fisher. All rights reserved. +// Copyright 2013, CoreOS, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,10 +18,9 @@ package log import ( "bitbucket.org/kardianos/osext" - "github.com/coreos/go-systemd/journal" + "os" "path" "time" - "os" ) // Logger is user-immutable immutable struct which can log to several outputs @@ -69,10 +68,5 @@ func NewSimple(sinks ...Sink) *Logger { var defaultLogger *Logger func init() { - sinks := make([]Sink, 0) - sinks = append(sinks, WriterSink(os.Stdout, BasicFormat, BasicFields)) - if journal.Enabled() { - sinks = append(sinks, JournalSink()) - } - defaultLogger = NewSimple(sinks...) + defaultLogger = NewSimple(CombinedSink(os.Stdout, BasicFormat, BasicFields)) } diff --git a/third_party/github.com/coreos/go-log/log/priority.go b/third_party/github.com/coreos/go-log/log/priority.go index 918dcaf..ac73fc8 100644 --- a/third_party/github.com/coreos/go-log/log/priority.go +++ b/third_party/github.com/coreos/go-log/log/priority.go @@ -1,5 +1,5 @@ package log -// Copyright 2013, David Fisher. All rights reserved. +// Copyright 2013, CoreOS, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/third_party/github.com/coreos/go-log/log/sinks.go b/third_party/github.com/coreos/go-log/log/sinks.go index 0542402..a41f336 100644 --- a/third_party/github.com/coreos/go-log/log/sinks.go +++ b/third_party/github.com/coreos/go-log/log/sinks.go @@ -1,6 +1,5 @@ package log - -// Copyright 2013, David Fisher. All rights reserved. +// Copyright 2013, CoreOS, Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -112,26 +111,25 @@ func JournalSink() Sink { return &journalSink{} } -type tryJournalSink struct { - j journalSink - w writerSink +type combinedSink struct { + sinks []Sink } -func (sink *tryJournalSink) Log(fields Fields) { - if journal.Enabled() { - sink.j.Log(fields) - } else { - sink.w.Log(fields) +func (sink *combinedSink) Log(fields Fields) { + for _, s := range sink.sinks { + s.Log(fields) } } -func JournalFallbackSink(out io.Writer, format string, fields []string) Sink { - return &tryJournalSink{ - w: writerSink{ - out: out, - format: format, - fields: fields, - }, +func CombinedSink(writer io.Writer, format string, fields []string) Sink { + sinks := make([]Sink, 0) + sinks = append(sinks, WriterSink(writer, format, fields)) + if journal.Enabled() { + sinks = append(sinks, JournalSink()) + } + + return &combinedSink{ + sinks: sinks, } } From 0c37fccd45064dc51b240f2260ad717dbbbd6436 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Wed, 9 Oct 2013 18:05:51 -0700 Subject: [PATCH 5/5] feat(etcdctl): obey the -C flag take a comma seperated list of nodes in the -C flag and use them in the etcd client. --- etcdctl.go | 7 +++++-- flags.go | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 flags.go diff --git a/etcdctl.go b/etcdctl.go index 8cc51d3..60f87c1 100644 --- a/etcdctl.go +++ b/etcdctl.go @@ -8,13 +8,16 @@ import ( ) var ( - cluster = flag.String("C", "0.0.0.0:4001", "a list of machine addresses in the cluster") - client = etcd.NewClient() + client *etcd.Client ) func main() { + cluster := ClusterValue{"http://localhost:4001"} + flag.Var(&cluster, "C", "a comma seperated list of machine addresses in the cluster e.g. 127.0.0.1:4001,127.0.0.1:4002") flag.Parse() + client = etcd.NewClient(cluster.GetMachines()) + args := flag.Args() if len(args) == 0 { diff --git a/flags.go b/flags.go new file mode 100644 index 0000000..3c92ad1 --- /dev/null +++ b/flags.go @@ -0,0 +1,27 @@ +package main + +import ( + "strings" +) + +type ClusterValue struct { + machines string +} + +func (c *ClusterValue) String() string { + return c.machines +} + +func (c *ClusterValue) Set(value string) error { + if len(value) == 0 { + return nil + } + + c.machines = value + + return nil +} + +func (c *ClusterValue) GetMachines() []string { + return strings.Split(c.machines, ",") +}