|
| 1 | +# Azure Database for PostgreSQL Flexible Server |
| 2 | + |
| 3 | +This sample demonstrates a Notes web application with full-text search, powered by [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/overview). The app is a Python Flask single-page application that creates, searches, and deletes notes stored in the `notes` table within the `sampledb` database on a PostgreSQL Flexible Server instance. The sample also includes Python and C# Azure SDK management demos that exercise server, database, configuration, and firewall rule operations. |
| 4 | + |
| 5 | +## Architecture |
| 6 | + |
| 7 | +The following diagram illustrates the architecture of the solution: |
| 8 | + |
| 9 | +```mermaid |
| 10 | +graph TB |
| 11 | + subgraph IaC["Infrastructure as Code"] |
| 12 | + CLI["Azure CLI<br/>(azlocal)"] |
| 13 | + Bicep["Bicep<br/>(main.bicep)"] |
| 14 | + TF["Terraform<br/>(main.tf)"] |
| 15 | + end |
| 16 | +
|
| 17 | + subgraph LS["LocalStack for Azure"] |
| 18 | + MGMT["Management API<br/>(ARM / REST)"] |
| 19 | + PG_SERVER["PostgreSQL Flexible Server"] |
| 20 | + subgraph DBs["Databases"] |
| 21 | + SAMPLEDB["sampledb"] |
| 22 | + ANALYTICSDB["analyticsdb"] |
| 23 | + end |
| 24 | + FW["Firewall Rules<br/>allow-all · corporate · vpn"] |
| 25 | + end |
| 26 | +
|
| 27 | + subgraph DC["Docker Compose Containers"] |
| 28 | + NOTES["Notes App<br/>(Flask · port 5001)"] |
| 29 | + SDK_PY["Python SDK Demo<br/>(azure-mgmt-postgresql)"] |
| 30 | + SDK_CS["C# SDK Demo<br/>(Azure.ResourceManager)"] |
| 31 | + end |
| 32 | +
|
| 33 | + USER((User<br/>Browser)) |
| 34 | +
|
| 35 | + CLI -->|provision| MGMT |
| 36 | + Bicep -->|provision| MGMT |
| 37 | + TF -->|provision| MGMT |
| 38 | + MGMT --> PG_SERVER |
| 39 | + PG_SERVER --> DBs |
| 40 | + PG_SERVER --> FW |
| 41 | +
|
| 42 | + USER -->|"http://localhost:5001"| NOTES |
| 43 | + NOTES <-->|"psycopg2 · CRUD + full-text search"| SAMPLEDB |
| 44 | +
|
| 45 | + SDK_PY -->|"management plane<br/>list servers · configs · DBs · rules"| MGMT |
| 46 | + SDK_PY -->|"psycopg2 · direct query"| SAMPLEDB |
| 47 | + SDK_PY -->|"POST results to UI"| NOTES |
| 48 | +
|
| 49 | + SDK_CS -->|"management plane<br/>ArmClient · list · get"| MGMT |
| 50 | + SDK_CS -->|"Npgsql · direct query"| SAMPLEDB |
| 51 | + SDK_CS -->|"POST results to UI"| NOTES |
| 52 | +
|
| 53 | + USER -.->|"trigger SDK demo"| NOTES |
| 54 | + NOTES -.->|"trigger signal"| SDK_PY |
| 55 | + NOTES -.->|"trigger signal"| SDK_CS |
| 56 | +``` |
| 57 | + |
| 58 | +- **Azure Database for PostgreSQL Flexible Server**: Managed PostgreSQL database server hosting the `sampledb` and `analyticsdb` databases |
| 59 | +- **Notes App (Flask)**: Python Flask web application with full-text search using PostgreSQL `tsvector` |
| 60 | +- **Python SDK Demo**: Demonstrates `azure-mgmt-postgresqlflexibleservers` management operations (list servers, get/update configurations, list databases, manage firewall rules, check name availability) |
| 61 | +- **C# SDK Demo**: Demonstrates `Azure.ResourceManager.PostgreSql` management operations from .NET |
| 62 | + |
| 63 | +## Prerequisites |
| 64 | + |
| 65 | +- [Azure Subscription](https://azure.microsoft.com/free/) |
| 66 | +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) |
| 67 | +- [Python 3.12+](https://www.python.org/downloads/) |
| 68 | +- [Docker](https://docs.docker.com/get-docker/) |
| 69 | +- [Bicep extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep), if you plan to install the sample via Bicep. |
| 70 | +- [Terraform](https://developer.hashicorp.com/terraform/downloads), if you plan to install the sample via Terraform. |
| 71 | + |
| 72 | +## Deployment |
| 73 | + |
| 74 | +Set up the Azure emulator using the LocalStack for Azure Docker image. Before starting, ensure you have a valid `LOCALSTACK_AUTH_TOKEN` to access the Azure emulator. Refer to the [Auth Token guide](https://docs.localstack.cloud/getting-started/auth-token/) to obtain your Auth Token and set it in the `LOCALSTACK_AUTH_TOKEN` environment variable. The Azure Docker image is available on the [LocalStack Docker Hub](https://hub.docker.com/r/localstack/localstack-azure-alpha). To pull the image, execute: |
| 75 | + |
| 76 | +```bash |
| 77 | +docker pull localstack/localstack-azure-alpha |
| 78 | +``` |
| 79 | + |
| 80 | +Start the LocalStack Azure emulator by running: |
| 81 | + |
| 82 | +```bash |
| 83 | +export LOCALSTACK_AUTH_TOKEN=<your_auth_token> |
| 84 | +IMAGE_NAME=localstack/localstack-azure-alpha localstack start |
| 85 | +``` |
| 86 | + |
| 87 | +Deploy the application to LocalStack for Azure using one of these methods: |
| 88 | + |
| 89 | +- [Azure CLI Deployment](./scripts/README.md) |
| 90 | +- [Bicep Deployment](./bicep/README.md) |
| 91 | +- [Terraform Deployment](./terraform/README.md) |
| 92 | + |
| 93 | +All deployment methods have been fully tested against Azure and the LocalStack for Azure local emulator. |
| 94 | + |
| 95 | +> **Note** |
| 96 | +> When you deploy the application to LocalStack for Azure for the first time, the initialization process involves downloading and building Docker images. This is a one-time operation—subsequent deployments will be significantly faster. Depending on your internet connection and system resources, this initial setup may take several minutes. |
| 97 | +
|
| 98 | +## Test |
| 99 | + |
| 100 | +After provisioning the PostgreSQL Flexible Server infrastructure using any of the deployment methods above, launch the application containers using Docker Compose: |
| 101 | + |
| 102 | +```bash |
| 103 | +cd samples/postgresql-flexible-server/python |
| 104 | + |
| 105 | +# Set environment variables (adjust values based on your deployment outputs) |
| 106 | +export RESOURCE_GROUP="rg-pgflex" |
| 107 | +export SERVER_NAME="pgflex-sample" |
| 108 | +export PG_HOST="host.docker.internal" |
| 109 | +export PG_PORT="5432" |
| 110 | +export PG_USER="pgadmin" |
| 111 | +export PG_PASSWORD="P@ssw0rd12345!" |
| 112 | +export PG_DATABASE="sampledb" |
| 113 | +export FLASK_PORT="5001" |
| 114 | + |
| 115 | +docker compose up --build |
| 116 | +``` |
| 117 | + |
| 118 | +Open a web browser and navigate to `http://localhost:5001`. If the deployment was successful, you will see the Notes application with full-text search and Azure SDK demo panels. |
| 119 | + |
| 120 | +You can use the `validate.sh` Bash script below to verify that all Azure resources were created and configured correctly: |
| 121 | + |
| 122 | +```bash |
| 123 | +#!/bin/bash |
| 124 | + |
| 125 | +# Variables |
| 126 | +RESOURCE_GROUP='rg-pgflex' |
| 127 | +SERVER_NAME='pgflex-sample' |
| 128 | +PRIMARY_DB='sampledb' |
| 129 | +SECONDARY_DB='analyticsdb' |
| 130 | +ENVIRONMENT=$(az account show --query environmentName --output tsv) |
| 131 | + |
| 132 | +# Choose the appropriate CLI based on the environment |
| 133 | +if [[ $ENVIRONMENT == "LocalStack" ]]; then |
| 134 | + echo "Using azlocal for LocalStack emulator environment." |
| 135 | + AZ="azlocal" |
| 136 | +else |
| 137 | + echo "Using standard az for AzureCloud environment." |
| 138 | + AZ="az" |
| 139 | +fi |
| 140 | + |
| 141 | +# Check resource group |
| 142 | +echo "=== Resource Group ===" |
| 143 | +$AZ group show \ |
| 144 | + --name "$RESOURCE_GROUP" \ |
| 145 | + --output table |
| 146 | + |
| 147 | +# List resources in the resource group |
| 148 | +echo "" |
| 149 | +echo "=== Resources ===" |
| 150 | +$AZ resource list \ |
| 151 | + --resource-group "$RESOURCE_GROUP" \ |
| 152 | + --output table |
| 153 | + |
| 154 | +# Check PostgreSQL Flexible Server |
| 155 | +echo "" |
| 156 | +echo "=== PostgreSQL Flexible Server ===" |
| 157 | +$AZ postgres flexible-server show \ |
| 158 | + --name "$SERVER_NAME" \ |
| 159 | + --resource-group "$RESOURCE_GROUP" \ |
| 160 | + --output table |
| 161 | + |
| 162 | +# List databases |
| 163 | +echo "" |
| 164 | +echo "=== Databases ===" |
| 165 | +$AZ postgres flexible-server db list \ |
| 166 | + --server-name "$SERVER_NAME" \ |
| 167 | + --resource-group "$RESOURCE_GROUP" \ |
| 168 | + --output table |
| 169 | + |
| 170 | +# List firewall rules |
| 171 | +echo "" |
| 172 | +echo "=== Firewall Rules ===" |
| 173 | +$AZ postgres flexible-server firewall-rule list \ |
| 174 | + --server-name "$SERVER_NAME" \ |
| 175 | + --resource-group "$RESOURCE_GROUP" \ |
| 176 | + --output table |
| 177 | +``` |
| 178 | + |
| 179 | +## PostgreSQL Tooling |
| 180 | + |
| 181 | +You can use [pgAdmin](https://www.pgadmin.org/) to explore and manage your PostgreSQL databases. When connecting, specify `localhost` as the host and use the port published by the PostgreSQL container on the host, mapped to the internal PostgreSQL port `5432`. |
| 182 | + |
| 183 | +Alternatively, you can use the [psql](https://www.postgresql.org/docs/current/app-psql.html) command-line tool to interact with and administer your PostgreSQL instance, as shown below: |
| 184 | + |
| 185 | +```bash |
| 186 | +~$ psql -h localhost -p 49114 -U pgadmin -d sampledb |
| 187 | +Password for user pgadmin: |
| 188 | +psql (16.0) |
| 189 | +Type "help" for help. |
| 190 | + |
| 191 | +sampledb=# SELECT id, title, SUBSTRING(content, 1, 30) FROM notes; |
| 192 | + id | title | substring |
| 193 | +----+----------------+-------------------------------- |
| 194 | + 1 | Meeting Notes | Discussed Q4 planning and bud |
| 195 | + 2 | Shopping List | Eggs, milk, bread, butter, ch |
| 196 | + 3 | Project Ideas | Build a notes app with full-te |
| 197 | +(3 rows) |
| 198 | +``` |
| 199 | + |
| 200 | +## References |
| 201 | + |
| 202 | +- [Azure Database for PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/overview) |
| 203 | +- [Azure CLI — PostgreSQL Flexible Server](https://learn.microsoft.com/en-us/cli/azure/postgres/flexible-server) |
| 204 | +- [Terraform — azurerm_postgresql_flexible_server](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/postgresql_flexible_server) |
| 205 | +- [Azure Identity Client Library for Python](https://learn.microsoft.com/en-us/python/api/overview/azure/identity-readme?view=azure-python) |
| 206 | +- [LocalStack for Azure](https://azure.localstack.cloud/) |
0 commit comments