ValueError: Fn::Sub not allowed to be nested in Fn::Equals.
cl33n opened this issue · comments
colleen deremiah commented
Template is from the AWS X-Ray sample app (cf-resources.yaml, converted to txt, attached.)
cf-resources.txt
Python 3.12.2
cf2tf version 0.6.2 output:
out.txt
Levi commented
This has been fixed in release v0.7.0. You can upgrade with pip install -U cf2tf
Here is your converted template:
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
locals {
UseT2MicroInstance = anytrue([anytrue(["${data.aws_region.current.name}" == "us-east-1", "${data.aws_region.current.name}" == "us-east-2", "${data.aws_region.current.name}" == "us-west-1", "${data.aws_region.current.name}" == "us-west-2", "${data.aws_region.current.name}" == "ap-south-1", "${data.aws_region.current.name}" == "ap-northeast-3", "${data.aws_region.current.name}" == "ap-northeast-2", "${data.aws_region.current.name}" == "ap-southeast-1", "${data.aws_region.current.name}" == "ap-southeast-2", "${data.aws_region.current.name}" == "ap-northeast-1"]), anytrue(["${data.aws_region.current.name}" == "ca-central-1", "${data.aws_region.current.name}" == "eu-central-1", "${data.aws_region.current.name}" == "eu-west-1", "${data.aws_region.current.name}" == "eu-west-2", "${data.aws_region.current.name}" == "eu-west-3", "${data.aws_region.current.name}" == "sa-east-1", "${data.aws_region.current.name}" == "cn-northwest-1"])])
CreateEC2LCWithKeyPair = !var.key_name == ""
SetEndpointToECSAgent = !var.ecs_endpoint == ""
CreateNewSecurityGroup = var.security_group_id == ""
CreateNewVpc = var.vpc_id == ""
CreateSubnet1 = alltrue([
!var.subnet_cidr1 == "",
local.CreateNewVpc
])
CreateSubnet2 = alltrue([
!var.subnet_cidr2 == "",
local.CreateSubnet1
])
CreateSubnet3 = alltrue([
!var.subnet_cidr3 == "",
local.CreateSubnet2
])
CreateWithSpot = var.use_spot == "true"
CreateWithASG = !local.CreateWithSpot
CreateWithSpotPrice = !var.spot_price == ""
IsConfiguringRootVolume = var.configure_root_volume == "true"
IsConfiguringDataVolume = var.configure_data_volume == "true"
IsInheritPublicIp = var.auto_assign_public_ip == "INHERIT"
stack_name = "cf-resources"
}
variable email {
type = string
default = "UPDATE_ME"
}
variable frontend_image_uri {
type = string
default = "public.ecr.aws/xray/scorekeep-frontend:latest"
}
variable backend_image_uri {
type = string
default = "public.ecr.aws/xray/scorekeep-api:latest"
}
variable ecs_cluster_name {
description = "Specifies the ECS Cluster Name with which the resources would be associated
"
type = string
default = "scorekeep-cluster"
}
variable ecs_ami_id {
description = "AMI ID"
type = string
default = "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id"
}
variable ecs_instance_type_t2 {
description = "Specifies the EC2 instance type for your container instances. Defaults to t2.micro.
"
type = string
default = "t2.micro"
}
variable ecs_instance_type_t3 {
description = "Specifies the EC2 instance type for your container instances. Defaults to t3.micro.
"
type = string
default = "t3.micro"
}
variable key_name {
description = "Optional - Specifies the name of an existing Amazon EC2 key pair to enable SSH access to the EC2 instances in your cluster.
"
type = string
}
variable vpc_id {
description = "Optional - Specifies the ID of an existing VPC in which to launch your container instances. If you specify a VPC ID, you must specify a list of existing subnets in that VPC. If you do not specify a VPC ID, a new VPC is created with atleast 1 subnet.
"
type = string
}
variable subnet_ids {
description = "Optional - Specifies the Comma separated list of existing VPC Subnet Ids where ECS instances will run
"
type = string
}
variable security_group_id {
description = "Optional - Specifies the Security Group Id of an existing Security Group. Leave blank to have a new Security Group created
"
type = string
}
variable vpc_cidr {
description = "Optional - Specifies the CIDR Block of VPC"
type = string
default = "10.173.0.0/16"
}
variable subnet_cidr1 {
description = "Specifies the CIDR Block of Subnet 1"
type = string
default = "10.173.0.0/24"
}
variable subnet_cidr2 {
description = "Specifies the CIDR Block of Subnet 2"
type = string
default = "10.173.1.0/24"
}
variable subnet_cidr3 {
description = "Specifies the CIDR Block of Subnet 3"
type = string
}
variable asg_max_size {
description = "Specifies the number of instances to launch and register to the cluster. Defaults to 1.
"
type = string
default = "1"
}
variable iam_role_instance_profile {
description = "Specifies the Name or the Amazon Resource Name (ARN) of the instance profile associated with the IAM role for the instance
"
type = string
default = "ScorekeepInstanceProfile"
}
variable security_ingress_from_port {
description = "Optional - Specifies the Start of Security Group port to open on ECS instances - defaults to port 0
"
type = string
default = "80"
}
variable security_ingress_to_port {
description = "Optional - Specifies the End of Security Group port to open on ECS instances - defaults to port 65535
"
type = string
default = "80"
}
variable security_ingress_cidr_ip {
description = "Optional - Specifies the CIDR/IP range for Security Ports - defaults to 0.0.0.0/0
"
type = string
default = "0.0.0.0/0"
}
variable ecs_endpoint {
description = "Optional - Specifies the ECS Endpoint for the ECS Agent to connect to
"
type = string
}
variable root_ebs_volume_size {
description = "Optional - Specifies the Size in GBs of the root EBS volume
"
type = string
default = 30
}
variable ebs_volume_size {
description = "Optional - Specifies the Size in GBs of the data storage EBS volume used by the Docker in the AL1 ECS-optimized AMI
"
type = string
default = 22
}
variable ebs_volume_type {
description = "Optional - Specifies the Type of (Amazon EBS) volume"
type = string
default = "gp2"
}
variable root_device_name {
description = "Optional - Specifies the device mapping for the root EBS volume."
type = string
default = "/dev/xvda"
}
variable device_name {
description = "Optional - Specifies the device mapping for the EBS volume used for data storage. Only applicable to AL1."
type = string
default = "/dev/xvdcz"
}
variable use_spot {
type = string
default = "false"
}
variable iam_spot_fleet_role_arn {
type = string
}
variable spot_price {
type = string
}
variable spot_allocation_strategy {
type = string
default = "diversified"
}
variable user_data {
type = string
default = "#!/bin/bash
echo ECS_CLUSTER=scorekeep-cluster >> /etc/ecs/ecs.config;echo ECS_BACKEND_HOST= >> /etc/ecs/ecs.config;
"
}
variable is_windows {
type = string
default = "false"
}
variable configure_root_volume {
description = "Optional - Specifies if there should be customization of the root volume"
type = string
default = "true"
}
variable configure_data_volume {
description = "Optional - Specifies if there should be customization of the data volume"
type = string
default = "false"
}
variable auto_assign_public_ip {
type = string
default = "INHERIT"
}
resource "aws_ecs_task_definition" "scorekeep_task_definition" {
container_definitions = [
{
Cpu = "256"
Image = var.frontend_image_uri
MemoryReservation = "256"
Name = "scorekeep-frontend"
PortMappings = [
{
ContainerPort = "80"
}
]
},
{
Cpu = "512"
Environment = [
{
Name = "AWS_REGION"
Value = "${data.aws_region.current.name}"
},
{
Name = "NOTIFICATION_TOPIC"
Value = "arn:aws:sns:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:scorekeep-notifications"
},
{
Name = "NOTIFICATION_EMAIL"
Value = var.email
}
]
Image = var.backend_image_uri
MemoryReservation = "512"
Name = "scorekeep-api"
PortMappings = [
{
ContainerPort = "5000"
}
]
},
{
Cpu = "256"
Essential = true
Image = "amazon/aws-xray-daemon"
MemoryReservation = "128"
Name = "xray-daemon"
PortMappings = [
{
ContainerPort = "2000"
HostPort = "2000"
Protocol = "udp"
}
]
}
]
cpu = "1024"
execution_role_arn = aws_iam_role.ecs_execution_role.arn
family = "scorekeep"
memory = "900"
network_mode = "host"
requires_compatibilities = [
"EC2"
]
task_role_arn = "scorekeepRole"
}
resource "aws_dynamodb_table" "user_table" {
name = "scorekeep-user"
// CF Property(KeySchema) = {
// HashKeyElement = {
// AttributeName = "id"
// AttributeType = "S"
// }
// }
// CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
}
resource "aws_dynamodb_table" "session_table" {
name = "scorekeep-session"
// CF Property(KeySchema) = {
// HashKeyElement = {
// AttributeName = "id"
// AttributeType = "S"
// }
// }
// CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
}
resource "aws_dynamodb_table" "game_table" {
name = "scorekeep-game"
attribute = [
{
name = "id"
type = "S"
},
{
name = "session"
type = "S"
}
]
// CF Property(KeySchema) = [
// {
// AttributeName = "id"
// KeyType = "HASH"
// }
// ]
global_secondary_index = [
{
name = "session-index"
non_key_attributes = [
{
AttributeName = "session"
KeyType = "HASH"
}
]
ProvisionedThroughput = // CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
projection_type = {
ProjectionType = "ALL"
}
}
]
// CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
}
resource "aws_dynamodb_table" "move_table" {
name = "scorekeep-move"
attribute = [
{
name = "id"
type = "S"
},
{
name = "game"
type = "S"
}
]
// CF Property(KeySchema) = [
// {
// AttributeName = "id"
// KeyType = "HASH"
// }
// ]
global_secondary_index = [
{
name = "game-index"
non_key_attributes = [
{
AttributeName = "game"
KeyType = "HASH"
}
]
ProvisionedThroughput = // CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
projection_type = {
ProjectionType = "ALL"
}
}
]
// CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
}
resource "aws_dynamodb_table" "state_table" {
name = "scorekeep-state"
attribute = [
{
name = "id"
type = "S"
},
{
name = "game"
type = "S"
}
]
// CF Property(KeySchema) = [
// {
// AttributeName = "id"
// KeyType = "HASH"
// }
// ]
global_secondary_index = [
{
name = "game-index"
non_key_attributes = [
{
AttributeName = "game"
KeyType = "HASH"
}
]
ProvisionedThroughput = // CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
projection_type = {
ProjectionType = "ALL"
}
}
]
// CF Property(ProvisionedThroughput) = {
// ReadCapacityUnits = 2
// WriteCapacityUnits = 2
// }
}
resource "aws_sns_topic" "notification_topic" {
name = "scorekeep-notifications"
}
resource "aws_iam_role" "ecs_execution_role" {
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = [
"ecs-tasks.amazonaws.com"
]
}
Action = [
"sts:AssumeRole"
]
}
]
}
managed_policy_arns = [
"arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
]
name = "scorekeepExecutionRole"
}
resource "aws_iam_role" "ecs_task_role" {
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = [
"ecs-tasks.amazonaws.com"
]
}
Action = [
"sts:AssumeRole"
]
}
]
}
managed_policy_arns = [
"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",
"arn:aws:iam::aws:policy/AmazonSNSFullAccess",
"arn:aws:iam::aws:policy/AWSXrayFullAccess"
]
name = "scorekeepRole"
}
resource "aws_iam_role" "scorekeep_ecs_role" {
name = "ScorekeepECSRole"
assume_role_policy = {
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Principal = {
Service = [
"ec2.amazonaws.com"
]
}
Effect = "Allow"
}
]
}
managed_policy_arns = [
"arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
]
}
resource "aws_iam_instance_profile" "scorekeep_instance_profile" {
name = var.iam_role_instance_profile
role = [
"ScorekeepECSRole"
]
}
resource "aws_ecs_cluster" "scorekeep_ecs_cluster" {
name = var.ecs_cluster_name
}
resource "aws_vpc" "vpc" {
count = local.CreateSubnet1 ? 1 : 0
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = join("_", [local.stack_name])
}
}
resource "aws_subnet" "pub_subnet_az1" {
count = local.CreateSubnet1 ? 1 : 0
vpc_id = aws_vpc.vpc[0].arn
cidr_block = var.subnet_cidr1
availability_zone = element(data.aws_availability_zones.available.names, 0)
map_public_ip_on_launch = true
}
resource "aws_subnet" "pub_subnet_az2" {
count = local.CreateSubnet2 ? 1 : 0
vpc_id = aws_vpc.vpc[0].arn
cidr_block = var.subnet_cidr2
availability_zone = element(data.aws_availability_zones.available.names, 1)
map_public_ip_on_launch = true
}
resource "aws_subnet" "pub_subnet_az3" {
count = local.CreateSubnet3 ? 1 : 0
vpc_id = aws_vpc.vpc[0].arn
cidr_block = var.subnet_cidr3
availability_zone = element(data.aws_availability_zones.available.names, 2)
map_public_ip_on_launch = true
}
resource "aws_internet_gateway" "internet_gateway" {
count = local.CreateSubnet1 ? 1 : 0
}
resource "aws_vpn_gateway_attachment" "attach_gateway" {
count = local.CreateSubnet1 ? 1 : 0
vpc_id = aws_internet_gateway.internet_gateway[0].id
}
resource "aws_route_table" "route_via_igw" {
count = local.CreateSubnet1 ? 1 : 0
vpc_id = aws_vpc.vpc[0].arn
}
resource "aws_route" "public_route_via_igw" {
count = local.CreateSubnet1 ? 1 : 0
route_table_id = aws_route_table.route_via_igw[0].id
destination_cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.internet_gateway[0].id
}
resource "aws_route_table_association" "pub_subnet1_route_table_association" {
count = local.CreateSubnet1 ? 1 : 0
subnet_id = aws_subnet.pub_subnet_az1[0].id
route_table_id = aws_route_table.route_via_igw[0].id
}
resource "aws_route_table_association" "pub_subnet2_route_table_association" {
count = local.CreateSubnet2 ? 1 : 0
subnet_id = aws_subnet.pub_subnet_az2[0].id
route_table_id = aws_route_table.route_via_igw[0].id
}
resource "aws_route_table_association" "pub_subnet3_route_table_association" {
count = local.CreateSubnet3 ? 1 : 0
subnet_id = aws_subnet.pub_subnet_az3[0].id
route_table_id = aws_route_table.route_via_igw[0].id
}
resource "aws_security_group" "ecs_security_group" {
count = local.CreateNewSecurityGroup ? 1 : 0
description = "ECS Allowed Ports"
vpc_id = local.CreateSubnet1 ? aws_vpc.vpc[0].arn : var.vpc_id
ingress = [
{
protocol = "tcp"
from_port = "80"
to_port = "80"
cidr_blocks = "0.0.0.0/0"
}
]
}
resource "aws_launch_configuration" "ecs_instance_lc" {
count = local.CreateWithASG ? 1 : 0
image_id = var.ecs_ami_id
instance_type = element(local.UseT2MicroInstance ? var.ecs_instance_type_t2 : var.ecs_instance_type_t3, 0)
associate_public_ip_address = local.IsInheritPublicIp ? null : var.auto_assign_public_ip
iam_instance_profile = var.iam_role_instance_profile
key_name = local.CreateEC2LCWithKeyPair ? var.key_name : null
security_groups = [
local.CreateNewSecurityGroup ? aws_security_group.ecs_security_group[0].arn : var.security_group_id
]
ebs_block_device = [
// local.IsConfiguringRootVolume ? {
// DeviceName = var.root_device_name
// Ebs = {
// VolumeSize = var.root_ebs_volume_size
// VolumeType = var.ebs_volume_type
// }
// } : null,
// local.IsConfiguringRootVolume ? {
// DeviceName = var.root_device_name
// Ebs = {
// VolumeSize = var.root_ebs_volume_size
// VolumeType = var.ebs_volume_type
// }
// } : null,
// local.IsConfiguringDataVolume ? {
// DeviceName = var.device_name
// Ebs = {
// VolumeSize = var.ebs_volume_size
// VolumeType = var.ebs_volume_type
// }
// } : null,
// local.IsConfiguringDataVolume ? {
// DeviceName = var.device_name
// Ebs = {
// VolumeSize = var.ebs_volume_size
// VolumeType = var.ebs_volume_type
// }
// } : null
]
user_data = base64encode(var.user_data)
}
resource "aws_autoscalingplans_scaling_plan" "ecs_instance_asg" {
count = local.CreateWithASG ? 1 : 0
// CF Property(VPCZoneIdentifier) = local.CreateSubnet1 ? local.CreateSubnet2 ? local.CreateSubnet3 ? [
// "${aws_subnet.pub_subnet_az1[0].id}, ${aws_subnet.pub_subnet_az2[0].id}, ${aws_subnet.pub_subnet_az3[0].id}"
// ] : [
// "${aws_subnet.pub_subnet_az1[0].id}, ${aws_subnet.pub_subnet_az2[0].id}"
// ] : [
// "${aws_subnet.pub_subnet_az1[0].id}"
// ] : var.subnet_ids
name = aws_launch_configuration.ecs_instance_lc[0].id
min_capacity = "0"
max_capacity = var.asg_max_size
predictive_scaling_max_capacity_behavior = var.asg_max_size
target_tracking_configuration = [
aws_lb_target_group_attachment.scorekeep_target_group.id
]
// CF Property(tags) = {
// Name = "ECS Instance - ${local.stack_name}"
// Description = "This instance is the part of the Auto Scaling group which was created through ECS Console"
// }
}
resource "aws_ecs_service" "scorekeep_service" {
cluster = "scorekeep-cluster"
// CF Property(DeploymentConfiguration) = {
// MaximumPercent = 100
// MinimumHealthyPercent = 0
// }
desired_count = 1
launch_type = "EC2"
scheduling_strategy = "REPLICA"
name = "scorekeep-service"
task_definition = aws_ecs_task_definition.scorekeep_task_definition.arn
}
resource "aws_lb_target_group_attachment" "scorekeep_target_group" {
// CF Property(Name) = "ScorekeepTargetGroup"
// CF Property(TargetType) = "instance"
port = 80
// CF Property(Protocol) = "HTTP"
target_id = aws_vpc.vpc[0].arn
}
resource "aws_load_balancer_listener_policy" "scorekeep_load_balancer" {
load_balancer_name = "scorekeep-lb"
// CF Property(Scheme) = "internet-facing"
// CF Property(SecurityGroups) = [
// aws_security_group.ecs_security_group[0].arn
// ]
// CF Property(Subnets) = local.CreateSubnet1 ? local.CreateSubnet2 ? local.CreateSubnet3 ? [
// aws_subnet.pub_subnet_az1[0].id,
// aws_subnet.pub_subnet_az2[0].id,
// aws_subnet.pub_subnet_az3[0].id
// ] : [
// aws_subnet.pub_subnet_az1[0].id,
// aws_subnet.pub_subnet_az2[0].id
// ] : [
// aws_subnet.pub_subnet_az1[0].id
// ] : var.subnet_ids
// CF Property(Type) = "application"
// CF Property(tags) = {
// Name = join("_", [local.stack_name])
// }
}
resource "aws_load_balancer_listener_policy" "scorekeep_load_balancer_listener" {
// CF Property(DefaultActions) = [
// {
// Type = "forward"
// TargetGroupArn = aws_lb_target_group_attachment.scorekeep_target_group.id
// }
// ]
load_balancer_name = aws_load_balancer_listener_policy.scorekeep_load_balancer.id
load_balancer_port = 80
// CF Property(Protocol) = "HTTP"
}
output "load_balancer_url" {
description = "The URL of the ALB"
value = aws_load_balancer_listener_policy.scorekeep_load_balancer.load_balancer_name
}