Skip to content

Cloud Run v2 module creating port for second container resulting in error #345

@jeunii

Description

@jeunii

When deploying multiple containers in a cloud Run service using the resource, the ports assignment assigns a port to the second container.

Deploying a CloudRun service using the TF resource directly

resource "google_cloud_run_v2_service" "default" {
  name     = "cloudrun-service"
  project = "XXXXXXX"
  location = "us-central1"
  deletion_protection = false
  ingress = "INGRESS_TRAFFIC_ALL"
  template {
    containers {
      name = "hello-1"
      ports {
        container_port = 8080
      }
      image = "us-docker.pkg.dev/cloudrun/container/hello"
      depends_on = ["hello-2"]
    }
    containers {
      name = "hello-2"
      image = "us-docker.pkg.dev/cloudrun/container/hello"
      env {
        name = "PORT"
        value = "8081"
      }
      startup_probe {
        http_get {
          port = 8081
        }
      }
    }
  }
}

The plan in this case is

❯ tofu apply

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

OpenTofu will perform the following actions:

  # google_cloud_run_v2_service.default will be created
  + resource "google_cloud_run_v2_service" "default" {
      + conditions              = (known after apply)
      + create_time             = (known after apply)
      + creator                 = (known after apply)
      + delete_time             = (known after apply)
      + deletion_protection     = false
      + effective_annotations   = (known after apply)
      + effective_labels        = {
          + "goog-terraform-provisioned" = "true"
        }
      + etag                    = (known after apply)
      + expire_time             = (known after apply)
      + generation              = (known after apply)
      + id                      = (known after apply)
      + ingress                 = "INGRESS_TRAFFIC_ALL"
      + last_modifier           = (known after apply)
      + latest_created_revision = (known after apply)
      + latest_ready_revision   = (known after apply)
      + launch_stage            = (known after apply)
      + location                = "us-central1"
      + name                    = "cloudrun-service"
      + observed_generation     = (known after apply)
      + project                 = "XXXXXXXX"
      + reconciling             = (known after apply)
      + terminal_condition      = (known after apply)
      + terraform_labels        = {
          + "goog-terraform-provisioned" = "true"
        }
      + traffic_statuses        = (known after apply)
      + uid                     = (known after apply)
      + update_time             = (known after apply)
      + uri                     = (known after apply)
      + urls                    = (known after apply)

      + template {
          + max_instance_request_concurrency = (known after apply)
          + service_account                  = (known after apply)
          + timeout                          = (known after apply)

          + containers {
              + build_info = (known after apply)
              + depends_on = [
                  + "hello-2",
                ]
              + image      = "us-docker.pkg.dev/cloudrun/container/hello"
              + name       = "hello-1"

              + ports {
                  + container_port = 8080
                  + name           = (known after apply)
                }

              + resources (known after apply)

              + startup_probe (known after apply)
            }
          + containers {
              + build_info = (known after apply)
              + image      = "us-docker.pkg.dev/cloudrun/container/hello"
              + name       = "hello-2"

              + env {
                  + name  = "PORT"
                  + value = "8081"
                }

              + ports (known after apply)       # <----- Notice this 

              + resources (known after apply)

              + startup_probe {
                  + failure_threshold     = 3
                  + initial_delay_seconds = 0
                  + period_seconds        = 10
                  + timeout_seconds       = 1

                  + http_get {
                      + path = "/"
                      + port = 8081
                    }
                }
            }

          + scaling (known after apply)
        }

      + traffic (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

The resource is successfully created.

But when using the module

module "cloud_run_core" {
  source  = "GoogleCloudPlatform/cloud-run/google//modules/v2"
  version = "0.17.4"

  project_id      = "XXXXXX"
  service_name    = "hello-world"
  location        = "us-central1"
  containers      = [
    {
      container_image = "us-docker.pkg.dev/cloudrun/container/hello"
      container_name = "hello-world"
      ports = {
        name = "http1"
        container_port = 8080
      }
    },
    {
      container_image = "us-docker.pkg.dev/cloudrun/container/hello"
      container_name = "hello-world-2"
    }
  ]
}

The plan looks like this

❯ tofu apply

OpenTofu used the selected providers to generate the following execution plan. Resource actions are indicated with
the following symbols:
  + create

OpenTofu will perform the following actions:

  # module.cloud_run_core.google_cloud_run_v2_service.main will be created
  + resource "google_cloud_run_v2_service" "main" {
      + conditions              = (known after apply)
      + create_time             = (known after apply)
      + creator                 = (known after apply)
      + delete_time             = (known after apply)
      + deletion_protection     = true
      + effective_annotations   = (known after apply)
      + effective_labels        = {
          + "goog-terraform-provisioned" = "true"
        }
      + etag                    = (known after apply)
      + expire_time             = (known after apply)
      + generation              = (known after apply)
      + id                      = (known after apply)
      + ingress                 = "INGRESS_TRAFFIC_ALL"
      + last_modifier           = (known after apply)
      + latest_created_revision = (known after apply)
      + latest_ready_revision   = (known after apply)
      + launch_stage            = "GA"
      + location                = "us-central1"
      + name                    = "hello-world"
      + observed_generation     = (known after apply)
      + project                 = "XXXXXX
      + reconciling             = (known after apply)
      + terminal_condition      = (known after apply)
      + terraform_labels        = {
          + "goog-terraform-provisioned" = "true"
        }
      + traffic_statuses        = (known after apply)
      + uid                     = (known after apply)
      + update_time             = (known after apply)
      + uri                     = (known after apply)
      + urls                    = (known after apply)

      + template {
          + execution_environment            = "EXECUTION_ENVIRONMENT_GEN2"
          + max_instance_request_concurrency = (known after apply)
          + service_account                  = "hello-world-us-central1-sa@clx-nprd-apigee-x-44dd.iam.gserviceaccount.com"
          + timeout                          = (known after apply)

          + containers {
              + build_info = (known after apply)
              + image      = "us-docker.pkg.dev/cloudrun/container/hello"
              + name       = "hello-world"

              + ports {
                  + container_port = 8080
                  + name           = "http1"
                }

              + resources {
                  + cpu_idle          = true
                  + limits            = (known after apply)
                  + startup_cpu_boost = false
                }

              + startup_probe (known after apply)
            }
          + containers {
              + build_info = (known after apply)
              + image      = "us-docker.pkg.dev/cloudrun/container/hello"
              + name       = "hello-world-2"

              + ports {                                          # <-------- Ports being declared for second container
                  + container_port = 8080
                  + name           = "http1"
                }

              + resources {
                  + cpu_idle          = true
                  + limits            = (known after apply)
                  + startup_cpu_boost = false
                }

              + startup_probe (known after apply)
            }

          + scaling (known after apply)
        }

      + traffic (known after apply)
    }

  # module.cloud_run_core.google_service_account.sa[0] will be created
  + resource "google_service_account" "sa" {
      + account_id   = "hello-world-us-central1-sa"
      + disabled     = false
      + display_name = "Service account for hello-world in us-central1"
      + email        = "[email protected]"
      + id           = (known after apply)
      + member       = "serviceAccount:[email protected]"
      + name         = (known after apply)
      + project      = "XXXXX"
      + unique_id    = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

This results in the below error

│ Error: Error creating Service: googleapi: Error 400: template.containers: Revision template should contain exactly one container with an exposed port.
│ Details:
│ [
│   {
│     "@type": "type.googleapis.com/google.rpc.BadRequest",
│     "fieldViolations": [
│       {
│         "description": "Revision template should contain exactly one container with an exposed port.",
│         "field": "template.containers"
│       }
│     ]
│   }
│ ]
│ 
│   with module.cloud_run_core.google_cloud_run_v2_service.main,
│   on .terraform/modules/cloud_run_core/main.tf line 96, in resource "google_cloud_run_v2_service" "main":
│   96: resource "google_cloud_run_v2_service" "main" {
│ 
╵

The module should not specify a port for the second container.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions