Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build
cmd/envbox/envbox
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
PROJECT_ROOT := $(shell git rev-parse --show-toplevel)
GO_FILES := $(shell git ls-files '*.go' '*.sum')
IMAGE_FILES := $(shell find deploy)

.PHONY: clean
clean:
rm -rf build

build/envbox: $(GO_FILES)
go build -o build/envbox ./cmd/envbox

.PHONY: build/image/envbox
build/image/envbox: build/image/envbox/.ctx

build/image/envbox/.ctx: build/envbox $(IMAGE_FILES)
mkdir -p $(@D)
cp -r build/envbox deploy/. $(@D)
docker build -t envbox $(@D)
touch $@
183 changes: 183 additions & 0 deletions cli/cliflag/cliflag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Package cliflag extends flagset with environment variable defaults.
//
// Usage:
//
// cliflag.String(root.Flags(), &address, "address", "a", "CODER_ADDRESS", "127.0.0.1:3000", "The address to serve the API and dashboard")
//
// Will produce the following usage docs:
//
// -a, --address string The address to serve the API and dashboard (uses $CODER_ADDRESS). (default "127.0.0.1:3000")
package cliflag

import (
"fmt"
"os"
"strconv"
"strings"
"time"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// IsSetBool returns the value of the boolean flag if it is set.
// It returns false if the flag isn't set or if any error occurs attempting
// to parse the value of the flag.
func IsSetBool(cmd *cobra.Command, name string) bool {
val, ok := IsSet(cmd, name)
if !ok {
return false
}

b, err := strconv.ParseBool(val)
return err == nil && b
}

// IsSet returns the string value of the flag and whether it was set.
func IsSet(cmd *cobra.Command, name string) (string, bool) {
flag := cmd.Flag(name)
if flag == nil {
return "", false
}

return flag.Value.String(), flag.Changed
}

// String sets a string flag on the given flag set.
func String(flagset *pflag.FlagSet, name, shorthand, env, def, usage string) {
v, ok := os.LookupEnv(env)
if !ok || v == "" {
v = def
}
flagset.StringP(name, shorthand, v, fmtUsage(usage, env))
}

// StringVarP sets a string flag on the given flag set.
func StringVarP(flagset *pflag.FlagSet, p *string, name string, shorthand string, env string, def string, usage string) {
v, ok := os.LookupEnv(env)
if !ok || v == "" {
v = def
}
flagset.StringVarP(p, name, shorthand, v, fmtUsage(usage, env))
}

func StringArray(flagset *pflag.FlagSet, name, shorthand, env string, def []string, usage string) {
v, ok := os.LookupEnv(env)
if !ok || v == "" {
if v == "" {
def = []string{}
} else {
def = strings.Split(v, ",")
}
}
flagset.StringArrayP(name, shorthand, def, fmtUsage(usage, env))
}

func StringArrayVarP(flagset *pflag.FlagSet, ptr *[]string, name string, shorthand string, env string, def []string, usage string) {
val, ok := os.LookupEnv(env)
if ok {
if val == "" {
def = []string{}
} else {
def = strings.Split(val, ",")
}
}
flagset.StringArrayVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
}

// Uint8VarP sets a uint8 flag on the given flag set.
func Uint8VarP(flagset *pflag.FlagSet, ptr *uint8, name string, shorthand string, env string, def uint8, usage string) {
val, ok := os.LookupEnv(env)
if !ok || val == "" {
flagset.Uint8VarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

vi64, err := strconv.ParseUint(val, 10, 8)
if err != nil {
flagset.Uint8VarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

flagset.Uint8VarP(ptr, name, shorthand, uint8(vi64), fmtUsage(usage, env))
}

// IntVarP sets a uint8 flag on the given flag set.
func IntVarP(flagset *pflag.FlagSet, ptr *int, name string, shorthand string, env string, def int, usage string) {
val, ok := os.LookupEnv(env)
if !ok || val == "" {
flagset.IntVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

vi64, err := strconv.ParseUint(val, 10, 8)
if err != nil {
flagset.IntVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

flagset.IntVarP(ptr, name, shorthand, int(vi64), fmtUsage(usage, env))
}

func Bool(flagset *pflag.FlagSet, name, shorthand, env string, def bool, usage string) {
val, ok := os.LookupEnv(env)
if !ok || val == "" {
flagset.BoolP(name, shorthand, def, fmtUsage(usage, env))
return
}

valb, err := strconv.ParseBool(val)
if err != nil {
flagset.BoolP(name, shorthand, def, fmtUsage(usage, env))
return
}

flagset.BoolP(name, shorthand, valb, fmtUsage(usage, env))
}

// BoolVarP sets a bool flag on the given flag set.
func BoolVarP(flagset *pflag.FlagSet, ptr *bool, name string, shorthand string, env string, def bool, usage string) {
val, ok := os.LookupEnv(env)
if !ok || val == "" {
flagset.BoolVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

valb, err := strconv.ParseBool(val)
if err != nil {
flagset.BoolVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

flagset.BoolVarP(ptr, name, shorthand, valb, fmtUsage(usage, env))
}

// DurationVarP sets a time.Duration flag on the given flag set.
func DurationVarP(flagset *pflag.FlagSet, ptr *time.Duration, name string, shorthand string, env string, def time.Duration, usage string) {
val, ok := os.LookupEnv(env)
if !ok || val == "" {
flagset.DurationVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

valb, err := time.ParseDuration(val)
if err != nil {
flagset.DurationVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
return
}

flagset.DurationVarP(ptr, name, shorthand, valb, fmtUsage(usage, env))
}

func fmtUsage(u string, env string) string {
if env != "" {
// Avoid double dotting.
dot := "."
if strings.HasSuffix(u, ".") {
dot = ""
}
u = fmt.Sprintf("%s%s\n(Consumes $%s", u, dot, env)
}

return u
}
Loading