commit 910af220c6a70be90b5c155aa82320b10dbd8efe Author: Tine Date: Fri Mar 1 15:11:34 2024 +0100 first commit diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..84fc8e5 --- /dev/null +++ b/.envrc @@ -0,0 +1,7 @@ +# Automatically sets up your devbox environment whenever you cd into this +# directory via our direnv integration: + +eval "$(devbox generate direnv --print-envrc)" + +# check out https://www.jetpack.io/devbox/docs/ide_configuration/direnv/ +# for more details diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca16f2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +dist/ +.venv/ + +.env + +.terraform +terraform.tfstate* + +__pycache__ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6b320ce --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +# syntax=docker/dockerfile:1.4 +FROM python:3.10-alpine + +WORKDIR /app + +COPY requirements.txt /app +RUN pip3 install -r requirements.txt + +COPY src /app + +ENTRYPOINT [ "python3" ] +CMD [ "app.py" ] diff --git a/devbox.json b/devbox.json new file mode 100644 index 0000000..f3663df --- /dev/null +++ b/devbox.json @@ -0,0 +1,24 @@ +{ + "packages": [ + "just@latest", + "python@3.12", + "python312Packages.pip@latest", + "terraform@latest", + "azure-cli@latest", + "azure-functions-core-tools@latest" + ], + "env": { + "VENV_DIR": ".venv" + }, + "shell": { + "init_hook": [ + ". $VENV_DIR/bin/activate", + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "test": [ + "echo \"Error: no test specified\" && exit 1" + ] + } + } +} diff --git a/devbox.lock b/devbox.lock new file mode 100644 index 0000000..48a9a2e --- /dev/null +++ b/devbox.lock @@ -0,0 +1,110 @@ +{ + "lockfile_version": "1", + "packages": { + "azure-cli@latest": { + "last_modified": "2024-02-26T19:46:43Z", + "resolved": "github:NixOS/nixpkgs/548a86b335d7ecd8b57ec617781f5e652ab0c38e#azure-cli", + "source": "devbox-search", + "version": "2.56.0", + "systems": { + "aarch64-darwin": { + "store_path": "/nix/store/dnbzp85nka7wdd3gdk4a7s0vgcv7f3ix-python3.11-azure-cli-2.56.0" + }, + "aarch64-linux": { + "store_path": "/nix/store/m7d0fwpw7zhsnhbr9b67qf780yrficgj-python3.11-azure-cli-2.56.0" + }, + "x86_64-darwin": { + "store_path": "/nix/store/l5kklfbbk9n9i3kj7vzqg4pmmcxy8z77-python3.11-azure-cli-2.56.0" + }, + "x86_64-linux": { + "store_path": "/nix/store/f96pm8sbihjd7cy98f5xyqn54gjfb1ys-python3.11-azure-cli-2.56.0" + } + } + }, + "azure-functions-core-tools@latest": { + "last_modified": "2024-02-26T19:46:43Z", + "resolved": "github:NixOS/nixpkgs/548a86b335d7ecd8b57ec617781f5e652ab0c38e#azure-functions-core-tools", + "source": "devbox-search", + "version": "4.0.5455", + "systems": { + "aarch64-darwin": { + "store_path": "/nix/store/90khpfynpfcxyiflvxj1nw605cc5ndsd-azure-functions-core-tools-4.0.5455" + }, + "x86_64-darwin": { + "store_path": "/nix/store/7n08wfcxk1by25787pw13gi8yk9ql3fb-azure-functions-core-tools-4.0.5455" + }, + "x86_64-linux": { + "store_path": "/nix/store/yb2av5h85h3h76rq0yy9l7wmyipwcyk9-azure-functions-core-tools-4.0.5455" + } + } + }, + "just@latest": { + "last_modified": "2024-02-26T19:46:43Z", + "resolved": "github:NixOS/nixpkgs/548a86b335d7ecd8b57ec617781f5e652ab0c38e#just", + "source": "devbox-search", + "version": "1.24.0", + "systems": { + "aarch64-darwin": { + "store_path": "/nix/store/4y0018ypsv9psa73sz6na2806ndpx5sf-just-1.24.0" + }, + "aarch64-linux": { + "store_path": "/nix/store/gafx9wd70rzrk16jwm1fdmvs0y15knzk-just-1.24.0" + }, + "x86_64-darwin": { + "store_path": "/nix/store/imhg52m87050xjs76mkdlql422n28kvg-just-1.24.0" + }, + "x86_64-linux": { + "store_path": "/nix/store/92k9inba4i5bs7cp0kh99y1f93v407v0-just-1.24.0" + } + } + }, + "python312Packages.pip@latest": { + "last_modified": "2024-02-26T19:46:43Z", + "plugin_version": "0.0.2", + "resolved": "github:NixOS/nixpkgs/548a86b335d7ecd8b57ec617781f5e652ab0c38e#python312Packages.pip", + "source": "devbox-search", + "version": "23.3.1", + "systems": { + "aarch64-darwin": { + "store_path": "/nix/store/mbjlr4zvqp2sn8xikz10cdsxhx4sj4z6-python3.12-pip-23.3.1" + }, + "aarch64-linux": { + "store_path": "/nix/store/2c4w8x04jczy8jjrkin25920100yapyn-python3.12-pip-23.3.1" + }, + "x86_64-darwin": { + "store_path": "/nix/store/fksz4hvb5f5snyy3n01fmwlqjb4dayjc-python3.12-pip-23.3.1" + }, + "x86_64-linux": { + "store_path": "/nix/store/xc1wzb3gvj5a4djwimldwgvlhv31qxs3-python3.12-pip-23.3.1" + } + } + }, + "python@3.12": { + "last_modified": "2024-02-26T19:46:43Z", + "plugin_version": "0.0.3", + "resolved": "github:NixOS/nixpkgs/548a86b335d7ecd8b57ec617781f5e652ab0c38e#python312", + "source": "devbox-search", + "version": "3.12.2", + "systems": { + "aarch64-darwin": { + "store_path": "/nix/store/15k5wj7q3psakinjs1czl6fdfghi5k6d-python3-3.12.2" + }, + "aarch64-linux": { + "store_path": "/nix/store/ks2j3hf91drxzbizlaiyxhbzcjbp015v-python3-3.12.2" + }, + "x86_64-darwin": { + "store_path": "/nix/store/x69mapgywbfgg8p4fdqy76lg0h9gf2kj-python3-3.12.2" + }, + "x86_64-linux": { + "store_path": "/nix/store/n3jf1lkdfakxskzsm4nlhss8mdgmcqhc-python3-3.12.2" + } + } + }, + "terraform@latest": { + "last_modified": "2024-02-24T23:06:34Z", + "resolved": "github:NixOS/nixpkgs/9a9dae8f6319600fa9aebde37f340975cab4b8c0#terraform", + "source": "devbox-search", + "version": "1.7.4" + } + } +} diff --git a/example.env b/example.env new file mode 100644 index 0000000..409730c --- /dev/null +++ b/example.env @@ -0,0 +1,2 @@ +# Name of the app +APP_NAME=python-azure-example diff --git a/justfile b/justfile new file mode 100644 index 0000000..7e08cf6 --- /dev/null +++ b/justfile @@ -0,0 +1,25 @@ +# Always use devbox environment to run commands. +set shell := ["devbox", "run"] +# Load dotenv +set dotenv-load + +export TF_VAR_name := env("APP_NAME") + +# Run server locally +run: + flask --app src/server run + +dependencies: + pip install -r src/requirements.txt + +dependencies-lock: + pip freeze -l > src/requirements.txt + +deploy: + +terraform-apply: + terraform -chdir=terraform init + terraform -chdir=terraform apply + +terraform-destroy: + terraform -chdir=terraform destroy diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d40fb70 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +blinker==1.7.0 +click==8.1.7 +Flask==3.0.2 +itsdangerous==2.1.2 +Werkzeug==3.0.1 diff --git a/src/app.py b/src/app.py new file mode 100644 index 0000000..8aa1c4e --- /dev/null +++ b/src/app.py @@ -0,0 +1,11 @@ +from flask import Flask + +app = Flask(__name__) + +@app.route("/health") +def health(): + return "OK" + +@app.route("/") +def hello_world(): + return "

Hello, World!

" diff --git a/terraform/.terraform.lock.hcl b/terraform/.terraform.lock.hcl new file mode 100644 index 0000000..59a6cca --- /dev/null +++ b/terraform/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/azurerm" { + version = "3.94.0" + constraints = "3.94.0" + hashes = [ + "h1:a51ZYUp5uuboql399mflWZDrErlhhYz0ujJFsc9gjhg=", + "zh:20d102bc63096ade82f8da81c91afaffa858aa56fe9a7ad02f24f5ae5618bc53", + "zh:3ddb9d6173a4fdb9b2352a76324ee321976915544ae66cbb863c7a60f0593f05", + "zh:4bc6c62142f67192d2def11f4fd419c54dddd89a5448af036bfc60b15eb0509a", + "zh:4c5120c2101a51524af32c4220c5e376f97a227730dd92ec0b06ac677e4b39f2", + "zh:585fa7ab876d09899cd2d842f12bc28c34556b4d47919eceadefab6fa47f909f", + "zh:59de7ea462470dee7088fc4deeff48e1ffd286eaca1185c219be68dadde745b8", + "zh:8421a46dd3bc4bc2eb56f7eb9b91cc84a66070b72195a805862c6022adee2da0", + "zh:a2fcb5a091d5944dc50f1e51f53fa4d370810a507fbf4122920d756083d8df19", + "zh:beb6b93a2a16942625bb6ac1e52bf26878e35f5562f3173279423ca66553b6d7", + "zh:c6846892ea68f49c838d90b75793d1f3a866871dd701ccb575b1eecccd4e7051", + "zh:ddd59492b6d5ce4c83f06a5b16c520048f3e9bb898bab4f3910042f5c01ffeda", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..ec8ec56 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,67 @@ +resource "azurerm_resource_group" "main" { + name = var.name + location = "West Europe" +} + +## +# Database +## +resource "azurerm_postgresql_server" "main" { + name = var.name + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + + administrator_login = "psqladmin" + administrator_login_password = "H@Sh1CoR3!" + + sku_name = "B_Gen5_1" + version = "11" + storage_mb = 5120 + + public_network_access_enabled = true + ssl_enforcement_enabled = true + ssl_minimal_tls_version_enforced = "TLS1_2" +} + +## +# Container Registry +## +resource "azurerm_container_registry" "main" { + name = replace(var.name, "-", "") + resource_group_name = azurerm_resource_group.main.name + location = azurerm_resource_group.main.location + sku = "Basic" +} + +## +# Application +## +resource "azurerm_log_analytics_workspace" "main" { + name = var.name + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + sku = "PerGB2018" + retention_in_days = 30 +} + +resource "azurerm_container_app_environment" "main" { + name = var.name + location = azurerm_resource_group.main.location + resource_group_name = azurerm_resource_group.main.name + log_analytics_workspace_id = azurerm_log_analytics_workspace.main.id +} +resource "azurerm_container_app" "main" { + name = var.name + container_app_environment_id = azurerm_container_app_environment.main.id + resource_group_name = azurerm_resource_group.main.name + revision_mode = "Single" + + template { + container { + name = "maincontainerapp" + image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest" + cpu = 0.25 + memory = "0.5Gi" + } + } +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..59ebba7 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,3 @@ +output "database_fqdn" { + value = azurerm_postgresql_server.main.fqdn +} diff --git a/terraform/providers.tf b/terraform/providers.tf new file mode 100644 index 0000000..0c5d37d --- /dev/null +++ b/terraform/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "3.94.0" + } + } +} + +provider "azurerm" { + features {} +} diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..3be12d2 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,4 @@ +variable "name" { + description = "The name of the application" + type = string +}