Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/pr-int-test-terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ jobs:
environment: dev
gcp_workload_identity_provider: ${{ vars.WORKLOAD_IDENTITY_PROVIDER }}
gcp_service_account: ${{ vars.SERVICE_ACCOUNT }}
- name: Authenticate with GKE
uses: entur/gha-meta/.github/actions/k8s-auth@v1
with:
environment: dev
- name: Run recursive Go integration tests
working-directory: test/integration
run: go test -tags=integration ./... -timeout 30m
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ A PostgreSQL module that uses the [init module](https://github.com/entur/terrafo
```terraform
module "postgresql" {
source = "github.com/entur/terraform-google-sql-db//modules/postgresql?ref=v1.7.4"
database_version = "POSTGRES_18" # Use the latest postgres version
...
}
```
Expand All @@ -42,13 +43,12 @@ If a desired machine size and/or availability type is not explicitly set, defaul
| non-production | Shared vCPU | <1 | 600 MB | No |
| production | Dedicated vCPU | 1 | 3840 MB | Yes |


### Edition

Changing this will cause a database restart on existing instances. Choosing **Enterprise Plus** (`ENTERPRISE_PLUS`) over **Enterprise** (`ENTERPRISE`) can also increase costs. Carefully evaluate your requirements before choosing this edition.

Ensure you select the appropriate tier for your use case. For more details about instance editions, refer to the [official documentation](https://cloud.google.com/sql/docs/postgres/instance-settings).


### Sizing

To specify the size of a database instance, supply the `cpu` and `memory` attributes in `var.machine_size` (recommended):
Expand Down Expand Up @@ -82,8 +82,6 @@ Run local integration tests in test/integration folder.
> Only Team-Plattform has rights to do this locally.
> Contributors can create a PR which will run the tests as well.

Make sure you are connected to the dev kubernetes cluster in GKE (kub-ent-dev-001)

```bash
cd test/integration
go test -v -tags=integration -timeout 30m ./...
Expand Down
7 changes: 4 additions & 3 deletions examples/minimal/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ module "init" {

# ci: x-release-please-start-version
module "postgresql" {
source = "github.com/entur/terraform-google-sql-db//modules/postgresql?ref=v1.7.4"
init = module.init
databases = ["my-database"]
source = "github.com/entur/terraform-google-sql-db//modules/postgresql?ref=v1.7.4"
database_version = "POSTGRES_18"
init = module.init
databases = ["my-database"]
}
# ci: x-release-please-end
15 changes: 4 additions & 11 deletions modules/postgresql/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=0.13.2 |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=1.3 |
| <a name="requirement_google"></a> [google](#requirement\_google) | >=5 |
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | ~> 2.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >=3.6.2 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | >=5 |
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | ~> 2.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >=3.6.2 |

## Modules
Expand All @@ -34,9 +32,6 @@ No modules.
| [google_sql_database_instance.main](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance) | resource |
| [google_sql_user.additional_users](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_user) | resource |
| [google_sql_user.main](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_user) | resource |
| [kubernetes_config_map.main_psql_connection](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/config_map) | resource |
| [kubernetes_secret.additional_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [kubernetes_secret.main_database_credentials](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
| [random_integer.additional_users_password_length](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource |
| [random_integer.password_length](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/integer) | resource |
| [random_password.additional_users_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |
Expand All @@ -46,17 +41,16 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_database_version"></a> [database\_version](#input\_database\_version) | The PostgreSQL version (see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance#database_version-1). | `string` | n/a | yes |
| <a name="input_databases"></a> [databases](#input\_databases) | Names of databases to create. | `list(string)` | n/a | yes |
| <a name="input_init"></a> [init](#input\_init) | Entur init module output. https://github.com/entur/terraform-google-init. Used to determine application name, application project, labels, and resource names. | <pre>object({<br/> app = object({<br/> id = string<br/> name = string<br/> owner = string<br/> project_id = string<br/> })<br/> networks = object({<br/> project_id = string<br/> vpc_id = string<br/> })<br/> environment = string<br/> labels = map(string)<br/> is_production = bool<br/> })</pre> | n/a | yes |
| <a name="input_add_additional_secret_manager_credentials"></a> [add\_additional\_secret\_manager\_credentials](#input\_add\_additional\_secret\_manager\_credentials) | Set to false to not store additional database credentials in secret manager | `bool` | `true` | no |
| <a name="input_add_main_secret_manager_credentials"></a> [add\_main\_secret\_manager\_credentials](#input\_add\_main\_secret\_manager\_credentials) | Set to false to not store main database credentials in secret manager | `bool` | `true` | no |
| <a name="input_additional_users"></a> [additional\_users](#input\_additional\_users) | A list of user-names in addition to the main user that should be created. | <pre>map(object({<br/> username = string<br/> create_kubernetes_secret = bool<br/> }))</pre> | `{}` | no |
| <a name="input_additional_users"></a> [additional\_users](#input\_additional\_users) | A list of user-names in addition to the main user that should be created. | <pre>map(object({<br/> username = string<br/> }))</pre> | `{}` | no |
| <a name="input_authorized_networks"></a> [authorized\_networks](#input\_authorized\_networks) | Values for authorized\_networks, list of objects with name and simple strings of IPs or CIDRs. Ex: {name: supermachine, value: 35.90.103.132/30} or {name: rogersmachine, value: 35.90.103.132} | <pre>list(object({<br/> value = string<br/> name = string<br/> }))</pre> | `[]` | no |
| <a name="input_availability_type"></a> [availability\_type](#input\_availability\_type) | Whether to enable high availability with automatic failover over multiple zones ('REGIONAL') vs. single zone ('ZONAL'). | `string` | `null` | no |
| <a name="input_backup_start_time"></a> [backup\_start\_time](#input\_backup\_start\_time) | Start time in UTC for daily backup job in the format HH:MM. This is the start time of a 4 hour time window. | `string` | `"00:00"` | no |
| <a name="input_create_kubernetes_resources"></a> [create\_kubernetes\_resources](#input\_create\_kubernetes\_resources) | Optionally disables creating k8s resources -psql-connection and -psql-credentials. Can be used to avoid overwriting existing resources on database creation. | `bool` | `true` | no |
| <a name="input_database_flags"></a> [database\_flags](#input\_database\_flags) | Override default CloudSQL configuration by specifying database-flags. Note that some flags require installing extensions. (see https://cloud.google.com/sql/docs/postgres/extensions#installing-an-extension). | <pre>map(object({<br/> name = string<br/> value = string<br/> }))</pre> | `{}` | no |
| <a name="input_database_version"></a> [database\_version](#input\_database\_version) | The PostgreSQL version (see https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance#database_version). | `string` | `"POSTGRES_14"` | no |
| <a name="input_deletion_protection"></a> [deletion\_protection](#input\_deletion\_protection) | Whether or not to allow Terraform to destroy the instance. | `bool` | `null` | no |
| <a name="input_disable_offsite_backup"></a> [disable\_offsite\_backup](#input\_disable\_offsite\_backup) | Disable offsite backup for this instance. Offsite backup is only applied to production environments. | `bool` | `false` | no |
| <a name="input_disk_autoresize"></a> [disk\_autoresize](#input\_disk\_autoresize) | Whether to enable auto-resizing of the storage disk. | `bool` | `true` | no |
Expand All @@ -66,7 +60,7 @@ No modules.
| <a name="input_enable_private_network"></a> [enable\_private\_network](#input\_enable\_private\_network) | Whether to enable private network connectivity for the Cloud SQL instance. Immutable after it has been enabled. | `bool` | `false` | no |
| <a name="input_generation"></a> [generation](#input\_generation) | The generation (aka serial no.) of the instance. Starts at 1, ends at 999. Will be padded with leading zeros. | `number` | `1` | no |
| <a name="input_instance_edition"></a> [instance\_edition](#input\_instance\_edition) | Override the default instance edition (`ENTERPRISE` or `ENTERPRISE_PLUS`). | `string` | `"ENTERPRISE"` | no |
| <a name="input_machine_size"></a> [machine\_size](#input\_machine\_size) | Map of the database instance CPU count (cpu) and memory sizes in MB (memory). Optionally, set a tier override (tier). See README.md for examples. | `map(any)` | `null` | no |
| <a name="input_machine_size"></a> [machine\_size](#input\_machine\_size) | Map of the database instance CPU count (cpu) and memory sizes in MB (memory). Optionally, set a tier override (tier). See README.md for examples. | <pre>object({<br/> tier = optional(string)<br/> cpu = optional(number)<br/> memory = optional(number)<br/> })</pre> | `null` | no |
| <a name="input_maintenance_window"></a> [maintenance\_window](#input\_maintenance\_window) | The day of the week (1-7), and hour of the day (0-24) in UTC to perform database instance maintenance. This is the start time of the one hour maintinance window. | <pre>object({<br/> day = number<br/> hour = number<br/> })</pre> | <pre>{<br/> "day": 2,<br/> "hour": 0<br/>}</pre> | no |
| <a name="input_point_in_time_recovery_enabled"></a> [point\_in\_time\_recovery\_enabled](#input\_point\_in\_time\_recovery\_enabled) | Whether to enable PITR on database instance. Requires enable\_backup to be true. | `bool` | `true` | no |
| <a name="input_query_insights_config"></a> [query\_insights\_config](#input\_query\_insights\_config) | Advanced config for Query Insights. | <pre>object({<br/> query_string_length = number<br/> record_application_tags = bool<br/> record_client_address = bool<br/> })</pre> | <pre>{<br/> "query_string_length": 1024,<br/> "record_application_tags": false,<br/> "record_client_address": false<br/>}</pre> | no |
Expand All @@ -86,6 +80,5 @@ No modules.
| <a name="output_databases"></a> [databases](#output\_databases) | Databases created on this instance. |
| <a name="output_init"></a> [init](#output\_init) | The output of the consumed init module. |
| <a name="output_instance"></a> [instance](#output\_instance) | The database instance output, as described in https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance. |
| <a name="output_kubernetes_namespace"></a> [kubernetes\_namespace](#output\_kubernetes\_namespace) | Name of the Kubernetes namespace where config maps and secrets are deployed. |
| <a name="output_user"></a> [user](#output\_user) | Map containing the username and password of the default application user. |
<!-- END_TF_DOCS -->
59 changes: 3 additions & 56 deletions modules/postgresql/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ locals {
# If updated, reflect changes in README.md
default_tiers = {
prod = "db-custom-1-3840"
non-prod = "db-f1-micro"
non-prod = "db-custom-1-3840"
}

user_name = var.user_name != null ? var.user_name : var.init.app.id
retained_backups = var.retained_backups != null ? var.retained_backups : var.init.is_production ? 30 : 7
deletion_protection = var.deletion_protection != null ? var.deletion_protection : var.init.is_production ? true : false
availability_type = var.availability_type != null ? var.availability_type : var.init.is_production ? "REGIONAL" : "ZONAL"
machine_size = var.machine_size != null ? try(var.machine_size.tier, "db-custom-${var.machine_size.cpu}-${var.machine_size.memory}") : var.init.is_production ? local.default_tiers.prod : local.default_tiers.non-prod
default_machine_size = var.init.is_production ? local.default_tiers.prod : local.default_tiers.non-prod
machine_size = var.machine_size != null ? var.machine_size.tier != null ? var.machine_size.tier : "db-custom-${var.machine_size.cpu}-${var.machine_size.memory}" : local.default_machine_size
offsite_backup_label = var.disable_offsite_backup == true && var.init.is_production ? { offsite_enabled = false } : {} # Add the label for opt-out of offsite backup in prod environments when disable_offsite_backup is true
labels = merge(var.init.labels, local.offsite_backup_label)
generation = format("%03d", var.generation)
disk_autoresize_limit = var.disk_autoresize_limit != null ? var.disk_autoresize_limit : var.init.is_production ? 500 : 50
additional_users = { for key, value in var.additional_users : key => value if value.username != local.user_name }
additional_user_credentials = !var.create_kubernetes_resources ? {} : { for key, value in local.additional_users : key => value if value.create_kubernetes_secret }
additional_sm_user_credentials = !var.add_additional_secret_manager_credentials ? {} : { for key, value in local.additional_users : key => value if var.add_additional_secret_manager_credentials }
}

Expand Down Expand Up @@ -108,21 +108,6 @@ resource "google_sql_user" "main" {
password = random_password.password.result
}

resource "kubernetes_config_map" "main_psql_connection" {
count = var.create_kubernetes_resources ? 1 : 0
depends_on = [
google_sql_database_instance.main
]
metadata {
name = "${var.init.app.name}-psql-connection"
namespace = var.init.app.name
labels = var.init.labels
}

data = {
INSTANCES = "${google_sql_database_instance.main.connection_name}=tcp:5432"
}
}
resource "random_integer" "password_length" {
min = 32
max = 64
Expand All @@ -133,24 +118,6 @@ resource "random_password" "password" {
override_special = "!#$%&*()-_=+[]{}<>:?"
}

resource "kubernetes_secret" "main_database_credentials" {
count = var.create_kubernetes_resources ? 1 : 0
depends_on = [
google_sql_database_instance.main
]
metadata {
name = "${var.init.app.name}-psql-credentials"
namespace = var.init.app.name
labels = var.init.labels
}
data = {
PGHOST = "localhost"
PGPORT = 5432
PGUSER = google_sql_user.main.name
PGPASSWORD = random_password.password.result
}
}

resource "google_sql_user" "additional_users" {
for_each = local.additional_users
name = each.value.username
Expand All @@ -172,28 +139,8 @@ resource "random_password" "additional_users_password" {
override_special = "!#$%&*()-_=+[]{}<>:?"
}

resource "kubernetes_secret" "additional_database_credentials" {
for_each = local.additional_user_credentials
depends_on = [
google_sql_database_instance.main
]
metadata {
name = "${var.init.app.name}-${each.value.username}-psql-credentials"
namespace = var.init.app.name
labels = var.init.labels
}
data = {
PGHOST = "localhost"
PGPORT = 5432
PGUSER = google_sql_user.additional_users[each.key].name
PGPASSWORD = random_password.additional_users_password[each.key].result
}
}

locals {
credentials = {
HOST = "localhost",
PORT = 5432,
USER = google_sql_user.main.name,
PASSWORD = random_password.password.result,
INSTANCES = google_sql_database_instance.main.connection_name
Expand Down
5 changes: 0 additions & 5 deletions modules/postgresql/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,3 @@ output "databases" {
description = "Databases created on this instance."
value = var.databases
}

output "kubernetes_namespace" {
description = "Name of the Kubernetes namespace where config maps and secrets are deployed."
value = var.create_kubernetes_resources ? kubernetes_secret.main_database_credentials[0].metadata[0].namespace : null
}
Loading
Loading