module "default_tags" {
  source             = "git@github.com:theorchard/terraform-default-tags.git//?ref=2.0.0"
  environment        = var.environment
  application_family = var.application_family
  team_name          = var.team_name
}

provider "aws" {
  region = var.aws_region

  default_tags {
    tags = module.default_tags.tags
  }
}

# Terraform backends cannot contain interpolations
terraform {
  backend "s3" {
    bucket  = "orcd-terraform-state"
    key     = "prod/datadog-metric-stream/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

data "aws_caller_identity" "current" {}

data "aws_secretsmanager_secret" "datadog_api" {
  name = "${var.environment}/datadog/DD_API_KEY"
}

data "aws_secretsmanager_secret_version" "datadog_api" {
  secret_id = data.aws_secretsmanager_secret.datadog_api.id
}

# S3 bucket for kinesis errors
module "s3_bucket" {
  source = "git@github.com:theorchard/terraform-s3.git//modules/s3_bucket?ref=3.12.1"

  env                 = var.environment
  bucket_name         = "datadog-firehose-${data.aws_caller_identity.current.account_id}"
  application_family  = var.application_family
  s3_read_only_policy = false
  block_public_access = true

  apply_server_side_encryption_by_default = {
    sse_algorithm = "AES256"
  }

  lifecycle_rules_options_current_version_expiration = [{
    prefix  = ""
    enabled = true
    days    = 180
  }]

  lifecycle_rules_options_noncurrent_version_expiration = [{
    prefix  = ""
    enabled = true
    days    = 365
  }]
}

# IAM
resource "aws_iam_role" "datadog_firehose" {
  name                = "datadog-firehose"
  assume_role_policy  = data.aws_iam_policy_document.datadog_firehose_assume_role.json
  managed_policy_arns = []

  inline_policy {
    name   = "s3-backup"
    policy = data.aws_iam_policy_document.datadog_firehose_s3_backup.json
  }
}

data "aws_iam_policy_document" "datadog_firehose_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

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

data "aws_iam_policy_document" "datadog_firehose_s3_backup" {
  statement {
    actions = [
      "s3:GetBucketLocation",
      "s3:ListBucket",
      "s3:ListBucketMultipartUploads",
    ]

    resources = [module.s3_bucket.s3_bucket_arn_output]
  }

  statement {
    actions = [
      "s3:AbortMultipartUpload",
      "s3:GetObject",
      "s3:PutObject",
    ]

    resources = ["${module.s3_bucket.s3_bucket_arn_output}/*"]
  }
}

resource "aws_iam_role" "datadog_metric_stream" {
  name                = "datadog-metric-stream"
  assume_role_policy  = data.aws_iam_policy_document.datadog_metric_stream_assume_role.json
  managed_policy_arns = []

  inline_policy {
    name   = "firehose"
    policy = data.aws_iam_policy_document.datadog_metric_stream_firehose.json
  }
}

data "aws_iam_policy_document" "datadog_metric_stream_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      identifiers = ["streams.metrics.cloudwatch.amazonaws.com"]
      type        = "Service"
    }
  }
}

data "aws_iam_policy_document" "datadog_metric_stream_firehose" {
  statement {
    actions = [
      "firehose:PutRecord",
      "firehose:PutRecordBatch",
    ]

    resources = [aws_kinesis_firehose_delivery_stream.datadog.arn]
  }
}

# Kinesis Firehose
resource "aws_kinesis_firehose_delivery_stream" "datadog" {
  name        = "datadog"
  destination = "http_endpoint"

  http_endpoint_configuration {
    name               = "Datadog"
    access_key         = data.aws_secretsmanager_secret_version.datadog_api.secret_string
    buffering_interval = 60 # seconds
    buffering_size     = 4  # MB
    retry_duration     = 60 # seconds
    role_arn           = aws_iam_role.datadog_firehose.arn
    s3_backup_mode     = "FailedDataOnly"
    url                = var.datadog_firehose_endpoint

    cloudwatch_logging_options {
      enabled         = true
      log_group_name  = aws_cloudwatch_log_group.datadog_metric_stream.name
      log_stream_name = aws_cloudwatch_log_stream.datadog_metric_stream_http_endpoint_delivery.name
    }

    processing_configuration {
      enabled = false
    }

    request_configuration {
      content_encoding = "GZIP"
    }

    s3_configuration {
      bucket_arn         = module.s3_bucket.s3_bucket_arn_output
      buffering_interval = 300 # seconds
      buffering_size     = 5   # MB
      prefix             = "metrics/"
      role_arn           = aws_iam_role.datadog_firehose.arn

      cloudwatch_logging_options {
        enabled         = true
        log_group_name  = aws_cloudwatch_log_group.datadog_metric_stream.name
        log_stream_name = aws_cloudwatch_log_stream.datadog_metric_stream_s3_backup.name
      }
    }
  }

  server_side_encryption {
    enabled = true
  }
}

# CloudWatch metric stream
resource "aws_cloudwatch_metric_stream" "datadog" {
  name          = "datadog"
  firehose_arn  = aws_kinesis_firehose_delivery_stream.datadog.arn
  output_format = "opentelemetry0.7"
  role_arn      = aws_iam_role.datadog_metric_stream.arn

  dynamic "include_filter" {
    for_each = var.datadog_metric_stream_namespace_list
    iterator = item

    content {
      namespace = item.value
    }
  }
}

# CloudWatch Log Group
resource "aws_cloudwatch_log_group" "datadog_metric_stream" {
  name = var.cloudwatch_log_group_name
}

resource "aws_cloudwatch_log_stream" "datadog_metric_stream_http_endpoint_delivery" {
  name           = "http_endpoint_delivery"
  log_group_name = aws_cloudwatch_log_group.datadog_metric_stream.name
}

resource "aws_cloudwatch_log_stream" "datadog_metric_stream_s3_backup" {
  name           = "s3_backup"
  log_group_name = aws_cloudwatch_log_group.datadog_metric_stream.name
}
