github.com/solo-io/cue@v0.4.7/pkg/tool/os/env.go (about) 1 // Copyright 2019 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package os 16 17 //go:generate go run gen.go 18 //go:generate gofmt -s -w . 19 20 import ( 21 "os" 22 "strings" 23 24 "github.com/solo-io/cue/cue" 25 "github.com/solo-io/cue/cue/ast" 26 "github.com/solo-io/cue/cue/errors" 27 "github.com/solo-io/cue/internal/cli" 28 "github.com/solo-io/cue/internal/task" 29 ) 30 31 func init() { 32 task.Register("tool/os.Getenv", newGetenvCmd) 33 task.Register("tool/os.Environ", newEnvironCmd) 34 35 // TODO: 36 // Tasks: 37 // - Exit? 38 // - Getwd/ Setwd (or in tool/file?) 39 40 // Functions: 41 // - Hostname 42 // - UserCache/Home/Config (or in os/user?) 43 } 44 45 type getenvCmd struct{} 46 47 func newGetenvCmd(v cue.Value) (task.Runner, error) { 48 return &getenvCmd{}, nil 49 } 50 51 func (c *getenvCmd) Run(ctx *task.Context) (res interface{}, err error) { 52 iter, err := ctx.Obj.Fields() 53 if err != nil { 54 return nil, err 55 } 56 57 update := map[string]interface{}{} 58 59 for iter.Next() { 60 name := iter.Label() 61 if strings.HasPrefix(name, "$") { 62 continue 63 } 64 v := iter.Value() 65 66 if err := v.Err(); err != nil { 67 return nil, err 68 } 69 70 if err := validateEntry(name, v); err != nil { 71 return nil, err 72 } 73 74 str, ok := os.LookupEnv(name) 75 if !ok { 76 update[name] = nil 77 continue 78 } 79 x, err := fromString(name, str, v) 80 if err != nil { 81 return nil, err 82 } 83 update[name] = x 84 } 85 86 return update, nil 87 } 88 89 type environCmd struct{} 90 91 func newEnvironCmd(v cue.Value) (task.Runner, error) { 92 return &environCmd{}, nil 93 } 94 95 func (c *environCmd) Run(ctx *task.Context) (res interface{}, err error) { 96 iter, err := ctx.Obj.Fields() 97 if err != nil { 98 return nil, err 99 } 100 101 update := map[string]interface{}{} 102 103 for _, kv := range os.Environ() { 104 a := strings.SplitN(kv, "=", 2) 105 106 name := a[0] 107 str := a[1] 108 109 if v := ctx.Obj.Lookup(name); v.Exists() { 110 update[name], err = fromString(name, str, v) 111 if err != nil { 112 return nil, err 113 } 114 } else { 115 update[name] = str 116 } 117 } 118 119 for iter.Next() { 120 name := iter.Label() 121 if strings.HasPrefix(name, "$") { 122 continue 123 } 124 v := iter.Value() 125 if err := v.Err(); err != nil { 126 return nil, err 127 } 128 if err := validateEntry(name, v); err != nil { 129 return nil, err 130 } 131 if _, ok := update[name]; !ok { 132 update[name] = nil 133 } 134 } 135 136 return update, nil 137 } 138 139 func validateEntry(name string, v cue.Value) error { 140 if k := v.IncompleteKind(); k&^(cue.NumberKind|cue.NullKind|cue.BoolKind|cue.StringKind) != 0 { 141 return errors.Newf(v.Pos(), 142 "invalid type %s for environment variable %s", k, name) 143 } 144 return nil 145 } 146 147 func fromString(name, str string, v cue.Value) (x ast.Node, err error) { 148 k := v.IncompleteKind() 149 return cli.ParseValue(v.Pos(), name, str, k) 150 }