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  }