# Get an existing vpc id
data "aws_vpc" "vpc_id" {
  id = var.vpc_id
}

# Get account information
data "aws_caller_identity" "current" {}

# Get an AMI id
data "aws_ami" "wowza" {
  most_recent = true

  owners = [
    "679593333241",
  ]

  filter {
    name = "virtualization-type"

    values = [
      "hvm",
    ]
  }

  filter {
    name = "product-code"

    values = [
      "aw0evgkw8e5c1q413zgy5pjce",
    ]
  }
}

# IAM policy document for ec2 instance's role within ASG
data "aws_iam_policy_document" "instance-assume-role-policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "wowza_role" {
  name               = "${var.aws_stack_name}-service-role"
  assume_role_policy = data.aws_iam_policy_document.instance-assume-role-policy.json
}

# Create a new classic load balancer
resource "aws_elb" "elb" {
  name            = "${var.aws_stack_name}-elb"
  subnets         = var.elb_vpc_subnet_ids
  security_groups = [
    aws_security_group.elb-sg.id]
  internal        = var.elb_scheme

  access_logs {
    bucket   = var.aws_elb_log_s3_bucket
    interval = var.aws_elb_log_interval
  }

  listener {
    instance_port      = 1935
    instance_protocol  = "http"
    lb_port            = 443
    lb_protocol        = "https"
    ssl_certificate_id = var.aws_elb_ssl_certificate
  }

  health_check {
    healthy_threshold   = 2
    unhealthy_threshold = 5
    timeout             = 10
    target              = "HTTP:1935/login"
    interval            = 30
  }

  cross_zone_load_balancing = var.cross_zone_load_balancing
  idle_timeout              = 400

  tags = {
    Name         = "${var.aws_stack_name}-elb"
    environment  = var.environment
    service_name = "aws-wowza"
    terraformed  = true
  }

}

# Load balancer cookie stickiness policy
resource "aws_lb_cookie_stickiness_policy" "lb_cookie_stickiness" {
  lb_port       = 443
  load_balancer = aws_elb.elb.id
  name          = "lbcookiestickinesspolicy"
}

# Set the listener policy for https port to use stronger ciphers
resource "aws_load_balancer_policy" "wowza-elb-ssl-tls-1-2" {
  load_balancer_name = aws_elb.elb.name
  policy_name        = "${aws_elb.elb.name}-tls-1-2-policy"
  policy_type_name   = "SSLNegotiationPolicyType"

  policy_attribute {
    name  = "Reference-Security-Policy"
    value = "ELBSecurityPolicy-TLS-1-2-2017-01"
  }
}

resource "aws_load_balancer_listener_policy" "wowza-listener-policies-443" {
  load_balancer_name = aws_elb.elb.name
  load_balancer_port = 443

  policy_names = [
    aws_load_balancer_policy.wowza-elb-ssl-tls-1-2.policy_name,
    aws_lb_cookie_stickiness_policy.lb_cookie_stickiness.name,
  ]
}

# A security group for the ELB
# It should be accesible within corporate network
resource "aws_security_group" "elb-sg" {
  name        = "${var.aws_stack_name}-elb-sg"
  description = "SG for Load balancer"
  vpc_id      = var.vpc_id

  # HTTPS access
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = var.aws_elb_access_ips
  }

  # Outbound internet access
  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0",
    ]
  }

  tags = {
    terraformed  = true
    environment  = var.environment
    service_name = "aws-wowza"
  }
}

# Security group to access the instances from ELB
resource "aws_security_group" "asg-sg" {
  name        = "${var.aws_stack_name}-asg"
  description = "AWS Security group for ASG instances"
  vpc_id      = var.vpc_id

  # HTTP access from ELB security group
  ingress {
    from_port = 1935
    to_port   = 1935
    protocol  = "tcp"

    security_groups = [
      aws_security_group.elb-sg.id,
    ]
  }

  # outbound internet access
  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0",
    ]
  }

  tags = {
    terraformed = true
  }
}

# A security group for cluster instances
resource "aws_security_group" "cluster-sg" {
  name        = "${var.aws_stack_name}-cluster"
  description = "SG for Admin communication from port 22(ssh), 1935(streaming) and 8088(web console)"
  vpc_id      = var.vpc_id

  # SSH from within this SG
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    self        = true
    cidr_blocks = var.sg_cidr_blocks
  }

  ingress {
    from_port   = 1935
    to_port     = 1935
    protocol    = "tcp"
    self        = true
    cidr_blocks = var.sg_cidr_blocks
  }

  ingress {
    from_port   = 8088
    to_port     = 8088
    protocol    = "tcp"
    self        = true
    cidr_blocks = var.sg_cidr_blocks
  }

  # Outbound internet access
  egress {
    from_port = 0
    to_port   = 0
    protocol  = "-1"

    cidr_blocks = [
      "0.0.0.0/0",
    ]
  }

  tags = {
    terraformed = true
  }
}

# Launch configuration
resource "aws_launch_configuration" "launch-config" {
  name_prefix                 = "${var.aws_stack_name}-lc-"
  image_id                    = data.aws_ami.wowza.id
  instance_type               = var.aws_instance_type
  associate_public_ip_address = false
  iam_instance_profile        = aws_iam_instance_profile.wowza_profile.name

  security_groups = [
    aws_security_group.asg-sg.id,
    aws_security_group.cluster-sg.id,
  ]

  key_name  = var.aws_key_name
  user_data = var.user_data

  root_block_device {
    volume_type = var.volume_type
    volume_size = var.aws_volume_size
  }

  lifecycle {
    create_before_destroy = true
  }
}

# Auto scaling group
resource "aws_autoscaling_group" "asg" {
  name = var.aws_stack_name

  max_size                  = var.aws_asg_max_instance
  min_size                  = var.aws_asg_min_instance
  desired_capacity          = var.aws_asg_desire_instance
  health_check_type         = "ELB"
  health_check_grace_period = 1800
  launch_configuration      = aws_launch_configuration.launch-config.name

  load_balancers = [
    aws_elb.elb.name,
  ]

  # Instances must be in same AZ as ELB
  vpc_zone_identifier = var.asg_vpc_subnet_ids

  tags = [
    {
      key                 = "Name"
      value               = var.aws_stack_name
      propagate_at_launch = true
    },
    {
      key                 = "environment"
      value               = var.environment
      propagate_at_launch = true
    },
    {
      key                 = "service_name"
      value               = "aws-wowza"
      propagate_at_launch = true
    },
  ]

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "dns" {
  zone_id = var.aws_route53_params["zone_id"]
  name    = var.aws_stack_name
  type    = "A"

  alias {
    name                   = aws_elb.elb.dns_name
    zone_id                = aws_elb.elb.zone_id
    evaluate_target_health = true
  }
}

resource "aws_iam_instance_profile" "wowza_profile" {
  name       = "${var.aws_stack_name}-instance-profile"
  role       = aws_iam_role.wowza_role.name
  depends_on = [aws_iam_role.wowza_role]
}

# Stack name variable to use in other terraform modules
output "aws_stack_name_output" {
  value = var.aws_stack_name
}

# ASG arn variable to use in other terraform modules
output "aws_asg_name_output" {
  value = aws_autoscaling_group.asg.name
}

# Route53 record output
output "aws_route53_record_output" {
  value = aws_route53_record.dns.fqdn
}

# Cluster security group
output "aws_cluster_sg_output" {
  value = aws_security_group.cluster-sg.id
}

output "aws_iam_role_id_output" {
  value = aws_iam_role.wowza_role.id
}
