Skip to content

Commit

Permalink
Merge pull request #45 from helgi/registry
Browse files Browse the repository at this point in the history
feat(registry): add support for setting private registry information per application
  • Loading branch information
helgi committed Apr 22, 2016
2 parents 5e76fc6 + eee81a2 commit 6fb32bf
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 21 deletions.
128 changes: 128 additions & 0 deletions cmd/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package cmd

import (
"fmt"
"strings"

"github.com/deis/pkg/prettyprint"

"github.com/deis/workflow-cli/controller/api"
"github.com/deis/workflow-cli/controller/models/config"
)

// RegistryList lists an app's registry information.
func RegistryList(appID string) error {
c, appID, err := load(appID)

if err != nil {
return err
}

config, err := config.List(c, appID)

fmt.Printf("=== %s Registry\n", appID)

registryMap := make(map[string]string)

for key, value := range config.Registry {
registryMap[key] = fmt.Sprintf("%v", value)
}

fmt.Print(prettyprint.PrettyTabs(registryMap, 5))

return nil
}

// RegistrySet sets an app's registry information.
func RegistrySet(appID string, item []string) error {
c, appID, err := load(appID)

if err != nil {
return err
}

registryMap := parseInfos(item)

fmt.Print("Applying registry information... ")

quit := progress()
configObj := api.Config{}
configObj.Registry = registryMap

_, err = config.Set(c, appID, configObj)

quit <- true
<-quit

if err != nil {
return err
}

fmt.Print("done\n\n")

return RegistryList(appID)
}

// RegistryUnset removes an app's registry information.
func RegistryUnset(appID string, items []string) error {
c, appID, err := load(appID)

if err != nil {
return err
}

fmt.Print("Applying registry information... ")

quit := progress()

configObj := api.Config{}

registryMap := make(map[string]interface{})

for _, key := range items {
registryMap[key] = nil
}

configObj.Registry = registryMap

_, err = config.Set(c, appID, configObj)

quit <- true
<-quit

if err != nil {
return err
}

fmt.Print("done\n\n")

return RegistryList(appID)
}

func parseInfos(items []string) map[string]interface{} {
registryMap := make(map[string]interface{})

for _, item := range items {
key, value, err := parseInfo(item)

if err != nil {
fmt.Println(err)
continue
}

registryMap[key] = value
}

return registryMap
}

