This repository has been archived by the owner on Nov 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 797
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(config): first pass at config subcommand
- Loading branch information
Gabriel Monroy
committed
Aug 28, 2014
1 parent
c182966
commit 6d541aa
Showing
5 changed files
with
201 additions
and
0 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
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,7 @@ | ||
package config | ||
|
||
// Client interface used for configuration | ||
type Client interface { | ||
Get(string) (string, error) | ||
Set(string) (string, error) | ||
} |
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,92 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
docopt "github.com/docopt/docopt-go" | ||
) | ||
|
||
// Config runs the config subcommand | ||
func Config() error { | ||
usage := `Deis Cluster Configuration | ||
Usage: | ||
deisctl config <target> get [<key>...] [options] | ||
deisctl config <target> set <key=val>... [options] | ||
Options: | ||
--verbose print out the request bodies [default: false] | ||
` | ||
// parse command-line arguments | ||
args, err := docopt.Parse(usage, nil, true, "", true) | ||
if err != nil { | ||
return err | ||
} | ||
err = setConfigFlags(args) | ||
if err != nil { | ||
return err | ||
} | ||
return doConfig(args) | ||
} | ||
|
||
// Flags for config package | ||
var Flags struct { | ||
} | ||
|
||
func setConfigFlags(args map[string]interface{}) error { | ||
return nil | ||
} | ||
|
||
func doConfig(args map[string]interface{}) error { | ||
client, err := getEtcdClient() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
rootPath := "/deis/" + args["<target>"].(string) + "/" | ||
|
||
var vals []string | ||
if args["set"] == true { | ||
vals, err = doConfigSet(client, rootPath, args["<key=val>"].([]string)) | ||
} else { | ||
vals, err = doConfigGet(client, rootPath, args["<key>"].([]string)) | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// print results | ||
for _, v := range vals { | ||
fmt.Printf("%v\n", v) | ||
} | ||
return nil | ||
} | ||
|
||
func doConfigSet(client *etcdClient, root string, kvs []string) ([]string, error) { | ||
var result []string | ||
for _, kv := range kvs { | ||
split := strings.Split(kv, "=") | ||
if len(split) != 2 { | ||
return result, fmt.Errorf("invalid argument: %v", kv) | ||
} | ||
val, err := client.Set(root+split[0], split[1]) | ||
if err != nil { | ||
return result, err | ||
} | ||
result = append(result, val) | ||
} | ||
return result, nil | ||
} | ||
|
||
func doConfigGet(client *etcdClient, root string, keys []string) ([]string, error) { | ||
var result []string | ||
for _, k := range keys { | ||
val, err := client.Get(root + k) | ||
if err != nil { | ||
return result, err | ||
} | ||
result = append(result, val) | ||
} | ||
return result, 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,92 @@ | ||
package config | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"net/http" | ||
"strings" | ||
"time" | ||
|
||
fleetEtcd "github.com/coreos/fleet/etcd" | ||
"github.com/coreos/fleet/ssh" | ||
"github.com/coreos/go-etcd/etcd" | ||
"github.com/deis/deisctl/client" | ||
) | ||
|
||
func getTunnelFlag() string { | ||
tun := client.Flags.Tunnel | ||
if tun != "" && !strings.Contains(tun, ":") { | ||
tun += ":22" | ||
} | ||
return tun | ||
} | ||
|
||
func getChecker() *ssh.HostKeyChecker { | ||
if !client.Flags.StrictHostKeyChecking { | ||
return nil | ||
} | ||
keyFile := ssh.NewHostKeyFile(client.Flags.KnownHostsFile) | ||
return ssh.NewHostKeyChecker(keyFile) | ||
} | ||
|
||
type etcdClient struct { | ||
etcd *etcd.Client | ||
} | ||
|
||
func (c *etcdClient) Get(key string) (string, error) { | ||
sort, recursive := true, false | ||
resp, err := c.etcd.Get(key, sort, recursive) | ||
if err != nil { | ||
return "", err | ||
} | ||
return resp.Node.Value, nil | ||
} | ||
|
||
func (c *etcdClient) Set(key string, value string) (string, error) { | ||
resp, err := c.etcd.Set(key, value, 0) // don't use TTLs | ||
if err != nil { | ||
return "", err | ||
} | ||
return resp.Node.Value, nil | ||
} | ||
|
||
func getEtcdClient() (*etcdClient, error) { | ||
var dial func(string, string) (net.Conn, error) | ||
tun := getTunnelFlag() | ||
if tun != "" { | ||
sshClient, err := ssh.NewSSHClient("core", tun, getChecker(), false) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed initializing SSH client: %v", err) | ||
} | ||
|
||
dial = func(network, addr string) (net.Conn, error) { | ||
tcpaddr, err := net.ResolveTCPAddr(network, addr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return sshClient.DialTCP(network, nil, tcpaddr) | ||
} | ||
} | ||
|
||
tlsConfig, err := fleetEtcd.ReadTLSConfigFiles(client.Flags.EtcdCAFile, | ||
client.Flags.EtcdCertFile, client.Flags.EtcdKeyFile) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
trans := http.Transport{ | ||
Dial: dial, | ||
TLSClientConfig: tlsConfig, | ||
} | ||
|
||
timeout := time.Duration(client.Flags.RequestTimeout*1000) * time.Millisecond | ||
machines := []string{client.Flags.Endpoint} | ||
|
||
c := etcd.NewClient(machines) | ||
c.SetDialTimeout(timeout) | ||
|
||
// use custom transport with SSH tunnel capability | ||
c.SetTransport(&trans) | ||
|
||
return &etcdClient{etcd: c}, 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