Skip to content

Commit

Permalink
Merge pull request #1 from truefoundry/gcp-control-plane
Browse files Browse the repository at this point in the history
Gcp control plane
  • Loading branch information
dunefro authored Feb 27, 2024
2 parents 9e3ce82 + a9a35d4 commit 282bc2e
Show file tree
Hide file tree
Showing 8 changed files with 525 additions and 0 deletions.
88 changes: 88 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,90 @@
# terraform-google-truefoundry-control-plane
Truefoundry Google Cloud Control Plane Module

<!-- BEGIN_TF_DOCS -->
## Requirements

No requirements.

## Providers

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | n/a |
| <a name="provider_random"></a> [random](#provider\_random) | n/a |

## Modules

| Name | Source | Version |
|------|--------|---------|
| <a name="module_postgresql-db"></a> [postgresql-db](#module\_postgresql-db) | GoogleCloudPlatform/sql-db/google//modules/postgresql | 19.0.0 |
| <a name="module_service_account_iam_bindings"></a> [service\_account\_iam\_bindings](#module\_service\_account\_iam\_bindings) | terraform-google-modules/iam/google//modules/service_accounts_iam | 7.7.1 |
| <a name="module_service_accounts"></a> [service\_accounts](#module\_service\_accounts) | terraform-google-modules/service-accounts/google | 4.2.2 |
| <a name="module_truefoundry_gcs"></a> [truefoundry\_gcs](#module\_truefoundry\_gcs) | terraform-google-modules/cloud-storage/google//modules/simple_bucket | 4.0.1 |

## Resources

| Name | Type |
|------|------|
| [google_compute_global_address.default](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_global_address) | resource |
| [google_service_networking_connection.default](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_networking_connection) | resource |
| [random_password.truefoundry_db_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_cluster_name"></a> [cluster\_name](#input\_cluster\_name) | Truefoundry deployment unique name | `string` | n/a | yes |
| <a name="input_mlfoundry_k8s_namespace"></a> [mlfoundry\_k8s\_namespace](#input\_mlfoundry\_k8s\_namespace) | The k8s mlfoundry namespace | `string` | n/a | yes |
| <a name="input_mlfoundry_k8s_service_account"></a> [mlfoundry\_k8s\_service\_account](#input\_mlfoundry\_k8s\_service\_account) | The k8s mlfoundry service account name | `string` | n/a | yes |
| <a name="input_project_id"></a> [project\_id](#input\_project\_id) | GCP Project | `string` | n/a | yes |
| <a name="input_region"></a> [region](#input\_region) | region | `string` | n/a | yes |
| <a name="input_svcfoundry_k8s_namespace"></a> [svcfoundry\_k8s\_namespace](#input\_svcfoundry\_k8s\_namespace) | The k8s svcfoundry namespace | `string` | n/a | yes |
| <a name="input_svcfoundry_k8s_service_account"></a> [svcfoundry\_k8s\_service\_account](#input\_svcfoundry\_k8s\_service\_account) | The k8s svcfoundry service account name | `string` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| <a name="input_truefoundry_db_availability_type"></a> [truefoundry\_db\_availability\_type](#input\_truefoundry\_db\_availability\_type) | Postgres availability type for the master instance. Accepted values are [ZONAL, REGIONAL]. Chose REGIONAL for HA | `string` | `"REGIONAL"` | no |
| <a name="input_truefoundry_db_database_charset"></a> [truefoundry\_db\_database\_charset](#input\_truefoundry\_db\_database\_charset) | Charset for the default database | `string` | `"UTF8"` | no |
| <a name="input_truefoundry_db_database_collation"></a> [truefoundry\_db\_database\_collation](#input\_truefoundry\_db\_database\_collation) | Collation for the default database | `string` | `"en_US.UTF8"` | no |
| <a name="input_truefoundry_db_database_name"></a> [truefoundry\_db\_database\_name](#input\_truefoundry\_db\_database\_name) | Name of the database | `string` | `"ctl"` | no |
| <a name="input_truefoundry_db_deletion_protection"></a> [truefoundry\_db\_deletion\_protection](#input\_truefoundry\_db\_deletion\_protection) | Enable deletion protection | `bool` | `false` | no |
| <a name="input_truefoundry_db_disk_autoresize"></a> [truefoundry\_db\_disk\_autoresize](#input\_truefoundry\_db\_disk\_autoresize) | Automically increase storage size | `bool` | `true` | no |
| <a name="input_truefoundry_db_disk_autoresize_limit"></a> [truefoundry\_db\_disk\_autoresize\_limit](#input\_truefoundry\_db\_disk\_autoresize\_limit) | Automically increase storage size | `number` | n/a | yes |
| <a name="input_truefoundry_db_disk_size"></a> [truefoundry\_db\_disk\_size](#input\_truefoundry\_db\_disk\_size) | Disk size of the master instance | `number` | `20` | no |
| <a name="input_truefoundry_db_disk_type"></a> [truefoundry\_db\_disk\_type](#input\_truefoundry\_db\_disk\_type) | Disk size of the master instance | `string` | `"PD_SSD"` | no |
| <a name="input_truefoundry_db_edition"></a> [truefoundry\_db\_edition](#input\_truefoundry\_db\_edition) | The edition of the instance, can be ENTERPRISE or ENTERPRISE\_PLUS | `string` | `null` | no |
| <a name="input_truefoundry_db_enable"></a> [truefoundry\_db\_enable](#input\_truefoundry\_db\_enable) | Enable CloudSQL database | `bool` | n/a | yes |
| <a name="input_truefoundry_db_enable_override"></a> [truefoundry\_db\_enable\_override](#input\_truefoundry\_db\_enable\_override) | Enable override for truefoundry db name. You must pass truefoundry\_db\_override\_name | `bool` | `false` | no |
| <a name="input_truefoundry_db_network_cidr"></a> [truefoundry\_db\_network\_cidr](#input\_truefoundry\_db\_network\_cidr) | Network CIDR for the truefoundry postgres database. Minimum range is /24. This CIDR must be different from the main subnet where your cluster is gettin created. This subnet is created inside the GCP's network. | `string` | n/a | yes |
| <a name="input_truefoundry_db_override_name"></a> [truefoundry\_db\_override\_name](#input\_truefoundry\_db\_override\_name) | Override name for truefoundry db. truefoundry\_db\_enable\_override must be set true | `string` | `""` | no |
| <a name="input_truefoundry_db_postgres_version"></a> [truefoundry\_db\_postgres\_version](#input\_truefoundry\_db\_postgres\_version) | Postgres version of cloudSQL | `string` | `"POSTGRES_15"` | no |
| <a name="input_truefoundry_db_tier"></a> [truefoundry\_db\_tier](#input\_truefoundry\_db\_tier) | Instance class for SQL DB | `string` | n/a | yes |
| <a name="input_truefoundry_db_zone"></a> [truefoundry\_db\_zone](#input\_truefoundry\_db\_zone) | Zone for SQL DB - This must match the region | `string` | n/a | yes |
| <a name="input_truefoundry_gcs_cors_origins"></a> [truefoundry\_gcs\_cors\_origins](#input\_truefoundry\_gcs\_cors\_origins) | Allowed CORS origin for GCS bucket | `list(string)` | <pre>[<br> "*"<br>]</pre> | no |
| <a name="input_truefoundry_gcs_enable_override"></a> [truefoundry\_gcs\_enable\_override](#input\_truefoundry\_gcs\_enable\_override) | Enable override for GCS bucket name. You must pass truefoundry\_gcs\_override\_name | `bool` | `false` | no |
| <a name="input_truefoundry_gcs_enabled"></a> [truefoundry\_gcs\_enabled](#input\_truefoundry\_gcs\_enabled) | Enable creation of GCS bucket | `bool` | `false` | no |
| <a name="input_truefoundry_gcs_force_destroy"></a> [truefoundry\_gcs\_force\_destroy](#input\_truefoundry\_gcs\_force\_destroy) | Enable force destroy on GCS bucket | `bool` | `true` | no |
| <a name="input_truefoundry_gcs_override_name"></a> [truefoundry\_gcs\_override\_name](#input\_truefoundry\_gcs\_override\_name) | Override name for GCS bucket. truefoundry\_gcs\_enable\_override must be set true | `string` | `""` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | ID of the network VPC | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_bucket_name"></a> [bucket\_name](#output\_bucket\_name) | GCS bucket name |
| <a name="output_bucket_url"></a> [bucket\_url](#output\_bucket\_url) | GCS bucket URL |
| <a name="output_database_password"></a> [database\_password](#output\_database\_password) | Database's password |
| <a name="output_instance_ip_address"></a> [instance\_ip\_address](#output\_instance\_ip\_address) | Database instance IP address |
| <a name="output_instance_name"></a> [instance\_name](#output\_instance\_name) | Database instance name |
| <a name="output_instance_self_link"></a> [instance\_self\_link](#output\_instance\_self\_link) | Self link of the database |
| <a name="output_instance_server_ca_cert"></a> [instance\_server\_ca\_cert](#output\_instance\_server\_ca\_cert) | Self link of the database server ca cert |
| <a name="output_instance_service_account_email_address"></a> [instance\_service\_account\_email\_address](#output\_instance\_service\_account\_email\_address) | Service account email address |
| <a name="output_instances"></a> [instances](#output\_instances) | n/a |
| <a name="output_primary"></a> [primary](#output\_primary) | n/a |
| <a name="output_private_ip_address"></a> [private\_ip\_address](#output\_private\_ip\_address) | Private IP address of the database instance |
| <a name="output_serviceaccount_binding_service_accounts"></a> [serviceaccount\_binding\_service\_accounts](#output\_serviceaccount\_binding\_service\_accounts) | Serviceaccount bindings |
| <a name="output_serviceaccount_detail"></a> [serviceaccount\_detail](#output\_serviceaccount\_detail) | Serviceaccount details |
| <a name="output_serviceaccount_email"></a> [serviceaccount\_email](#output\_serviceaccount\_email) | Serviceaccount email |
| <a name="output_serviceaccount_iam_email"></a> [serviceaccount\_iam\_email](#output\_serviceaccount\_iam\_email) | Serviceaccount IAM email |
| <a name="output_serviceaccount_members"></a> [serviceaccount\_members](#output\_serviceaccount\_members) | Serviceaccount members |
| <a name="output_serviceaccount_roles"></a> [serviceaccount\_roles](#output\_serviceaccount\_roles) | Serviceaccount roles |
<!-- END_TF_DOCS -->
26 changes: 26 additions & 0 deletions gcs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module "truefoundry_gcs" {
count = var.truefoundry_gcs_enabled ? 1 : 0
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "4.0.1"
project_id = var.project_id
name = local.truefoundry_blob_storage_name
location = var.region
force_destroy = var.truefoundry_gcs_force_destroy
labels = local.tags
public_access_prevention = "enforced"
cors = [{
origin = var.truefoundry_gcs_cors_origins
method = ["GET", "POST", "PUT"]
max_age_seconds = 3000
}]
lifecycle_rules = [
{
action = {
type = "AbortIncompleteMultipartUpload"
}
condition = {
age = "7"
}
}
]
}
25 changes: 25 additions & 0 deletions iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module "service_accounts" {
source = "terraform-google-modules/service-accounts/google"
version = "4.2.2"
project_id = var.project_id
names = [local.serviceaccount_name]
descriptions = ["Truefoundry serviceaccount for truefoundry control-plane components"]
display_name = "Terraform-managed truefoundry control-plane service account"
generate_keys = false
project_roles = local.serviceaccount_roles
}

# // binding the serviceaccount to k8s serviceaccount
module "service_account_iam_bindings" {
source = "terraform-google-modules/iam/google//modules/service_accounts_iam"
version = "7.7.1"
service_accounts = module.service_accounts.service_accounts[*].email
project = var.project_id
mode = "additive"
bindings = {
"roles/iam.workloadIdentityUser" = [
"serviceAccount:${var.project_id}.svc.id.goog[${var.svcfoundry_k8s_namespace}/${var.svcfoundry_k8s_service_account}]",
"serviceAccount:${var.project_id}.svc.id.goog[${var.mlfoundry_k8s_namespace}/${var.mlfoundry_k8s_service_account}]",
]
}
}
21 changes: 21 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
locals {
truefoundry_blob_storage_name = var.truefoundry_gcs_enable_override ? var.truefoundry_gcs_override_name : "${var.cluster_name}-truefoundry"
truefoundry_db_unique_name = var.truefoundry_db_enable_override ? var.truefoundry_db_override_name : "${var.cluster_name}-db"
serviceaccount_name = "${var.cluster_name}-sa"
serviceaccount_roles = [
"${var.project_id}=>roles/artifactregistry.admin",
"${var.project_id}=>roles/secretmanager.admin",
"${var.project_id}=>roles/iam.serviceAccountTokenCreator",
"${var.project_id}=>roles/storage.admin"
]
tags = merge({
"terraform-module" = "tfy-control-plane"
"terraform" = "true"
"cluster-name" = var.cluster_name
"truefoundry" = "managed"
},
var.tags
)
database_address = split("/", var.truefoundry_db_network_cidr)[0]
database_prefix = tonumber(split("/", var.truefoundry_db_network_cidr)[1])
}
14 changes: 14 additions & 0 deletions network.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "google_compute_global_address" "default" {
name = local.truefoundry_db_unique_name
address_type = "INTERNAL"
purpose = "VPC_PEERING"
network = var.vpc_id
prefix_length = local.database_prefix
address = local.database_address
}

resource "google_service_networking_connection" "default" {
network = var.vpc_id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [google_compute_global_address.default.name]
}
99 changes: 99 additions & 0 deletions output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
################################################################################
# Buket
################################################################################

output "bucket_name" {
value = var.truefoundry_gcs_enabled ? module.truefoundry_gcs[0].name : ""
description = "GCS bucket name"
}

output "bucket_url" {
value = var.truefoundry_gcs_enabled ? module.truefoundry_gcs[0].url : ""
description = "GCS bucket URL"
}

################################################################################
# IAM serviceaccount
################################################################################

output "serviceaccount_email" {
value = module.service_accounts.email
description = "Serviceaccount email"
}

output "serviceaccount_iam_email" {
value = module.service_accounts.iam_email
description = "Serviceaccount IAM email"
}

output "serviceaccount_detail" {
value = module.service_accounts.service_account
description = "Serviceaccount details"
}

output "serviceaccount_members" {
value = module.service_account_iam_bindings.members
description = "Serviceaccount members"
}

output "serviceaccount_roles" {
value = module.service_account_iam_bindings.roles
description = "Serviceaccount roles"
}

output "serviceaccount_binding_service_accounts" {
value = module.service_account_iam_bindings.service_accounts
description = "Serviceaccount bindings"
}

################################################################################
# Database
################################################################################


output "database_password" {
value = var.truefoundry_db_enable ? random_password.truefoundry_db_password[0].result : ""
sensitive = true
description = "Database's password"
}

output "instance_ip_address" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instance_ip_address : ""
description = "Database instance IP address"
}

output "instance_name" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instance_name : ""
description = "Database instance name"
}

output "instance_self_link" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instance_self_link : ""
description = "Self link of the database"
}

output "instance_server_ca_cert" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instance_server_ca_cert : ""
sensitive = true
description = "Self link of the database server ca cert"
}

output "instance_service_account_email_address" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instance_service_account_email_address : ""
description = "Service account email address"
}

output "instances" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].instances : ""
sensitive = true
}

output "primary" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].primary : ""
sensitive = true
}

output "private_ip_address" {
value = var.truefoundry_db_enable ? module.postgresql-db[0].private_ip_address : ""
description = "Private IP address of the database instance"
}
60 changes: 60 additions & 0 deletions postgres.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

resource "random_password" "truefoundry_db_password" {
count = var.truefoundry_db_enable ? 1 : 0
length = 42
special = true
override_special = "-_=+"
}

module "postgresql-db" {
source = "GoogleCloudPlatform/sql-db/google//modules/postgresql"
version = "19.0.0"

count = var.truefoundry_db_enable ? 1 : 0
name = local.truefoundry_db_unique_name
database_version = var.truefoundry_db_postgres_version
project_id = var.project_id

activation_policy = "ALWAYS"
availability_type = var.truefoundry_db_availability_type

backup_configuration = {
enabled = true
start_time = "20:55"
location = null # will store in multi-region by default
point_in_time_recovery_enabled = true
transaction_log_retention_days = "7"
retained_backups = 14
retention_unit = "COUNT"
}
db_charset = var.truefoundry_db_database_charset
db_collation = var.truefoundry_db_database_collation
db_name = var.truefoundry_db_database_name
deletion_protection = var.truefoundry_db_deletion_protection
disk_autoresize = var.truefoundry_db_disk_autoresize
disk_autoresize_limit = var.truefoundry_db_disk_autoresize_limit
disk_size = var.truefoundry_db_disk_size
disk_type = var.truefoundry_db_disk_type
edition = var.truefoundry_db_edition

ip_configuration = {
ipv4_enabled = false # recheck
private_network = var.vpc_id
require_ssl = false
allocated_ip_range = null
authorized_networks = [
{
name = "sample-gcp-health-checkers-range"
value = "130.211.0.0/28"
}
]
}
region = var.region
root_password = random_password.truefoundry_db_password[0].result
zone = var.truefoundry_db_zone
tier = var.truefoundry_db_tier
user_labels = local.tags
random_instance_name = true

depends_on = [google_service_networking_connection.default]
}
Loading

0 comments on commit 282bc2e

Please sign in to comment.