github.com/grafana/tanka@v0.26.1-0.20240506093700-c22cfc35c21a/pkg/tanka/evaluators.go (about)

     1  package tanka
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/pkg/errors"
     8  
     9  	"github.com/grafana/tanka/pkg/jsonnet"
    10  	"github.com/grafana/tanka/pkg/jsonnet/implementations/types"
    11  	"github.com/grafana/tanka/pkg/jsonnet/jpath"
    12  )
    13  
    14  // EvalJsonnet evaluates the jsonnet environment at the given file system path
    15  func evalJsonnet(path string, impl types.JsonnetImplementation, opts jsonnet.Opts) (raw string, err error) {
    16  	entrypoint, err := jpath.Entrypoint(path)
    17  	if err != nil {
    18  		return "", err
    19  	}
    20  
    21  	// evaluate Jsonnet
    22  	if opts.EvalScript != "" {
    23  		var tla []string
    24  		for k := range opts.TLACode {
    25  			tla = append(tla, k+"="+k)
    26  		}
    27  		evalScript := fmt.Sprintf(`
    28    local main = (import '%s');
    29    %s
    30  `, entrypoint, opts.EvalScript)
    31  
    32  		if len(tla) != 0 {
    33  			tlaJoin := strings.Join(tla, ", ")
    34  			evalScript = fmt.Sprintf(`
    35  function(%s)
    36    local main = (import '%s')(%s);
    37    %s
    38  `, tlaJoin, entrypoint, tlaJoin, opts.EvalScript)
    39  		}
    40  
    41  		raw, err = jsonnet.Evaluate(path, impl, evalScript, opts)
    42  		if err != nil {
    43  			return "", fmt.Errorf("evaluating jsonnet in path '%s': %w", path, err)
    44  		}
    45  		return raw, nil
    46  	}
    47  
    48  	raw, err = jsonnet.EvaluateFile(impl, entrypoint, opts)
    49  	if err != nil {
    50  		return "", errors.Wrap(err, "evaluating jsonnet")
    51  	}
    52  	return raw, nil
    53  }
    54  
    55  func PatternEvalScript(expr string) string {
    56  	if strings.HasPrefix(expr, "[") {
    57  		return fmt.Sprintf("main%s", expr)
    58  	}
    59  	return fmt.Sprintf("main.%s", expr)
    60  }
    61  
    62  // MetadataEvalScript finds the Environment object (without its .data object)
    63  const MetadataEvalScript = `
    64  local noDataEnv(object) =
    65    std.prune(
    66      if std.isObject(object)
    67      then
    68        if std.objectHas(object, 'apiVersion')
    69           && std.objectHas(object, 'kind')
    70        then
    71          if object.kind == 'Environment'
    72          then object { data+:: {} }
    73          else {}
    74        else
    75          std.mapWithKey(
    76            function(key, obj)
    77              noDataEnv(obj),
    78            object
    79          )
    80      else if std.isArray(object)
    81      then
    82        std.map(
    83          function(obj)
    84            noDataEnv(obj),
    85          object
    86        )
    87      else {}
    88    );
    89  
    90  noDataEnv(main)
    91  `
    92  
    93  // MetadataSingleEnvEvalScript returns a Single Environment object
    94  const MetadataSingleEnvEvalScript = `
    95  local singleEnv(object) =
    96    std.prune(
    97      if std.isObject(object)
    98      then
    99        if std.objectHas(object, 'apiVersion')
   100           && std.objectHas(object, 'kind')
   101        then
   102          if object.kind == 'Environment'
   103          && object.metadata.name == '%s'
   104          then object { data:: super.data }
   105          else {}
   106        else
   107          std.mapWithKey(
   108            function(key, obj)
   109              singleEnv(obj),
   110            object
   111          )
   112      else if std.isArray(object)
   113      then
   114        std.map(
   115          function(obj)
   116            singleEnv(obj),
   117          object
   118        )
   119      else {}
   120    );
   121  
   122  singleEnv(main)
   123  `
   124  
   125  // SingleEnvEvalScript returns a Single Environment object
   126  const SingleEnvEvalScript = `
   127  local singleEnv(object) =
   128    if std.isObject(object)
   129    then
   130      if std.objectHas(object, 'apiVersion')
   131         && std.objectHas(object, 'kind')
   132      then
   133        if object.kind == 'Environment'
   134        && std.member(object.metadata.name, '%s')
   135        then object
   136        else {}
   137      else
   138        std.mapWithKey(
   139          function(key, obj)
   140            singleEnv(obj),
   141          object
   142        )
   143    else if std.isArray(object)
   144    then
   145      std.map(
   146        function(obj)
   147          singleEnv(obj),
   148        object
   149      )
   150    else {};
   151  
   152  singleEnv(main)
   153  `