Skip to content

Commit 8d1e123

Browse files
committed
upd: README
1 parent 96fe4c9 commit 8d1e123

1 file changed

Lines changed: 118 additions & 49 deletions

File tree

README.md

Lines changed: 118 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,41 @@ Back up and restore NHP Azure Table Storage (ATS) via JSON snapshots in Blob Sto
1010

1111
## Configuration
1212

13-
Create a `.env` file in the repo root:
13+
Create a `.env` file in the repo root by copying and filling in the values below:
1414

1515
```bash
16-
export AZURE_STORAGE_ACCOUNT_NAME=<storage_name>
17-
export PROD_TABLE_NAME=<ats_name>
18-
export BACKUP_CONTAINER_NAME=<backup_container_name>
19-
export DEV_TABLE_NAME=<ats_dev_name>
16+
# Azure resources
17+
AZURE_STORAGE_ACCOUNT_NAME=<storage-name> # Globally unique, lowercase letters+numbers, 3-24 chars
18+
AZURE_RESOURCE_GROUP_NAME=<resource-group> # Existing resource group where resources are created
19+
AZURE_LOCATION=<region> # e.g. australiaeast; pick one near your users
20+
21+
# Storage configuration
22+
AZURE_SKU=Standard_LRS # Cheapest; fine for dev/test and small prod workloads
23+
AZURE_STORAGE_KIND=StorageV2 # General-purpose v2; supports blobs, queues, tables
24+
25+
# Backup targets
26+
PROD_TABLE_NAME=<ats-name> # Production Azure Table Storage table to back up
27+
BACKUP_CONTAINER_NAME=<backup-container-name> # Blob container for JSON snapshots
28+
DEV_TABLE_NAME=<ats-dev-name> # Dev/test table for safe restore experiments
29+
30+
# Function App
31+
AZURE_FUNCTION_APP_NAME=<function-app-name> # Globally unique, used in URLs and deployment
32+
AZURE_PYTHON_VERSION=3.13 # Max version supported by Azure Functions; 3.14 is still in preview
33+
AZURE_FUNCTION_INSTANCE_MEMORY=2048 # Flex Consumption memory in MB; 2048 is a good default
2034
```
2135

2236
Windows users should omit `export` or use `set` instead.
37+
Notice that `AZURE_SKU` and `AZURE_STORAGE_KIND` default to `Standard_LRS` and `StorageV2` if omitted.
2338

2439
## Quick deploy
2540

41+
42+
### Automated deploy
43+
44+
Run `uv run deploy.py` to interactively create the resource group, storage account,
45+
Function App, backup container, app settings, and publish the functions.
46+
Add `--yes` to skip confirmation prompts.
47+
2648
This project uses **Azure Functions on Flex Consumption** (Python 3.13).
2749

2850
### 1. Generate `requirements.txt`
@@ -33,7 +55,7 @@ Azure's remote build uses pip, not uv. Compile a lockfile before every deploy:
3355
uv pip compile pyproject.toml -o requirements.txt
3456
```
3557

36-
### 1.5. Prepare `.funcignore`
58+
### 2. Prepare `.funcignore`
3759

3860
Ensure `.funcignore` exists so the publish step skips your local venv and build artefacts:
3961

@@ -51,10 +73,64 @@ tests/
5173
.github/
5274
```
5375

54-
### 2. Publish
76+
### 3. Azure resources and app settings
77+
78+
<details>
79+
<summary><b>Click to expand: create storage account, Function App, and configure app settings</b></summary>
80+
81+
Create the storage account. The name must be globally unique, lowercase letters and numbers only, 3–24 characters.
82+
83+
```bash
84+
az storage account create \
85+
--name "$AZURE_STORAGE_ACCOUNT_NAME" \
86+
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
87+
--location "$AZURE_LOCATION" \
88+
--sku "$AZURE_SKU" \
89+
--kind "$AZURE_STORAGE_KIND"
90+
```
91+
92+
Create the backup container:
5593

