Resource Packs

Cloud

Example

Flavor

Feature

Postgres

Example: postgres resource based on Azure Database for PostgresSQL


Using this examples requires the “Enable Private Endpoints for PostgreSQL flexible servers” preview feature to be enabled.


Configuration

This example configures a postgres-instance and postgres Resource Definition using Azure Database for PostgreSQL - Flexible Server.

The postgres-instance represent the actual server and is provisioned only once for the entire environment.

Workloads use the postgres resource to dynamically create databases on this server, the respective score definition would look like:

resources:
  ...
  db:
    type: postgres

Infrastructure setup

graph TD;
    subgraph Database Resource Group
        subgraph server["Azure Database for PostgreSQL - Flexible Server"]
            database["SQL Database"]
        end
    end
    subgraph Workload Resource Group
       subgraph Workload Virtual Network
          pip["Private IP"]
          server -- private endpoint --> pip
          subgraph AKS Cluster
            workload-pod["Workload Pod"]
          end
            workload-pod --> pip
       end
    end

Orchestrator setup

graph LR;
    workload_1 --> db_1["db_1, resource_type: postgres"]
    workload_2 --> db_2["db_2, resource_type: postgres"]
    workload_2 --> shared.db_1["shared.db_1, resource_type: postgres"]
    workload_3 --> shared.db_1["shared.db_1, resource_type: postgres"]
    db_1 --> server["main-postgres, resource_type: postgres-instance"]
    db_2 --> server
    shared.db_1 --> server

Terraform docs

Requirements

Name Version
terraform >= 1.3.0
azuread ~> 2.47
azurerm ~> 3.91
humanitec ~> 1.0

Providers

Name Version
azuread ~> 2.47
azurerm ~> 3.91
humanitec ~> 1.0

Modules

Name Source Version
postgres ../../humanitec-resource-defs/postgres/basic n/a
postgres_instance ../../humanitec-resource-defs/postgres-instance/basic n/a

Resources

Name Type
azuread_application.humanitec_provisioner resource
azuread_service_principal.humanitec_provisioner resource
azuread_service_principal_password.humanitec_provisioner resource
azurerm_role_assignment.resource_group_resource resource
azurerm_role_assignment.resource_group_workload resource
humanitec_application.example resource
humanitec_resource_account.humanitec_provisioner resource
humanitec_resource_definition_criteria.postgres resource
humanitec_resource_definition_criteria.postgres_instance resource
azurerm_resource_group.resource data source
azurerm_resource_group.workload data source

Inputs

Name Description Type Default Required
resource_group_name Specifies the Name of the Resource Group within which this database will reside. string n/a yes
subnet_name The name of the subnet where the Private Endpoint will be allocated. string n/a yes
subscription_id The Subscription ID which should be used. string n/a yes
virtual_network_name The name of the virtual network where Private Endpoint will be allocated. string n/a yes
workload_resource_group_name The name of the resource group where the Private Endpoint will be allocated. string n/a yes
administrator_login The Administrator login for the PostgreSQL Server. string "" no
administrator_password The Password associated with the administrator_login for the PostgreSQL Server. string "" no
name Name of the example application. string "hum-rp-postgres-example" no
prefix Prefix of the created resources string "hum-rp-postgres-ex-" no
resource_packs_azure_rev Azure Resource Pack git branch. string "refs/heads/main" no
resource_packs_azure_url Azure Resource Pack git url. string "https://github.com/humanitec-architecture/resource-packs-azure.git" no

main.tf (view on GitHub) :

# Service principal used by Humanitec to provision resources
data "azurerm_resource_group" "resource" {
  name = var.resource_group_name
}

data "azurerm_resource_group" "workload" {
  name = var.workload_resource_group_name
}

resource "azuread_application" "humanitec_provisioner" {
  display_name = var.name
}

resource "azuread_service_principal" "humanitec_provisioner" {
  client_id = azuread_application.humanitec_provisioner.client_id
}

resource "azuread_service_principal_password" "humanitec_provisioner" {
  service_principal_id = azuread_service_principal.humanitec_provisioner.object_id
}

resource "azurerm_role_assignment" "resource_group_resource" {
  scope                = data.azurerm_resource_group.resource.id
  role_definition_name = "Contributor"
  principal_id         = azuread_service_principal.humanitec_provisioner.object_id
}

resource "azurerm_role_assignment" "resource_group_workload" {
  scope                = data.azurerm_resource_group.workload.id
  role_definition_name = "Contributor"
  principal_id         = azuread_service_principal.humanitec_provisioner.object_id
}

resource "humanitec_resource_account" "humanitec_provisioner" {
  id   = var.name
  name = var.name
  type = "azure"

  credentials = jsonencode({
    "appId" : azuread_service_principal.humanitec_provisioner.client_id,
    "displayName" : azuread_application.humanitec_provisioner.display_name,
    "password" : azuread_service_principal_password.humanitec_provisioner.value,
    "tenant" : azuread_service_principal.humanitec_provisioner.application_tenant_id
  })

  depends_on = [
    # Otherwise the account looses permissions before the resources are deleted
    azurerm_role_assignment.resource_group_resource,
    azurerm_role_assignment.resource_group_workload
  ]
}

