Skip to content

Commit eee81a2

Browse files
committed
feat(registry): add support for setting private registry information per application
ref deis/controller#653
1 parent 32d64f9 commit eee81a2

5 files changed

Lines changed: 282 additions & 21 deletions

File tree

cmd/registry.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/deis/pkg/prettyprint"
8+
9+
"github.com/deis/workflow-cli/controller/api"
10+
"github.com/deis/workflow-cli/controller/models/config"
11+
)
12+
13+
// RegistryList lists an app's registry information.
14+
func RegistryList(appID string) error {
15+
c, appID, err := load(appID)
16+
17+
if err != nil {
18+
return err
19+
}
20+
21+
config, err := config.List(c, appID)
22+
23+
fmt.Printf("=== %s Registry\n", appID)
24+
25+
registryMap := make(map[string]string)
26+
27+
for key, value := range config.Registry {
28+
registryMap[key] = fmt.Sprintf("%v", value)
29+
}
30+
31+
fmt.Print(prettyprint.PrettyTabs(registryMap, 5))
32+
33+
return nil
34+
}
35+
36+
// RegistrySet sets an app's registry information.
37+
func RegistrySet(appID string, item []string) error {
38+
c, appID, err := load(appID)
39+
40+
if err != nil {
41+
return err
42+
}
43+
44+
registryMap := parseInfos(item)
45+
46+
fmt.Print("Applying registry information... ")
47+
48+
quit := progress()
49+
configObj := api.Config{}
50+
configObj.Registry = registryMap
51+
52+
_, err = config.Set(c, appID, configObj)
53+
54+
quit <- true
55+
<-quit
56+
57+
if err != nil {
58+
return err
59+
}
60+
61+
fmt.Print("done\n\n")
62+
63+
return RegistryList(appID)
64+
}
65+
66+
// RegistryUnset removes an app's registry information.
67+
func RegistryUnset(appID string, items []string) error {
68+
c, appID, err := load(appID)
69+
70+
if err != nil {
71+
return err
72+
}
73+
74+
fmt.Print("Applying registry information... ")
75+
76+
quit := progress()
77+
78+
configObj := api.Config{}
79+
80+
registryMap := make(map[string]interface{})
81+
82+
for _, key := range items {
83+
registryMap[key] = nil
84+
}
85+
86+
configObj.Registry = registryMap
87+
88+
_, err = config.Set(c, appID, configObj)
89+
90+
quit <- true
91+
<-quit
92+
93+
if err != nil {
94+
return err
95+
}
96+
97+
fmt.Print("done\n\n")
98+
99+
return RegistryList(appID)
100+
}
101+
102+
func parseInfos(items []string) map[string]interface{} {
103+
registryMap := make(map[string]interface{})
104+
105+
for _, item := range items {
106+
key, value, err := parseInfo(item)
107+
108+
if err != nil {
109+
fmt.Println(err)
110+
continue
111+
}
112+
113+
registryMap[key] = value
114+
}
115+
116+
return registryMap
117+
}
118+
119+
func parseInfo(item string) (string, string, error) {
120+
parts := strings.Split(item, "=")
121+
122+
if len(parts) != 2 {
123+
return "", "", fmt.Errorf(`%s is invalid, Must be in format key=value
124+
Examples: username=bob password=s3cur3pw1`, item)
125+
}
126+
127+
return parts[0], parts[1], nil
128+
}

