[config] refactor package structure
This commit is contained in:
@@ -4,32 +4,33 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/common"
|
"github.com/dokku/dokku/plugins/common"
|
||||||
configenv "github.com/dokku/dokku/plugins/config/src/configenv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//GetWithDefault gets a value from a config. If appName is empty the global config is used.
|
//Get retreives a value from a config. If appName is empty the global config is used.
|
||||||
func GetWithDefault(appName string, key string, defaultValue string) (value string) {
|
func Get(appName string, key string) (value string, ok bool) {
|
||||||
env, err := loadConfig(appName)
|
env, err := loadAppOrGlobalEnv(appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return defaultValue
|
return "", false
|
||||||
}
|
}
|
||||||
return env.GetDefault(key, defaultValue)
|
return env.Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
//HasKey determines if the config given by appName has a value for the given key
|
//GetWithDefault gets a value from a config. If appName is empty the global config is used. If the appName or key do not exist defaultValue is returned.
|
||||||
func HasKey(appName string, key string) (ok bool) {
|
func GetWithDefault(appName string, key string, defaultValue string) (value string) {
|
||||||
env, err := loadConfig(appName)
|
value, ok := Get(appName, key)
|
||||||
if err != nil {
|
if !ok {
|
||||||
return false
|
return defaultValue
|
||||||
}
|
}
|
||||||
_, ok = env.Get(key)
|
return value
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//SetMany variables in the environment. If appName is empty the global config is used. If restart is true the app is restarted.
|
//SetMany variables in the environment. If appName is empty the global config is used. If restart is true the app is restarted.
|
||||||
func SetMany(appName string, entries map[string]string, restart bool) {
|
func SetMany(appName string, entries map[string]string, restart bool) (err error) {
|
||||||
global := appName == ""
|
global := appName == ""
|
||||||
env := GetConfig(appName, false)
|
env, err := loadAppOrGlobalEnv(appName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
keys := make([]string, 0, len(entries))
|
keys := make([]string, 0, len(entries))
|
||||||
for k, v := range entries {
|
for k, v := range entries {
|
||||||
env.Set(k, v)
|
env.Set(k, v)
|
||||||
@@ -37,20 +38,24 @@ func SetMany(appName string, entries map[string]string, restart bool) {
|
|||||||
}
|
}
|
||||||
if len(entries) != 0 {
|
if len(entries) != 0 {
|
||||||
common.LogInfo1("Setting config vars")
|
common.LogInfo1("Setting config vars")
|
||||||
fmt.Println(configenv.PrettyPrintEnvEntries(" ", entries))
|
fmt.Println(prettyPrintEnvEntries(" ", entries))
|
||||||
env.Write()
|
env.Write()
|
||||||
args := append([]string{appName, "set"}, keys...)
|
args := append([]string{appName, "set"}, keys...)
|
||||||
common.PlugnTrigger("post-config-update", args...)
|
common.PlugnTrigger("post-config-update", args...)
|
||||||
}
|
}
|
||||||
if !global && restart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
if !global && restart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
||||||
Restart(appName)
|
triggerRestart(appName)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//UnsetMany a value in a config. If appName is empty the global config is used. If restart is true the app is restarted.
|
//UnsetMany a value in a config. If appName is empty the global config is used. If restart is true the app is restarted.
|
||||||
func UnsetMany(appName string, keys []string, restart bool) {
|
func UnsetMany(appName string, keys []string, restart bool) (err error) {
|
||||||
global := appName == ""
|
global := appName == ""
|
||||||
env := GetConfig(appName, false)
|
env, err := loadAppOrGlobalEnv(appName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
var changed = false
|
var changed = false
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
common.LogInfo1(fmt.Sprintf("Unsetting %s", k))
|
common.LogInfo1(fmt.Sprintf("Unsetting %s", k))
|
||||||
@@ -63,53 +68,19 @@ func UnsetMany(appName string, keys []string, restart bool) {
|
|||||||
common.PlugnTrigger("post-config-update", args...)
|
common.PlugnTrigger("post-config-update", args...)
|
||||||
}
|
}
|
||||||
if !global && restart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
if !global && restart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
||||||
Restart(appName)
|
triggerRestart(appName)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//GetCommonArgs extracts common positional args (appName and keys)
|
func triggerRestart(appName string) {
|
||||||
func GetCommonArgs(global bool, args []string) (appName string, keys []string) {
|
|
||||||
nextArg := 0
|
|
||||||
if !global {
|
|
||||||
if len(args) > 0 {
|
|
||||||
appName = args[0]
|
|
||||||
}
|
|
||||||
if appName == "" {
|
|
||||||
common.LogFail("Please specify an app or --global")
|
|
||||||
} else {
|
|
||||||
nextArg++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
keys = args[nextArg:]
|
|
||||||
return appName, keys
|
|
||||||
}
|
|
||||||
|
|
||||||
//GetConfig for the given app (global config if appName is empty). Merge with global config if merged is true.
|
|
||||||
func GetConfig(appName string, merged bool) (env *configenv.Env) {
|
|
||||||
env, err := loadConfig(appName)
|
|
||||||
if err != nil {
|
|
||||||
common.LogFail(err.Error())
|
|
||||||
}
|
|
||||||
if appName != "" && merged {
|
|
||||||
global, err := configenv.LoadGlobal()
|
|
||||||
if err != nil {
|
|
||||||
common.LogFail(err.Error())
|
|
||||||
}
|
|
||||||
global.Merge(env)
|
|
||||||
return global
|
|
||||||
}
|
|
||||||
return env
|
|
||||||
}
|
|
||||||
|
|
||||||
//Restart trigger restart on app
|
|
||||||
func Restart(appName string) {
|
|
||||||
common.LogInfo1(fmt.Sprintf("Restarting app %s", appName))
|
common.LogInfo1(fmt.Sprintf("Restarting app %s", appName))
|
||||||
common.PlugnTrigger("app-restart", appName)
|
common.PlugnTrigger("app-restart", appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig(appName string) (env *configenv.Env, err error) {
|
func loadAppOrGlobalEnv(appName string) (env *Env, err error) {
|
||||||
if appName == "" || appName == "--global" {
|
if appName == "" || appName == "--global" {
|
||||||
return configenv.LoadGlobal()
|
return LoadGlobalEnv()
|
||||||
}
|
}
|
||||||
return configenv.LoadApp(appName)
|
return LoadAppEnv(appName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,20 +6,29 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
testAppName = "test-app-1"
|
testAppName = "test-app-1"
|
||||||
testAppDir = strings.Join([]string{"/home/dokku/", testAppName}, "")
|
dokkuRoot = common.MustGetEnv("DOKKU_ROOT")
|
||||||
|
testAppDir = strings.Join([]string{dokkuRoot, testAppName}, "/")
|
||||||
|
globalConfigFile = strings.Join([]string{dokkuRoot, "ENV"}, "/")
|
||||||
)
|
)
|
||||||
|
|
||||||
func setupTestApp() (err error) {
|
func setupTestApp() (err error) {
|
||||||
Expect(os.MkdirAll(testAppDir, 0644)).To(Succeed())
|
Expect(os.MkdirAll(testAppDir, 0766)).To(Succeed())
|
||||||
b := []byte("export testKey=TESTING\n")
|
b := []byte("export testKey=TESTING\n")
|
||||||
if err = ioutil.WriteFile(strings.Join([]string{testAppDir, "/ENV"}, ""), b, 0644); err != nil {
|
if err = ioutil.WriteFile(strings.Join([]string{testAppDir, "/ENV"}, ""), b, 0644); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = []byte("export testKey=GLOBAL_TESTING\nexport globalKey=GLOBAL_VALUE")
|
||||||
|
if err = ioutil.WriteFile(globalConfigFile, b, 0644); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,5 +41,96 @@ func TestConfigGetWithDefault(t *testing.T) {
|
|||||||
Expect(setupTestApp()).To(Succeed())
|
Expect(setupTestApp()).To(Succeed())
|
||||||
Expect(GetWithDefault(testAppName, "unknownKey", "UNKNOWN")).To(Equal("UNKNOWN"))
|
Expect(GetWithDefault(testAppName, "unknownKey", "UNKNOWN")).To(Equal("UNKNOWN"))
|
||||||
Expect(GetWithDefault(testAppName, "testKey", "testKey")).To(Equal("TESTING"))
|
Expect(GetWithDefault(testAppName, "testKey", "testKey")).To(Equal("TESTING"))
|
||||||
|
Expect(GetWithDefault(testAppName+"-nonexistent", "testKey", "default")).To(Equal("default"))
|
||||||
teardownTestApp()
|
teardownTestApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigGet(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
Expect(setupTestApp()).To(Succeed())
|
||||||
|
defer teardownTestApp()
|
||||||
|
|
||||||
|
expectValue(testAppName, "testKey", "TESTING")
|
||||||
|
expectValue("", "testKey", "GLOBAL_TESTING")
|
||||||
|
|
||||||
|
expectNoValue(testAppName, "testKey2")
|
||||||
|
expectNoValue("", "testKey2")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigSetMany(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
Expect(setupTestApp()).To(Succeed())
|
||||||
|
defer teardownTestApp()
|
||||||
|
|
||||||
|
expectValue(testAppName, "testKey", "TESTING")
|
||||||
|
|
||||||
|
vals := map[string]string{"testKey": "updated", "testKey2": "new"}
|
||||||
|
Expect(SetMany(testAppName, vals, false)).To(Succeed())
|
||||||
|
expectValue(testAppName, "testKey", "updated")
|
||||||
|
expectValue(testAppName, "testKey2", "new")
|
||||||
|
|
||||||
|
vals = map[string]string{"testKey": "updated_global", "testKey2": "new_global"}
|
||||||
|
Expect(SetMany("", vals, false)).To(Succeed())
|
||||||
|
expectValue("", "testKey", "updated_global")
|
||||||
|
expectValue("", "testKey2", "new_global")
|
||||||
|
expectValue("", "globalKey", "GLOBAL_VALUE")
|
||||||
|
expectValue(testAppName, "testKey", "updated")
|
||||||
|
expectValue(testAppName, "testKey2", "new")
|
||||||
|
|
||||||
|
Expect(SetMany(testAppName+"does_not_exist", vals, false)).ToNot(Succeed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigUnsetMany(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
Expect(setupTestApp()).To(Succeed())
|
||||||
|
defer teardownTestApp()
|
||||||
|
|
||||||
|
expectValue(testAppName, "testKey", "TESTING")
|
||||||
|
expectValue("", "testKey", "GLOBAL_TESTING")
|
||||||
|
|
||||||
|
keys := []string{"testKey", "noKey"}
|
||||||
|
Expect(UnsetMany(testAppName, keys, false)).To(Succeed())
|
||||||
|
expectNoValue(testAppName, "testKey")
|
||||||
|
expectValue("", "testKey", "GLOBAL_TESTING")
|
||||||
|
|
||||||
|
Expect(UnsetMany(testAppName, keys, false)).To(Succeed())
|
||||||
|
expectNoValue(testAppName, "testKey")
|
||||||
|
expectNoValue(testAppName, "globalKey")
|
||||||
|
|
||||||
|
Expect(UnsetMany(testAppName+"does-not-exist", keys, false)).ToNot(Succeed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnvironmentLoading(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
Expect(setupTestApp()).To(Succeed())
|
||||||
|
defer teardownTestApp()
|
||||||
|
|
||||||
|
env, err := LoadMergedAppEnv(testAppName)
|
||||||
|
Expect(err).To(Succeed())
|
||||||
|
v, _ := env.Get("testKey")
|
||||||
|
Expect(v).To(Equal("TESTING"))
|
||||||
|
v, _ = env.Get("globalKey")
|
||||||
|
Expect(v).To(Equal("GLOBAL_VALUE"))
|
||||||
|
Expect(env.Write()).ToNot(Succeed())
|
||||||
|
|
||||||
|
env, err = LoadAppEnv(testAppName)
|
||||||
|
env.Set("testKey", "TESTING-updated")
|
||||||
|
env.Set("testKey2", "TESTING-'\n'-updated")
|
||||||
|
env.Write()
|
||||||
|
|
||||||
|
expectValue(testAppName, "testKey", "TESTING-updated")
|
||||||
|
expectValue(testAppName, "testKey2", "TESTING-'\n'-updated")
|
||||||
|
expectValue("", "testKey", "GLOBAL_TESTING")
|
||||||
|
Expect(err).To(Succeed())
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectValue(appName string, key string, expected string) {
|
||||||
|
v, ok := Get(appName, key)
|
||||||
|
Expect(ok).To(Equal(true))
|
||||||
|
Expect(v).To(Equal(expected))
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectNoValue(appName string, key string) {
|
||||||
|
_, ok := Get(appName, key)
|
||||||
|
Expect(ok).To(Equal(false))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package configenv
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@@ -21,16 +21,16 @@ import (
|
|||||||
type ExportFormat int
|
type ExportFormat int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//Exports format: Sourceable exports
|
//ExportFormatExports format: Sourceable exports
|
||||||
Exports ExportFormat = iota
|
ExportFormatExports ExportFormat = iota
|
||||||
//Envfile format: dotenv file
|
//ExportFormatEnvfile format: dotenv file
|
||||||
Envfile
|
ExportFormatEnvfile
|
||||||
//DockerArgs format: --env args for docker
|
//ExportFormatDockerArgs format: --env args for docker
|
||||||
DockerArgs
|
ExportFormatDockerArgs
|
||||||
//Shell format: env arguments for shell
|
//ExportFormatShell format: env arguments for shell
|
||||||
Shell
|
ExportFormatShell
|
||||||
//Pretty format: pretty-printed in columns
|
//ExportFormatPretty format: pretty-printed in columns
|
||||||
Pretty
|
ExportFormatPretty
|
||||||
)
|
)
|
||||||
|
|
||||||
//Env is a representation for global or app environment
|
//Env is a representation for global or app environment
|
||||||
@@ -40,8 +40,8 @@ type Env struct {
|
|||||||
env map[string]string
|
env map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewFromString creates an env from the given ENVFILE contents representation
|
//newEnvFromString creates an env from the given ENVFILE contents representation
|
||||||
func NewFromString(rep string) (env *Env, err error) {
|
func newEnvFromString(rep string) (env *Env, err error) {
|
||||||
envMap, err := godotenv.Unmarshal(rep)
|
envMap, err := godotenv.Unmarshal(rep)
|
||||||
env = &Env{
|
env = &Env{
|
||||||
"<unknown>",
|
"<unknown>",
|
||||||
@@ -51,8 +51,8 @@ func NewFromString(rep string) (env *Env, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//LoadApp loads an environment for the given app
|
//LoadAppEnv loads an environment for the given app
|
||||||
func LoadApp(appName string) (env *Env, err error) {
|
func LoadAppEnv(appName string) (env *Env, err error) {
|
||||||
appfile, err := getAppFile(appName)
|
appfile, err := getAppFile(appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@@ -60,8 +60,24 @@ func LoadApp(appName string) (env *Env, err error) {
|
|||||||
return loadFromFile(appName, appfile)
|
return loadFromFile(appName, appfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
//LoadGlobal loads the global environmen
|
//LoadMergedAppEnv loads an app environment merged with the global environment
|
||||||
func LoadGlobal() (*Env, error) {
|
func LoadMergedAppEnv(appName string) (env *Env, err error) {
|
||||||
|
env, err = LoadAppEnv(appName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
global, err := LoadGlobalEnv()
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
global.Merge(env)
|
||||||
|
global.filename = ""
|
||||||
|
global.name = env.name
|
||||||
|
return global, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//LoadGlobalEnv loads the global environment
|
||||||
|
func LoadGlobalEnv() (*Env, error) {
|
||||||
return loadFromFile("global", getGlobalFile())
|
return loadFromFile("global", getGlobalFile())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,16 +158,16 @@ func (e *Env) Write() error {
|
|||||||
//Export the Env in the given format
|
//Export the Env in the given format
|
||||||
func (e *Env) Export(format ExportFormat) string {
|
func (e *Env) Export(format ExportFormat) string {
|
||||||
switch format {
|
switch format {
|
||||||
case Exports:
|
case ExportFormatExports:
|
||||||
return e.ExportfileString()
|
return e.ExportfileString()
|
||||||
case Envfile:
|
case ExportFormatEnvfile:
|
||||||
return e.EnvfileString()
|
return e.EnvfileString()
|
||||||
case DockerArgs:
|
case ExportFormatDockerArgs:
|
||||||
return e.DockerArgsString()
|
return e.DockerArgsString()
|
||||||
case Shell:
|
case ExportFormatShell:
|
||||||
return e.ShellString()
|
return e.ShellString()
|
||||||
case Pretty:
|
case ExportFormatPretty:
|
||||||
return PrettyPrintEnvEntries("", e.Map())
|
return prettyPrintEnvEntries("", e.Map())
|
||||||
default:
|
default:
|
||||||
common.LogFail(fmt.Sprintf("Unknown export format: %v", format))
|
common.LogFail(fmt.Sprintf("Unknown export format: %v", format))
|
||||||
return ""
|
return ""
|
||||||
@@ -166,18 +182,18 @@ func (e *Env) EnvfileString() string {
|
|||||||
|
|
||||||
//ExportfileString returns the contents of this Env as bash exports
|
//ExportfileString returns the contents of this Env as bash exports
|
||||||
func (e *Env) ExportfileString() string {
|
func (e *Env) ExportfileString() string {
|
||||||
return e.stringWithPrefixAndSeparator("export ", "\n", true)
|
return e.stringWithPrefixAndSeparator("export ", "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
//DockerArgsString gets the contents of this Env in the form -env=KEY=VALUE --env...
|
//DockerArgsString gets the contents of this Env in the form -env=KEY=VALUE --env...
|
||||||
func (e *Env) DockerArgsString() string {
|
func (e *Env) DockerArgsString() string {
|
||||||
return e.stringWithPrefixAndSeparator("--env=", " ", true)
|
return e.stringWithPrefixAndSeparator("--env=", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
//ShellString gets the contents of this Env in the form "KEY='value' KEY2='value'"
|
//ShellString gets the contents of this Env in the form "KEY='value' KEY2='value'"
|
||||||
// for passing the environment in the shell
|
// for passing the environment in the shell
|
||||||
func (e *Env) ShellString() string {
|
func (e *Env) ShellString() string {
|
||||||
return e.stringWithPrefixAndSeparator("", " ", true)
|
return e.stringWithPrefixAndSeparator("", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
//ExportBundle writes a tarfile of the environmnet to the given io.Writer.
|
//ExportBundle writes a tarfile of the environmnet to the given io.Writer.
|
||||||
@@ -202,13 +218,25 @@ func (e *Env) ExportBundle(dest io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//SingleQuoteEscape escapes the value as if it were shell-quoted in single quotes
|
//stringWithPrefixAndSeparator makes a string of the environment
|
||||||
func SingleQuoteEscape(value string) string { // so that 'esc'apped' -> 'esc'\''aped'
|
// with the given prefix and separator for each entry
|
||||||
|
func (e *Env) stringWithPrefixAndSeparator(prefix string, separator string) string {
|
||||||
|
keys := e.Keys()
|
||||||
|
entries := make([]string, len(keys))
|
||||||
|
for i, k := range keys {
|
||||||
|
v := singleQuoteEscape(e.env[k])
|
||||||
|
entries[i] = fmt.Sprintf("%s%s='%s'", prefix, k, v)
|
||||||
|
}
|
||||||
|
return strings.Join(entries, separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
//singleQuoteEscape escapes the value as if it were shell-quoted in single quotes
|
||||||
|
func singleQuoteEscape(value string) string { // so that 'esc'apped' -> 'esc'\''aped'
|
||||||
return strings.Replace(value, "'", "'\\''", -1)
|
return strings.Replace(value, "'", "'\\''", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
//PrettyPrintEnvEntries in columns
|
//prettyPrintEnvEntries in columns
|
||||||
func PrettyPrintEnvEntries(prefix string, entries map[string]string) (representation string) {
|
func prettyPrintEnvEntries(prefix string, entries map[string]string) (representation string) {
|
||||||
colConfig := columnize.DefaultConfig()
|
colConfig := columnize.DefaultConfig()
|
||||||
colConfig.Prefix = prefix
|
colConfig.Prefix = prefix
|
||||||
colConfig.Delim = "\x00"
|
colConfig.Delim = "\x00"
|
||||||
@@ -233,21 +261,6 @@ func loadFromFile(name string, filename string) (env *Env, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//stringWithPrefixAndSeparator makes a string of the environment
|
|
||||||
// with the given prefix and separator for each entry
|
|
||||||
func (e *Env) stringWithPrefixAndSeparator(prefix string, separator string, allowNewlines bool) string {
|
|
||||||
keys := e.Keys()
|
|
||||||
entries := make([]string, len(keys))
|
|
||||||
for i, k := range keys {
|
|
||||||
v := SingleQuoteEscape(e.env[k])
|
|
||||||
if !allowNewlines {
|
|
||||||
v = strings.Replace(v, "\n", "'$'\\n''", -1)
|
|
||||||
}
|
|
||||||
entries[i] = fmt.Sprintf("%s%s='%s'", prefix, k, v)
|
|
||||||
}
|
|
||||||
return strings.Join(entries, separator)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAppFile(appName string) (string, error) {
|
func getAppFile(appName string) (string, error) {
|
||||||
err := common.VerifyAppName(appName)
|
err := common.VerifyAppName(appName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
102
plugins/config/environment_test.go
Normal file
102
plugins/config/environment_test.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestExportfileRoundtrip(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
env, err := newEnvFromString("HI='ho'\nFoo='Bar'\n\nBaz='BOFF'")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(env.Map()).To(Equal(pairs("Baz", "BOFF", "Foo", "Bar", "HI", "ho")))
|
||||||
|
Expect(env.String()).To(Equal("Baz=\"BOFF\"\nFoo=\"Bar\"\nHI=\"ho\""))
|
||||||
|
|
||||||
|
env, err = newEnvFromString(`export HI="h\no"`)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(env.Map()).To(Equal(pairs("HI", "h\no")))
|
||||||
|
Expect(env.String()).To(Equal(`HI="h\no"`))
|
||||||
|
|
||||||
|
env, err = newEnvFromString("HI='ho'\nFOO=\"'\\nBAR=''\"")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(env.Map()).To(Equal(pairs("HI", "ho", "FOO", "'\nBAR=''")))
|
||||||
|
Expect(env.String()).To(Equal("FOO=\"'\\nBAR=''\"\nHI=\"ho\""))
|
||||||
|
|
||||||
|
env, err = newEnvFromString("FOO='bar' ")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(env.Map()).To(Equal(pairs("FOO", "bar")))
|
||||||
|
Expect(env.String()).To(Equal(`FOO="bar"`))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExportfileErrors(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
|
||||||
|
_, err := newEnvFromString("F\nOO='bar'") //keys cannot have embedded newlines
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMerge(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
e, _ := newEnvFromString("FOO='bar'")
|
||||||
|
e2, _ := newEnvFromString("BAR='baz'")
|
||||||
|
e.Merge(e2)
|
||||||
|
Expect(e.Map()).To(Equal(pairs("BAR", "baz", "FOO", "bar")))
|
||||||
|
|
||||||
|
e3, _ := newEnvFromString("FOO='ba \\nz'")
|
||||||
|
e.Merge(e3)
|
||||||
|
Expect(e.Map()).To(Equal(pairs("BAR", "baz", "FOO", "ba \nz")))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestExport(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
e, _ := newEnvFromString("BAR='BAZ'\nFOO='b'ar '\nBAZ='a\\nb'")
|
||||||
|
Expect(e.Export(ExportFormatEnvfile)).To(Equal("BAR=\"BAZ\"\nBAZ=\"a\\nb\"\nFOO=\"b'ar \""))
|
||||||
|
Expect(e.Export(ExportFormatDockerArgs)).To(Equal("--env=BAR='BAZ' --env=BAZ='a\nb' --env=FOO='b'\\''ar '"))
|
||||||
|
Expect(e.Export(ExportFormatShell)).To(Equal("BAR='BAZ' BAZ='a\nb' FOO='b'\\''ar '"))
|
||||||
|
Expect(e.Export(ExportFormatExports)).To(Equal("export BAR='BAZ'\nexport BAZ='a\nb'\nexport FOO='b'\\''ar '"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
RegisterTestingT(t)
|
||||||
|
e, err := newEnvFromString("BAR='BAZ'\nFOO='ba\\nr '\nGO='1'\nNOGO='0'")
|
||||||
|
Expect(err).To(Succeed())
|
||||||
|
|
||||||
|
v, ok := e.Get("GO")
|
||||||
|
Expect(ok).To(Equal(true))
|
||||||
|
Expect(v).To(Equal("1"))
|
||||||
|
|
||||||
|
v = e.GetDefault("GO", "default")
|
||||||
|
Expect(v).To(Equal("1"))
|
||||||
|
|
||||||
|
v = e.GetDefault("dne", "default")
|
||||||
|
Expect(v).To(Equal("default"))
|
||||||
|
|
||||||
|
b := e.GetBoolDefault("dne", true)
|
||||||
|
Expect(b).To(Equal(true))
|
||||||
|
|
||||||
|
b = e.GetBoolDefault("dne", false)
|
||||||
|
Expect(b).To(Equal(false))
|
||||||
|
|
||||||
|
b = e.GetBoolDefault("GO", false)
|
||||||
|
Expect(b).To(Equal(true))
|
||||||
|
|
||||||
|
b = e.GetBoolDefault("NOGO", true)
|
||||||
|
Expect(b).To(Equal(false))
|
||||||
|
|
||||||
|
b = e.GetBoolDefault("BAR", false)
|
||||||
|
Expect(b).To(Equal(true)) //anything but "0" is true
|
||||||
|
}
|
||||||
|
|
||||||
|
func pairs(vars ...string) map[string]string {
|
||||||
|
res := map[string]string{}
|
||||||
|
var i = 0
|
||||||
|
for i < len(vars)-1 {
|
||||||
|
key := vars[i]
|
||||||
|
value := vars[i+1]
|
||||||
|
res[key] = value
|
||||||
|
i += 2
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
@@ -7,9 +7,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/common"
|
|
||||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/config"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
columnize "github.com/ryanuber/columnize"
|
columnize "github.com/ryanuber/columnize"
|
||||||
)
|
)
|
||||||
@@ -43,25 +40,9 @@ func main() {
|
|||||||
global := args.Bool("global", false, "--global: use the global environment")
|
global := args.Bool("global", false, "--global: use the global environment")
|
||||||
shell := args.Bool("shell", false, "--shell: in a single-line for usage in command-line utilities [deprecated]")
|
shell := args.Bool("shell", false, "--shell: in a single-line for usage in command-line utilities [deprecated]")
|
||||||
export := args.Bool("export", false, "--export: print the env as eval-compatible exports [deprecated]")
|
export := args.Bool("export", false, "--export: print the env as eval-compatible exports [deprecated]")
|
||||||
|
merged := args.Bool("merged", false, "--merged: display the app's envionment merged with the global environment")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
appName, _ := config.GetCommonArgs(*global, args.Args())
|
config.CommandShow(args.Args(), *global, *shell, *export, *merged)
|
||||||
env := config.GetConfig(appName, false)
|
|
||||||
|
|
||||||
if *shell && *export {
|
|
||||||
common.LogFail("Only one of --shell and --export can be given")
|
|
||||||
}
|
|
||||||
if *shell {
|
|
||||||
fmt.Print(env.Export(configenv.Shell))
|
|
||||||
} else if *export {
|
|
||||||
fmt.Println(env.Export(configenv.Exports))
|
|
||||||
} else {
|
|
||||||
contextName := "global"
|
|
||||||
if appName != "" {
|
|
||||||
contextName = appName
|
|
||||||
}
|
|
||||||
common.LogInfo2(contextName + " config vars")
|
|
||||||
fmt.Println(env.Export(configenv.Pretty))
|
|
||||||
}
|
|
||||||
case "config:help":
|
case "config:help":
|
||||||
case "help":
|
case "help":
|
||||||
usage()
|
usage()
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
package configenv
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExportfileRoundtrip(t *testing.T) {
|
|
||||||
RegisterTestingT(t)
|
|
||||||
env, err := NewFromString("HI='ho'\nFoo='Bar'\n\nBaz='BOFF'")
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(env.Map()).To(Equal(pairs("Baz", "BOFF", "Foo", "Bar", "HI", "ho")))
|
|
||||||
Expect(env.String()).To(Equal("Baz=\"BOFF\"\nFoo=\"Bar\"\nHI=\"ho\""))
|
|
||||||
|
|
||||||
env, err = NewFromString(`export HI="h\no"`)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(env.Map()).To(Equal(pairs("HI", "h\no")))
|
|
||||||
Expect(env.String()).To(Equal(`HI="h\no"`))
|
|
||||||
|
|
||||||
env, err = NewFromString("HI='ho'\nFOO=\"'\\nBAR=''\"")
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(env.Map()).To(Equal(pairs("HI", "ho", "FOO", "'\nBAR=''")))
|
|
||||||
Expect(env.String()).To(Equal("FOO=\"'\\nBAR=''\"\nHI=\"ho\""))
|
|
||||||
|
|
||||||
env, err = NewFromString("FOO='bar' ")
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(env.Map()).To(Equal(pairs("FOO", "bar")))
|
|
||||||
Expect(env.String()).To(Equal(`FOO="bar"`))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExportfileErrors(t *testing.T) {
|
|
||||||
RegisterTestingT(t)
|
|
||||||
|
|
||||||
_, err := NewFromString("F\nOO='bar'") //keys cannot have embedded newlines
|
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMerge(t *testing.T) {
|
|
||||||
RegisterTestingT(t)
|
|
||||||
e, _ := NewFromString("FOO='bar'")
|
|
||||||
e2, _ := NewFromString("BAR='baz'")
|
|
||||||
e.Merge(e2)
|
|
||||||
Expect(e.Map()).To(Equal(pairs("BAR", "baz", "FOO", "bar")))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestArrayExport(t *testing.T) {
|
|
||||||
RegisterTestingT(t)
|
|
||||||
e, _ := NewFromString("BAR='BAZ'\nFOO='b'ar '")
|
|
||||||
Expect(e.EnvfileString()).To(Equal("BAR=\"BAZ\"\nFOO=\"b'ar \""))
|
|
||||||
Expect(e.DockerArgsString()).To(Equal("--env=BAR='BAZ' --env=FOO='b'\\''ar '"))
|
|
||||||
Expect(e.ShellString()).To(Equal("BAR='BAZ' FOO='b'\\''ar '"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func pairs(vars ...string) map[string]string {
|
|
||||||
res := map[string]string{}
|
|
||||||
var i = 0
|
|
||||||
for i < len(vars)-1 {
|
|
||||||
key := vars[i]
|
|
||||||
value := vars[i+1]
|
|
||||||
res[key] = value
|
|
||||||
i += 2
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/common"
|
|
||||||
"github.com/dokku/dokku/plugins/config"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,11 +12,5 @@ func main() {
|
|||||||
global := args.Bool("global", false, "--global: use the global environment")
|
global := args.Bool("global", false, "--global: use the global environment")
|
||||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
config.CommandBundle(args.Args(), *global, *merged)
|
||||||
appName, trailingArgs := config.GetCommonArgs(*global, args.Args())
|
|
||||||
if len(trailingArgs) > 0 {
|
|
||||||
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
|
||||||
}
|
|
||||||
config := config.GetConfig(appName, *merged)
|
|
||||||
config.ExportBundle(os.Stdout)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
common "github.com/dokku/dokku/plugins/common"
|
|
||||||
"github.com/dokku/dokku/plugins/config"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// print the environment to stdout
|
// print the environment to stdout
|
||||||
@@ -19,28 +16,5 @@ func main() {
|
|||||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||||
format := args.String("format", "exports", "--format: [ exports | envfile | docker-args | shell ] which format to export as)")
|
format := args.String("format", "exports", "--format: [ exports | envfile | docker-args | shell ] which format to export as)")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
config.CommandExport(args.Args(), *global, *merged, *format)
|
||||||
appName, trailingArgs := config.GetCommonArgs(*global, args.Args())
|
|
||||||
if len(trailingArgs) > 0 {
|
|
||||||
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
|
||||||
}
|
|
||||||
|
|
||||||
env := config.GetConfig(appName, *merged)
|
|
||||||
exportType := configenv.Exports
|
|
||||||
suffix := "\n"
|
|
||||||
switch *format {
|
|
||||||
case "exports":
|
|
||||||
exportType = configenv.Exports
|
|
||||||
case "envfile":
|
|
||||||
exportType = configenv.Envfile
|
|
||||||
case "docker-args":
|
|
||||||
exportType = configenv.DockerArgs
|
|
||||||
case "shell":
|
|
||||||
exportType = configenv.Shell
|
|
||||||
suffix = " "
|
|
||||||
default:
|
|
||||||
common.LogFail(fmt.Sprintf("Unknown export format: %v", *format))
|
|
||||||
}
|
|
||||||
exported := env.Export(exportType)
|
|
||||||
fmt.Print(exported + suffix)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
common "github.com/dokku/dokku/plugins/common"
|
|
||||||
"github.com/dokku/dokku/plugins/config"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// get the given entries from the specified environment
|
// get the given entries from the specified environment
|
||||||
@@ -16,22 +13,5 @@ func main() {
|
|||||||
global := args.Bool("global", false, "--global: use the global environment")
|
global := args.Bool("global", false, "--global: use the global environment")
|
||||||
quoted := args.Bool("quoted", false, "--quoted: get the value quoted")
|
quoted := args.Bool("quoted", false, "--quoted: get the value quoted")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
config.CommandGet(args.Args(), *global, *quoted)
|
||||||
appName, keys := config.GetCommonArgs(*global, args.Args())
|
|
||||||
if len(keys) > 1 {
|
|
||||||
common.LogFail(fmt.Sprintf("Unexpected argument(s): %v", keys[1:]))
|
|
||||||
}
|
|
||||||
if len(keys) == 0 {
|
|
||||||
common.LogFail("Expected: key")
|
|
||||||
}
|
|
||||||
if !config.HasKey(appName, keys[0]) {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
value := config.GetWithDefault(appName, keys[0], "")
|
|
||||||
if *quoted {
|
|
||||||
fmt.Printf("'%s'", configenv.SingleQuoteEscape(value))
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%s", value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/dokku/dokku/plugins/common"
|
|
||||||
"github.com/dokku/dokku/plugins/config"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,13 +12,5 @@ func main() {
|
|||||||
global := args.Bool("global", false, "--global: use the global environment")
|
global := args.Bool("global", false, "--global: use the global environment")
|
||||||
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
merged := args.Bool("merged", false, "--merged: merge app environment and global environment")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
|
config.CommandKeys(args.Args(), *global, *merged)
|
||||||
appName, trailingArgs := config.GetCommonArgs(*global, args.Args())
|
|
||||||
if len(trailingArgs) > 0 {
|
|
||||||
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
|
||||||
}
|
|
||||||
config := config.GetConfig(appName, *merged)
|
|
||||||
for _, k := range config.Keys() {
|
|
||||||
fmt.Println(k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
common "github.com/dokku/dokku/plugins/common"
|
"github.com/dokku/dokku/plugins/config"
|
||||||
config "github.com/dokku/dokku/plugins/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// set the given entries from the specified environment
|
// set the given entries from the specified environment
|
||||||
@@ -18,23 +14,5 @@ func main() {
|
|||||||
encoded := args.Bool("encoded", false, "--encoded: interpret VALUEs as base64")
|
encoded := args.Bool("encoded", false, "--encoded: interpret VALUEs as base64")
|
||||||
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
appName, pairs := config.GetCommonArgs(*global, args.Args())
|
config.CommandSet(args.Args(), *global, *noRestart, *encoded)
|
||||||
|
|
||||||
updated := make(map[string]string)
|
|
||||||
for _, e := range pairs {
|
|
||||||
parts := strings.SplitN(e, "=", 2)
|
|
||||||
if len(parts) == 1 {
|
|
||||||
common.LogFail("Invalid env pair: " + e)
|
|
||||||
}
|
|
||||||
key, value := parts[0], parts[1]
|
|
||||||
if *encoded {
|
|
||||||
decoded, err := base64.StdEncoding.DecodeString(value)
|
|
||||||
if err != nil {
|
|
||||||
common.LogFail(fmt.Sprintf("%s for key '%s'", err.Error(), key))
|
|
||||||
}
|
|
||||||
value = string(decoded)
|
|
||||||
}
|
|
||||||
updated[key] = value
|
|
||||||
}
|
|
||||||
config.SetMany(appName, updated, !*noRestart)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ func main() {
|
|||||||
args := flag.NewFlagSet("config:unset", flag.ExitOnError)
|
args := flag.NewFlagSet("config:unset", flag.ExitOnError)
|
||||||
global := args.Bool("global", false, "--global: use the global environment")
|
global := args.Bool("global", false, "--global: use the global environment")
|
||||||
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
noRestart := args.Bool("no-restart", false, "--no-restart: no restart")
|
||||||
|
|
||||||
args.Parse(os.Args[2:])
|
args.Parse(os.Args[2:])
|
||||||
appName, keys := config.GetCommonArgs(*global, args.Args())
|
config.CommandUnset(args.Args(), *global, *noRestart)
|
||||||
config.UnsetMany(appName, keys, !*noRestart)
|
|
||||||
}
|
}
|
||||||
|
|||||||
167
plugins/config/subcommands.go
Normal file
167
plugins/config/subcommands.go
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
//CommandShow implementes config:show
|
||||||
|
func CommandShow(args []string, global bool, shell bool, export bool, merged bool) {
|
||||||
|
appName, _ := getCommonArgs(global, args)
|
||||||
|
env := getEnvironment(appName, merged)
|
||||||
|
if shell && export {
|
||||||
|
common.LogFail("Only one of --shell and --export can be given")
|
||||||
|
}
|
||||||
|
if shell {
|
||||||
|
fmt.Print(env.Export(ExportFormatShell))
|
||||||
|
} else if export {
|
||||||
|
fmt.Println(env.Export(ExportFormatExports))
|
||||||
|
} else {
|
||||||
|
contextName := "global"
|
||||||
|
if appName != "" {
|
||||||
|
contextName = appName
|
||||||
|
}
|
||||||
|
common.LogInfo2(contextName + " env vars")
|
||||||
|
fmt.Println(env.Export(ExportFormatPretty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandGet implements config:get
|
||||||
|
func CommandGet(args []string, global bool, quoted bool) {
|
||||||
|
appName, keys := getCommonArgs(global, args)
|
||||||
|
if len(keys) > 1 {
|
||||||
|
common.LogFail(fmt.Sprintf("Unexpected argument(s): %v", keys[1:]))
|
||||||
|
}
|
||||||
|
if len(keys) == 0 {
|
||||||
|
common.LogFail("Expected: key")
|
||||||
|
}
|
||||||
|
if value, ok := Get(appName, keys[0]); !ok {
|
||||||
|
os.Exit(1)
|
||||||
|
} else {
|
||||||
|
if quoted {
|
||||||
|
fmt.Printf("'%s'", singleQuoteEscape(value))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandUnset implements config:unset
|
||||||
|
func CommandUnset(args []string, global bool, noRestart bool) {
|
||||||
|
appName, keys := getCommonArgs(global, args)
|
||||||
|
err := UnsetMany(appName, keys, !noRestart)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandSet implements config:set
|
||||||
|
func CommandSet(args []string, global bool, noRestart bool, encoded bool) {
|
||||||
|
appName, pairs := getCommonArgs(global, args)
|
||||||
|
updated := make(map[string]string)
|
||||||
|
for _, e := range pairs {
|
||||||
|
parts := strings.SplitN(e, "=", 2)
|
||||||
|
if len(parts) == 1 {
|
||||||
|
common.LogFail("Invalid env pair: " + e)
|
||||||
|
}
|
||||||
|
key, value := parts[0], parts[1]
|
||||||
|
if encoded {
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(value)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(fmt.Sprintf("%s for key '%s'", err.Error(), key))
|
||||||
|
}
|
||||||
|
value = string(decoded)
|
||||||
|
}
|
||||||
|
updated[key] = value
|
||||||
|
}
|
||||||
|
err := SetMany(appName, updated, !noRestart)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandKeys implements config:keys
|
||||||
|
func CommandKeys(args []string, global bool, merged bool) {
|
||||||
|
appName, trailingArgs := getCommonArgs(global, args)
|
||||||
|
if len(trailingArgs) > 0 {
|
||||||
|
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
||||||
|
}
|
||||||
|
env := getEnvironment(appName, merged)
|
||||||
|
for _, k := range env.Keys() {
|
||||||
|
fmt.Println(k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandExport implements config:export
|
||||||
|
func CommandExport(args []string, global bool, merged bool, format string) {
|
||||||
|
appName, trailingArgs := getCommonArgs(global, args)
|
||||||
|
if len(trailingArgs) > 0 {
|
||||||
|
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
||||||
|
}
|
||||||
|
env := getEnvironment(appName, merged)
|
||||||
|
exportType := ExportFormatExports
|
||||||
|
suffix := "\n"
|
||||||
|
switch format {
|
||||||
|
case "exports":
|
||||||
|
exportType = ExportFormatExports
|
||||||
|
case "envfile":
|
||||||
|
exportType = ExportFormatEnvfile
|
||||||
|
case "docker-args":
|
||||||
|
exportType = ExportFormatDockerArgs
|
||||||
|
case "shell":
|
||||||
|
exportType = ExportFormatShell
|
||||||
|
suffix = " "
|
||||||
|
case "pretty":
|
||||||
|
exportType = ExportFormatPretty
|
||||||
|
default:
|
||||||
|
common.LogFail(fmt.Sprintf("Unknown export format: %v", format))
|
||||||
|
}
|
||||||
|
exported := env.Export(exportType)
|
||||||
|
fmt.Print(exported + suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
//CommandBundle implements config:bundle
|
||||||
|
func CommandBundle(args []string, global bool, merged bool) {
|
||||||
|
appName, trailingArgs := getCommonArgs(global, args)
|
||||||
|
if len(trailingArgs) > 0 {
|
||||||
|
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
||||||
|
}
|
||||||
|
env := getEnvironment(appName, merged)
|
||||||
|
env.ExportBundle(os.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
//getEnvironment for the given app (global config if appName is empty). Merge with global environment if merged is true.
|
||||||
|
func getEnvironment(appName string, merged bool) (env *Env) {
|
||||||
|
env, err := loadAppOrGlobalEnv(appName)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
if appName != "" && merged {
|
||||||
|
env, err = LoadMergedAppEnv(appName)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return env
|
||||||
|
}
|
||||||
|
|
||||||
|
//getCommonArgs extracts common positional args (appName and keys)
|
||||||
|
func getCommonArgs(global bool, args []string) (appName string, keys []string) {
|
||||||
|
nextArg := 0
|
||||||
|
if !global {
|
||||||
|
if len(args) > 0 {
|
||||||
|
appName = args[0]
|
||||||
|
}
|
||||||
|
if appName == "" {
|
||||||
|
common.LogFail("Please specify an app or --global")
|
||||||
|
} else {
|
||||||
|
nextArg++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
keys = args[nextArg:]
|
||||||
|
return appName, keys
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user