github.com/octohelm/cuemod@v0.9.4/pkg/cuex/eval.go (about)

     1  package cuex
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"cuelang.org/go/cue"
    10  	"cuelang.org/go/cue/build"
    11  	"cuelang.org/go/cue/cuecontext"
    12  	cueerrors "cuelang.org/go/cue/errors"
    13  	"sigs.k8s.io/yaml"
    14  )
    15  
    16  type Encoding = build.Encoding
    17  
    18  const (
    19  	JSON = build.JSON
    20  	YAML = build.YAML
    21  	CUE  = build.CUE
    22  )
    23  
    24  type EvalOptionFunc = func(o *EvalOption)
    25  
    26  type EvalOption struct {
    27  	Encoding Encoding
    28  }
    29  
    30  func (o *EvalOption) SetDefaults() {
    31  	if o.Encoding == "" {
    32  		o.Encoding = build.JSON
    33  	}
    34  }
    35  
    36  func WithEncoding(e build.Encoding) EvalOptionFunc {
    37  	return func(o *EvalOption) {
    38  		o.Encoding = e
    39  	}
    40  }
    41  
    42  func WithEncodingFromFileExt(ext string) EvalOptionFunc {
    43  	return func(o *EvalOption) {
    44  		switch v := ext; v {
    45  		case ".yaml":
    46  			o.Encoding = YAML
    47  		case ".json":
    48  			o.Encoding = JSON
    49  		case ".cue":
    50  			o.Encoding = CUE
    51  		default:
    52  			panic(fmt.Errorf("unsupport output format %s", v))
    53  		}
    54  	}
    55  }
    56  
    57  func Eval(instance *build.Instance, options ...EvalOptionFunc) ([]byte, error) {
    58  	o := &EvalOption{}
    59  
    60  	for i := range options {
    61  		options[i](o)
    62  	}
    63  
    64  	v := cuecontext.New().BuildInstance(instance)
    65  
    66  	if err := v.Validate(cue.Final(), cue.Concrete(true)); err != nil {
    67  		b := bytes.NewBuffer(nil)
    68  		cueerrors.Print(b, err, nil)
    69  		return nil, errors.New(b.String())
    70  	}
    71  
    72  	data, err := encode(instance, v, o.Encoding)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	return data, nil
    78  }
    79  
    80  func encode(inst *build.Instance, v cue.Value, encoding Encoding) ([]byte, error) {
    81  	switch encoding {
    82  	case CUE:
    83  		return BundleToRaw(inst)
    84  	case JSON:
    85  		return json.Marshal(v)
    86  	case YAML:
    87  		data, err := json.Marshal(v)
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  		return yaml.JSONToYAML(data)
    92  	}
    93  	return nil, fmt.Errorf("unsupoort encoding %s", encoding)
    94  }