controller/api/config.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ type ConfigUnset struct {
1212

1313
// Config is the structure of an app's config.
1414
type Config struct {
15-
Owner string `json:"owner,omitempty"`
16-
App string `json:"app,omitempty"`
17-
Values map[string]interface{} `json:"values,omitempty"`
18-
Memory map[string]interface{} `json:"memory,omitempty"`
19-
CPU map[string]interface{} `json:"cpu,omitempty"`
20-
Tags map[string]interface{} `json:"tags,omitempty"`
21-
Created string `json:"created,omitempty"`
22-
Updated string `json:"updated,omitempty"`
23-
UUID string `json:"uuid,omitempty"`
15+
Owner string `json:"owner,omitempty"`
16+
App string `json:"app,omitempty"`
17+
Values map[string]interface{} `json:"values,omitempty"`
18+
Memory map[string]interface{} `json:"memory,omitempty"`
19+
CPU map[string]interface{} `json:"cpu,omitempty"`
20+
Tags map[string]interface{} `json:"tags,omitempty"`
21+
Registry map[string]interface{} `json:"registry,omitempty"`
22+
Created string `json:"created,omitempty"`
23+
Updated string `json:"updated,omitempty"`
24+
UUID string `json:"uuid,omitempty"`
2425
}

controller/models/config/config_test.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const configFixture string = `
3131
"tags": {
3232
"test": "tests"
3333
},
34+
"registry": {
35+
"username": "bob"
36+
},
3437
"created": "2014-01-01T00:00:00UTC",
3538
"updated": "2014-01-01T00:00:00UTC",
3639
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
@@ -45,14 +48,15 @@ const configUnsetFixture string = `
4548
"memory": {},
4649
"cpu": {},
4750
"tags": {},
51+
"registry": {},
4852
"created": "2014-01-01T00:00:00UTC",
4953
"updated": "2014-01-01T00:00:00UTC",
5054
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
5155
}
5256
`
5357

54-
const configSetExpected string = `{"values":{"FOO":"bar","TEST":"testing"},"memory":{"web":"1G"},"cpu":{"web":"1000"},"tags":{"test":"tests"}}`
55-
const configUnsetExpected string = `{"values":{"FOO":null,"TEST":null},"memory":{"web":null},"cpu":{"web":null},"tags":{"test":null}}`
58+
const configSetExpected string = `{"values":{"FOO":"bar","TEST":"testing"},"memory":{"web":"1G"},"cpu":{"web":"1000"},"tags":{"test":"tests"},"registry":{"username":"bob"}}`
59+
const configUnsetExpected string = `{"values":{"FOO":null,"TEST":null},"memory":{"web":null},"cpu":{"web":null},"tags":{"test":null},"registry":{"username":null}}`
5660

5761
type fakeHTTPServer struct{}
5862

@@ -144,6 +148,9 @@ func TestConfigSet(t *testing.T) {
144148
Tags: map[string]interface{}{
145149
"test": "tests",
146150
},
151+
Registry: map[string]interface{}{
152+
"username": "bob",
153+
},
147154
Created: "2014-01-01T00:00:00UTC",
148155
Updated: "2014-01-01T00:00:00UTC",
149156
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
@@ -163,6 +170,9 @@ func TestConfigSet(t *testing.T) {
163170
Tags: map[string]interface{}{
164171
"test": "tests",
165172
},
173+
Registry: map[string]interface{}{
174+
"username": "bob",
175+
},
166176
}
167177

168178
actual, err := Set(&client, "example-go", configVars)
@@ -194,15 +204,16 @@ func TestConfigUnset(t *testing.T) {
194204
client := client.Client{HTTPClient: httpClient, ControllerURL: *u, Token: "abc"}
195205

196206
expected := api.Config{
197-
Owner: "test",
198-
App: "unset-test",
199-
Values: map[string]interface{}{},
200-
Memory: map[string]interface{}{},
201-
CPU: map[string]interface{}{},
202-
Tags: map[string]interface{}{},
203-
Created: "2014-01-01T00:00:00UTC",
204-
Updated: "2014-01-01T00:00:00UTC",
205-
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
207+
Owner: "test",
208+
App: "unset-test",
209+
Values: map[string]interface{}{},
210+
Memory: map[string]interface{}{},
211+
CPU: map[string]interface{}{},
212+
Tags: map[string]interface{}{},
213+
Registry: map[string]interface{}{},
214+
Created: "2014-01-01T00:00:00UTC",
215+
Updated: "2014-01-01T00:00:00UTC",
216+
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
206217
}
207218

208219
configVars := api.Config{
@@ -219,6 +230,9 @@ func TestConfigUnset(t *testing.T) {
219230
Tags: map[string]interface{}{
220231
"test": nil,
221232
},
233+
Registry: map[string]interface{}{
234+
"username": nil,
235+
},
222236
}
223237

224238
actual, err := Set(&client, "unset-test", configVars)
@@ -265,6 +279,9 @@ func TestConfigList(t *testing.T) {
265279
Tags: map[string]interface{}{
266280
"test": "tests",
267281
},
282+
Registry: map[string]interface{}{
283+
"username": "bob",
284+
},
268285
Created: "2014-01-01T00:00:00UTC",
269286
Updated: "2014-01-01T00:00:00UTC",
270287
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",

deis.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Subcommands, use 'deis help [subcommand]' to learn more::
4646
tags manage tags for application containers
4747
releases manage releases of an application
4848
certs manage SSL endpoints for an app
49-
49+
registry manage private registry information for your application
5050
keys manage ssh keys used for 'git push' deployments
5151
perms manage permissions for applications
5252
git manage git for applications

parser/registry.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package parser
2+
3+
import (
4+
"github.com/deis/workflow-cli/cmd"
5+
docopt "github.com/docopt/docopt-go"
6+
)
7+
8+
// Registry routes registry commands to their specific function
9+
func Registry(argv []string) error {
10+
usage := `
11+
Valid commands for registry:
12+
13+
registry:list list registry info for an app
14+
registry:set set registry info for an app
15+
registry:unset unset registry info for an app
16+
17+
Use 'deis help [command]' to learn more.
18+
`
19+
20+
switch argv[0] {
21+
case "registry:list":
22+
return registryList(argv)
23+
case "registry:set":
24+
return registrySet(argv)
25+
case "registry:unset":
26+
return registryUnset(argv)
27+
default:
28+
if printHelp(argv, usage) {
29+
return nil
30+
}
31+
32+
if argv[0] == "registry" {
33+
argv[0] = "registry:list"
34+
return registryList(argv)
35+
}
36+
37+
PrintUsage()
38+
return nil
39+
}
40+
}
41+
42+
func registryList(argv []string) error {
43+
usage := `
44+
Lists registry information for an application.
45+
46+
Usage: deis registry:list [options]
47+
48+
Options:
49+
-a --app=<app>
50+
the uniquely identifiable name of the application.
51+
`
52+
53+
args, err := docopt.Parse(usage, argv, true, "", false, true)
54+
55+
if err != nil {
56+
return err
57+
}
58+
59+
return cmd.RegistryList(safeGetValue(args, "--app"))
60+
}
61+
62+
func registrySet(argv []string) error {
63+
usage := `
64+
Sets registry information for an application.
65+
66+
key/value pairs used to configure / authenticate against external registries
67+
68+
Usage: deis registry:set [options] <key>=<value>...
69+
70+
Arguments:
71+
<key> the registry key, for example: "username" or "password"
72+
<value> the registry value, for example: "bob" or "s3cur3pw1"
73+
74+
Options:
75+
-a --app=<app>
76+
the uniquely identifiable name for the application.
77+
`
78+
79+
args, err := docopt.Parse(usage, argv, true, "", false, true)
80+
81+
if err != nil {
82+
return err
83+
}
84+
85+
app := safeGetValue(args, "--app")
86+
info := args["<key>=<value>"].([]string)
87+
88+
return cmd.RegistrySet(app, info)
89+
}
90+
91+
func registryUnset(argv []string) error {
92+
usage := `
93+
Unsets registry information for an application.
94+
95+
Usage: deis registry:unset [options] <key>...
96+
97+
Arguments:
98+
<key> the registry key to unset, for example: "username" or "password"
99+
100+
Options:
101+
-a --app=<app>
102+
the uniquely identifiable name for the application.
103+
`
104+
105+
args, err := docopt.Parse(usage, argv, true, "", false, true)
106+
107+
if err != nil {
108+
return err
109+
}
110+
111+
app := safeGetValue(args, "--app")
112+
key := args["<key>"].([]string)
113+
114+
return cmd.RegistryUnset(app, key)
115+
}

0 commit comments

Comments
 (0)