Skip to content
Merged
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
34 changes: 0 additions & 34 deletions .flake8

This file was deleted.

1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Copyright (c) Alianza, Inc. All rights reserved.
name: Lint

on: [push]
Expand Down
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ Status: Available for use

### Fixed

## [1.0.0] - 2025-10-02

### Breaking Changes
- Switch to using FlexConsumption as Consumption apps are being deprecated.

## [0.1.0] - 2024-05-16

### Added
- Initial release

### Changed

[unreleased]: https://github.com/microsoft/apt-package-function/compare/0.1.0...HEAD
[0.1.0]: https://github.com/microsoft/apt-package-function/tree/0.1.0
[unreleased]: https://github.com/Metaswitch/apt-package-function/compare/1.0.0...HEAD
[1.0.0]: https://github.com/Metaswitch/apt-package-function/compare/0.1.0...1.0.0
[0.1.0]: https://github.com/Metaswitch/apt-package-function/tree/0.1.0
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Functionality to create a Debian package repository in Azure Blob Storage with
an Azure Function App to keep it up to date. For use with
[apt-transport-blob](https://github.com/microsoft/apt-transport-blob).
[apt-transport-blob](https://github.com/Metaswitch/apt-transport-blob).

# Getting Started

Expand Down
8 changes: 5 additions & 3 deletions function_app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# Copyright (c) Alianza, Inc. All rights reserved.
# Licensed under the MIT License.
"""A function app to manage a Debian repository in Azure Blob Storage."""

Expand All @@ -9,7 +9,7 @@
import os
import tempfile
from pathlib import Path
from typing import Generator
from typing import Generator, Optional

import azure.functions as func
import pydpkg
Expand All @@ -32,12 +32,14 @@
@contextlib.contextmanager
def temporary_filename() -> Generator[str, None, None]:
"""Create a temporary file and return the filename."""
temporary_name: Optional[str] = None
try:
with tempfile.NamedTemporaryFile(delete=False) as f:
temporary_name = f.name
yield temporary_name
finally:
os.unlink(temporary_name)
if temporary_name:
os.unlink(temporary_name)


class PackageBlob:
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Copyright (c) Alianza, Inc. All rights reserved.
# Highly Confidential Material
[project]
name = "apt-package-function"
description = "Functionality to create a Debian package repository in Azure Blob Storage"
license = "MIT"
version = "0.1.0"
version = "1.0.0"
readme = "README.md"
authors = [{name = "Max Dymond", email = "max.dymond@alianza.com"}]
requires-python = '>=3.9.2,<4.0.0'
Expand Down
10 changes: 5 additions & 5 deletions rg.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ resource packageContainer 'Microsoft.Storage/storageAccounts/blobServices/contai
properties: {
}
}
resource pythonContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-01-01' = if (!use_shared_keys) {
resource pythonContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-01-01' = {
parent: defBlobServices
name: python_container_name
properties: {
Expand Down Expand Up @@ -122,14 +122,14 @@ az storage blob upload --auth-mode login -f Packages -c "${AZURE_BLOB_CONTAINER}
}
}

// Create the function app directly, if shared key support is enabled
module funcapp 'rg_funcapp.bicep' = if (use_shared_keys) {
// Create the function app directly
module funcapp 'rg_funcapp.bicep' = {
name: 'funcapp${suffix}'
params: {
location: location
storage_account_name: storageAccount.name
appName: appName
use_shared_keys: true
use_shared_keys: use_shared_keys
suffix: suffix
}
}
Expand All @@ -139,4 +139,4 @@ output apt_sources string = 'deb [trusted=yes] blob://${storageAccount.name}.blo
output function_app_name string = appName
output storage_account string = storageAccount.name
output package_container string = packageContainer.name
output python_container string = use_shared_keys ? '' : pythonContainer.name
output python_container string = pythonContainer.name
69 changes: 44 additions & 25 deletions rg_funcapp.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ var package_container_name = 'packages'
// Create a container for the Python code
var python_container_name = 'python'

var storage_connection_string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'

// The version of Python to run with
var python_version = '3.11'

Expand All @@ -50,7 +52,7 @@ resource packageContainer 'Microsoft.Storage/storageAccounts/blobServices/contai
parent: defBlobServices
name: package_container_name
}
resource pythonContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-01-01' existing = if (!use_shared_keys) {
resource pythonContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2025-01-01' existing = {
parent: defBlobServices
name: python_container_name
}
Expand All @@ -65,12 +67,14 @@ resource storageBlobDataContributorRoleAssignment 'Microsoft.Authorization/roleA
}

