funcs

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2024 License: MPL-2.0 Imports: 44 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AbsPathFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "path",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		absPath, err := filepath.Abs(args[0].AsString())
		return cty.StringVal(filepath.ToSlash(absPath)), err
	},
})

AbsPathFunc constructs a function that converts a filesystem path to an absolute path

View Source
var AllTrueFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.List(cty.Bool),
		},
	},
	Type:         function.StaticReturnType(cty.Bool),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		result := cty.True
		for it := args[0].ElementIterator(); it.Next(); {
			_, v := it.Element()
			if !v.IsKnown() {
				return cty.UnknownVal(cty.Bool), nil
			}
			if v.IsNull() {
				return cty.False, nil
			}
			result = result.And(v)
			if result.False() {
				return cty.False, nil
			}
		}
		return result, nil
	},
})

AllTrueFunc constructs a function that returns true if all elements of the list are true. If the list is empty, return true.

View Source
var AnyTrueFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.List(cty.Bool),
		},
	},
	Type:         function.StaticReturnType(cty.Bool),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		result := cty.False
		var hasUnknown bool
		for it := args[0].ElementIterator(); it.Next(); {
			_, v := it.Element()
			if !v.IsKnown() {
				hasUnknown = true
				continue
			}
			if v.IsNull() {
				continue
			}
			result = result.Or(v)
			if result.True() {
				return cty.True, nil
			}
		}
		if hasUnknown {
			return cty.UnknownVal(cty.Bool), nil
		}
		return result, nil
	},
})

AnyTrueFunc constructs a function that returns true if any element of the list is true. If the list is empty, return false.

View Source
var Base64DecodeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "str",
			Type:        cty.String,
			AllowMarked: true,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		str, strMarks := args[0].Unmark()
		s := str.AsString()
		sDec, err := base64.StdEncoding.DecodeString(s)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to decode base64 data %s", redactIfSensitive(s, strMarks))
		}
		if !utf8.Valid([]byte(sDec)) {
			log.Printf("[DEBUG] the result of decoding the provided string is not valid UTF-8: %s", redactIfSensitive(sDec, strMarks))
			return cty.UnknownVal(cty.String), fmt.Errorf("the result of decoding the provided string is not valid UTF-8")
		}
		return cty.StringVal(string(sDec)).WithMarks(strMarks), nil
	},
})

Base64DecodeFunc constructs a function that decodes a string containing a base64 sequence.

View Source
var Base64EncodeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.StringVal(base64.StdEncoding.EncodeToString([]byte(args[0].AsString()))), nil
	},
})

Base64EncodeFunc constructs a function that encodes a string to a base64 sequence.

View Source
var Base64GunzipFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		str, strMarks := args[0].Unmark()
		s := str.AsString()
		sDec, err := base64.StdEncoding.DecodeString(s)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to decode base64 data %s", redactIfSensitive(s, strMarks))
		}
		sDecBuffer := bytes.NewReader(sDec)
		gzipReader, err := gzip.NewReader(sDecBuffer)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to gunzip bytestream: %w", err)
		}
		gunzip, err := io.ReadAll(gzipReader)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to read gunzip raw data: %w", err)
		}

		return cty.StringVal(string(gunzip)), nil
	},
})

Base64GunzipFunc constructs a function that Bae64 decodes a string and decompresses the result with gunzip.

View Source
var Base64GzipFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		s := args[0].AsString()

		var b bytes.Buffer
		gz := gzip.NewWriter(&b)
		if _, err := gz.Write([]byte(s)); err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to write gzip raw data: %w", err)
		}
		if err := gz.Flush(); err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to flush gzip writer: %w", err)
		}
		if err := gz.Close(); err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to close gzip writer: %w", err)
		}
		return cty.StringVal(base64.StdEncoding.EncodeToString(b.Bytes())), nil
	},
})

Base64GzipFunc constructs a function that compresses a string with gzip and then encodes the result in Base64 encoding.

View Source
var Base64Sha256Func = makeStringHashFunction(sha256.New, base64.StdEncoding.EncodeToString)

Base64Sha256Func constructs a function that computes the SHA256 hash of a given string and encodes it with Base64.

View Source
var Base64Sha512Func = makeStringHashFunction(sha512.New, base64.StdEncoding.EncodeToString)

Base64Sha512Func constructs a function that computes the SHA256 hash of a given string and encodes it with Base64.

View Source
var BasenameFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "path",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.StringVal(filepath.Base(args[0].AsString())), nil
	},
})

BasenameFunc constructs a function that takes a string containing a filesystem path and removes all except the last portion from it.

View Source
var BcryptFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	VarParam: &function.Parameter{
		Name: "cost",
		Type: cty.Number,
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		defaultCost := 10

		if len(args) > 1 {
			var val int
			if err := gocty.FromCtyValue(args[1], &val); err != nil {
				return cty.UnknownVal(cty.String), err
			}
			defaultCost = val
		}

		if len(args) > 2 {
			return cty.UnknownVal(cty.String), fmt.Errorf("bcrypt() takes no more than two arguments")
		}

		input := args[0].AsString()
		out, err := bcrypt.GenerateFromPassword([]byte(input), defaultCost)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("error occurred generating password %w", err)
		}

		return cty.StringVal(string(out)), nil
	},
})

BcryptFunc constructs a function that computes a hash of the given string using the Blowfish cipher.

View Source
var CidrContainsFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "containing_prefix",
			Type: cty.String,
		},
		{
			Name: "contained_ip_or_prefix",
			Type: cty.String,
		},
	},
	Type: function.StaticReturnType(cty.Bool),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		prefix := args[0].AsString()
		addr := args[1].AsString()

		_, containing, err := ipaddr.ParseCIDR(prefix)
		if err != nil {
			return cty.UnknownVal(cty.Bool), err
		}

		startIP := ipaddr.ParseIP(addr)
		var endIP ipaddr.IP

		if startIP == nil {
			_, contained, err := ipaddr.ParseCIDR(addr)

			if err != nil {
				return cty.UnknownVal(cty.Bool), fmt.Errorf("invalid IP address or prefix: %s", addr)
			}

			startIP, endIP = cidr.AddressRange(contained)
		}

		if (startIP.To4() == nil) != (containing.IP.To4() == nil) {
			return cty.UnknownVal(cty.Bool), fmt.Errorf("address family mismatch: %s vs. %s", prefix, addr)
		}

		result := containing.Contains(startIP)

		if endIP != nil {
			result = result && containing.Contains(endIP)
		}

		return cty.BoolVal(result), nil
	},
})

CidrContainsFunc constructs a function that checks whether a given IP address is within a given IP network address prefix.

View Source
var CidrHostFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
		{
			Name: "hostnum",
			Type: cty.Number,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var hostNum *big.Int
		if err := gocty.FromCtyValue(args[1], &hostNum); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		_, network, err := ipaddr.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %w", err)
		}

		ip, err := cidr.HostBig(network, hostNum)
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}

		return cty.StringVal(ip.String()), nil
	},
})

CidrHostFunc contructs a function that calculates a full host IP address within a given IP network address prefix.

View Source
var CidrNetmaskFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		_, network, err := ipaddr.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %w", err)
		}

		if network.IP.To4() == nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("IPv6 addresses cannot have a netmask: %s", args[0].AsString())
		}

		return cty.StringVal(ipaddr.IP(network.Mask).String()), nil
	},
})

