mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
cdd9464f9a
This is part of a general effort to move all of Terraform's non-library package surface under internal in order to reinforce that these are for internal use within Terraform only. If you were previously importing packages under this prefix into an external codebase, you could pin to an earlier release tag as an interim solution until you've make a plan to achieve the same functionality some other way.
201 lines
7.9 KiB
Go
201 lines
7.9 KiB
Go
package lang
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl/v2/ext/tryfunc"
|
|
ctyyaml "github.com/zclconf/go-cty-yaml"
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/function"
|
|
"github.com/zclconf/go-cty/cty/function/stdlib"
|
|
|
|
"github.com/hashicorp/terraform/internal/experiments"
|
|
"github.com/hashicorp/terraform/internal/lang/funcs"
|
|
)
|
|
|
|
var impureFunctions = []string{
|
|
"bcrypt",
|
|
"timestamp",
|
|
"uuid",
|
|
}
|
|
|
|
// Functions returns the set of functions that should be used to when evaluating
|
|
// expressions in the receiving scope.
|
|
func (s *Scope) Functions() map[string]function.Function {
|
|
s.funcsLock.Lock()
|
|
if s.funcs == nil {
|
|
// Some of our functions are just directly the cty stdlib functions.
|
|
// Others are implemented in the subdirectory "funcs" here in this
|
|
// repository. New functions should generally start out their lives
|
|
// in the "funcs" directory and potentially graduate to cty stdlib
|
|
// later if the functionality seems to be something domain-agnostic
|
|
// that would be useful to all applications using cty functions.
|
|
|
|
s.funcs = map[string]function.Function{
|
|
"abs": stdlib.AbsoluteFunc,
|
|
"abspath": funcs.AbsPathFunc,
|
|
"alltrue": funcs.AllTrueFunc,
|
|
"anytrue": funcs.AnyTrueFunc,
|
|
"basename": funcs.BasenameFunc,
|
|
"base64decode": funcs.Base64DecodeFunc,
|
|
"base64encode": funcs.Base64EncodeFunc,
|
|
"base64gzip": funcs.Base64GzipFunc,
|
|
"base64sha256": funcs.Base64Sha256Func,
|
|
"base64sha512": funcs.Base64Sha512Func,
|
|
"bcrypt": funcs.BcryptFunc,
|
|
"can": tryfunc.CanFunc,
|
|
"ceil": stdlib.CeilFunc,
|
|
"chomp": stdlib.ChompFunc,
|
|
"cidrhost": funcs.CidrHostFunc,
|
|
"cidrnetmask": funcs.CidrNetmaskFunc,
|
|
"cidrsubnet": funcs.CidrSubnetFunc,
|
|
"cidrsubnets": funcs.CidrSubnetsFunc,
|
|
"coalesce": funcs.CoalesceFunc,
|
|
"coalescelist": stdlib.CoalesceListFunc,
|
|
"compact": stdlib.CompactFunc,
|
|
"concat": stdlib.ConcatFunc,
|
|
"contains": stdlib.ContainsFunc,
|
|
"csvdecode": stdlib.CSVDecodeFunc,
|
|
"defaults": s.experimentalFunction(experiments.ModuleVariableOptionalAttrs, funcs.DefaultsFunc),
|
|
"dirname": funcs.DirnameFunc,
|
|
"distinct": stdlib.DistinctFunc,
|
|
"element": stdlib.ElementFunc,
|
|
"chunklist": stdlib.ChunklistFunc,
|
|
"file": funcs.MakeFileFunc(s.BaseDir, false),
|
|
"fileexists": funcs.MakeFileExistsFunc(s.BaseDir),
|
|
"fileset": funcs.MakeFileSetFunc(s.BaseDir),
|
|
"filebase64": funcs.MakeFileFunc(s.BaseDir, true),
|
|
"filebase64sha256": funcs.MakeFileBase64Sha256Func(s.BaseDir),
|
|
"filebase64sha512": funcs.MakeFileBase64Sha512Func(s.BaseDir),
|
|
"filemd5": funcs.MakeFileMd5Func(s.BaseDir),
|
|
"filesha1": funcs.MakeFileSha1Func(s.BaseDir),
|
|
"filesha256": funcs.MakeFileSha256Func(s.BaseDir),
|
|
"filesha512": funcs.MakeFileSha512Func(s.BaseDir),
|
|
"flatten": stdlib.FlattenFunc,
|
|
"floor": stdlib.FloorFunc,
|
|
"format": stdlib.FormatFunc,
|
|
"formatdate": stdlib.FormatDateFunc,
|
|
"formatlist": stdlib.FormatListFunc,
|
|
"indent": stdlib.IndentFunc,
|
|
"index": funcs.IndexFunc, // stdlib.IndexFunc is not compatible
|
|
"join": stdlib.JoinFunc,
|
|
"jsondecode": stdlib.JSONDecodeFunc,
|
|
"jsonencode": stdlib.JSONEncodeFunc,
|
|
"keys": stdlib.KeysFunc,
|
|
"length": funcs.LengthFunc,
|
|
"list": funcs.ListFunc,
|
|
"log": stdlib.LogFunc,
|
|
"lookup": funcs.LookupFunc,
|
|
"lower": stdlib.LowerFunc,
|
|
"map": funcs.MapFunc,
|
|
"matchkeys": funcs.MatchkeysFunc,
|
|
"max": stdlib.MaxFunc,
|
|
"md5": funcs.Md5Func,
|
|
"merge": stdlib.MergeFunc,
|
|
"min": stdlib.MinFunc,
|
|
"one": funcs.OneFunc,
|
|
"parseint": stdlib.ParseIntFunc,
|
|
"pathexpand": funcs.PathExpandFunc,
|
|
"pow": stdlib.PowFunc,
|
|
"range": stdlib.RangeFunc,
|
|
"regex": stdlib.RegexFunc,
|
|
"regexall": stdlib.RegexAllFunc,
|
|
"replace": funcs.ReplaceFunc,
|
|
"reverse": stdlib.ReverseListFunc,
|
|
"rsadecrypt": funcs.RsaDecryptFunc,
|
|
"sensitive": funcs.SensitiveFunc,
|
|
"nonsensitive": funcs.NonsensitiveFunc,
|
|
"setintersection": stdlib.SetIntersectionFunc,
|
|
"setproduct": stdlib.SetProductFunc,
|
|
"setsubtract": stdlib.SetSubtractFunc,
|
|
"setunion": stdlib.SetUnionFunc,
|
|
"sha1": funcs.Sha1Func,
|
|
"sha256": funcs.Sha256Func,
|
|
"sha512": funcs.Sha512Func,
|
|
"signum": stdlib.SignumFunc,
|
|
"slice": stdlib.SliceFunc,
|
|
"sort": stdlib.SortFunc,
|
|
"split": stdlib.SplitFunc,
|
|
"strrev": stdlib.ReverseFunc,
|
|
"substr": stdlib.SubstrFunc,
|
|
"sum": funcs.SumFunc,
|
|
"textdecodebase64": funcs.TextDecodeBase64Func,
|
|
"textencodebase64": funcs.TextEncodeBase64Func,
|
|
"timestamp": funcs.TimestampFunc,
|
|
"timeadd": stdlib.TimeAddFunc,
|
|
"title": stdlib.TitleFunc,
|
|
"tostring": funcs.MakeToFunc(cty.String),
|
|
"tonumber": funcs.MakeToFunc(cty.Number),
|
|
"tobool": funcs.MakeToFunc(cty.Bool),
|
|
"toset": funcs.MakeToFunc(cty.Set(cty.DynamicPseudoType)),
|
|
"tolist": funcs.MakeToFunc(cty.List(cty.DynamicPseudoType)),
|
|
"tomap": funcs.MakeToFunc(cty.Map(cty.DynamicPseudoType)),
|
|
"transpose": funcs.TransposeFunc,
|
|
"trim": stdlib.TrimFunc,
|
|
"trimprefix": stdlib.TrimPrefixFunc,
|
|
"trimspace": stdlib.TrimSpaceFunc,
|
|
"trimsuffix": stdlib.TrimSuffixFunc,
|
|
"try": tryfunc.TryFunc,
|
|
"upper": stdlib.UpperFunc,
|
|
"urlencode": funcs.URLEncodeFunc,
|
|
"uuid": funcs.UUIDFunc,
|
|
"uuidv5": funcs.UUIDV5Func,
|
|
"values": stdlib.ValuesFunc,
|
|
"yamldecode": ctyyaml.YAMLDecodeFunc,
|
|
"yamlencode": ctyyaml.YAMLEncodeFunc,
|
|
"zipmap": stdlib.ZipmapFunc,
|
|
}
|
|
|
|
s.funcs["templatefile"] = funcs.MakeTemplateFileFunc(s.BaseDir, func() map[string]function.Function {
|
|
// The templatefile function prevents recursive calls to itself
|
|
// by copying this map and overwriting the "templatefile" entry.
|
|
return s.funcs
|
|
})
|
|
|
|
if s.ConsoleMode {
|
|
// The type function is only available in terraform console.
|
|
s.funcs["type"] = funcs.TypeFunc
|
|
}
|
|
|
|
if s.PureOnly {
|
|
// Force our few impure functions to return unknown so that we
|
|
// can defer evaluating them until a later pass.
|
|
for _, name := range impureFunctions {
|
|
s.funcs[name] = function.Unpredictable(s.funcs[name])
|
|
}
|
|
}
|
|
}
|
|
s.funcsLock.Unlock()
|
|
|
|
return s.funcs
|
|
}
|
|
|
|
// experimentalFunction checks whether the given experiment is enabled for
|
|
// the recieving scope. If so, it will return the given function verbatim.
|
|
// If not, it will return a placeholder function that just returns an
|
|
// error explaining that the function requires the experiment to be enabled.
|
|
func (s *Scope) experimentalFunction(experiment experiments.Experiment, fn function.Function) function.Function {
|
|
if s.activeExperiments.Has(experiment) {
|
|
return fn
|
|
}
|
|
|
|
err := fmt.Errorf(
|
|
"this function is experimental and available only when the experiment keyword %s is enabled for the current module",
|
|
experiment.Keyword(),
|
|
)
|
|
|
|
return function.New(&function.Spec{
|
|
Params: fn.Params(),
|
|
VarParam: fn.VarParam(),
|
|
Type: func(args []cty.Value) (cty.Type, error) {
|
|
return cty.DynamicPseudoType, err
|
|
},
|
|
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
|
|
// It would be weird to get here because the Type function always
|
|
// fails, but we'll return an error here too anyway just to be
|
|
// robust.
|
|
return cty.DynamicVal, err
|
|
},
|
|
})
|
|
}
|