Skip to content

Commit

Permalink
export environ as its own lib (#169)
Browse files Browse the repository at this point in the history
* expose environ as its own lib

* return err directly from load
  • Loading branch information
nickatsegment authored Nov 14, 2018
1 parent a94b7aa commit 1561472
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 43 deletions.
55 changes: 12 additions & 43 deletions cmd/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/pkg/errors"
"github.com/segmentio/chamber/environ"
"github.com/spf13/cobra"
analytics "gopkg.in/segmentio/analytics-go.v3"
)
Expand Down Expand Up @@ -50,67 +51,35 @@ func execRun(cmd *cobra.Command, args []string) error {
})
}

env := environ(os.Environ())
env := environ.Environ(os.Environ())
secretStore, err := getSecretStore()
if err != nil {
return errors.Wrap(err, "Failed to get secret store")
}
envVarKeys := make([]string, 0)
for _, service := range services {
if err := validateService(service); err != nil {
return errors.Wrap(err, "Failed to validate service")
}

rawSecrets, err := secretStore.ListRaw(strings.ToLower(service))
collisions := make([]string, 0)
var err error
if _, noPaths := os.LookupEnv("CHAMBER_NO_PATHS"); noPaths {
err = env.LoadNoPaths(secretStore, service, &collisions)
} else {
err = env.Load(secretStore, service, &collisions)
}
if err != nil {
return errors.Wrap(err, "Failed to list store contents")
}
for _, rawSecret := range rawSecrets {
envVarKey := strings.ToUpper(key(rawSecret.Key))
envVarKey = strings.Replace(envVarKey, "-", "_", -1)

envVarKeys = append(envVarKeys, envVarKey)

if env.IsSet(envVarKey) {
fmt.Fprintf(os.Stderr, "warning: overwriting environment variable %s\n", envVarKey)
}
env.Set(envVarKey, rawSecret.Value)
for _, c := range collisions {
fmt.Fprintf(os.Stderr, "warning: service %s overwriting environment variable %s\n", service, c)
}
}

if verbose {
fmt.Fprintf(os.Stdout, "info: With environment %s\n", strings.Join(envVarKeys, ","))
fmt.Fprintf(os.Stdout, "info: With environment %s\n", strings.Join(env, ","))
}

return exec(command, commandArgs, env)
}

// environ is a slice of strings representing the environment, in the form "key=value".
type environ []string

// Unset an environment variable by key
func (e *environ) Unset(key string) {
for i := range *e {
if strings.HasPrefix((*e)[i], key+"=") {
(*e)[i] = (*e)[len(*e)-1]
*e = (*e)[:len(*e)-1]
break
}
}
}

// IsSet returns whether or not a key is currently set in the environ
func (e *environ) IsSet(key string) bool {
for i := range *e {
if strings.HasPrefix((*e)[i], key+"=") {
return true
}
}
return false
}

// Set adds an environment variable, replacing any existing ones of the same key
func (e *environ) Set(key, val string) {
e.Unset(key)
*e = append(*e, key+"="+val)
}
84 changes: 84 additions & 0 deletions environ/environ.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package environ

import (
"strings"

"github.com/segmentio/chamber/store"
)

// environ is a slice of strings representing the environment, in the form "key=value".
type Environ []string

// Unset an environment variable by key
func (e *Environ) Unset(key string) {
for i := range *e {
if strings.HasPrefix((*e)[i], key+"=") {
(*e)[i] = (*e)[len(*e)-1]
*e = (*e)[:len(*e)-1]
break
}
}
}

// IsSet returns whether or not a key is currently set in the environ
func (e *Environ) IsSet(key string) bool {
for i := range *e {
if strings.HasPrefix((*e)[i], key+"=") {
return true
}
}
return false
}

// Set adds an environment variable, replacing any existing ones of the same key
func (e *Environ) Set(key, val string) {
e.Unset(key)
*e = append(*e, key+"="+val)
}

// like cmd/list.key, but without the env var lookup
func key(s string, noPaths bool) string {
sep := "/"
if noPaths {
sep = "."
}
tokens := strings.Split(s, sep)
secretKey := tokens[len(tokens)-1]
return secretKey
}

// load loads environment variables into e from s given a service
// collisions will be populated with any keys that get overwritten
// noPaths enables the behavior as if CHAMBER_NO_PATHS had been set
func (e *Environ) load(s store.Store, service string, collisions *[]string, noPaths bool) error {
rawSecrets, err := s.ListRaw(strings.ToLower(service))
if err != nil {
return err
}
envVarKeys := make([]string, 0)
for _, rawSecret := range rawSecrets {
envVarKey := strings.ToUpper(key(rawSecret.Key, noPaths))
envVarKey = strings.Replace(envVarKey, "-", "_", -1)

envVarKeys = append(envVarKeys, envVarKey)

if e.IsSet(envVarKey) {
*collisions = append(*collisions, envVarKey)
}
e.Set(envVarKey, rawSecret.Value)
}
return nil
}

// Load loads environment variables into e from s given a service
// collisions will be populated with any keys that get overwritten
func (e *Environ) Load(s store.Store, service string, collisions *[]string) error {
return e.load(s, service, collisions, false)
}

// LoadNoPaths is identical to Load, but uses v1-style "."-separated paths
//
// Deprecated like all noPaths functionality
func (e *Environ) LoadNoPaths(s store.Store, service string, collisions *[]string) error {
return e.load(s, service, collisions, true)
}

0 comments on commit 1561472

Please sign in to comment.