CidrNetmaskFunc contructs a function that converts an IPv4 address prefix given in CIDR notation into a subnet mask address.

View Source
var CidrSubnetFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
		{
			Name: "newbits",
			Type: cty.Number,
		},
		{
			Name: "netnum",
			Type: cty.Number,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var newbits int
		if err := gocty.FromCtyValue(args[1], &newbits); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		var netnum *big.Int
		if err := gocty.FromCtyValue(args[2], &netnum); err != nil {
			return cty.UnknownVal(cty.String), err
		}

		_, network, err := ipaddr.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("invalid CIDR expression: %w", err)
		}

		newNetwork, err := cidr.SubnetBig(network, newbits, netnum)
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}

		return cty.StringVal(newNetwork.String()), nil
	},
})

CidrSubnetFunc contructs a function that calculates a subnet address within a given IP network address prefix.

View Source
var CidrSubnetsFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "prefix",
			Type: cty.String,
		},
	},
	VarParam: &function.Parameter{
		Name: "newbits",
		Type: cty.Number,
	},
	Type:         function.StaticReturnType(cty.List(cty.String)),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		_, network, err := ipaddr.ParseCIDR(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "invalid CIDR expression: %s", err)
		}
		startPrefixLen, _ := network.Mask.Size()

		prefixLengthArgs := args[1:]
		if len(prefixLengthArgs) == 0 {
			return cty.ListValEmpty(cty.String), nil
		}

		var firstLength int
		if err := gocty.FromCtyValue(prefixLengthArgs[0], &firstLength); err != nil {
			return cty.UnknownVal(cty.String), function.NewArgError(1, err)
		}
		firstLength += startPrefixLen

		retVals := make([]cty.Value, len(prefixLengthArgs))

		current, _ := cidr.PreviousSubnet(network, firstLength)
		for i, lengthArg := range prefixLengthArgs {
			var length int
			if err := gocty.FromCtyValue(lengthArg, &length); err != nil {
				return cty.UnknownVal(cty.String), function.NewArgError(i+1, err)
			}

			if length < 1 {
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "must extend prefix by at least one bit")
			}

			if length > 32 {
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "may not extend prefix by more than 32 bits")
			}
			length += startPrefixLen
			if length > (len(network.IP) * 8) {
				protocol := "IP"
				switch len(network.IP) * 8 {
				case 32:
					protocol = "IPv4"
				case 128:
					protocol = "IPv6"
				}
				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "would extend prefix to %d bits, which is too long for an %s address", length, protocol)
			}

			next, rollover := cidr.NextSubnet(current, length)
			if rollover || !network.Contains(next.IP) {

				return cty.UnknownVal(cty.String), function.NewArgErrorf(i+1, "not enough remaining address space for a subnet with a prefix of %d bits after %s", length, current.String())
			}

			current = next
			retVals[i] = cty.StringVal(current.String())
		}

		return cty.ListVal(retVals), nil
	},
})

CidrSubnetsFunc is similar to CidrSubnetFunc but calculates many consecutive subnet addresses at once, rather than just a single subnet extension.

View Source
var CoalesceFunc = function.New(&function.Spec{
	Params: []function.Parameter{},
	VarParam: &function.Parameter{
		Name:             "vals",
		Type:             cty.DynamicPseudoType,
		AllowUnknown:     true,
		AllowDynamicType: true,
		AllowNull:        true,
	},
	Type: func(args []cty.Value) (ret cty.Type, err error) {
		argTypes := make([]cty.Type, len(args))
		for i, val := range args {
			argTypes[i] = val.Type()
		}
		retType, _ := convert.UnifyUnsafe(argTypes)
		if retType == cty.NilType {
			return cty.NilType, errors.New("all arguments must have the same type")
		}
		return retType, nil
	},
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		for _, argVal := range args {

			argVal, _ = convert.Convert(argVal, retType)
			if !argVal.IsKnown() {
				return cty.UnknownVal(retType), nil
			}
			if argVal.IsNull() {
				continue
			}
			if retType == cty.String && argVal.RawEquals(cty.StringVal("")) {
				continue
			}

			return argVal, nil
		}
		return cty.NilVal, errors.New("no non-null, non-empty-string arguments")
	},
})

CoalesceFunc constructs a function that takes any number of arguments and returns the first one that isn't empty. This function was copied from go-cty stdlib and modified so that it returns the first *non-empty* non-null element from a sequence, instead of merely the first non-null.

View Source
var DescriptionList = map[string]descriptionEntry{}/* 123 elements not displayed */

DescriptionList is a consolidated list containing all descriptions for all functions available within OpenTofu. A function's description should point to the matching entry in this list.

We keep this as a single list, so we can quickly review descriptions within a single file and copy the whole list to other projects, like terraform-schema.

View Source
var DirnameFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "path",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.StringVal(filepath.Dir(args[0].AsString())), nil
	},
})

DirnameFunc constructs a function that takes a string containing a filesystem path and removes the last portion from it.

View Source
var EndsWithFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
		{
			Name: "suffix",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.Bool),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		str := args[0].AsString()
		suffix := args[1].AsString()

		if strings.HasSuffix(str, suffix) {
			return cty.True, nil
		}

		return cty.False, nil
	},
})

EndsWithFunc constructs a function that checks if a string ends with a specific suffix using strings.HasSuffix

View Source
var IndexFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.DynamicPseudoType,
		},
		{
			Name: "value",
			Type: cty.DynamicPseudoType,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		if !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {
			return cty.NilVal, errors.New("argument must be a list or tuple")
		}

		if !args[0].IsKnown() {
			return cty.UnknownVal(cty.Number), nil
		}

		if args[0].LengthInt() == 0 {
			return cty.NilVal, errors.New("cannot search an empty list")
		}

		for it := args[0].ElementIterator(); it.Next(); {
			i, v := it.Element()
			eq, err := stdlib.Equal(v, args[1])
			if err != nil {
				return cty.NilVal, err
			}
			if !eq.IsKnown() {
				return cty.UnknownVal(cty.Number), nil
			}
			if eq.True() {
				return i, nil
			}
		}
		return cty.NilVal, errors.New("item not found")

	},
})

IndexFunc constructs a function that finds the element index for a given value in a list.

View Source
var IsSensitiveFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:             "value",
			Type:             cty.DynamicPseudoType,
			AllowUnknown:     true,
			AllowNull:        true,
			AllowMarked:      true,
			AllowDynamicType: true,
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {
		return cty.Bool, nil
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		return cty.BoolVal(args[0].HasMark(marks.Sensitive)), nil
	},
})

IsSensitiveFunc returns whether or not the value is sensitive.