# Example application and resource definition criteria

# Define the shared postgres-instance resource id and class
locals {
  postgres_instance_res_id = "main-postgres"
  postgres_instance_class  = "default"
}

resource "humanitec_application" "example" {
  id   = var.name
  name = var.name
}

module "postgres_instance" {
  source = "github.com/humanitec-architecture/resource-packs-azure?ref=v2024-06-14//humanitec-resource-defs/postgres-instance/basic"

  prefix                       = var.prefix
  resource_packs_azure_url     = var.resource_packs_azure_url
  resource_packs_azure_rev     = var.resource_packs_azure_rev
  append_logs_to_error         = true
  driver_account               = humanitec_resource_account.humanitec_provisioner.id
  subscription_id              = var.subscription_id
  resource_group_name          = data.azurerm_resource_group.resource.name
  administrator_login          = var.administrator_login
  administrator_password       = var.administrator_password
  virtual_network_name         = var.virtual_network_name
  subnet_name                  = var.subnet_name
  workload_resource_group_name = data.azurerm_resource_group.workload.name
}

resource "humanitec_resource_definition_criteria" "postgres_instance" {
  resource_definition_id = module.postgres_instance.id
  app_id                 = humanitec_application.example.id
  res_id                 = local.postgres_instance_res_id
  class                  = local.postgres_instance_class

  force_delete = true
}

module "postgres" {
  source = "github.com/humanitec-architecture/resource-packs-azure?ref=v2024-06-14//humanitec-resource-defs/postgres/basic"

  prefix                   = var.prefix
  resource_packs_azure_url = var.resource_packs_azure_url
  resource_packs_azure_rev = var.resource_packs_azure_rev
  append_logs_to_error     = true
  driver_account           = humanitec_resource_account.humanitec_provisioner.id
  subscription_id          = var.subscription_id
  instance_resource        = "postgres-instance.${local.postgres_instance_class}#${local.postgres_instance_res_id}"
}

resource "humanitec_resource_definition_criteria" "postgres" {
  resource_definition_id = module.postgres.id
  app_id                 = humanitec_application.example.id

  force_delete = true
}


providers.tf (view on GitHub) :

terraform {
  required_providers {
    azuread = {
      source  = "hashicorp/azuread"
      version = "~> 2.47"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.91"
    }
    humanitec = {
      source  = "humanitec/humanitec"
      version = "~> 1.0"
    }
  }

  required_version = ">= 1.3.0"
}

provider "humanitec" {
}

provider "azuread" {
}

provider "azurerm" {
  features {}

  subscription_id = var.subscription_id
}


terraform.tfvars.example (view on GitHub) :


# The Administrator login for the PostgreSQL Server.
administrator_login = ""

# The Password associated with the administrator_login for the PostgreSQL Server.
administrator_password = ""

# Name of the example application.
name = "hum-rp-postgres-example"

# Prefix of the created resources
prefix = "hum-rp-postgres-ex-"

# Specifies the Name of the Resource Group within which this database will reside.
resource_group_name = ""

# Azure Resource Pack git branch.
resource_packs_azure_rev = "refs/tags/v2024-06-14"

# Azure Resource Pack git url.
resource_packs_azure_url = "https://github.com/humanitec-architecture/resource-packs-azure.git"

# The name of the subnet where the Private Endpoint will be allocated.
subnet_name = ""

# The Subscription ID which should be used.
subscription_id = ""

# The name of the virtual network where Private Endpoint will be allocated.
virtual_network_name = ""

# The name of the resource group where the Private Endpoint will be allocated.
workload_resource_group_name = ""

variables.tf (view on GitHub) :

variable "prefix" {
  description = "Prefix of the created resources"
  type        = string
  default     = "hum-rp-postgres-ex-"
}

variable "name" {
  description = "Name of the example application."
  type        = string
  default     = "hum-rp-postgres-example"
}

variable "resource_packs_azure_url" {
  description = "Azure Resource Pack git url."
  type        = string
  default     = "https://github.com/humanitec-architecture/resource-packs-azure.git"
}

variable "resource_packs_azure_rev" {
  description = "Azure Resource Pack git branch."
  type        = string
  default     = "refs/tags/v2024-06-14"
}

variable "subscription_id" {
  description = "The Subscription ID which should be used."
  type        = string
}

variable "resource_group_name" {
  description = "Specifies the Name of the Resource Group within which this database will reside."
  type        = string
}

variable "administrator_login" {
  description = "The Administrator login for the PostgreSQL Server."
  type        = string
  default     = ""
}

variable "administrator_password" {
  description = "The Password associated with the administrator_login for the PostgreSQL Server."
  type        = string
  default     = ""
}

variable "virtual_network_name" {
  description = "The name of the virtual network where Private Endpoint will be allocated."
  type        = string
}

variable "subnet_name" {
  description = "The name of the subnet where the Private Endpoint will be allocated."
  type        = string
}

variable "workload_resource_group_name" {
  description = "The name of the resource group where the Private Endpoint will be allocated."
  type        = string
}

Top