mirror of
https://github.com/dokku/dokku.git
synced 2026-02-23 19:50:34 +01:00
refactor: split out config logic to remove need to check app name for function-based usage
This MR splits out the logic such that there is now a binary that handles function based calls without validating the app name. We should only every check the app name for the subcommands and not internally. Internal calls should have their arguments taken at face value.
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
SUBCOMMANDS = subcommands/bundle subcommands/clear subcommands/export subcommands/get subcommands/keys subcommands/show subcommands/set subcommands/unset
|
||||
TRIGGERS = triggers/config-export triggers/config-get triggers/config-get-global
|
||||
BUILD = commands subcommands triggers
|
||||
BUILD = commands config_sub subcommands triggers
|
||||
PLUGIN_NAME = config
|
||||
|
||||
clean-config_sub:
|
||||
rm -rf config_sub
|
||||
|
||||
config_sub: clean-config_sub **/**/config_sub.go
|
||||
go build -ldflags="-s -w" $(GO_ARGS) -o config_sub src/config_sub/config_sub.go
|
||||
|
||||
include ../../common.mk
|
||||
|
||||
@@ -7,7 +7,7 @@ config_sub() {
|
||||
declare desc="executes a config subcommand"
|
||||
local name="$1"
|
||||
shift
|
||||
"$PLUGIN_AVAILABLE_PATH/config/subcommands/$name" "config:$name" "$@"
|
||||
"$PLUGIN_AVAILABLE_PATH/config/config_sub" "$name" "$@"
|
||||
}
|
||||
|
||||
config_export() {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package config
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
func export(appName string, global bool, merged bool, format string) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
func export(appName string, merged bool, format string) error {
|
||||
env := getEnvironment(appName, merged)
|
||||
exportType := ExportFormatExports
|
||||
suffix := "\n"
|
||||
@@ -37,3 +40,113 @@ func export(appName string, global bool, merged bool, format string) error {
|
||||
fmt.Print(exported + suffix)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubBundle implements the logic for config:bundle without app name validation
|
||||
func SubBundle(appName string, merged bool) error {
|
||||
env := getEnvironment(appName, merged)
|
||||
return env.ExportBundle(os.Stdout)
|
||||
}
|
||||
|
||||
// SubClear implements the logic for config:clear without app name validation
|
||||
func SubClear(appName string, noRestart bool) error {
|
||||
return UnsetAll(appName, !noRestart)
|
||||
}
|
||||
|
||||
// SubExport implements the logic for config:export without app name validation
|
||||
func SubExport(appName string, merged bool, format string) error {
|
||||
return export(appName, merged, format)
|
||||
}
|
||||
|
||||
// SubGet implements the logic for config:get without app name validation
|
||||
func SubGet(appName string, keys []string, quoted bool) error {
|
||||
if len(keys) == 0 {
|
||||
return errors.New("Expected: key")
|
||||
}
|
||||
|
||||
if len(keys) != 1 {
|
||||
return fmt.Errorf("Unexpected argument(s): %v", keys[1:])
|
||||
}
|
||||
|
||||
value, ok := Get(appName, keys[0])
|
||||
if !ok {
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
if quoted {
|
||||
fmt.Printf("'%s'\n", singleQuoteEscape(value))
|
||||
} else {
|
||||
fmt.Printf("%s\n", value)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubKeys implements the logic for config:keys without app name validation
|
||||
func SubKeys(appName string, merged bool) error {
|
||||
env := getEnvironment(appName, merged)
|
||||
for _, k := range env.Keys() {
|
||||
fmt.Println(k)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubSet implements the logic for config:set without app name validation
|
||||
func SubSet(appName string, pairs []string, noRestart bool, encoded bool) error {
|
||||
if len(pairs) == 0 {
|
||||
return errors.New("At least one env pair must be given")
|
||||
}
|
||||
|
||||
updated := make(map[string]string)
|
||||
for _, e := range pairs {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
if len(parts) == 1 {
|
||||
return fmt.Errorf("Invalid env pair: %v", e)
|
||||
}
|
||||
|
||||
key, value := parts[0], parts[1]
|
||||
if encoded {
|
||||
decoded, err := base64.StdEncoding.DecodeString(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s for key '%s'", err.Error(), key)
|
||||
}
|
||||
value = string(decoded)
|
||||
}
|
||||
updated[key] = value
|
||||
}
|
||||
|
||||
return SetMany(appName, updated, !noRestart)
|
||||
}
|
||||
|
||||
// SubShow implements the logic for config:show without app name validation
|
||||
func SubShow(appName string, merged bool, shell bool, export bool) error {
|
||||
env := getEnvironment(appName, merged)
|
||||
if shell && export {
|
||||
return errors.New("Only one of --shell and --export can be given")
|
||||
}
|
||||
if shell {
|
||||
common.LogWarn("Deprecated: Use 'config:export --format shell' instead")
|
||||
fmt.Print(env.Export(ExportFormatShell))
|
||||
} else if export {
|
||||
common.LogWarn("Deprecated: Use 'config:export --format exports' instead")
|
||||
fmt.Println(env.Export(ExportFormatExports))
|
||||
} else {
|
||||
contextName := "global"
|
||||
if appName != "" {
|
||||
contextName = appName
|
||||
}
|
||||
common.LogInfo2Quiet(contextName + " env vars")
|
||||
fmt.Println(env.Export(ExportFormatPretty))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SubUnset implements the logic for config:unset without app name validation
|
||||
func SubUnset(appName string, keys []string, noRestart bool) error {
|
||||
if len(keys) == 0 {
|
||||
return fmt.Errorf("At least one key must be given")
|
||||
}
|
||||
|
||||
return UnsetMany(appName, keys, !noRestart)
|
||||
}
|
||||
|
||||
112
plugins/config/src/config_sub/config_sub.go
Normal file
112
plugins/config/src/config_sub/config_sub.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func getKeys(args []string, global bool) []string {
|
||||
keys := args
|
||||
if !global && len(keys) > 0 {
|
||||
keys = keys[1:]
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// main entrypoint to all subcommands
|
||||
func main() {
|
||||
action := os.Args[1]
|
||||
|
||||
var err error
|
||||
appName := "--global"
|
||||
switch action {
|
||||
case "bundle":
|
||||
args := flag.NewFlagSet("bundle", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
err = config.SubBundle(appName, *merged)
|
||||
case "clear":
|
||||
args := flag.NewFlagSet("clear", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
err = config.SubClear(appName, *noRestart)
|
||||
case "export":
|
||||
args := flag.NewFlagSet("export", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||
format := args.String("format", "exports", "--format: [ docker-args | docker-args-keys | exports | envfile | json | json-list | pack-keys | pretty | shell ] which format to export as)")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
err = config.SubExport(appName, *merged, *format)
|
||||
case "get":
|
||||
args := flag.NewFlagSet("get", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
quoted := args.Bool("quoted", false, "--quoted: get the value quoted")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
keys := getKeys(args.Args(), *global)
|
||||
err = config.SubGet(appName, keys, *quoted)
|
||||
case "keys":
|
||||
args := flag.NewFlagSet("keys", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
err = config.SubKeys(appName, *merged)
|
||||
case "show":
|
||||
args := flag.NewFlagSet("show", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
merged := args.Bool("merged", false, "--merged: display the app's environment merged with the global environment")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
err = config.SubShow(appName, *merged, false, false)
|
||||
case "set":
|
||||
args := flag.NewFlagSet("set", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
encoded := args.Bool("encoded", false, "--encoded: interpret VALUEs as base64")
|
||||
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
pairs := getKeys(args.Args(), *global)
|
||||
err = config.SubSet(appName, pairs, *noRestart, *encoded)
|
||||
case "unset":
|
||||
args := flag.NewFlagSet("unset", flag.ExitOnError)
|
||||
global := args.Bool("global", false, "--global: use the global environment")
|
||||
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
||||
args.Parse(os.Args[2:])
|
||||
if !*global {
|
||||
appName = args.Arg(0)
|
||||
}
|
||||
keys := getKeys(args.Args(), *global)
|
||||
err = config.SubUnset(appName, keys, *noRestart)
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin config_sub call: %s", action)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
common.LogFailWithError(err)
|
||||
}
|
||||
}
|
||||
@@ -1,156 +1,83 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
// CommandBundle implements config:bundle
|
||||
// CommandBundle creates a tarball of a .env.d directory
|
||||
// containing env vars for the app
|
||||
func CommandBundle(appName string, global bool, merged bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env := getEnvironment(appName, merged)
|
||||
return env.ExportBundle(os.Stdout)
|
||||
return SubBundle(appName, merged)
|
||||
}
|
||||
|
||||
// CommandClear implements config:clear
|
||||
// CommandClear unsets all environment variables in use
|
||||
func CommandClear(appName string, global bool, noRestart bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return UnsetAll(appName, !noRestart)
|
||||
return SubClear(appName, noRestart)
|
||||
}
|
||||
|
||||
// CommandExport implements config:export
|
||||
// CommandExport outputs all env vars (merged or not, global or not)
|
||||
// in the specified format for consumption by other tools
|
||||
func CommandExport(appName string, global bool, merged bool, format string) error {
|
||||
return export(appName, global, merged, format)
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return SubExport(appName, merged, format)
|
||||
}
|
||||
|
||||
// CommandGet implements config:get
|
||||
// CommandGet gets the value for the specified environment variable
|
||||
func CommandGet(appName string, keys []string, global bool, quoted bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return errors.New("Expected: key")
|
||||
}
|
||||
|
||||
if len(keys) != 1 {
|
||||
return fmt.Errorf("Unexpected argument(s): %v", keys[1:])
|
||||
}
|
||||
|
||||
value, ok := Get(appName, keys[0])
|
||||
if !ok {
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
if quoted {
|
||||
fmt.Printf("'%s'\n", singleQuoteEscape(value))
|
||||
} else {
|
||||
fmt.Printf("%s\n", value)
|
||||
}
|
||||
|
||||
return nil
|
||||
return SubGet(appName, keys, quoted)
|
||||
}
|
||||
|
||||
// CommandKeys implements config:keys
|
||||
// CommandKeys shows the keys set for the specified environment
|
||||
func CommandKeys(appName string, global bool, merged bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env := getEnvironment(appName, merged)
|
||||
for _, k := range env.Keys() {
|
||||
fmt.Println(k)
|
||||
}
|
||||
return nil
|
||||
return SubKeys(appName, merged)
|
||||
}
|
||||
|
||||
// CommandSet implements config:set
|
||||
// CommandSet sets one or more environment variable pairs
|
||||
func CommandSet(appName string, pairs []string, global bool, noRestart bool, encoded bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(pairs) == 0 {
|
||||
return errors.New("At least one env pair must be given")
|
||||
}
|
||||
|
||||
updated := make(map[string]string)
|
||||
for _, e := range pairs {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
if len(parts) == 1 {
|
||||
return fmt.Errorf("Invalid env pair: %v", e)
|
||||
}
|
||||
|
||||
key, value := parts[0], parts[1]
|
||||
if encoded {
|
||||
decoded, err := base64.StdEncoding.DecodeString(value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s for key '%s'", err.Error(), key)
|
||||
}
|
||||
value = string(decoded)
|
||||
}
|
||||
updated[key] = value
|
||||
}
|
||||
|
||||
return SetMany(appName, updated, !noRestart)
|
||||
return SubSet(appName, pairs, noRestart, encoded)
|
||||
}
|
||||
|
||||
// CommandShow implements config:show
|
||||
// CommandShow pretty-prints the specified environment vaiables
|
||||
func CommandShow(appName string, global bool, merged bool, shell bool, export bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env := getEnvironment(appName, merged)
|
||||
if shell && export {
|
||||
return errors.New("Only one of --shell and --export can be given")
|
||||
}
|
||||
if shell {
|
||||
common.LogWarn("Deprecated: Use 'config:export --format shell' instead")
|
||||
fmt.Print(env.Export(ExportFormatShell))
|
||||
} else if export {
|
||||
common.LogWarn("Deprecated: Use 'config:export --format exports' instead")
|
||||
fmt.Println(env.Export(ExportFormatExports))
|
||||
} else {
|
||||
contextName := "global"
|
||||
if appName != "" {
|
||||
contextName = appName
|
||||
}
|
||||
common.LogInfo2Quiet(contextName + " env vars")
|
||||
fmt.Println(env.Export(ExportFormatPretty))
|
||||
}
|
||||
|
||||
return nil
|
||||
return SubShow(appName, merged, shell, export)
|
||||
}
|
||||
|
||||
// CommandUnset implements config:unset
|
||||
// CommandUnset unsets one or more keys in a specified environment
|
||||
func CommandUnset(appName string, keys []string, global bool, noRestart bool) error {
|
||||
appName, err := getAppNameOrGlobal(appName, global)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return fmt.Errorf("At least one key must be given")
|
||||
}
|
||||
|
||||
return UnsetMany(appName, keys, !noRestart)
|
||||
return SubUnset(appName, keys, noRestart)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,13 @@ func TriggerConfigExport(appName string, global string, merged string, format st
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return export(appName, g, m, format)
|
||||
|
||||
appName, err = getAppNameOrGlobal(appName, g)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return export(appName, m, format)
|
||||
}
|
||||
|
||||
// TriggerConfigGet returns an app config value by key
|
||||
|
||||
Reference in New Issue
Block a user