github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/dos/env.go (about)

     1  package dos
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"sort"
     7  	"strings"
     8  )
     9  
    10  // Env is an abstraction of the environment related functions with the same name in the os package.
    11  type Env interface {
    12  	Environ() []string
    13  	ExpandEnv(string) string
    14  	Getenv(string) string
    15  	Setenv(string, string) error
    16  	Lookup(string) (string, bool)
    17  }
    18  
    19  type MapEnv map[string]string
    20  
    21  // FromEnvPairs converts a slice of strings int the form KEY=VALUE into
    22  // a map[string]string.
    23  func FromEnvPairs(env []string) MapEnv {
    24  	m := make(MapEnv, len(env))
    25  	m.MergeEnvPairs(env)
    26  	return m
    27  }
    28  
    29  // MergeEnvPairs merges env entries in the form of KEY=VALUE into the
    30  // given map, giving the env entries higher priority.
    31  func (e MapEnv) MergeEnvPairs(env []string) {
    32  	for _, ep := range env {
    33  		if ix := strings.IndexByte(ep, '='); ix > 0 {
    34  			e[ep[:ix]] = ep[ix+1:]
    35  		}
    36  	}
    37  }
    38  
    39  func (e MapEnv) Environ() []string {
    40  	ks := make([]string, len(e))
    41  	i := 0
    42  	for k := range e {
    43  		ks[i] = k
    44  		i++
    45  	}
    46  	sort.Strings(ks)
    47  	for i, k := range ks {
    48  		ks[i] = k + "=" + e[k]
    49  	}
    50  	return ks
    51  }
    52  
    53  func (e MapEnv) ExpandEnv(s string) string {
    54  	return os.Expand(s, e.Getenv)
    55  }
    56  
    57  func (e MapEnv) Getenv(key string) string {
    58  	return e[key]
    59  }
    60  
    61  func (e MapEnv) Setenv(key, value string) error {
    62  	e[key] = value
    63  	return nil
    64  }
    65  
    66  func (e MapEnv) Lookup(key string) (string, bool) {
    67  	s, ok := e[key]
    68  	return s, ok
    69  }
    70  
    71  type envKey struct{}
    72  
    73  func WithEnv(ctx context.Context, env Env) context.Context {
    74  	return context.WithValue(ctx, envKey{}, env)
    75  }
    76  
    77  // EnvAPI returns the Env that has been registered with the given context, or
    78  // the instance that delegates to the env functions in the os package.
    79  func EnvAPI(ctx context.Context) Env {
    80  	if e, ok := ctx.Value(envKey{}).(Env); ok {
    81  		return e
    82  	}
    83  	return osEnv{}
    84  }
    85  
    86  func Environ(ctx context.Context) []string {
    87  	return EnvAPI(ctx).Environ()
    88  }
    89  
    90  func ExpandEnv(ctx context.Context, s string) string {
    91  	return EnvAPI(ctx).ExpandEnv(s)
    92  }
    93  
    94  func Getenv(ctx context.Context, key string) string {
    95  	return EnvAPI(ctx).Getenv(key)
    96  }
    97  
    98  func Setenv(ctx context.Context, key, value string) error {
    99  	return EnvAPI(ctx).Setenv(key, value)
   100  }
   101  
   102  func LookupEnv(ctx context.Context, key string) (string, bool) {
   103  	return EnvAPI(ctx).Lookup(key)
   104  }
   105  
   106  type osEnv struct{}
   107  
   108  func (osEnv) Environ() []string {
   109  	return os.Environ()
   110  }
   111  
   112  func (osEnv) ExpandEnv(s string) string {
   113  	return os.ExpandEnv(s)
   114  }
   115  
   116  func (osEnv) Getenv(s string) string {
   117  	return os.Getenv(s)
   118  }
   119  
   120  func (osEnv) Setenv(key, value string) error {
   121  	return os.Setenv(key, value)
   122  }
   123  
   124  func (osEnv) Lookup(s string) (string, bool) {
   125  	return os.LookupEnv(s)
   126  }