[config] move to godotenv
This commit is contained in:
@@ -7,9 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
configenv "github.com/dokku/dokku/plugins/config/src/configenv"
|
||||
columnize "github.com/ryanuber/columnize"
|
||||
)
|
||||
|
||||
@@ -26,6 +24,8 @@ Additional commands:`
|
||||
config:set (<app>|--global) [--encoded] [--no-restart] KEY1=VALUE1 [KEY2=VALUE2 ...], Set one or more config vars
|
||||
config:unset (<app>|--global) KEY1 [KEY2 ...], Unset one or more config vars
|
||||
config:export (<app>|--global) [--envfile], Export a global or app environment
|
||||
config:keys (<app> | --global) [--merged], Show keys set in environment
|
||||
config:bundle (<app> | --global) [--merged], Bundle environment into tarfile
|
||||
`
|
||||
)
|
||||
|
||||
@@ -37,16 +37,8 @@ func main() {
|
||||
switch cmd {
|
||||
case "config", "config:show":
|
||||
target := flag.Arg(1)
|
||||
if target == "" {
|
||||
usage()
|
||||
common.LogFail("Please specify an app or --global")
|
||||
}
|
||||
env, err := configenv.NewFromTarget(target)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
} else {
|
||||
fmt.Println(config.PrettyPrintLogEntries("", env.Map()))
|
||||
}
|
||||
env := config.GetConfig(target, false)
|
||||
fmt.Print(config.PrettyPrintEnvEntries("", env.Map()))
|
||||
case "config:help":
|
||||
usage()
|
||||
case "help":
|
||||
|
||||
@@ -4,46 +4,75 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"archive/tar"
|
||||
|
||||
"os"
|
||||
|
||||
godotenv "github.com/alexquick/godotenv"
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
type ExportFormat int
|
||||
|
||||
const (
|
||||
Exports ExportFormat = iota
|
||||
Envfile
|
||||
DockerArgs
|
||||
)
|
||||
|
||||
//Env is a representation for global or app environment
|
||||
type Env struct {
|
||||
name string
|
||||
env map[string]string
|
||||
filename string
|
||||
EscapeNewlines bool
|
||||
name string
|
||||
filename string
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
func (e *Env) String() string {
|
||||
return e.EnvfileString()
|
||||
}
|
||||
|
||||
//EnvfileString returns the contents of this Env in ENVFILE format
|
||||
func (e *Env) Export(format ExportFormat) string {
|
||||
switch format {
|
||||
case Exports:
|
||||
return e.ExportfileString()
|
||||
case Envfile:
|
||||
return e.EnvfileString()
|
||||
case DockerArgs:
|
||||
return e.DockerArgsString()
|
||||
default:
|
||||
common.LogFail(fmt.Sprintf("Unknown export format: %v", format))
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
//EnvfileString returns the contents of this Env in dotenv format
|
||||
func (e *Env) EnvfileString() string {
|
||||
return e.StringWithPrefixAndSeparator("", "\n")
|
||||
rep, _ := godotenv.WriteString(e.Map())
|
||||
return rep
|
||||
}
|
||||
|
||||
//ExportfileString returns the contents of this Env as bash exports
|
||||
func (e *Env) ExportfileString() string {
|
||||
return e.StringWithPrefixAndSeparator("export ", "\n")
|
||||
return e.stringWithPrefixAndSeparator("export ", "\n", true)
|
||||
}
|
||||
|
||||
//DockerArgsString gets the contents of this Env in the form -env=KEY=VALUE --env...
|
||||
func (e *Env) DockerArgsString() string {
|
||||
return e.stringWithPrefixAndSeparator("--env=", " ", true)
|
||||
}
|
||||
|
||||
//StringWithPrefixAndSeparator makes a string of the environment
|
||||
// with the given prefix and separator for each entry
|
||||
func (e *Env) StringWithPrefixAndSeparator(prefix string, separator string) string {
|
||||
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 e.EscapeNewlines {
|
||||
if !allowNewlines {
|
||||
v = strings.Replace(v, "\n", "'$'\\n''", -1)
|
||||
}
|
||||
entries[i] = fmt.Sprintf("%s%s='%s'", prefix, k, v)
|
||||
@@ -78,31 +107,45 @@ func (e *Env) ExportBundle(dest io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//NewFromTarget creates an env from the given target. Target is either "--global" or an app name
|
||||
func NewFromTarget(target string) (*Env, error) {
|
||||
if target == "--global" {
|
||||
return LoadGlobal()
|
||||
}
|
||||
return LoadApp(target)
|
||||
}
|
||||
|
||||
//LoadApp loads an environment for the given app
|
||||
func LoadApp(appName string) (*Env, error) {
|
||||
appfile, err := getAppFile(appName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseEnv(appName, appfile)
|
||||
|
||||
if _, err := os.Stat(appfile); os.IsNotExist(err) {
|
||||
_, err := os.Create(appfile)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
}
|
||||
return loadFromFile(appName, appfile)
|
||||
}
|
||||
|
||||
//LoadGlobal loads the global environmen
|
||||
func LoadGlobal() (*Env, error) {
|
||||
return parseEnv("global", getGlobalFile())
|
||||
return loadFromFile("global", getGlobalFile())
|
||||
}
|
||||
|
||||
//NewFromString creates an env from the given ENVFILE contents representation
|
||||
func NewFromString(rep string) (*Env, error) {
|
||||
return parseEnvFromReader("<unknown>", "", strings.NewReader(rep))
|
||||
envMap, err := godotenv.ReadFromReader(strings.NewReader(rep))
|
||||
env := &Env{
|
||||
"<unknown>",
|
||||
"",
|
||||
envMap,
|
||||
}
|
||||
return env, err
|
||||
}
|
||||
func loadFromFile(name string, filename string) (*Env, error) {
|
||||
envMap, err := godotenv.Read(filename)
|
||||
env := &Env{
|
||||
name,
|
||||
filename,
|
||||
envMap,
|
||||
}
|
||||
return env, err
|
||||
}
|
||||
|
||||
//Merge merges the given environment on top of the reciever
|
||||
@@ -172,13 +215,7 @@ func (e *Env) Write() error {
|
||||
if e.filename == "" {
|
||||
return errors.New("this Env was created unbound to a file")
|
||||
}
|
||||
file, err := os.Create(e.filename)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = file.WriteString(e.ExportfileString())
|
||||
return err
|
||||
return godotenv.Write(e.Map(), e.filename)
|
||||
}
|
||||
|
||||
func getAppFile(appName string) (string, error) {
|
||||
|
||||
@@ -11,39 +11,29 @@ func TestExportfileRoundtrip(t *testing.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'"))
|
||||
Expect(env.String()).To(Equal("Baz=\"BOFF\"\nFoo=\"Bar\"\nHI=\"ho\""))
|
||||
|
||||
env, err = NewFromString("\n export HI='h\\\no\\' \n")
|
||||
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\\'"))
|
||||
Expect(env.Map()).To(Equal(pairs("HI", "h\no")))
|
||||
Expect(env.String()).To(Equal(`HI="h\no"`))
|
||||
|
||||
env, err = NewFromString("\n export HI=ho\n")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(env.Map()).To(Equal(pairs("HI", "ho")))
|
||||
Expect(env.String()).To(Equal("HI='ho'"))
|
||||
|
||||
env, err = NewFromString("HI='ho'\nFOO=''\\''\nBAR='\\'''\\'''")
|
||||
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'"))
|
||||
Expect(env.String()).To(Equal("FOO=\"'\\nBAR=''\"\nHI=\"ho\""))
|
||||
|
||||
env, err = NewFromString("HI='ho\n'\n\nFOO='=bar\"\n'\\''\nbaz'")
|
||||
env, err = NewFromString("FOO='bar' ")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(env.Map()).To(Equal(pairs("HI", "ho\n", "FOO", "=bar\"\n'\nbaz")))
|
||||
Expect(env.String()).To(Equal("FOO='=bar\"\n'\\''\nbaz'\nHI='ho\n'"))
|
||||
Expect(env.Map()).To(Equal(pairs("FOO", "bar")))
|
||||
Expect(env.String()).To(Equal(`FOO="bar"`))
|
||||
|
||||
}
|
||||
|
||||
func TestExportfileErrors(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
|
||||
_, err := NewFromString("FOO='bar\\''") //single quotes are not escaped this way
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
_, err = NewFromString("F\nOO='bar'") //keys cannot have embedded newlines
|
||||
Expect(err).To(HaveOccurred())
|
||||
|
||||
_, err = NewFromString("FOO='bar' ") //no trailing content
|
||||
_, err := NewFromString("F\nOO='bar'") //keys cannot have embedded newlines
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
|
||||
@@ -57,9 +47,9 @@ func TestMerge(t *testing.T) {
|
||||
|
||||
func TestArrayExport(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
e, _ := NewFromString("BAR='BAZ'\nFOO='b'\\''ar '")
|
||||
Expect(e.StringWithPrefixAndSeparator("", " ")).To(Equal("BAR='BAZ' FOO='b'\\''ar '"))
|
||||
Expect(e.StringWithPrefixAndSeparator("-e", " ")).To(Equal("-eBAR='BAZ' -eFOO='b'\\''ar '"))
|
||||
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 '"))
|
||||
}
|
||||
|
||||
func pairs(vars ...string) map[string]string {
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
package configenv
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseEnv(name string, filename string) (*Env, error) {
|
||||
var file *os.File
|
||||
var err error
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
file, err = os.Create(filename)
|
||||
} else {
|
||||
file, err = os.Open(filename)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
return parseEnvFromReader(name, filename, file)
|
||||
}
|
||||
|
||||
func parseEnvFromReader(name string, filename string, reader io.Reader) (*Env, error) {
|
||||
//The file format looks like: `KEY='VALUE'`. Each pair is terminated with a newline.
|
||||
//All characters are valid for VALUE without escaping but one: the single quote.
|
||||
//A single quote literal is represented by ending the quoting
|
||||
//emitting a \' and resuming the quoting. So for VALUE to be "don't care":
|
||||
//`KEY='don'\''t care'`
|
||||
//The advantage of this is that it's easily parsed and sourced by bash correctly.
|
||||
|
||||
buffered := bufio.NewReader(reader)
|
||||
const (
|
||||
StateKey = iota
|
||||
StateValue = iota
|
||||
)
|
||||
env := &Env{name, map[string]string{}, filename, false}
|
||||
var buffer bytes.Buffer
|
||||
var state = StateKey
|
||||
var quoted = false
|
||||
var exportStyle = false
|
||||
var escaped = false
|
||||
var key = ""
|
||||
for char, _, err := buffered.ReadRune(); err == nil; char, _, err = buffered.ReadRune() {
|
||||
switch state {
|
||||
case StateKey:
|
||||
switch char {
|
||||
case ' ':
|
||||
if buffer.String() == "export" {
|
||||
exportStyle = true
|
||||
buffer.Truncate(0) //so we can read exportfiles as well as envfiles
|
||||
} else if buffer.Len() == 0 {
|
||||
continue //leading spaced are allowed but not encouraged
|
||||
} else {
|
||||
return nil, errors.New("keys cannot have spaces")
|
||||
}
|
||||
case '=':
|
||||
key = buffer.String()
|
||||
buffer.Truncate(0)
|
||||
state = StateValue
|
||||
case '\n':
|
||||
if buffer.Len() > 0 {
|
||||
return nil, errors.New("keys cannot contain newlines")
|
||||
}
|
||||
default:
|
||||
buffer.WriteRune(char)
|
||||
}
|
||||
case StateValue:
|
||||
switch char {
|
||||
case '\'':
|
||||
if escaped {
|
||||
buffer.WriteRune('\'')
|
||||
escaped = false
|
||||
} else {
|
||||
quoted = !quoted
|
||||
}
|
||||
case '\n':
|
||||
if quoted {
|
||||
buffer.WriteRune(char)
|
||||
} else {
|
||||
state = StateKey
|
||||
value := buffer.String()
|
||||
if exportStyle {
|
||||
value = strings.TrimSpace(value)
|
||||
}
|
||||
env.Set(key, value)
|
||||
buffer.Truncate(0)
|
||||
key = ""
|
||||
escaped = false
|
||||
quoted = false
|
||||
exportStyle = false
|
||||
}
|
||||
case '\\':
|
||||
if quoted {
|
||||
buffer.WriteRune(char)
|
||||
escaped = false
|
||||
} else {
|
||||
escaped = true
|
||||
}
|
||||
default:
|
||||
if !quoted && !exportStyle {
|
||||
return nil, errors.New("trailing content for value of " + key)
|
||||
}
|
||||
if escaped {
|
||||
return nil, errors.New("invalid escape for " + key)
|
||||
}
|
||||
buffer.WriteRune(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
if escaped {
|
||||
return nil, errors.New("unterminated escape at end")
|
||||
}
|
||||
if quoted {
|
||||
return nil, errors.New("unterminated quote at end")
|
||||
}
|
||||
|
||||
if state == StateValue {
|
||||
env.Set(key, buffer.String())
|
||||
} else {
|
||||
if buffer.Len() > 0 {
|
||||
return nil, errors.New("invalid trailing content: '" + buffer.String() + "'")
|
||||
}
|
||||
}
|
||||
return env, nil
|
||||
}
|
||||
24
plugins/config/src/subcommands/bundle/bundle.go
Normal file
24
plugins/config/src/subcommands/bundle/bundle.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
args := flag.NewFlagSet("config:get", 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:])
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
||||
)
|
||||
|
||||
@@ -16,66 +17,26 @@ func main() {
|
||||
args := flag.NewFlagSet("config: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")
|
||||
keys := args.Bool("keys", false, "--keys: export keys only")
|
||||
bundle := args.Bool("bundle", false, "--bundle: export as tar bundle")
|
||||
envfile := args.Bool("envfile", false, "--envfile: export as envfile rather than bash exports (--prefix='')")
|
||||
prefix := args.String("prefix", defaultPrefix, "--prefix: prefix")
|
||||
separator := args.String("separator", defaultSeparator, "--separator: separator")
|
||||
escapeNewlines := args.Bool("escape-newlines", false, "--escape-newlines: replace literal newlines with $'\n'")
|
||||
format := args.String("format", "exports", "--format: [ exports | envfile | docker-args ] which format to export as)")
|
||||
args.Parse(os.Args[2:])
|
||||
|
||||
appName := args.Arg(0)
|
||||
if appName == "" && !*global {
|
||||
common.LogFail("Please specify an app or --global")
|
||||
appName, trailingArgs := config.GetCommonArgs(*global, args.Args())
|
||||
if len(trailingArgs) > 0 {
|
||||
common.LogFail(fmt.Sprintf("Trailing argument(s): %v", trailingArgs))
|
||||
}
|
||||
|
||||
if *global {
|
||||
if appName != "" {
|
||||
common.LogFail("Trailing argument: " + appName)
|
||||
}
|
||||
if *merged == true {
|
||||
common.LogFail("Only app environments can be merged")
|
||||
}
|
||||
appName = "--global"
|
||||
env := config.GetConfig(appName, *merged)
|
||||
exportType := configenv.Exports
|
||||
switch *format {
|
||||
case "exports":
|
||||
exportType = configenv.Exports
|
||||
case "envfile":
|
||||
exportType = configenv.Envfile
|
||||
case "docker-args":
|
||||
exportType = configenv.DockerArgs
|
||||
default:
|
||||
common.LogFail(fmt.Sprintf("Unknown export format: %v", *format))
|
||||
}
|
||||
|
||||
env, err := configenv.NewFromTarget(appName)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
|
||||
if *merged {
|
||||
global, err := configenv.LoadGlobal()
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
global.Merge(env)
|
||||
env = global
|
||||
}
|
||||
|
||||
if *keys {
|
||||
for _, k := range env.Keys() {
|
||||
fmt.Println(k)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if *escapeNewlines {
|
||||
env.EscapeNewlines = true
|
||||
}
|
||||
|
||||
if *bundle {
|
||||
if *prefix != defaultPrefix || *separator != defaultSeparator || *envfile {
|
||||
common.LogFail("--bundle cannot be given with --envfile, --prefix, or --separator")
|
||||
}
|
||||
env.ExportBundle(os.Stdout)
|
||||
}
|
||||
if *envfile {
|
||||
if *prefix != defaultPrefix {
|
||||
common.LogFail("--prefix and --envfile cannot both be given")
|
||||
return
|
||||
}
|
||||
*prefix = ""
|
||||
}
|
||||
fmt.Println(env.StringWithPrefixAndSeparator(*prefix, *separator))
|
||||
exported := env.Export(exportType)
|
||||
fmt.Println(exported)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
||||
)
|
||||
|
||||
@@ -15,28 +16,13 @@ func main() {
|
||||
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:])
|
||||
appName := args.Arg(0)
|
||||
nextArg := 0
|
||||
if appName == "" && !*global {
|
||||
common.LogFail("Please specify an app or --global")
|
||||
}
|
||||
|
||||
if *global {
|
||||
appName = "--global"
|
||||
} else {
|
||||
nextArg = 1
|
||||
appName, keys := config.GetCommonArgs(*global, args.Args())
|
||||
if len(keys) > 1 {
|
||||
common.LogFail(fmt.Sprintf("Unexpected argument(s): %v", keys[1:]))
|
||||
}
|
||||
value := config.GetWithDefault(appName, keys[0], "")
|
||||
|
||||
env, err := configenv.NewFromTarget(appName)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
|
||||
if args.NArg() > nextArg+1 {
|
||||
common.LogFail(fmt.Sprintf("Unexpected argument(s): %v", args.Args()[nextArg+1:]))
|
||||
}
|
||||
key := args.Arg(nextArg)
|
||||
value := env.GetDefault(key, "")
|
||||
if *quoted {
|
||||
fmt.Printf("'%s'", configenv.SingleQuoteEscape(value))
|
||||
} else {
|
||||
|
||||
26
plugins/config/src/subcommands/keys/keys.go
Normal file
26
plugins/config/src/subcommands/keys/keys.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
args := flag.NewFlagSet("config:get", 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:])
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
config "github.com/dokku/dokku/plugins/config"
|
||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
||||
)
|
||||
|
||||
// set the given entries from the specified environment
|
||||
@@ -19,28 +18,10 @@ func main() {
|
||||
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:])
|
||||
shouldRestart := !*global && !*noRestart
|
||||
var nextArg = 0
|
||||
appName := args.Arg(0)
|
||||
if appName == "" && !*global {
|
||||
common.LogFail("Please specify an app or --global")
|
||||
}
|
||||
appName, pairs := config.GetCommonArgs(*global, args.Args())
|
||||
|
||||
if *global {
|
||||
appName = "--global"
|
||||
} else {
|
||||
nextArg = 1
|
||||
}
|
||||
|
||||
env, err := configenv.NewFromTarget(appName)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
|
||||
entries := args.Args()[nextArg:]
|
||||
updated := make(map[string]string)
|
||||
for _, e := range entries {
|
||||
//log
|
||||
for _, e := range pairs {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
if len(parts) == 1 {
|
||||
common.LogFail("Invalid env pair: " + e)
|
||||
@@ -53,21 +34,7 @@ func main() {
|
||||
}
|
||||
value = string(decoded)
|
||||
}
|
||||
env.Set(key, value)
|
||||
updated[key] = value
|
||||
}
|
||||
|
||||
if len(updated) != 0 {
|
||||
common.LogInfo1("Setting config vars")
|
||||
fmt.Println(config.PrettyPrintLogEntries(" ", updated))
|
||||
env.Write()
|
||||
args := append([]string{appName, "set"}, entries...)
|
||||
common.PlugnTrigger("post-config-update", args...)
|
||||
}
|
||||
|
||||
if shouldRestart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
||||
common.LogInfo1(fmt.Sprintf("Restarting app %s", appName))
|
||||
cmd := common.NewTokenizedShellCmd("dokku", "ps:restart", appName)
|
||||
cmd.Execute()
|
||||
}
|
||||
config.SetMany(appName, updated, !*noRestart)
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"fmt"
|
||||
|
||||
common "github.com/dokku/dokku/plugins/common"
|
||||
"github.com/dokku/dokku/plugins/config/src/configenv"
|
||||
"github.com/dokku/dokku/plugins/config"
|
||||
)
|
||||
|
||||
//unset the given entries from the given environment
|
||||
@@ -15,42 +12,8 @@ func main() {
|
||||
args := flag.NewFlagSet("config: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:])
|
||||
shouldRestart := !*global && !*noRestart
|
||||
var nextArg = 0
|
||||
appName := args.Arg(0)
|
||||
if appName == "" && !*global {
|
||||
common.LogFail("Please specify an app or --global")
|
||||
}
|
||||
|
||||
if *global {
|
||||
appName = "--global"
|
||||
} else {
|
||||
nextArg = 1
|
||||
}
|
||||
|
||||
env, err := configenv.NewFromTarget(appName)
|
||||
if err != nil {
|
||||
common.LogFail(err.Error())
|
||||
}
|
||||
|
||||
var changed = false
|
||||
keys := args.Args()[nextArg:]
|
||||
for _, k := range keys {
|
||||
common.LogInfo1(fmt.Sprintf("Unsetting %s", k))
|
||||
env.Unset(k)
|
||||
changed = true
|
||||
}
|
||||
|
||||
if changed {
|
||||
env.Write()
|
||||
args := append([]string{appName, "unset"}, keys...)
|
||||
common.PlugnTrigger("post-config-update", args...)
|
||||
}
|
||||
|
||||
if shouldRestart && env.GetBoolDefault("DOKKU_APP_RESTORE", true) {
|
||||
common.LogInfo1(fmt.Sprintf("Restarting app %s", appName))
|
||||
cmd := common.NewTokenizedShellCmd("dokku", "ps:restart", appName)
|
||||
cmd.Execute()
|
||||
}
|
||||
appName, keys := config.GetCommonArgs(*global, args.Args())
|
||||
config.Unset(appName, keys, !*noRestart)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user