Skip to content

Commit

Permalink
feat(intrinsics): add intrinsics ptr versions
Browse files Browse the repository at this point in the history
  • Loading branch information
xrn authored and rubenfonseca committed Jul 12, 2022
1 parent c55d1d3 commit ffdc5af
Showing 1 changed file with 73 additions and 1 deletion.
74 changes: 73 additions & 1 deletion cloudformation/intrinsics.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,26 +126,46 @@ func Ref(logicalName interface{}) string {
return encode(fmt.Sprintf(`{ "Ref": %q }`, logicalName))
}

func RefPtr(logicalName interface{}) *string {
return String(Ref(logicalName))
}

// ImportValue returns the value of an output exported by another stack. You typically use this function to create cross-stack references. In the following example template snippets, Stack A exports VPC security group values and Stack B imports them.
func ImportValue(name interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::ImportValue": %q }`, name))
}

func ImportValuePtr(name interface{}) *string {
return String(ImportValue(name))
}

// Base64 returns the Base64 representation of the input string. This function is typically used to pass encoded data to Amazon EC2 instances by way of the UserData property
func Base64(input interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::Base64": %q }`, input))
}

func Base64Ptr(input interface{}) *string {
return String(Base64(input))
}

// GetAZs returns an array that lists Availability Zones for a specified region. Because customers have access to different Availability Zones, the intrinsic function Fn::GetAZs enables template authors to write templates that adapt to the calling user's access. That way you don't have to hard-code a full list of Availability Zones for a specified region.
func GetAZs(region interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::GetAZs": %q }`, region))
}

func GetAZsPtr(region interface{}) *string {
return String(GetAZs(region))
}

// Sub substitutes variables in an input string with values that you specify. In your templates, you can use this function to construct commands or outputs that include values that aren't available until you create or update a stack.
func Sub(value interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::Sub" : %q }`, value))
}

func SubPtr(value interface{}) *string {
return String(Sub(value))
}

// SubVars works like Sub(), except it accepts a map of variable values to replace
func SubVars(value interface{}, variables map[string]interface{}) string {
pairs := make([]string, 0, len(variables))
Expand All @@ -156,16 +176,28 @@ func SubVars(value interface{}, variables map[string]interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::Sub" : [ %q, { %s } ] }`, value, strings.Join(pairs, ",")))
}

func SubVarsPtr(value interface{}, variables map[string]interface{}) *string {
return String(SubVars(value, variables))
}

// (str, str) -> str

// GetAtt returns the value of an attribute from a resource in the template.
func GetAtt(logicalName string, attribute string) string {
return encode(fmt.Sprintf(`{ "Fn::GetAtt" : [ %q, %q ] }`, logicalName, attribute))
}

func GetAttPtr(logicalName string, attribute string) *string {
return String(GetAtt(logicalName, attribute))
}

// Split splits a string into a list of string values so that you can select an element from the resulting string list, use the Fn::Split intrinsic function. Specify the location of splits with a delimiter, such as , (a comma). After you split a string, use the Fn::Select function to pick a specific element.
func Split(delimiter, source interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::Split" : [ %q, %q ] }`, delimiter, source))
return fmt.Sprintf(`{ "Fn::Split" : [ %q, %q ] }`, delimiter, source)
}

func SplitPtr(delimiter, source interface{}) *[]string {
return Strings(Split(delimiter, source))
}

// Equals compares if two values are equal. Returns true if the two values are equal or false if they aren't.
Expand All @@ -178,18 +210,30 @@ func Equals(value1, value2 interface{}) string {
}
}

func EqualsPtr(value1, value2 interface{}) *string {
return String(Equals(value1, value2))
}

// (str, str, str) -> str

// CIDR returns an array of CIDR address blocks. The number of CIDR blocks returned is dependent on the count parameter.
func CIDR(ipBlock, count, cidrBits interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::Cidr" : [ %q, %q, %q ] }`, ipBlock, count, cidrBits))
}

func CIDRPtr(ipBlock, count, cidrBits interface{}) *string {
return String(CIDR(ipBlock, count, cidrBits))
}