View Source
var LengthFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:             "value",
			Type:             cty.DynamicPseudoType,
			AllowDynamicType: true,
			AllowUnknown:     true,
			AllowMarked:      true,
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {
		collTy := args[0].Type()
		switch {
		case collTy == cty.String || collTy.IsTupleType() || collTy.IsObjectType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType:
			return cty.Number, nil
		default:
			return cty.Number, errors.New("argument must be a string, a collection type, or a structural type")
		}
	},
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		coll := args[0]
		collTy := args[0].Type()
		marks := coll.Marks()
		switch {
		case collTy == cty.DynamicPseudoType:
			return cty.UnknownVal(cty.Number).WithMarks(marks), nil
		case collTy.IsTupleType():
			l := len(collTy.TupleElementTypes())
			return cty.NumberIntVal(int64(l)).WithMarks(marks), nil
		case collTy.IsObjectType():
			l := len(collTy.AttributeTypes())
			return cty.NumberIntVal(int64(l)).WithMarks(marks), nil
		case collTy == cty.String:

			return stdlib.Strlen(coll)
		case collTy.IsListType() || collTy.IsSetType() || collTy.IsMapType():
			return coll.Length(), nil
		default:

			return cty.UnknownVal(cty.Number), errors.New("impossible value type for length(...)")
		}
	},
})
View Source
var ListFunc = function.New(&function.Spec{
	Params: []function.Parameter{},
	VarParam: &function.Parameter{
		Name:             "vals",
		Type:             cty.DynamicPseudoType,
		AllowUnknown:     true,
		AllowDynamicType: true,
		AllowNull:        true,
	},
	Type: func(args []cty.Value) (ret cty.Type, err error) {
		return cty.DynamicPseudoType, fmt.Errorf("the \"list\" function was deprecated in Terraform v0.12 and is not available in OpenTofu; use tolist([ ... ]) syntax to write a literal list")
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		return cty.DynamicVal, fmt.Errorf("the \"list\" function was deprecated in Terraform v0.12 and is not available in OpenTofu; use tolist([ ... ]) syntax to write a literal list")
	},
})

ListFunc constructs a function that takes an arbitrary number of arguments and returns a list containing those values in the same order.

This function is deprecated in Terraform v0.12

View Source
var LogFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "num",
			Type: cty.Number,
		},
		{
			Name: "base",
			Type: cty.Number,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var num float64
		if err := gocty.FromCtyValue(args[0], &num); err != nil {
			return cty.UnknownVal(cty.String), err
		}

		var base float64
		if err := gocty.FromCtyValue(args[1], &base); err != nil {
			return cty.UnknownVal(cty.String), err
		}

		return cty.NumberFloatVal(math.Log(num) / math.Log(base)), nil
	},
})

LogFunc contructs a function that returns the logarithm of a given number in a given base.

View Source
var LookupFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "inputMap",
			Type:        cty.DynamicPseudoType,
			AllowMarked: true,
		},
		{
			Name:        "key",
			Type:        cty.String,
			AllowMarked: true,
		},
	},
	VarParam: &function.Parameter{
		Name:             "default",
		Type:             cty.DynamicPseudoType,
		AllowUnknown:     true,
		AllowDynamicType: true,
		AllowNull:        true,
		AllowMarked:      true,
	},
	Type: func(args []cty.Value) (ret cty.Type, err error) {
		if len(args) < 1 || len(args) > 3 {
			return cty.NilType, fmt.Errorf("lookup() takes two or three arguments, got %d", len(args))
		}

		ty := args[0].Type()

		switch {
		case ty.IsObjectType():
			if !args[1].IsKnown() {
				return cty.DynamicPseudoType, nil
			}

			keyVal, _ := args[1].Unmark()
			key := keyVal.AsString()
			if ty.HasAttribute(key) {
				return args[0].GetAttr(key).Type(), nil
			} else if len(args) == 3 {

				return args[2].Type(), nil
			}
			return cty.DynamicPseudoType, function.NewArgErrorf(0, "the given object has no attribute %q", key)
		case ty.IsMapType():
			if len(args) == 3 {
				_, err = convert.Convert(args[2], ty.ElementType())
				if err != nil {
					return cty.NilType, function.NewArgErrorf(2, "the default value must have the same type as the map elements")
				}
			}
			return ty.ElementType(), nil
		default:
			return cty.NilType, function.NewArgErrorf(0, "lookup() requires a map as the first argument")
		}
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var defaultVal cty.Value
		defaultValueSet := false

		if len(args) == 3 {

			defaultVal = args[2]
			defaultValueSet = true
		}

		// keep track of marks from the collection and key
		var markses []cty.ValueMarks

		mapVar, mapMarks := args[0].Unmark()
		markses = append(markses, mapMarks)

		keyVal, keyMarks := args[1].Unmark()
		if len(keyMarks) > 0 {
			markses = append(markses, keyMarks)
		}
		lookupKey := keyVal.AsString()

		if !mapVar.IsKnown() {
			return cty.UnknownVal(retType).WithMarks(markses...), nil
		}

		if mapVar.Type().IsObjectType() {
			if mapVar.Type().HasAttribute(lookupKey) {
				return mapVar.GetAttr(lookupKey).WithMarks(markses...), nil
			}
		} else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
			return mapVar.Index(cty.StringVal(lookupKey)).WithMarks(markses...), nil
		}

		if defaultValueSet {
			defaultVal, err = convert.Convert(defaultVal, retType)
			if err != nil {
				return cty.NilVal, err
			}
			return defaultVal.WithMarks(markses...), nil
		}

		return cty.UnknownVal(cty.DynamicPseudoType), fmt.Errorf(
			"lookup failed to find key %s", redactIfSensitive(lookupKey, keyMarks))
	},
})

LookupFunc constructs a function that performs dynamic lookups of map types.

View Source
var MapFunc = function.New(&function.Spec{
	Params: []function.Parameter{},
	VarParam: &function.Parameter{
		Name:             "vals",
		Type:             cty.DynamicPseudoType,
		AllowUnknown:     true,
		AllowDynamicType: true,
		AllowNull:        true,
	},
	Type: func(args []cty.Value) (ret cty.Type, err error) {
		return cty.DynamicPseudoType, fmt.Errorf("the \"map\" function was deprecated in Terraform v0.12 and is not available in OpenTofu; use tomap({ ... }) syntax to write a literal map")
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		return cty.DynamicVal, fmt.Errorf("the \"map\" function was deprecated in Terraform v0.12 and is not available in OpenTofu; use tomap({ ... }) syntax to write a literal map")
	},
})

MapFunc constructs a function that takes an even number of arguments and returns a map whose elements are constructed from consecutive pairs of arguments.

This function is deprecated in Terraform v0.12

View Source
var MatchkeysFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "values",
			Type: cty.List(cty.DynamicPseudoType),
		},
		{
			Name: "keys",
			Type: cty.List(cty.DynamicPseudoType),
		},
		{
			Name: "searchset",
			Type: cty.List(cty.DynamicPseudoType),
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {
		ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
		if ty == cty.NilType {
			return cty.NilType, errors.New("keys and searchset must be of the same type")
		}

		return args[0].Type(), nil
	},
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		if !args[0].IsKnown() {
			return cty.UnknownVal(cty.List(retType.ElementType())), nil
		}

		if args[0].LengthInt() != args[1].LengthInt() {
			return cty.ListValEmpty(retType.ElementType()), errors.New("length of keys and values should be equal")
		}

		output := make([]cty.Value, 0)
		values := args[0]

		ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
		keys, _ := convert.Convert(args[1], ty)
		searchset, _ := convert.Convert(args[2], ty)

		if searchset.LengthInt() == 0 {
			return cty.ListValEmpty(retType.ElementType()), nil
		}

		if !values.IsWhollyKnown() || !keys.IsWhollyKnown() {
			return cty.UnknownVal(retType), nil
		}

		i := 0
		for it := keys.ElementIterator(); it.Next(); {
			_, key := it.Element()
			for iter := searchset.ElementIterator(); iter.Next(); {
				_, search := iter.Element()
				eq, err := stdlib.Equal(key, search)
				if err != nil {
					return cty.NilVal, err
				}
				if !eq.IsKnown() {
					return cty.ListValEmpty(retType.ElementType()), nil
				}
				if eq.True() {
					v := values.Index(cty.NumberIntVal(int64(i)))
					output = append(output, v)
					break
				}
			}
			i++
		}

		if len(output) == 0 {
			return cty.ListValEmpty(retType.ElementType()), nil
		}
		return cty.ListVal(output), nil
	},
})