// Create a hosting plan for the function app
// Using Flex Consumption plan for serverless hosting with enhanced features
// Reference: https://learn.microsoft.com/en-us/azure/azure-functions/flex-consumption-plan
resource hostingPlan 'Microsoft.Web/serverfarms@2024-11-01' = {
name: hostingPlanName
location: location
sku: {
name: 'Y1'
tier: 'Dynamic'
name: 'FC1'
tier: 'FlexConsumption'
}
properties: {
reserved: true
Expand All @@ -90,18 +94,10 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {

// Construct the app settings
var common_settings = [
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: '~4'
}
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
value: applicationInsights.properties.InstrumentationKey
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'python'
}
// Pass the blob container name to the function app - this is the
// container which is monitored for new packages.
{
Expand All @@ -114,32 +110,56 @@ var common_settings = [
var app_settings = use_shared_keys ? concat(common_settings, [
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
value: storage_connection_string
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
}
{
name: 'WEBSITE_CONTENTSHARE'
value: toLower(functionAppName)
name: 'DEPLOYMENT_STORAGE_CONNECTION_STRING'
value: storage_connection_string
}
]) : concat(common_settings, [
{
name: 'AzureWebJobsStorage__accountName'
value: storageAccount.name
}
{
name: 'WEBSITE_RUN_FROM_PACKAGE'
value: 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/${pythonContainer.name}/function_app.zip'
}
// Pass the container URL to the function app for the `from_container_url` call.
{
name: 'BLOB_CONTAINER_URL'
value: 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/${packageContainer.name}/'
}
])

var function_runtime = {
name: 'python'
version: python_version
}

var deployment_storage_value = 'https://${storageAccount.name}.blob.${environment().suffixes.storage}/${pythonContainer.name}'

var deployment_authentication = use_shared_keys ? {
type: 'StorageAccountConnectionString'
storageAccountConnectionStringName: 'DEPLOYMENT_STORAGE_CONNECTION_STRING'
} : {
type: 'SystemAssignedIdentity'
}

var flex_deployment_configuration = {
storage: {
type: 'blobContainer'
value: deployment_storage_value
authentication: deployment_authentication
}
}

var flex_scale_and_concurrency = {
maximumInstanceCount: 100
instanceMemoryMB: 2048
}

var function_app_config = {
runtime: function_runtime
scaleAndConcurrency: flex_scale_and_concurrency
deployment: flex_deployment_configuration
}

// Create the function app.
resource functionApp 'Microsoft.Web/sites@2024-11-01' = {
name: functionAppName
Expand All @@ -152,13 +172,12 @@ resource functionApp 'Microsoft.Web/sites@2024-11-01' = {
properties: {
serverFarmId: hostingPlan.id
siteConfig: {
linuxFxVersion: 'Python|${python_version}'
pythonVersion: python_version
appSettings: app_settings
ftpsState: 'FtpsOnly'
minTlsVersion: '1.2'
}
httpsOnly: true
functionAppConfig: function_app_config
}
}

Expand Down
3 changes: 2 additions & 1 deletion ruff.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Copyright (c) Alianza, Inc. All rights reserved.
exclude = [
".venv",
"__pycache__",
Expand Down Expand Up @@ -56,4 +57,4 @@ indent-style = "space"
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"
line-ending = "auto"
2 changes: 1 addition & 1 deletion src/apt_package_function/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# Copyright (c) Alianza, Inc. All rights reserved.
# Licensed under the MIT License.
"""Tooling for creating apt repositories in Azure."""

Expand Down
2 changes: 1 addition & 1 deletion src/apt_package_function/azcmd.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# Copyright (c) Alianza, Inc. All rights reserved.
# Licensed under the MIT License.
"""Functions for interacting with az cli"""

Expand Down
2 changes: 1 addition & 1 deletion src/apt_package_function/bicep_deployment.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# Copyright (c) Alianza, Inc. All rights reserved.
# Licensed under the MIT License.
"""Manages Bicep deployments."""

Expand Down
15 changes: 7 additions & 8 deletions src/apt_package_function/create_resources.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation.
# Copyright (c) Alianza, Inc. All rights reserved.
# Licensed under the MIT License.
"""Creates resources for the apt package function in Azure."""

Expand All @@ -10,7 +10,11 @@

from apt_package_function import common_logging
from apt_package_function.bicep_deployment import BicepDeployment
from apt_package_function.func_app import FuncApp, FuncAppBundle, FuncAppZip
from apt_package_function.func_app import (
FuncApp,
FuncAppBundle,
FuncAppZip,
)
from apt_package_function.poetry import extract_requirements
from apt_package_function.resource_group import create_rg

Expand Down Expand Up @@ -78,7 +82,6 @@ def main() -> None:
apt_sources = outputs["apt_sources"]
function_app_name = outputs["function_app_name"]
package_container = outputs["package_container"]
python_container = outputs["python_container"]
storage_account = outputs["storage_account"]

# Create the function app
Expand All @@ -87,11 +90,7 @@ def main() -> None:
funcapp = FuncAppZip(name=function_app_name, resource_group=args.resource_group)
else:
funcapp = FuncAppBundle(
name=function_app_name,
resource_group=args.resource_group,
storage_account=storage_account,
python_container=python_container,
parameters=common_parameters,
name=function_app_name, resource_group=args.resource_group
)

with funcapp as cm:
Expand Down
Loading