// FindInMap returns the value corresponding to keys in a two-level map that is declared in the Mappings section.
func FindInMap(mapName, topLevelKey, secondLevelKey interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::FindInMap" : [ %q, %q, %q ] }`, mapName, topLevelKey, secondLevelKey))
}

func FindInMapPtr(mapName, topLevelKey, secondLevelKey interface{}) *string {
return String(FindInMap(mapName, topLevelKey, secondLevelKey))
}

// If returns one value if the specified condition evaluates to true and another value if the specified condition evaluates to false. Currently, AWS CloudFormation supports the Fn::If intrinsic function in the metadata attribute, update policy attribute, and property values in the Resources section and Outputs sections of a template. You can use the AWS::NoValue pseudo parameter as a return value to remove the corresponding property.
func If(value, ifEqual interface{}, ifNotEqual interface{}) string {
var equal string
Expand Down Expand Up @@ -232,6 +276,10 @@ func If(value, ifEqual interface{}, ifNotEqual interface{}) string {
return encode(fmt.Sprintf(`{ "Fn::If" : [ %q, %v, %v ] }`, value, equal, notEqual))
}

func IfPtr(value, ifEqual interface{}, ifNotEqual interface{}) *string {
return String(If(value, ifEqual, ifNotEqual))
}

// (str, []str) -> str

// Join appends a set of values into a single value, separated by the specified delimiter. If a delimiter is the empty string, the set of values are concatenated with no delimiter.
Expand All @@ -249,6 +297,10 @@ func Join(delimiter interface{}, value interface{}) string {
}
}

func JoinPtr(delimiter interface{}, value interface{}) *string {
return String(Join(delimiter, value))
}

// Select returns a single object from a list of objects by index.
func Select(index interface{}, list []string) string {
if len(list) == 1 {
Expand All @@ -257,23 +309,39 @@ func Select(index interface{}, list []string) string {
return encode(fmt.Sprintf(`{ "Fn::Select": [ %q, [ %v ] ] }`, index, printList(list)))
}

func SelectPtr(index interface{}, list []string) *string {
return String(Select(index, list))
}

// ([]str) -> str

// And returns true if all the specified conditions evaluate to true, or returns false if any one of the conditions evaluates to false. Fn::And acts as an AND operator. The minimum number of conditions that you can include is 2, and the maximum is 10.
func And(conditions []string) string {
return encode(fmt.Sprintf(`{ "Fn::And": [ %v ] }`, printList(conditions)))
}

func AndPtr(conditions []string) *string {
return String(And(conditions))
}

// Not returns true for a condition that evaluates to false or returns false for a condition that evaluates to true. Fn::Not acts as a NOT operator.
func Not(conditions []string) string {
return encode(fmt.Sprintf(`{ "Fn::Not": [ %v ] }`, printList(conditions)))
}

func NotPtr(conditions []string) *string {
return String(Not(conditions))
}

// Or returns true if any one of the specified conditions evaluate to true, or returns false if all of the conditions evaluates to false. Fn::Or acts as an OR operator. The minimum number of conditions that you can include is 2, and the maximum is 10.
func Or(conditions []string) string {
return encode(fmt.Sprintf(`{ "Fn::Or": [ %v ] }`, printList(conditions)))
}

func OrPtr(conditions []string) *string {
return String(Or(conditions))
}

// (str, map[str]str) -> str

func TransformFn(name string, parameters map[string]string) string {
Expand All @@ -285,6 +353,10 @@ func TransformFn(name string, parameters map[string]string) string {
return encode(fmt.Sprintf(`{ "Fn::Transform" : { "Name" : "%v", "Parameters" : { "%v" } } }`, name, strings.Trim(strings.Join(params, `, `), `, "`)))
}

func TransformFnPtr(name string, parameters map[string]string) *string {
return String(TransformFn(name, parameters))
}

// encode takes a string representation of an intrinsic function, and base64 encodes it.
// This prevents the escaping issues when nesting multiple layers of intrinsic functions.
func encode(value string) string {
Expand Down

0 comments on commit ffdc5af

Please sign in to comment.