MatchkeysFunc constructs a function that constructs a new list by taking a subset of elements from one list whose indexes match the corresponding indexes of values in another list.

View Source
var Md5Func = makeStringHashFunction(md5.New, hex.EncodeToString)

Md5Func constructs a function that computes the MD5 hash of a given string and encodes it with hexadecimal digits.

View Source
var NonsensitiveFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:             "value",
			Type:             cty.DynamicPseudoType,
			AllowUnknown:     true,
			AllowNull:        true,
			AllowMarked:      true,
			AllowDynamicType: true,
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {

		return args[0].Type(), nil
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		v, m := args[0].Unmark()
		delete(m, marks.Sensitive)
		return v.WithMarks(m), nil
	},
})

NonsensitiveFunc takes a sensitive value and returns the same value without the sensitive marking, effectively exposing the value.

View Source
var OneFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.DynamicPseudoType,
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {
		ty := args[0].Type()
		switch {
		case ty.IsListType() || ty.IsSetType():
			return ty.ElementType(), nil
		case ty.IsTupleType():
			etys := ty.TupleElementTypes()
			switch len(etys) {
			case 0:

				return cty.DynamicPseudoType, nil
			case 1:
				return etys[0], nil
			}
		}
		return cty.NilType, function.NewArgErrorf(0, "must be a list, set, or tuple value with either zero or one elements")
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		val := args[0]
		ty := val.Type()

		switch {
		case ty.IsListType() || ty.IsSetType():
			lenVal := val.Length()
			if !lenVal.IsKnown() {
				return cty.UnknownVal(retType), nil
			}
			var l int
			err := gocty.FromCtyValue(lenVal, &l)
			if err != nil {

				return cty.NilVal, fmt.Errorf("invalid collection length: %w", err)
			}
			switch l {
			case 0:
				return cty.NullVal(retType), nil
			case 1:
				var ret cty.Value

				for it := val.ElementIterator(); it.Next(); {
					_, ret = it.Element()
				}
				return ret, nil
			}
		case ty.IsTupleType():
			etys := ty.TupleElementTypes()
			switch len(etys) {
			case 0:
				return cty.NullVal(retType), nil
			case 1:
				ret := val.Index(cty.NumberIntVal(0))
				return ret, nil
			}
		}
		return cty.NilVal, function.NewArgErrorf(0, "must be a list, set, or tuple value with either zero or one elements")
	},
})

OneFunc returns either the first element of a one-element list, or null if given a zero-element list.

View Source
var ParseIntFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:        "number",
			Type:        cty.DynamicPseudoType,
			AllowMarked: true,
		},
		{
			Name:        "base",
			Type:        cty.Number,
			AllowMarked: true,
		},
	},

	Type: func(args []cty.Value) (cty.Type, error) {
		if !args[0].Type().Equals(cty.String) {
			return cty.Number, function.NewArgErrorf(0, "first argument must be a string, not %s", args[0].Type().FriendlyName())
		}
		return cty.Number, nil
	},
	RefineResult: refineNotNull,

	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		var numstr string
		var base int
		var err error

		numArg, numMarks := args[0].Unmark()
		if err = gocty.FromCtyValue(numArg, &numstr); err != nil {
			return cty.UnknownVal(cty.String), function.NewArgError(0, err)
		}

		baseArg, baseMarks := args[1].Unmark()
		if err = gocty.FromCtyValue(baseArg, &base); err != nil {
			return cty.UnknownVal(cty.Number), function.NewArgError(1, err)
		}

		if base < 2 || base > 62 {
			return cty.UnknownVal(cty.Number), function.NewArgErrorf(
				1,
				"base must be a whole number between 2 and 62 inclusive",
			)
		}

		num, ok := (&big.Int{}).SetString(numstr, base)
		if !ok {
			return cty.UnknownVal(cty.Number), function.NewArgErrorf(
				0,
				"cannot parse %s as a base %s integer",
				redactIfSensitive(numstr, numMarks),
				redactIfSensitive(base, baseMarks),
			)
		}

		parsedNum := cty.NumberVal((&big.Float{}).SetInt(num)).WithMarks(numMarks, baseMarks)

		return parsedNum, nil
	},
})

ParseIntFunc contructs a function that parses a string argument and returns an integer of the specified base.

View Source
var PathExpandFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "path",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {

		homePath, err := homedir.Expand(args[0].AsString())
		return cty.StringVal(homePath), err
	},
})

PathExpandFunc constructs a function that expands a leading ~ character to the current user's home directory.

View Source
var PowFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "num",
			Type: cty.Number,
		},
		{
			Name: "power",
			Type: cty.Number,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var num float64
		if err := gocty.FromCtyValue(args[0], &num); err != nil {
			return cty.UnknownVal(cty.String), err
		}

		var power float64
		if err := gocty.FromCtyValue(args[1], &power); err != nil {
			return cty.UnknownVal(cty.String), err
		}

		return cty.NumberFloatVal(math.Pow(num, power)), nil
	},
})

PowFunc contructs a function that returns the logarithm of a given number in a given base.

View Source
var ReplaceFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
		{
			Name: "substr",
			Type: cty.String,
		},
		{
			Name: "replace",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		str := args[0].AsString()
		substr := args[1].AsString()
		replace := args[2].AsString()

		if len(substr) > 1 && substr[0] == '/' && substr[len(substr)-1] == '/' {
			re, err := regexp.Compile(substr[1 : len(substr)-1])
			if err != nil {
				return cty.UnknownVal(cty.String), err
			}

			return cty.StringVal(re.ReplaceAllString(str, replace)), nil
		}

		return cty.StringVal(strings.Replace(str, substr, replace, -1)), nil
	},
})

ReplaceFunc constructs a function that searches a given string for another given substring, and replaces each occurence with a given replacement string.