func parseInfo(item string) (string, string, error) {
parts := strings.Split(item, "=")

if len(parts) != 2 {
return "", "", fmt.Errorf(`%s is invalid, Must be in format key=value
Examples: username=bob password=s3cur3pw1`, item)
}

return parts[0], parts[1], nil
}
19 changes: 10 additions & 9 deletions controller/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ type ConfigUnset struct {

// Config is the structure of an app's config.
type Config struct {
Owner string `json:"owner,omitempty"`
App string `json:"app,omitempty"`
Values map[string]interface{} `json:"values,omitempty"`
Memory map[string]interface{} `json:"memory,omitempty"`
CPU map[string]interface{} `json:"cpu,omitempty"`
Tags map[string]interface{} `json:"tags,omitempty"`
Created string `json:"created,omitempty"`
Updated string `json:"updated,omitempty"`
UUID string `json:"uuid,omitempty"`
Owner string `json:"owner,omitempty"`
App string `json:"app,omitempty"`
Values map[string]interface{} `json:"values,omitempty"`
Memory map[string]interface{} `json:"memory,omitempty"`
CPU map[string]interface{} `json:"cpu,omitempty"`
Tags map[string]interface{} `json:"tags,omitempty"`
Registry map[string]interface{} `json:"registry,omitempty"`
Created string `json:"created,omitempty"`
Updated string `json:"updated,omitempty"`
UUID string `json:"uuid,omitempty"`
}
39 changes: 28 additions & 11 deletions controller/models/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const configFixture string = `
"tags": {
"test": "tests"
},
"registry": {
"username": "bob"
},
"created": "2014-01-01T00:00:00UTC",
"updated": "2014-01-01T00:00:00UTC",
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
Expand All @@ -45,14 +48,15 @@ const configUnsetFixture string = `
"memory": {},
"cpu": {},
"tags": {},
"registry": {},
"created": "2014-01-01T00:00:00UTC",
"updated": "2014-01-01T00:00:00UTC",
"uuid": "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75"
}
`

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

type fakeHTTPServer struct{}

Expand Down Expand Up @@ -144,6 +148,9 @@ func TestConfigSet(t *testing.T) {
Tags: map[string]interface{}{
"test": "tests",
},
Registry: map[string]interface{}{
"username": "bob",
},
Created: "2014-01-01T00:00:00UTC",
Updated: "2014-01-01T00:00:00UTC",
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
Expand All @@ -163,6 +170,9 @@ func TestConfigSet(t *testing.T) {
Tags: map[string]interface{}{
"test": "tests",
},
Registry: map[string]interface{}{
"username": "bob",
},
}

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

expected := api.Config{
Owner: "test",
App: "unset-test",
Values: map[string]interface{}{},
Memory: map[string]interface{}{},
CPU: map[string]interface{}{},
Tags: map[string]interface{}{},
Created: "2014-01-01T00:00:00UTC",
Updated: "2014-01-01T00:00:00UTC",
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
Owner: "test",
App: "unset-test",
Values: map[string]interface{}{},
Memory: map[string]interface{}{},
CPU: map[string]interface{}{},
Tags: map[string]interface{}{},
Registry: map[string]interface{}{},
Created: "2014-01-01T00:00:00UTC",
Updated: "2014-01-01T00:00:00UTC",
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
}

configVars := api.Config{
Expand All @@ -219,6 +230,9 @@ func TestConfigUnset(t *testing.T) {
Tags: map[string]interface{}{
"test": nil,
},
Registry: map[string]interface{}{
"username": nil,
},
}

actual, err := Set(&client, "unset-test", configVars)
Expand Down Expand Up @@ -265,6 +279,9 @@ func TestConfigList(t *testing.T) {
Tags: map[string]interface{}{
"test": "tests",
},
Registry: map[string]interface{}{
"username": "bob",
},
Created: "2014-01-01T00:00:00UTC",
Updated: "2014-01-01T00:00:00UTC",
UUID: "de1bf5b5-4a72-4f94-a10c-d2a3741cdf75",
Expand Down
2 changes: 1 addition & 1 deletion deis.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Subcommands, use 'deis help [subcommand]' to learn more::
tags manage tags for application containers
releases manage releases of an application
certs manage SSL endpoints for an app
registry manage private registry information for your application
keys manage ssh keys used for 'git push' deployments
perms manage permissions for applications
git manage git for applications
Expand Down
115 changes: 115 additions & 0 deletions parser/registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package parser

import (
"github.com/deis/workflow-cli/cmd"
docopt "github.com/docopt/docopt-go"
)

// Registry routes registry commands to their specific function
func Registry(argv []string) error {
usage := `
Valid commands for registry:
registry:list list registry info for an app
registry:set set registry info for an app
registry:unset unset registry info for an app
Use 'deis help [command]' to learn more.
`

switch argv[0] {
case "registry:list":
return registryList(argv)
case "registry:set":
return registrySet(argv)
case "registry:unset":
return registryUnset(argv)
default:
if printHelp(argv, usage) {
return nil
}

if argv[0] == "registry" {
argv[0] = "registry:list"
return registryList(argv)
}

PrintUsage()
return nil
}
}

func registryList(argv []string) error {
usage := `
Lists registry information for an application.
Usage: deis registry:list [options]
Options:
-a --app=<app>
the uniquely identifiable name of the application.
`

args, err := docopt.Parse(usage, argv, true, "", false, true)

if err != nil {
return err
}

return cmd.RegistryList(safeGetValue(args, "--app"))
}

func registrySet(argv []string) error {
usage := `
Sets registry information for an application.
key/value pairs used to configure / authenticate against external registries
Usage: deis registry:set [options] <key>=<value>...
Arguments:
<key> the registry key, for example: "username" or "password"
<value> the registry value, for example: "bob" or "s3cur3pw1"
Options:
-a --app=<app>
the uniquely identifiable name for the application.
`

args, err := docopt.Parse(usage, argv, true, "", false, true)

if err != nil {
return err
}

app := safeGetValue(args, "--app")
info := args["<key>=<value>"].([]string)

return cmd.RegistrySet(app, info)
}

func registryUnset(argv []string) error {
usage := `
Unsets registry information for an application.
Usage: deis registry:unset [options] <key>...
Arguments:
<key> the registry key to unset, for example: "username" or "password"
Options:
-a --app=<app>
the uniquely identifiable name for the application.
`

args, err := docopt.Parse(usage, argv, true, "", false, true)

if err != nil {
return err
}

app := safeGetValue(args, "--app")
key := args["<key>"].([]string)

return cmd.RegistryUnset(app, key)
}

0 comments on commit 6fb32bf

Please sign in to comment.