terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

variable "project_id" {
  description = "The GCP Project ID where resources will be deployed."
  type        = string
}

locals {
  dragonfly_worker_service_account_email     = "prodv2-control-plane-cw@dragonflydb.iam.gserviceaccount.com"
  dragonfly_api_server_service_account_email = "prodv2-control-plane-as@dragonflydb.iam.gserviceaccount.com"
  dataplane_service_account_id               = "prodv2-data-plane-instance"
}

provider "google" {
  project = var.project_id
}

resource "google_project_iam_custom_role" "dragonfly_byoc_role" {
  role_id     = "dragonflyByoc"
  title       = "Dragonfly BYOC Role"
  project     = var.project_id

  permissions = [
    # Storage
    "storage.buckets.create",
    "storage.buckets.delete",
    "storage.buckets.get",
    "storage.objects.list",
    "storage.objects.delete",
    "storage.objects.get",
    "storage.objects.create",

    # Compute Instances
    "compute.disks.create",
    "compute.disks.setLabels",
    "compute.instances.create",
    "compute.instances.get",
    "compute.instances.list",
    "compute.instances.setLabels",
    "compute.instances.setMetadata",
    "compute.instances.setServiceAccount",
    "compute.instances.setTags",
    "compute.instances.stop",
    "compute.instances.reset",
    "compute.instances.delete",
    "compute.machineTypes.get",
    "compute.instances.setDeletionProtection",

    # Networking
    "compute.firewalls.create",
    "compute.firewalls.delete",
    "compute.firewalls.list",
    "compute.firewalls.get",
    "compute.networks.create",
    "compute.networks.delete",
    "compute.networks.get",
    "compute.networks.updatePolicy",
    "compute.networks.addPeering",
    "compute.networks.removePeering",
    "compute.subnetworks.create",
    "compute.subnetworks.delete",
    "compute.subnetworks.get",
    "compute.subnetworks.list",
    "compute.subnetworks.use",
    "compute.routes.list",

    # Project Metadata
    "compute.projects.get"
  ]
}

# Grant the Dragonfly worker service account a custom role on the project
resource "google_project_iam_member" "dragonfly_byoc_worker_role_binding" {
  project = var.project_id
  role    = google_project_iam_custom_role.dragonfly_byoc_role.id
  member  = "serviceAccount:${local.dragonfly_worker_service_account_email}"
}

# Grant the Dragonfly API server service account a custom role on the project
resource "google_project_iam_member" "dragonfly_byoc_api_server_role_binding" {
  project = var.project_id
  role    = google_project_iam_custom_role.dragonfly_byoc_role.id
  member  = "serviceAccount:${local.dragonfly_api_server_service_account_email}"
}

# Create the service account that the Dragonfly VM will actually use/run as
resource "google_service_account" "data_plane_service_account" {
  project      = var.project_id
  account_id   = local.dataplane_service_account_id
  display_name = "Data plane instance service account"
}

# Allow the Dragonfly service account to 'pass' this new Service Account to VMs it creates.
# This acts as a permission bridge: Dragonfly -> Creates VM -> Attaches Data Plane SA.
resource "google_service_account_iam_member" "allow_impersonation" {
  service_account_id = google_service_account.data_plane_service_account.name
  role               = "roles/iam.serviceAccountUser"
  member             = "serviceAccount:${local.dragonfly_worker_service_account_email}"
}

resource "google_project_iam_custom_role" "data_plane_storage_role" {
  role_id = "dragonflyDataPlaneStorage"
  title   = "Dragonfly Data Plane Storage Role"
  project = var.project_id

  permissions = [
    "storage.objects.create",
    "storage.objects.get",
    "storage.objects.list",
    "storage.objects.delete",
    "storage.buckets.get",
  ]
}

# Grant the data plane service account storage permissions for backups
resource "google_project_iam_member" "data_plane_storage_binding" {
  project = var.project_id
  role    = google_project_iam_custom_role.data_plane_storage_role.id
  member  = "serviceAccount:${google_service_account.data_plane_service_account.email}"
}