View Source
var RsaDecryptFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "ciphertext",
			Type: cty.String,
		},
		{
			Name: "privatekey",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		s := args[0].AsString()
		key := args[1].AsString()

		b, err := base64.StdEncoding.DecodeString(s)
		if err != nil {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "failed to decode input %q: cipher text must be base64-encoded", s)
		}

		rawKey, err := ssh.ParseRawPrivateKey([]byte(key))
		if err != nil {
			var errStr string
			switch e := err.(type) {
			case asn1.SyntaxError:
				errStr = strings.ReplaceAll(e.Error(), "asn1: syntax error", "invalid ASN1 data in the given private key")
			case asn1.StructuralError:
				errStr = strings.ReplaceAll(e.Error(), "asn1: struture error", "invalid ASN1 data in the given private key")
			default:
				errStr = fmt.Sprintf("invalid private key: %s", e)
			}
			return cty.UnknownVal(cty.String), function.NewArgErrorf(1, errStr)
		}
		privateKey, ok := rawKey.(*rsa.PrivateKey)
		if !ok {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(1, "invalid private key type %t", rawKey)
		}

		out, err := rsa.DecryptPKCS1v15(nil, privateKey, b)
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to decrypt: %w", err)
		}

		return cty.StringVal(string(out)), nil
	},
})

RsaDecryptFunc constructs a function that decrypts an RSA-encrypted ciphertext.

View Source
var SensitiveFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:             "value",
			Type:             cty.DynamicPseudoType,
			AllowUnknown:     true,
			AllowNull:        true,
			AllowMarked:      true,
			AllowDynamicType: true,
		},
	},
	Type: func(args []cty.Value) (cty.Type, error) {

		return args[0].Type(), nil
	},
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		val, _ := args[0].Unmark()
		return val.Mark(marks.Sensitive), nil
	},
})

SensitiveFunc returns a value identical to its argument except that OpenTofu will consider it to be sensitive.

View Source
var Sha1Func = makeStringHashFunction(sha1.New, hex.EncodeToString)

Sha1Func contructs a function that computes the SHA1 hash of a given string and encodes it with hexadecimal digits.

View Source
var Sha256Func = makeStringHashFunction(sha256.New, hex.EncodeToString)

Sha256Func contructs a function that computes the SHA256 hash of a given string and encodes it with hexadecimal digits.

View Source
var Sha512Func = makeStringHashFunction(sha512.New, hex.EncodeToString)

Sha512Func contructs a function that computes the SHA512 hash of a given string and encodes it with hexadecimal digits.

View Source
var SignumFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "num",
			Type: cty.Number,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var num int
		if err := gocty.FromCtyValue(args[0], &num); err != nil {
			return cty.UnknownVal(cty.String), err
		}
		switch {
		case num < 0:
			return cty.NumberIntVal(-1), nil
		case num > 0:
			return cty.NumberIntVal(+1), nil
		default:
			return cty.NumberIntVal(0), nil
		}
	},
})

SignumFunc contructs a function that returns the closest whole number greater than or equal to the given value.

View Source
var StartsWithFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:         "str",
			Type:         cty.String,
			AllowUnknown: true,
		},
		{
			Name: "prefix",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.Bool),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		prefix := args[1].AsString()

		if !args[0].IsKnown() {

			if prefix == "" {

				return cty.True, nil
			}
			if knownPrefix := args[0].Range().StringPrefix(); knownPrefix != "" {
				if strings.HasPrefix(knownPrefix, prefix) {
					return cty.True, nil
				}
				if len(knownPrefix) >= len(prefix) {

					return cty.False, nil
				}
			}
			return cty.UnknownVal(cty.Bool), nil
		}

		str := args[0].AsString()

		if strings.HasPrefix(str, prefix) {
			return cty.True, nil
		}

		return cty.False, nil
	},
})

StartsWithFunc constructs a function that checks if a string starts with a specific prefix using strings.HasPrefix

View Source
var StrContainsFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
		{
			Name: "substr",
			Type: cty.String,
		},
	},
	Type: function.StaticReturnType(cty.Bool),
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		str := args[0].AsString()
		substr := args[1].AsString()

		if strings.Contains(str, substr) {
			return cty.True, nil
		}

		return cty.False, nil
	},
})

StrContainsFunc searches a given string for another given substring, if found the function returns true, otherwise returns false.

View Source
var SumFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.DynamicPseudoType,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {

		if !args[0].CanIterateElements() {
			return cty.NilVal, function.NewArgErrorf(0, "cannot sum noniterable")
		}

		if args[0].LengthInt() == 0 {
			return cty.NilVal, function.NewArgErrorf(0, "cannot sum an empty list")
		}

		arg := args[0].AsValueSlice()
		ty := args[0].Type()

		if !ty.IsListType() && !ty.IsSetType() && !ty.IsTupleType() {
			return cty.NilVal, function.NewArgErrorf(0, fmt.Sprintf("argument must be list, set, or tuple. Received %s", ty.FriendlyName()))
		}

		if !args[0].IsWhollyKnown() {
			return cty.UnknownVal(cty.Number), nil
		}

		defer func() {
			if r := recover(); r != nil {
				if _, ok := r.(big.ErrNaN); ok {
					ret = cty.NilVal
					err = fmt.Errorf("can't compute sum of opposing infinities")
				} else {

					panic(r)
				}
			}
		}()

		s := arg[0]
		if s.IsNull() {
			return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
		}
		s, err = convert.Convert(s, cty.Number)
		if err != nil {
			return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
		}
		for _, v := range arg[1:] {
			if v.IsNull() {
				return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
			}
			v, err = convert.Convert(v, cty.Number)
			if err != nil {
				return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
			}
			s = s.Add(v)
		}

		return s, nil
	},
})

SumFunc constructs a function that returns the sum of all numbers provided in a list

View Source
var TextDecodeBase64Func = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "source",
			Type: cty.String,
		},
		{
			Name: "encoding",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		encoding, err := ianaindex.IANA.Encoding(args[1].AsString())
		if err != nil || encoding == nil {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(1, "%q is not a supported IANA encoding name or alias in this OpenTofu version", args[1].AsString())
		}

		encName, err := ianaindex.IANA.Name(encoding)
		if err != nil {
			encName = args[1].AsString()
		}

		s := args[0].AsString()
		sDec, err := base64.StdEncoding.DecodeString(s)
		if err != nil {
			switch err := err.(type) {
			case base64.CorruptInputError:
				return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "the given value is has an invalid base64 symbol at offset %d", int(err))
			default:
				return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "invalid source string: %w", err)
			}

		}

		decoder := encoding.NewDecoder()
		decoded, err := decoder.Bytes(sDec)
		if err != nil || bytes.ContainsRune(decoded, '�') {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "the given string contains symbols that are not defined for %s", encName)
		}

		return cty.StringVal(string(decoded)), nil
	},
})

TextDecodeBase64Func constructs a function that decodes a base64 sequence to a target encoding.

View Source
var TextEncodeBase64Func = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "string",
			Type: cty.String,
		},
		{
			Name: "encoding",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		encoding, err := ianaindex.IANA.Encoding(args[1].AsString())
		if err != nil || encoding == nil {
			return cty.UnknownVal(cty.String), function.NewArgErrorf(1, "%q is not a supported IANA encoding name or alias in this OpenTofu version", args[1].AsString())
		}

		encName, err := ianaindex.IANA.Name(encoding)
		if err != nil {
			encName = args[1].AsString()
		}

		encoder := encoding.NewEncoder()
		encodedInput, err := encoder.Bytes([]byte(args[0].AsString()))
		if err != nil {

			return cty.UnknownVal(cty.String), function.NewArgErrorf(0, "the given string contains characters that cannot be represented in %s", encName)
		}

		return cty.StringVal(base64.StdEncoding.EncodeToString(encodedInput)), nil
	},
})

