diff --git a/examples/factories/project-factory/README.md b/examples/factories/project-factory/README.md
index 268c173f..8cc45c00 100644
--- a/examples/factories/project-factory/README.md
+++ b/examples/factories/project-factory/README.md
@@ -218,26 +218,28 @@ vpc:
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
| [billing_account_id](variables.tf#L17) | Billing account id. | string
| ✓ | |
-| [defaults](variables.tf#L35) | Project factory default values. | object({…})
| ✓ | |
-| [folder_id](variables.tf#L68) | Folder ID for the folder where the project will be created. | string
| ✓ | |
-| [project_id](variables.tf#L111) | Project id. | string
| ✓ | |
+| [folder_id](variables.tf#L69) | Folder ID for the folder where the project will be created. | string
| ✓ | |
+| [project_id](variables.tf#L119) | Project id. | string
| ✓ | |
| [billing_alert](variables.tf#L22) | Billing alert configuration. | object({…})
| | null
|
-| [dns_zones](variables.tf#L56) | DNS private zones to create as child of var.defaults.environment_dns_zone. | list(string)
| | []
|
-| [essential_contacts](variables.tf#L62) | Email contacts to be used for billing and GCP notifications. | list(string)
| | []
|
-| [group_iam](variables.tf#L73) | Custom IAM settings in group => [role] format. | map(list(string))
| | {}
|
-| [iam](variables.tf#L79) | Custom IAM settings in role => [principal] format. | map(list(string))
| | {}
|
-| [kms_service_agents](variables.tf#L85) | KMS IAM configuration in as service => [key]. | map(list(string))
| | {}
|
-| [labels](variables.tf#L91) | Labels to be assigned at project level. | map(string)
| | {}
|
-| [org_policies](variables.tf#L97) | Org-policy overrides at project level. | object({…})
| | null
|
-| [service_accounts](variables.tf#L116) | Service accounts to be created, and roles to assign them. | map(list(string))
| | {}
|
-| [services](variables.tf#L122) | Services to be enabled for the project. | list(string)
| | []
|
-| [services_iam](variables.tf#L128) | Custom IAM settings for robot ServiceAccounts in service => [role] format. | map(list(string))
| | {}
|
-| [vpc](variables.tf#L134) | VPC configuration for the project. | object({…})
| | null
|
+| [defaults](variables.tf#L35) | Project factory default values. | object({…})
| | null
|
+| [dns_zones](variables.tf#L57) | DNS private zones to create as child of var.defaults.environment_dns_zone. | list(string)
| | []
|
+| [essential_contacts](variables.tf#L63) | Email contacts to be used for billing and GCP notifications. | list(string)
| | []
|
+| [group_iam](variables.tf#L74) | Custom IAM settings in group => [role] format. | map(list(string))
| | {}
|
+| [iam](variables.tf#L80) | Custom IAM settings in role => [principal] format. | map(list(string))
| | {}
|
+| [kms_service_agents](variables.tf#L86) | KMS IAM configuration in as service => [key]. | map(list(string))
| | {}
|
+| [labels](variables.tf#L92) | Labels to be assigned at project level. | map(string)
| | {}
|
+| [org_policies](variables.tf#L98) | Org-policy overrides at project level. | object({…})
| | null
|
+| [prefix](variables.tf#L112) | Prefix used for the project id. | string
| | null
|
+| [service_accounts](variables.tf#L124) | Service accounts to be created, and roles to assign them. | map(list(string))
| | {}
|
+| [services](variables.tf#L130) | Services to be enabled for the project. | list(string)
| | []
|
+| [services_iam](variables.tf#L136) | Custom IAM settings for robot ServiceAccounts in service => [role] format. | map(list(string))
| | {}
|
+| [vpc](variables.tf#L142) | VPC configuration for the project. | object({…})
| | null
|
## Outputs
| name | description | sensitive |
|---|---|:---:|
-| [project_id](outputs.tf#L19) | Project ID. | |
+| [project](outputs.tf#L19) | The project resource as return by the `project` module | |
+| [project_id](outputs.tf#L30) | Project ID. | |
diff --git a/examples/factories/project-factory/main.tf b/examples/factories/project-factory/main.tf
index c4928371..df449edb 100644
--- a/examples/factories/project-factory/main.tf
+++ b/examples/factories/project-factory/main.tf
@@ -15,15 +15,12 @@
*/
locals {
- _gke_iam_hsau = try(var.vpc.gke_setup.enable_security_admin, false) ? {
- "roles/container.hostServiceAgentUser" = [
- "serviceAccount:${local.service_accounts_robots["container-engine"]}"
- ] } : {}
-
+ _gke_iam_hsau = try(var.vpc.gke_setup.enable_host_service_agent, false) ? {
+ "roles/container.hostServiceAgentUser" = "serviceAccount:${module.project.service_accounts.robots.container-engine}"
+ } : {}
_gke_iam_securityadmin = try(var.vpc.gke_setup.enable_security_admin, false) ? {
- "roles/compute.securityAdmin" = [
- "serviceAccount:${local.service_accounts_robots["container-engine"]}"
- ] } : {}
+ "roles/compute.securityAdmin" = "serviceAccount:${module.project.service_accounts.robots.container-engine}"
+ } : {}
_group_iam = {
for r in local._group_iam_roles : r => [
for k, v in var.group_iam : "group:${k}" if try(index(v, r), null) != null
@@ -47,59 +44,41 @@ locals {
_services_iam_roles = distinct(flatten(values(var.services_iam)))
_services_iam = {
for r in local._services_iam_roles : r => [
- for k, v in var.services_iam : "serviceAccount:${local.service_accounts_robots[k]}" if try(index(v, r), null) != null
+ for k, v in var.services_iam : "serviceAccount:${module.project.service_accounts.robots[k]}" if try(index(v, r), null) != null
]
}
- billing_account_id = coalesce(var.billing_account_id, var.defaults.billing_account_id)
- billing_alert = var.billing_alert == null ? var.defaults.billing_alert : var.billing_alert
+ billing_account_id = coalesce(var.billing_account_id, try(var.defaults.billing_account_id, ""))
+ billing_alert = var.billing_alert == null ? try(var.defaults.billing_alert, null) : var.billing_alert
essential_contacts = concat(try(var.defaults.essential_contacts, []), var.essential_contacts)
+ host_project_bindings = merge(
+ local._gke_iam_hsau,
+ local._gke_iam_securityadmin
+ )
iam = {
for role in distinct(concat(
keys(var.iam),
keys(local._group_iam),
- keys(local._gke_iam_hsau),
- keys(local._gke_iam_securityadmin),
keys(local._service_accounts_iam),
keys(local._services_iam),
)) :
role => concat(
try(var.iam[role], []),
try(local._group_iam[role], []),
- try(local._gke_iam_hsau[role], []),
- try(local._gke_iam_securityadmin[role], []),
try(local._service_accounts_iam[role], []),
try(local._services_iam[role], []),
)
}
- labels = merge(coalesce(var.labels, {}), coalesce(var.defaults.labels, {}))
+ labels = merge(coalesce(var.labels, {}), coalesce(try(var.defaults.labels, {}), {}))
network_user_service_accounts = concat(
contains(local.services, "compute.googleapis.com") ? [
- "serviceAccount:${local.service_accounts_robots.compute}"
+ "serviceAccount:${module.project.service_accounts.robots.compute}"
] : [],
contains(local.services, "container.googleapis.com") ? [
- "serviceAccount:${local.service_accounts_robots.container-engine}",
- "serviceAccount:${local.service_accounts.cloud_services}"
+ "serviceAccount:${module.project.service_accounts.robots.container-engine}",
+ "serviceAccount:${module.project.service_accounts.cloud_services}"
] : [],
[])
- services = distinct(concat(var.services, local._services))
- service_accounts_robots = {
- for service, name in local.service_accounts_robot_services :
- service => "${service == "bq" ? "bq" : "service"}-${module.project.number}@${name}.iam.gserviceaccount.com"
- }
- service_accounts_robot_services = {
- cloudasset = "gcp-sa-cloudasset"
- cloudbuild = "gcp-sa-cloudbuild"
- compute = "compute-system"
- container-engine = "container-engine-robot"
- containerregistry = "containerregistry"
- dataflow = "dataflow-service-producer-prod"
- dataproc = "dataproc-accounts"
- gae-flex = "gae-api-prod"
- gcf = "gcf-admin-robot"
- pubsub = "gcp-sa-pubsub"
- secretmanager = "gcp-sa-secretmanager"
- storage = "gs-project-accounts"
- }
+ services = distinct(concat(var.services, local._services))
vpc_host_project = try(var.vpc.host_project, var.defaults.vpc_host_project)
vpc_setup = var.vpc != null
}
@@ -134,6 +113,7 @@ module "project" {
source = "../../../modules/project"
billing_account = local.billing_account_id
name = var.project_id
+ prefix = var.prefix
contacts = { for c in local.essential_contacts : c => ["ALL"] }
iam = local.iam
labels = local.labels
@@ -155,6 +135,7 @@ module "service-accounts" {
project_id = module.project.project_id
}
+# TODO(jccb): we should probably change this to non-authoritative bindings
resource "google_compute_subnetwork_iam_binding" "binding" {
for_each = local.vpc_setup ? coalesce(var.vpc.subnets_iam, {}) : {}
project = local.vpc_host_project
@@ -163,3 +144,10 @@ resource "google_compute_subnetwork_iam_binding" "binding" {
role = "roles/compute.networkUser"
members = concat(each.value, local.network_user_service_accounts)
}
+
+resource "google_project_iam_member" "host_project_bindings" {
+ for_each = local.host_project_bindings
+ project = local.vpc_host_project
+ role = each.key
+ member = each.value
+}
diff --git a/examples/factories/project-factory/outputs.tf b/examples/factories/project-factory/outputs.tf
index 1ee734ed..7504eda5 100644
--- a/examples/factories/project-factory/outputs.tf
+++ b/examples/factories/project-factory/outputs.tf
@@ -16,7 +16,23 @@
# TODO(): proper outputs
+output "project" {
+ description = "The project resource as return by the `project` module"
+ value = module.project
+
+ depends_on = [
+ google_compute_subnetwork_iam_binding.binding,
+ google_project_iam_member.host_project_bindings,
+ module.dns
+ ]
+}
+
output "project_id" {
description = "Project ID."
value = module.project.project_id
+ depends_on = [
+ google_compute_subnetwork_iam_binding.binding,
+ google_project_iam_member.host_project_bindings,
+ module.dns
+ ]
}
diff --git a/examples/factories/project-factory/variables.tf b/examples/factories/project-factory/variables.tf
index adae051a..777dce71 100644
--- a/examples/factories/project-factory/variables.tf
+++ b/examples/factories/project-factory/variables.tf
@@ -51,6 +51,7 @@ variable "defaults" {
shared_vpc_self_link = string
vpc_host_project = string
})
+ default = null
}
variable "dns_zones" {
@@ -108,6 +109,12 @@ variable "org_policies" {
default = null
}
+variable "prefix" {
+ description = "Prefix used for the project id."
+ type = string
+ default = null
+}
+
variable "project_id" {
description = "Project id."
type = string