rostran/providers/ros/functions.py (80 lines of code) (raw):

from typing import TYPE_CHECKING, Any from rostran.providers.terraform import template_blocks as tf from tools.utils import camel_to_snake if TYPE_CHECKING: from rostran.providers.ros.template import ROS2TerraformTemplate def ref(ros2tf: "ROS2TerraformTemplate", args: str): if args.startswith("ALIYUN::") and args in ALL_FUNCTIONS: return ALL_FUNCTIONS[args](ros2tf, args) tf_value = ros2tf.get_tf_params(camel_to_snake(args)) if args in ros2tf.parameters: return tf.LiteralType(f"var.{tf_value}") elif args in ros2tf.resources: resource = ros2tf.resources[args] resource_rule = ros2tf.get_resource_rule(resource.get("Type")) tf_res_type = resource_rule.target_resource_type if args in ros2tf.resources_with_count: tf_item = f"{tf_res_type}.{tf_value}[*].id" return tf.LiteralType(f"length({tf_item}) > 0 ? {tf_item} : {tf.NullType()}") return tf.LiteralType(f'{tf_res_type}.{tf_value}.id') raise ValueError(f"Ref - {args} is not a valid Resource or Parameter.") def get_att(ros2tf: "ROS2TerraformTemplate", args: list): res_name, att_name = args tf_res_name = camel_to_snake(res_name) resource = ros2tf.resources[res_name] resource_rule = ros2tf.get_resource_rule(resource.get("Type")) msg = f"Could not transform ROS Attribute {att_name} to Terraform attribute." if not resource_rule: return tf.CommentType(msg) tf_res_type = resource_rule.target_resource_type rule_attr = resource_rule.attributes if not rule_attr: return tf.CommentType(msg) tf_attr = rule_attr.get(att_name, {}).get('To') if not tf_attr: return tf.CommentType(msg) if res_name in ros2tf.resources_with_count: tf_item = f"{tf_res_type}.{tf_res_name}[*].{tf_attr}" return tf.LiteralType(f"length({tf_item}) > 0 ? {tf_item} : {tf.NullType()}") return tf.LiteralType(f'{tf_res_type}.{tf_res_name}.{tf_attr}') def equals(_, args: list): tf_args = [item if isinstance(item, tf.TerraformType) else tf.convert_to_tf_type(item) for item in args] return tf.LiteralType(f"{tf_args[0]} == {tf_args[1]}") def and_(_, args: list): tf_args = [item if isinstance(item, tf.TerraformType) else tf.convert_to_tf_type(item) for item in args] return tf.LiteralType(f"alltrue({tf_args})") def or_(_, args: list): tf_args = [item if isinstance(item, tf.TerraformType) else tf.convert_to_tf_type(item) for item in args] return tf.LiteralType(f"anytrue({tf_args})") def if_(_, args: list): tf_args = [item if isinstance(item, tf.TerraformType) else tf.convert_to_tf_type(item) for item in args[1:]] return tf.LiteralType(f"local.{args[0]} ? {tf_args[0]} : {tf_args[1]}") def not_(_, args: str): if not isinstance(args, tf.TerraformType): args = tf.convert_to_tf_type(args) return tf.LiteralType(f"!{args}") def index_(_, __): return tf.LiteralType(f"count.index") def handle_tags(ros2tf: "ROS2TerraformTemplate", args: Any, tag_key="Key", tag_value="Value"): if isinstance(args, list): result = {} for tag in args: if not isinstance(tag, dict): continue key = tag.get(tag_key) if not key: continue value = tag.get(tag_value) result[key] = ros2tf.resolve_values(value) return tf.JsonType(result) return ros2tf.resolve_values(args) ALL_FUNCTIONS = { "Ref": ref, "Fn::GetAtt": get_att, "Fn::Equals": equals, "Fn::And": and_, "Fn::Or": or_, "Fn::If": if_, "Fn::Not": not_, "ALIYUN::Index": index_ }