TextEncodeBase64Func constructs a function that encodes a string to a target encoding and then to a base64 sequence.

View Source
var TimeAddFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "timestamp",
			Type: cty.String,
		},
		{
			Name: "duration",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		ts, err := parseTimestamp(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		duration, err := time.ParseDuration(args[1].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}

		return cty.StringVal(ts.Add(duration).Format(time.RFC3339)), nil
	},
})

TimeAddFunc constructs a function that adds a duration to a timestamp, returning a new timestamp.

View Source
var TimeCmpFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "timestamp_a",
			Type: cty.String,
		},
		{
			Name: "timestamp_b",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		tsA, err := parseTimestamp(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), function.NewArgError(0, err)
		}
		tsB, err := parseTimestamp(args[1].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), function.NewArgError(1, err)
		}

		switch {
		case tsA.Equal(tsB):
			return cty.NumberIntVal(0), nil
		case tsA.Before(tsB):
			return cty.NumberIntVal(-1), nil
		default:

			return cty.NumberIntVal(1), nil
		}
	},
})

TimeCmpFunc is a function that compares two timestamps.

View Source
var TimestampFunc = function.New(&function.Spec{
	Params:       []function.Parameter{},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.StringVal(time.Now().UTC().Format(time.RFC3339)), nil
	},
})

TimestampFunc constructs a function that returns a string representation of the current date and time.

View Source
var TransposeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "values",
			Type: cty.Map(cty.List(cty.String)),
		},
	},
	Type:         function.StaticReturnType(cty.Map(cty.List(cty.String))),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		inputMap := args[0]
		if !inputMap.IsWhollyKnown() {
			return cty.UnknownVal(retType), nil
		}

		outputMap := make(map[string]cty.Value)
		tmpMap := make(map[string][]string)

		for it := inputMap.ElementIterator(); it.Next(); {
			inKey, inVal := it.Element()
			for iter := inVal.ElementIterator(); iter.Next(); {
				_, val := iter.Element()
				if !val.Type().Equals(cty.String) {
					return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must be a map of lists of strings")
				}

				outKey := val.AsString()
				if _, ok := tmpMap[outKey]; !ok {
					tmpMap[outKey] = make([]string, 0)
				}
				outVal := tmpMap[outKey]
				outVal = append(outVal, inKey.AsString())
				sort.Strings(outVal)
				tmpMap[outKey] = outVal
			}
		}

		for outKey, outVal := range tmpMap {
			values := make([]cty.Value, 0)
			for _, v := range outVal {
				values = append(values, cty.StringVal(v))
			}
			outputMap[outKey] = cty.ListVal(values)
		}

		if len(outputMap) == 0 {
			return cty.MapValEmpty(cty.List(cty.String)), nil
		}

		return cty.MapVal(outputMap), nil
	},
})

TransposeFunc constructs a function that takes a map of lists of strings and swaps the keys and values to produce a new map of lists of strings.

View Source
var TypeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name:             "value",
			Type:             cty.DynamicPseudoType,
			AllowDynamicType: true,
			AllowUnknown:     true,
			AllowNull:        true,
		},
	},
	Type: function.StaticReturnType(types.TypeType),
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		givenType := args[0].Type()
		return cty.CapsuleVal(types.TypeType, &givenType).Mark(marks.TypeType), nil
	},
})

TypeFunc returns an encapsulated value containing its argument's type. This value is marked to allow us to limit the use of this function at the moment to only a few supported use cases.

View Source
var URLDecodeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		query, err := url.QueryUnescape(args[0].AsString())
		if err != nil {
			return cty.UnknownVal(cty.String), fmt.Errorf("failed to decode URL '%s': %v", query, err)
		}

		return cty.StringVal(query), nil
	},
})

URLDecodeFunc constructs a function that applies URL decoding to a given encoded string.

View Source
var URLEncodeFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "str",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
		return cty.StringVal(url.QueryEscape(args[0].AsString())), nil
	},
})

URLEncodeFunc constructs a function that applies URL encoding to a given string.

View Source
var UUIDFunc = function.New(&function.Spec{
	Params:       []function.Parameter{},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		result, err := uuid.GenerateUUID()
		if err != nil {
			return cty.UnknownVal(cty.String), err
		}
		return cty.StringVal(result), nil
	},
})
View Source
var UUIDV5Func = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "namespace",
			Type: cty.String,
		},
		{
			Name: "name",
			Type: cty.String,
		},
	},
	Type:         function.StaticReturnType(cty.String),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		var namespace uuidv5.UUID
		switch {
		case args[0].AsString() == "dns":
			namespace = uuidv5.NameSpaceDNS
		case args[0].AsString() == "url":
			namespace = uuidv5.NameSpaceURL
		case args[0].AsString() == "oid":
			namespace = uuidv5.NameSpaceOID
		case args[0].AsString() == "x500":
			namespace = uuidv5.NameSpaceX500
		default:
			if namespace, err = uuidv5.Parse(args[0].AsString()); err != nil {
				return cty.UnknownVal(cty.String), fmt.Errorf("uuidv5() doesn't support namespace %s (%w)", args[0].AsString(), err)
			}
		}
		val := args[1].AsString()
		return cty.StringVal(uuidv5.NewSHA1(namespace, []byte(val)).String()), nil
	},
})

Functions

func AllTrue

func AllTrue(collection cty.Value) (cty.Value, error)

AllTrue returns true if all elements of the list are true. If the list is empty, return true.

func AnyTrue

func AnyTrue(collection cty.Value) (cty.Value, error)

AnyTrue returns true if any element of the list is true. If the list is empty, return false.

func Base64Decode

func Base64Decode(str cty.Value) (cty.Value, error)

Base64Decode decodes a string containing a base64 sequence.

OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

Strings in the OpenTofu language are sequences of unicode characters rather than bytes, so this function will also interpret the resulting bytes as UTF-8. If the bytes after Base64 decoding are _not_ valid UTF-8, this function produces an error.

func Base64Encode

func Base64Encode(str cty.Value) (cty.Value, error)

Base64Encode applies Base64 encoding to a string.

OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

Strings in the OpenTofu language are sequences of unicode characters rather than bytes, so this function will first encode the characters from the string as UTF-8, and then apply Base64 encoding to the result.

func Base64Gunzip

func Base64Gunzip(str cty.Value) (cty.Value, error)

Base64Gunzip decodes a Base64-encoded string and uncompresses the result with gzip.

Opentofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

func Base64Gzip

func Base64Gzip(str cty.Value) (cty.Value, error)

Base64Gzip compresses a string with gzip and then encodes the result in Base64 encoding.

OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

Strings in the OpenTofu language are sequences of unicode characters rather than bytes, so this function will first encode the characters from the string as UTF-8, then apply gzip compression, and then finally apply Base64 encoding.

func Base64Sha256

func Base64Sha256(str cty.Value) (cty.Value, error)

Base64Sha256 computes the SHA256 hash of a given string and encodes it with Base64.

The given string is first encoded as UTF-8 and then the SHA256 algorithm is applied as defined in RFC 4634. The raw hash is then encoded with Base64 before returning. OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

func Base64Sha512

func Base64Sha512(str cty.Value) (cty.Value, error)

