@@ -5,9 +5,33 @@ import (
55 "os"
66
77 "github.com/codegangsta/cli"
8+ "github.com/deis/deis/trireme/storage"
89)
910
11+ var parts = map [string ]string {
12+ // In alpha order, please.
13+ "builder" : "the builder" ,
14+ "controller" : "the controller" ,
15+ "database" : "the database" ,
16+ "router" : "the router mesh" ,
17+ "store" : "the store and all of its components" ,
18+ // FIXME: Do the rest.
19+ }
20+
21+ var config storage.Storer
22+
1023func main () {
24+
25+ // This is temporary: We need a place to store configuration data in
26+ // lieu of etcd. For now, we'll store it locally in a configuration
27+ // file.
28+ var err error
29+ config , err = storage .New (defaultConfigFile ())
30+ if err != nil {
31+ fmt .Printf ("Failed to load or create file %s" , defaultConfigFile ())
32+ os .Exit (321 )
33+ }
34+
1135 app := cli .NewApp ()
1236 app .Name = "trireme"
1337 app .Usage = "A control tool for Deis"
@@ -27,19 +51,126 @@ func commands() []cli.Command {
2751 */
2852 Subcommands : installCommands (),
2953 },
54+ {
55+ Name : "config" ,
56+ Usage : "Get and set configuration values" ,
57+ Subcommands : configCommands (),
58+ },
3059 }
3160}
3261
33- func installCommands () []cli.Command {
34- parts := map [string ]string {
35- // In alpha order, please.
36- "builder" : "the builder" ,
37- "controller" : "the controller" ,
38- "database" : "the database" ,
39- "router" : "the router mesh" ,
40- "store" : "the store and all of its components" ,
41- // FIXME: Do the rest.
62+ func defaultConfigFile () string {
63+ return os .ExpandEnv ("${HOME}/.trireme" )
64+ }
65+
66+ func configCommands () []cli.Command {
67+ cmds := make ([]cli.Command , 0 , len (parts )+ 3 )
68+
69+ // Why deprecate `deisctl config <target> set ...`? Three reasons:
70+ // 1. The predominant form of multi-commands is <CMD> <VERB> <DO>..., not
71+ // <CMD> <NOUN> <DO> <VERB>...
72+ // 2. The common unix paradigm for subcommands is to move all variables to
73+ // the arguments portion: <CMD> <SUBCMD> <ARG1>..., not <CMD> <SUBCMD> <ARG1> <SUBCMD> <ARG2>...
74+ // 3. The logic is simply cleaner when arguments are grouped together.
75+ cmds = append (cmds ,
76+ cli.Command {
77+ Name : "get" ,
78+ Usage : "Get an existing parameter from an existing component" ,
79+ Action : func (c * cli.Context ) {
80+ a := c .Args ()
81+ if len (a ) < 2 {
82+ fmt .Println ("Usage: deisctl config get <TARGET> <KEY>" )
83+ os .Exit (1 )
84+ }
85+ ns := a [0 ]
86+ key := a [1 ]
87+ val , err := config .Get (ns , key )
88+ if err != nil {
89+ fmt .Printf ("Failed to get %s:%s: '%s'\n " , ns , key , err )
90+ os .Exit (2 )
91+ }
92+ fmt .Println (val )
93+ },
94+ },
95+ cli.Command {
96+ Name : "set" ,
97+ Usage : "Set an existing parameter for an existing component" ,
98+ Action : func (c * cli.Context ) {
99+ a := c .Args ()
100+ if len (a ) < 3 {
101+ fmt .Println ("Usage: deisctl config get <TARGET> <KEY> <VALUE>" )
102+ os .Exit (1 )
103+ }
104+ ns := a [0 ]
105+ key := a [1 ]
106+ val := a [2 ]
107+ if err := config .Set (ns , key , val ); err != nil {
108+ fmt .Printf ("Failed to set %s:%s=%s: '%s'\n " , ns , key , val , err )
109+ os .Exit (3 )
110+ }
111+ fmt .Println (val )
112+ },
113+ },
114+ cli.Command {
115+ Name : "rm" ,
116+ Usage : "Remove an existing parameter from an existing component" ,
117+ Action : func (c * cli.Context ) {
118+ a := c .Args ()
119+ if len (a ) < 2 {
120+ fmt .Println ("Usage: deisctl config rm <TARGET> <KEY>" )
121+ os .Exit (1 )
122+ }
123+ ns := a [0 ]
124+ key := a [1 ]
125+ if err := config .Remove (ns , key ); err != nil {
126+ fmt .Printf ("Failed to remove %s:%s: '%s'\n " , ns , key , err )
127+ os .Exit (4 )
128+ }
129+ },
130+ },
131+ )
132+
133+ for n , _ := range parts {
134+ cmds = append (cmds , cli.Command {
135+ Name : n ,
136+ Usage : fmt .Sprintf ("Deprecated. Use `deisctl config set|get|rm %s`" , n ),
137+ Action : func (c * cli.Context ) {
138+ a := c .Args ()
139+ if len (a ) < 2 {
140+ fmt .Println ("Usage: deisctl config get|set|rm <TARGET> <KEY> [<VALUE>]" )
141+ os .Exit (1 )
142+ }
143+ key := a [1 ]
144+ switch a [0 ] {
145+ case "get" :
146+ val , err := config .Get (n , key )
147+ if err != nil {
148+ fmt .Println (err )
149+ os .Exit (2 )
150+ }
151+ fmt .Println (val )
152+ case "set" :
153+ if err := config .Set (n , key , a [2 ]); err != nil {
154+ fmt .Println ("Usage: deisctl config get|set|rm <TARGET> <KEY> [<VALUE>]" )
155+ os .Exit (3 )
156+ }
157+ fmt .Println (a [2 ])
158+ case "rm" :
159+ if err := config .Remove (n , key ); err != nil {
160+ fmt .Println ("Usage: deisctl config get|set|rm <TARGET> <KEY> [<VALUE>]" )
161+ os .Exit (4 )
162+ }
163+ default :
164+ fmt .Println ("Usage: deisctl config get|set|rm <TARGET> <KEY> [<VALUE>]" )
165+ os .Exit (1 )
166+ }
167+ },
168+ })
42169 }
170+ return cmds
171+ }
172+
173+ func installCommands () []cli.Command {
43174
44175 // This basically ensures that append() will not have to reallocate.
45176 cmds := make ([]cli.Command , 0 , len (parts )+ 1 )
0 commit comments