Repository: coreos/fleet (go)

Issue:
fleetd no longer has default etcd endpoints
since approximately 30f9f1f3ef73a118a691ac67188b14506cdce3a3, fleetd no longer has default etcd endpoints, resulting in fleetd exiting if no configuration is specified.

```
Jul 09 22:03:22 localhost systemd[1]: Started fleet daemon.
Jul 09 22:03:22 localhost systemd[1]: Starting fleet daemon...
Jul 09 22:03:22 localhost fleetd[566]: INFO fleetd.go:64: Starting fleetd version 0.11.0
Jul 09 22:03:22 localhost fleetd[566]: INFO fleetd.go:168: No provided or default config file found - proceeding without
Jul 09 22:03:22 localhost fleetd[566]: FATAL fleetd.go:90: Failed creating Server: client: no endpoints available
Jul 09 22:03:22 localhost systemd[1]: fleet.service: Main process exited, code=exited, status=1/FAILURE
Jul 09 22:03:22 localhost systemd[1]: fleet.service: Unit entered failed state.
Jul 09 22:03:22 localhost systemd[1]: fleet.service: Failed with result 'exit-code'.
```

Pull request description:
fleetd: use a sane default set of etcd endpoints
fixes #1301

Patch:
diff --git a/fleetd/fleetd.go b/fleetd/fleetd.go
index 76392444..aee7a599 100644
--- a/fleetd/fleetd.go
+++ b/fleetd/fleetd.go
@@ -20,7 +20,6 @@ import (
 	"fmt"
 	"os"
 	"os/signal"
-	"strings"
 	"syscall"
 
 	"github.com/coreos/fleet/Godeps/_workspace/src/github.com/rakyll/globalconf"
@@ -28,6 +27,7 @@ import (
 	"github.com/coreos/fleet/agent"
 	"github.com/coreos/fleet/config"
 	"github.com/coreos/fleet/log"
+	"github.com/coreos/fleet/pkg"
 	"github.com/coreos/fleet/registry"
 	"github.com/coreos/fleet/server"
 	"github.com/coreos/fleet/version"
@@ -65,7 +65,7 @@ func main() {
 
 	cfgset := flag.NewFlagSet("fleet", flag.ExitOnError)
 	cfgset.Int("verbosity", 0, "Logging level")
-	cfgset.Var(&stringSlice{}, "etcd_servers", "List of etcd endpoints")
+	cfgset.Var(&pkg.StringSlice{"http://127.0.0.1:2379", "http://127.0.0.1:4001"}, "etcd_servers", "List of etcd endpoints")
 	cfgset.String("etcd_keyfile", "", "SSL key file used to secure etcd communication")
 	cfgset.String("etcd_certfile", "", "SSL certification file used to secure etcd communication")
 	cfgset.String("etcd_cafile", "", "SSL Certificate Authority file used to secure etcd communication")
@@ -177,7 +177,7 @@ func getConfig(flagset *flag.FlagSet, userCfgFile string) (*config.Config, error
 
 	cfg := config.Config{
 		Verbosity:               (*flagset.Lookup("verbosity")).Value.(flag.Getter).Get().(int),
-		EtcdServers:             (*flagset.Lookup("etcd_servers")).Value.(flag.Getter).Get().(stringSlice),
+		EtcdServers:             (*flagset.Lookup("etcd_servers")).Value.(flag.Getter).Get().(pkg.StringSlice),
 		EtcdKeyPrefix:           (*flagset.Lookup("etcd_key_prefix")).Value.(flag.Getter).Get().(string),
 		EtcdKeyFile:             (*flagset.Lookup("etcd_keyfile")).Value.(flag.Getter).Get().(string),
 		EtcdCertFile:            (*flagset.Lookup("etcd_certfile")).Value.(flag.Getter).Get().(string),
@@ -220,27 +220,3 @@ func listenForSignals(sigmap map[os.Signal]func()) {
 		}
 	}
 }
-
-type stringSlice []string
-
-func (f *stringSlice) Set(value string) error {
-	for _, item := range strings.Split(value, ",") {
-		item = strings.TrimLeft(item, " [\"")
-		item = strings.TrimRight(item, " \"]")
-		*f = append(*f, item)
-	}
-
-	return nil
-}
-
-func (f *stringSlice) String() string {
-	return fmt.Sprintf("%v", *f)
-}
-
-func (f *stringSlice) Value() []string {
-	return *f
-}
-
-func (f *stringSlice) Get() interface{} {
-	return *f
-}
diff --git a/pkg/flag.go b/pkg/flag.go
new file mode 100644
index 00000000..3ce0b654
--- /dev/null
+++ b/pkg/flag.go
@@ -0,0 +1,47 @@
+// Copyright 2015 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 pkg
+
+import (
+	"fmt"
+	"strings"
+)
+
+type StringSlice []string
+
+func (f *StringSlice) Set(value string) error {
+	var s StringSlice
+	for _, item := range strings.Split(value, ",") {
+		item = strings.TrimLeft(item, " [\"")
+		item = strings.TrimRight(item, " \"]")
+		s = append(s, item)
+	}
+
+	*f = s
+
+	return nil
+}
+
+func (f *StringSlice) String() string {
+	return fmt.Sprintf("%v", *f)
+}
+
+func (f *StringSlice) Value() []string {
+	return *f
+}
+
+func (f *StringSlice) Get() interface{} {
+	return *f
+}


Test patch:
diff --git a/pkg/flag_test.go b/pkg/flag_test.go
new file mode 100644
index 00000000..60c8547c
--- /dev/null
+++ b/pkg/flag_test.go
@@ -0,0 +1,39 @@
+// Copyright 2015 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 pkg
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestStringSlice(t *testing.T) {
+	tests := []struct {
+		input  string
+		output []string
+	}{
+		{`["a"]`, []string{"a"}},
+		{`["a","b"]`, []string{"a", "b"}},
+	}
+
+	for _, tt := range tests {
+		var ss StringSlice
+		ss.Set(tt.input)
+		r := ss.Value()
+		if !reflect.DeepEqual(r, tt.output) {
+			t.Errorf("error setting StringSlice: expected %+v, got %+v", tt.output, r)
+		}
+	}
+}