Base64Sha512 computes the SHA512 hash of a given string and encodes it with Base64.

The given string is first encoded as UTF-8 and then the SHA256 algorithm is applied as defined in RFC 4634. The raw hash is then encoded with Base64 before returning. OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4

func Basename

func Basename(path cty.Value) (cty.Value, error)

Basename takes a string containing a filesystem path and removes all except the last portion from it.

The underlying function implementation works only with the path string and does not access the filesystem itself. It is therefore unable to take into account filesystem features such as symlinks.

If the path is empty then the result is ".", representing the current working directory.

func Bcrypt

func Bcrypt(str cty.Value, cost ...cty.Value) (cty.Value, error)

Bcrypt computes a hash of the given string using the Blowfish cipher, returning a string in the Modular Crypt Format usually expected in the shadow password file on many Unix systems.

func CidrContains

func CidrContains(prefix, address cty.Value) (cty.Value, error)

CidrContains checks whether a given IP address is within a given IP network address prefix.

func CidrHost

func CidrHost(prefix, hostnum cty.Value) (cty.Value, error)

CidrHost calculates a full host IP address within a given IP network address prefix.

func CidrNetmask

func CidrNetmask(prefix cty.Value) (cty.Value, error)

CidrNetmask converts an IPv4 address prefix given in CIDR notation into a subnet mask address.

func CidrSubnet

func CidrSubnet(prefix, newbits, netnum cty.Value) (cty.Value, error)

CidrSubnet calculates a subnet address within a given IP network address prefix.

func CidrSubnets

func CidrSubnets(prefix cty.Value, newbits ...cty.Value) (cty.Value, error)

CidrSubnets calculates a sequence of consecutive subnet prefixes that may be of different prefix lengths under a common base prefix.

func Coalesce

func Coalesce(args ...cty.Value) (cty.Value, error)

Coalesce takes any number of arguments and returns the first one that isn't empty.

func Dirname

func Dirname(path cty.Value) (cty.Value, error)

Dirname takes a string containing a filesystem path and removes the last portion from it.

The underlying function implementation works only with the path string and does not access the filesystem itself. It is therefore unable to take into account filesystem features such as symlinks.

If the path is empty then the result is ".", representing the current working directory.

func File

func File(baseDir string, path cty.Value) (cty.Value, error)

File reads the contents of the file at the given path.

The file must contain valid UTF-8 bytes, or this function will return an error.

The underlying function implementation works relative to a particular base directory, so this wrapper takes a base directory string and uses it to construct the underlying function before calling it.

func FileBase64

func FileBase64(baseDir string, path cty.Value) (cty.Value, error)

FileBase64 reads the contents of the file at the given path.

The bytes from the file are encoded as base64 before returning.

The underlying function implementation works relative to a particular base directory, so this wrapper takes a base directory string and uses it to construct the underlying function before calling it.

func FileExists

func FileExists(baseDir string, path cty.Value) (cty.Value, error)

FileExists determines whether a file exists at the given path.

The underlying function implementation works relative to a particular base directory, so this wrapper takes a base directory string and uses it to construct the underlying function before calling it.

func FileSet

func FileSet(baseDir string, path, pattern cty.Value) (cty.Value, error)

FileSet enumerates a set of files given a glob pattern

The underlying function implementation works relative to a particular base directory, so this wrapper takes a base directory string and uses it to construct the underlying function before calling it.

func Index

func Index(list, value cty.Value) (cty.Value, error)

Index finds the element index for a given value in a list.

func IsSensitive

func IsSensitive(v cty.Value) (cty.Value, error)

func Length

func Length(collection cty.Value) (cty.Value, error)

Length returns the number of elements in the given collection or number of Unicode characters in the given string.

func List

func List(args ...cty.Value) (cty.Value, error)

List takes any number of arguments of types that can unify into a single type and returns a list containing those values in the same order, or returns an error if there is no single element type that all values can convert to.

func Log

func Log(num, base cty.Value) (cty.Value, error)

Log returns returns the logarithm of a given number in a given base.

func Lookup

func Lookup(args ...cty.Value) (cty.Value, error)

Lookup performs a dynamic lookup into a map. There are two required arguments, map and key, plus an optional default, which is a value to return if no key is found in map.

func MakeFileBase64Sha256Func

func MakeFileBase64Sha256Func(baseDir string) function.Function

MakeFileBase64Sha256Func constructs a function that is like Base64Sha256Func but reads the contents of a file rather than hashing a given literal string.

func MakeFileBase64Sha512Func

func MakeFileBase64Sha512Func(baseDir string) function.Function

MakeFileBase64Sha512Func constructs a function that is like Base64Sha512Func but reads the contents of a file rather than hashing a given literal string.

func MakeFileExistsFunc

func MakeFileExistsFunc(baseDir string) function.Function

MakeFileExistsFunc constructs a function that takes a path and determines whether a file exists at that path

func MakeFileFunc

func MakeFileFunc(baseDir string, encBase64 bool) function.Function

MakeFileFunc constructs a function that takes a file path and returns the contents of that file, either directly as a string (where valid UTF-8 is required) or as a string containing base64 bytes.

func MakeFileMd5Func

func MakeFileMd5Func(baseDir string) function.Function

MakeFileMd5Func constructs a function that is like Md5Func but reads the contents of a file rather than hashing a given literal string.

func MakeFileSetFunc

func MakeFileSetFunc(baseDir string) function.Function

MakeFileSetFunc constructs a function that takes a glob pattern and enumerates a file set from that pattern

func MakeFileSha1Func

func MakeFileSha1Func(baseDir string) function.Function

MakeFileSha1Func constructs a function that is like Sha1Func but reads the contents of a file rather than hashing a given literal string.

func MakeFileSha256Func

func MakeFileSha256Func(baseDir string) function.Function

MakeFileSha256Func constructs a function that is like Sha256Func but reads the contents of a file rather than hashing a given literal string.

func MakeFileSha512Func

func MakeFileSha512Func(baseDir string) function.Function

MakeFileSha512Func constructs a function that is like Sha512Func but reads the contents of a file rather than hashing a given literal string.

func MakeStaticTimestampFunc

func MakeStaticTimestampFunc(static time.Time) function.Function

MakeStaticTimestampFunc constructs a function that returns a string representation of the date and time specified by the provided argument.

func MakeTemplateFileFunc

func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Function) function.Function

MakeTemplateFileFunc constructs a function that takes a file path and an arbitrary object of named values and attempts to render the referenced file as a template using HCL template syntax.

The template itself may recursively call other functions so a callback must be provided to get access to those functions. The template cannot, however, access any variables defined in the scope: it is restricted only to those variables provided in the second function argument, to ensure that all dependencies on other graph nodes can be seen before executing this function.

As a special exception, a referenced template file may call the templatefile function, with a recursion depth limit providing an error when reached

func MakeTemplateStringFunc

func MakeTemplateStringFunc(content string, funcsCb func() map[string]function.Function) function.Function

MakeTemplateStringFunc constructs a function that takes a string and an arbitrary object of named values and attempts to render that string as a template using HCL template syntax.

func MakeToFunc

func MakeToFunc(wantTy cty.Type) function.Function

MakeToFunc constructs a "to..." function, like "tostring", which converts its argument to a specific type or type kind.