5694
```bash
57-
func azure functionapp publish <function-app-name>
95+
az storage container create \
96+
--name "$BACKUP_CONTAINER_NAME" \
97+
--account-name "$AZURE_STORAGE_ACCOUNT_NAME" \
98+
--auth-mode login
99+
```
100+
101+
Create the Function App:
102+
103+
```bash
104+
az functionapp create \
105+
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
106+
--name "$AZURE_FUNCTION_APP_NAME" \
107+
--storage-account "$AZURE_STORAGE_ACCOUNT_NAME" \
108+
--flexconsumption-location "$AZURE_LOCATION" \
109+
--runtime python \
110+
--runtime-version "$AZURE_PYTHON_VERSION" \
111+
--functions-version 4 \
112+
--instance-memory "$AZURE_FUNCTION_INSTANCE_MEMORY"
113+
```
114+
115+
Configure app settings:
116+
117+
```bash
118+
az functionapp config appsettings set \
119+
--name "$AZURE_FUNCTION_APP_NAME" \
120+
--resource-group "$AZURE_RESOURCE_GROUP_NAME" \
121+
--settings \
122+
"AZURE_STORAGE_ACCOUNT_NAME=$AZURE_STORAGE_ACCOUNT_NAME" \
123+
"PROD_TABLE_NAME=$PROD_TABLE_NAME" \
124+
"BACKUP_CONTAINER_NAME=$BACKUP_CONTAINER_NAME" \
125+
"DEV_TABLE_NAME=$DEV_TABLE_NAME"
126+
```
127+
128+
</details>
129+
130+
### 4. Publish
131+
132+
```bash
133+
func azure functionapp publish "$AZURE_FUNCTION_APP_NAME"
58134
```
59135

60136
The app contains two functions:
@@ -107,54 +183,45 @@ az storage blob download --account-name "$AZURE_STORAGE_ACCOUNT_NAME" \
107183
uv run --env-file .env python -m backup.core --restore snapshot.json --target-table <table_name>
108184
```
109185

110-
## Details
111-
112-
<details>
113-
<summary><b>Azure Function setup (first time)</b></summary>
114-
115-
```bash
116-
az functionapp create \
117-
--resource-group <your-rg> \
118-
--name <new-app-name> \
119-
--storage-account <your-storage> \
120-
--flexconsumption-location <region> \
121-
--runtime python \
122-
--runtime-version 3.13 \
123-
--functions-version 4 \
124-
--instance-memory 2048
125-
126-
az functionapp config appsettings set \
127-
--name <your-app-name> \
128-
--resource-group <your-rg> \
129-
--settings \
130-
'AZURE_STORAGE_ACCOUNT_NAME=<your-account>' \
131-
'PROD_TABLE_NAME=<your-table>' \
132-
'BACKUP_CONTAINER_NAME=<backup-container-name>' \
133-
'DEV_TABLE_NAME=<your-dev-table>'
134-
```
135-
136-
</details>
186+
## Local testing
137187

138188
<details>
139-
<summary><b>Local testing</b></summary>
189+
<summary><b>Click to expand</b></summary>
140190

141191
Create `local.settings.json`:
142192

143-
```json
144-
{
145-
"IsEncrypted": false,
146-
"Values": {
147-
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
148-
"FUNCTIONS_WORKER_RUNTIME": "python",
149-
"AZURE_FUNCTIONS_ENVIRONMENT": "Development",
150-
"AZURE_STORAGE_ACCOUNT_NAME": "<your-account>",
151-
"PROD_TABLE_NAME": "<your-table>",
152-
"BACKUP_CONTAINER_NAME": "<your-container>",
153-
"DEV_TABLE_NAME": "<your-dev-table>"
154-
}
193+
```python
194+
import json
195+
import re
196+
197+
env = {}
198+
with open(".env") as f:
199+
for line in f:
200+
line = line.strip()
201+
if line and not line.startswith("#"):
202+
key, _, value = line.partition("=")
203+
env[key.strip()] = value.strip().strip("'\"")
204+
205+
settings = {
206+
"IsEncrypted": False,
207+
"Values": {
208+
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
209+
"FUNCTIONS_WORKER_RUNTIME": "python",
210+
"AZURE_FUNCTIONS_ENVIRONMENT": "Development",
211+
"AZURE_STORAGE_ACCOUNT_NAME": env["AZURE_STORAGE_ACCOUNT_NAME"],
212+
"PROD_TABLE_NAME": env["PROD_TABLE_NAME"],
213+
"BACKUP_CONTAINER_NAME": env["BACKUP_CONTAINER_NAME"],
214+
"DEV_TABLE_NAME": env["DEV_TABLE_NAME"],
215+
}
155216
}
217+
218+
with open("local.settings.json", "w") as f:
219+
json.dump(settings, f, indent=2)
220+
f.write("\n")
156221
```
157222

223+
Save the above Python code in `local_settings.py` and run it: `uv run local_settings.py`
224+
158225
Run the host:
159226

160227
```bash
@@ -169,8 +236,10 @@ curl http://localhost:7071/admin/functions/nhp_ats_backup -X POST -d '{}'
169236

170237
</details>
171238

239+
## Developer notes
240+
172241
<details>
173-
<summary><b>Developer notes</b></summary>
242+
<summary><b>Click to expand</b></summary>
174243

175244
- `backup/core.py` — library functions and non-interactive backup/restore
176245
- `backup/cli.py` — interactive workflow and snapshot resolution

0 commit comments

Comments
 (0)