Skip to content
This repository was archived by the owner on Apr 10, 2024. It is now read-only.
Open
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
6 changes: 3 additions & 3 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
ARG VARIANT=bullseye
FROM --platform=amd64 mcr.microsoft.com/vscode/devcontainers/base:0-${VARIANT}
ARG IMAGE=bullseye
FROM --platform=amd64 mcr.microsoft.com/devcontainers/${IMAGE}
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
&& mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg \
&& sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/debian/$(lsb_release -rs | cut -d'.' -f 1)/prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list' \
&& apt-get update && apt-get install -y xdg-utils \
&& apt-get update && apt-get install -y azure-functions-core-tools-4 \
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://aka.ms/install-azd.sh | bash
RUN curl -fsSL https://aka.ms/install-azd.sh | bash
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"build": {
"dockerfile": "Dockerfile",
"args": {
"IMAGE": "python:3.9"
"IMAGE": "python:3.10-bullseye"
}
},
"features": {
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ dmypy.json
bin
obj
appsettings.json
local.settings.json

# Azurite artifacts
__blobstorage__
Expand Down
20 changes: 0 additions & 20 deletions IconWriter/function.json

This file was deleted.

63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Icon Writer (Function App)

This repository contains a simple Azure Function App that can generate icons using Python and the Pillow library.

The deployment step also creates an Azure API Management service to serve the function, to handle aspects like CORS, rate-limiting, and keys.

## Opening the project

This project has Dev Container support, so it will be automatically setup if you open it in Github Codespaces or in local VS Code with the Dev Containers extension.

If you're unable to open the Dev Container, then you'll need to:

1. Create a [Python virtual environment](https://docs.python.org/3/tutorial/venv.html#creating-virtual-environments) and activate it.

2. Install requirements:

```shell
python3 -m pip install --user -r requirements.txt
```

3. Install the [Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/install-azd).

## Local development

Use the local emulator from Azure Functions Core Tools to test the function locally.
(There is no local emulator for the API Management service).

1. Open this repository in Github Codespaces or VS Code with Remote Dev Containers extension.
2. Open the Terminal and make sure you're in the root folder.
3. Run `func host start --python`
4. Click 'http://localhost:7071/api/IconWriter' in the terminal, which should open a website in a new tab. Change the URL to "/" to see the auto-generated documentation and try generating a map.

## Deployment

This repo is set up for deployment using the
[Azure Developer CLI](https://learn.microsoft.com/azure/developer/azure-developer-cli/overview),
which relies on the `azure.yaml` file and the configuration files in the `infra` folder.

Steps for deployment:

1. Sign up for a [free Azure account](https://azure.microsoft.com/free/) and create an Azure Subscription.
3. Login to Azure:

```shell
azd auth login
```

3. Provision and deploy all the resources:

```shell
azd up
```

It will prompt you to provide an `azd` environment name (like "staticmaps"), select a subscription from your Azure account, and select a location (like "eastus"). Then it will provision the resources in your account and deploy the latest code.

4. Once it finishes deploying, navigate to the API endpoint URL from the output. Since the function is secured, you should see a 401 when navigating to the function endpoint.

5. When you've made any changes to the app code, you can just run:

```shell
azd deploy
```

2 changes: 1 addition & 1 deletion azure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ services:
api:
project: .
language: py
host: function
host: function
5 changes: 5 additions & 0 deletions IconWriter/__init__.py → function_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import azure.functions as func
from icon_writer import write_icon

app = func.FunctionApp()


def get_param(req, param_name, default_value=None):
param_value = req.params.get(param_name)
if not param_value:
Expand All @@ -14,6 +17,8 @@ def get_param(req, param_name, default_value=None):
param_value = req_body.get(param_name)
return param_value if param_value is not None else default_value

@app.function_name(name="IconWriter")
@app.route(route="IconWriter", methods=['GET'])
def main(req: func.HttpRequest) -> func.HttpResponse:
text = get_param(req, 'text')
size = int(get_param(req, 'size', 80))
Expand Down
1 change: 1 addition & 0 deletions infra/apimanagement.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,4 @@ resource apimAPIDiagnostics 'Microsoft.ApiManagement/service/apis/diagnostics@20
}

output apimServiceID string = apimService.id
output apimServiceUrl string = apimService.properties.gatewayUrl
56 changes: 56 additions & 0 deletions infra/app-diagnostics.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
param appName string = ''

@description('The kind of the app.')
@allowed([
'functionapp'
'webapp'
])
param kind string

@description('Resource ID of log analytics workspace.')
param diagnosticWorkspaceId string

param diagnosticLogCategoriesToEnable array = kind == 'functionapp' ? [
'FunctionAppLogs'
] : [
'AppServiceHTTPLogs'
'AppServiceConsoleLogs'
'AppServiceAppLogs'
'AppServiceAuditLogs'
'AppServiceIPSecAuditLogs'
'AppServicePlatformLogs'
]

@description('Optional. The name of metrics that will be streamed.')
@allowed([
'AllMetrics'
])
param diagnosticMetricsToEnable array = [
'AllMetrics'
]


var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: {
category: category
enabled: true
}]

var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: {
category: metric
timeGrain: null
enabled: true
}]

resource app 'Microsoft.Web/sites@2022-03-01' existing = {
name: appName
}

resource app_diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
name: '${appName}-diagnostics'
scope: app
properties: {
workspaceId: diagnosticWorkspaceId
metrics: diagnosticsMetrics
logs: diagnosticsLogs
}
}
2 changes: 2 additions & 0 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,5 @@ module resources 'resources.bicep' = {
allowedOrigin: allowedOrigin
}
}

output SERVICE_API_ENDPOINTS array = ['${resources.outputs.apimServiceUrl}/icon-writer-function/IconWriter']
18 changes: 17 additions & 1 deletion infra/resources.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ resource functionApp 'Microsoft.Web/sites@2020-06-01' = {
serverFarmId: hostingPlan.id
clientAffinityEnabled: false
siteConfig: {
linuxFxVersion: 'Python|3.9'
linuxFxVersion: 'Python|3.10'
appSettings: [
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
Expand All @@ -90,6 +90,10 @@ resource functionApp 'Microsoft.Web/sites@2020-06-01' = {
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'python'
}
{
name: 'AzureWebJobsFeatureFlags'
value: 'EnableWorkerIndexing'
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${az.environment().suffixes.storage};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value}'
Expand Down Expand Up @@ -138,3 +142,15 @@ resource functionAppProperties 'Microsoft.Web/sites/config@2022-03-01' = {
apiManagementResources
]
}


module diagnostics 'app-diagnostics.bicep' = {
name: '${name}-functions-diagnostics'
params: {
appName: functionApp.name
kind: 'functionapp'
diagnosticWorkspaceId: logAnalytics.id
}
}

output apimServiceUrl string = apiManagementResources.outputs.apimServiceUrl
7 changes: 7 additions & 0 deletions local.settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "python",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
}
}