The given type wantTy can be any type constraint that cty's "convert" package would accept. In particular, this means that you can pass cty.List(cty.DynamicPseudoType) to mean "list of any single type", which will then cause cty to attempt to unify all of the element types when given a tuple.

func Map

func Map(args ...cty.Value) (cty.Value, error)

Map takes an even number of arguments and returns a map whose elements are constructed from consecutive pairs of arguments.

func Matchkeys

func Matchkeys(values, keys, searchset cty.Value) (cty.Value, error)

Matchkeys constructs a new list by taking a subset of elements from one list whose indexes match the corresponding indexes of values in another list.

func Md5

func Md5(str cty.Value) (cty.Value, error)

Md5 computes the MD5 hash of a given string and encodes it with hexadecimal digits.

func Nonsensitive

func Nonsensitive(v cty.Value) (cty.Value, error)

func One

func One(list cty.Value) (cty.Value, error)

One returns either the first element of a one-element list, or null if given a zero-element list..

func ParseInt

func ParseInt(num cty.Value, base cty.Value) (cty.Value, error)

ParseInt parses a string argument and returns an integer of the specified base.

func Pathexpand

func Pathexpand(path cty.Value) (cty.Value, error)

Pathexpand takes a string that might begin with a `~` segment, and if so it replaces that segment with the current user's home directory path.

The underlying function implementation works only with the path string and does not access the filesystem itself. It is therefore unable to take into account filesystem features such as symlinks.

If the leading segment in the path is not `~` then the given path is returned unmodified.

func Pow

func Pow(num, power cty.Value) (cty.Value, error)

Pow returns the logarithm of a given number in a given base.

func Replace

func Replace(str, substr, replace cty.Value) (cty.Value, error)

Replace searches a given string for another given substring, and replaces all occurences with a given replacement string.

func RsaDecrypt

func RsaDecrypt(ciphertext, privatekey cty.Value) (cty.Value, error)

RsaDecrypt decrypts an RSA-encrypted ciphertext, returning the corresponding cleartext.

func Sensitive

func Sensitive(v cty.Value) (cty.Value, error)

func Sha1

func Sha1(str cty.Value) (cty.Value, error)

Sha1 computes the SHA1 hash of a given string and encodes it with hexadecimal digits.

func Sha256

func Sha256(str cty.Value) (cty.Value, error)

Sha256 computes the SHA256 hash of a given string and encodes it with hexadecimal digits.

func Sha512

func Sha512(str cty.Value) (cty.Value, error)

Sha512 computes the SHA512 hash of a given string and encodes it with hexadecimal digits.

func Signum

func Signum(num cty.Value) (cty.Value, error)

Signum determines the sign of a number, returning a number between -1 and 1 to represent the sign.

func StrContains

func StrContains(str, substr cty.Value) (cty.Value, error)

func Sum

func Sum(list cty.Value) (cty.Value, error)

Sum adds numbers in a list, set, or tuple

func TextDecodeBase64

func TextDecodeBase64(str, enc cty.Value) (cty.Value, error)

TextDecodeBase64 decodes a string containing a base64 sequence whereas a specific encoding of the string is expected.

OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

Strings in the OpenTofu language are sequences of unicode characters rather than bytes, so this function will also interpret the resulting bytes as the target encoding.

func TextEncodeBase64

func TextEncodeBase64(str, enc cty.Value) (cty.Value, error)

TextEncodeBase64 applies Base64 encoding to a string that was encoded before with a target encoding.

OpenTofu uses the "standard" Base64 alphabet as defined in RFC 4648 section 4.

First step is to apply the target IANA encoding (e.g. UTF-16LE). Strings in the OpenTofu language are sequences of unicode characters rather than bytes, so this function will first encode the characters from the string as UTF-8, and then apply Base64 encoding to the result.

func TimeAdd

func TimeAdd(timestamp cty.Value, duration cty.Value) (cty.Value, error)

TimeAdd adds a duration to a timestamp, returning a new timestamp.

In the OpenTofu language, timestamps are conventionally represented as strings using RFC 3339 "Date and Time format" syntax. Timeadd requires the timestamp argument to be a string conforming to this syntax.

`duration` is a string representation of a time difference, consisting of sequences of number and unit pairs, like `"1.5h"` or `1h30m`. The accepted units are `ns`, `us` (or `µs`), `"ms"`, `"s"`, `"m"`, and `"h"`. The first number may be negative to indicate a negative duration, like `"-2h5m"`.

The result is a string, also in RFC 3339 format, representing the result of adding the given direction to the given timestamp.

func TimeCmp

func TimeCmp(timestampA, timestampB cty.Value) (cty.Value, error)

TimeCmp compares two timestamps, indicating whether they are equal or if one is before the other.

TimeCmp considers the UTC offset of each given timestamp when making its decision, so for example 6:00 +0200 and 4:00 UTC are equal.

In the OpenTofu language, timestamps are conventionally represented as strings using RFC 3339 "Date and Time format" syntax. TimeCmp requires the timestamp argument to be a string conforming to this syntax.

The result is always a number between -1 and 1. -1 indicates that timestampA is earlier than timestampB. 1 indicates that timestampA is later. 0 indicates that the two timestamps represent the same instant.

func Timestamp

func Timestamp() (cty.Value, error)

Timestamp returns a string representation of the current date and time.

In the OpenTofu language, timestamps are conventionally represented as strings using RFC 3339 "Date and Time format" syntax, and so timestamp returns a string in this format.

func Transpose

func Transpose(values cty.Value) (cty.Value, error)

Transpose takes a map of lists of strings and swaps the keys and values to produce a new map of lists of strings.

func Type

func Type(input []cty.Value) (cty.Value, error)

func URLDecode

func URLDecode(str cty.Value) (cty.Value, error)

URLDecode decodes a URL encoded string.

This function decodes the given string that has been encoded.

If the given string contains non-ASCII characters, these are first encoded as UTF-8 and then percent decoding is applied separately to each UTF-8 byte.

func URLEncode

func URLEncode(str cty.Value) (cty.Value, error)

URLEncode applies URL encoding to a given string.

This function identifies characters in the given string that would have a special meaning when included as a query string argument in a URL and escapes them using RFC 3986 "percent encoding".

If the given string contains non-ASCII characters, these are first encoded as UTF-8 and then percent encoding is applied separately to each UTF-8 byte.

func UUID

func UUID() (cty.Value, error)

UUID generates and returns a Type-4 UUID in the standard hexadecimal string format.

This is not a pure function: it will generate a different result for each call. It must therefore be registered as an impure function in the function table in the "lang" package.

func UUIDV5

func UUIDV5(namespace cty.Value, name cty.Value) (cty.Value, error)

UUIDV5 generates and returns a Type-5 UUID in the standard hexadecimal string format.

func WithDescription

func WithDescription(name string, f function.Function) function.Function

WithDescription looks up the description for a given function and uses go-cty's WithNewDescriptions to replace the function's description and parameter descriptions.

Types

type ErrorTemplateRecursionLimit

type ErrorTemplateRecursionLimit struct {
	// contains filtered or unexported fields
}

func (ErrorTemplateRecursionLimit) Error

func (err ErrorTemplateRecursionLimit) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL