Skip to content

fix: Consumption tests fixes #1717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: dev
Choose a base branch
from
Draft
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
9 changes: 4 additions & 5 deletions eng/ci/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ extends:
dependsOn: []
jobs:
- template: /eng/templates/official/jobs/ci-e2e-tests.yml@self
# Skipping consumption tests till pipeline is fixed
# - stage: RunLCTests
# dependsOn: []
# jobs:
# - template: /eng/templates/official/jobs/ci-lc-tests.yml@self
- stage: RunLCTests
dependsOn: []
jobs:
- template: /eng/templates/official/jobs/ci-lc-tests.yml@self
79 changes: 72 additions & 7 deletions eng/templates/official/jobs/ci-lc-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,36 @@ jobs:

strategy:
matrix:
Python37:
PYTHON_VERSION: '3.7'
Python38:
PYTHON_VERSION: '3.8'
Python39:
PYTHON_VERSION: '3.9'
Python310:
PYTHON_VERSION: '3.10'
Python311:
PYTHON_VERSION: '3.11'

Python312:
PYTHON_VERSION: '3.12'
Python313:
PYTHON_VERSION: '3.13'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: $(PYTHON_VERSION)

- bash: |
# Start Azurite storage emulator in the background
docker run -d -p 10000:10000 -p 10001:10001 -p 10002:10002 \
--name azurite-storage \
mcr.microsoft.com/azure-storage/azurite:latest \
azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0

# Wait for Azurite to be ready
sleep 5

# Verify Azurite is running
docker ps | grep azurite-storage
displayName: 'Start Azurite Storage Emulator'
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))

- bash: |
python -m pip install --upgrade pip
python -m pip install -U -e ${{ parameters.PROJECT_DIRECTORY }}/[dev]
Expand All @@ -36,11 +51,61 @@ jobs:
displayName: 'Install dependencies and the worker'
# Skip the installation stage for SDK and Extensions release branches. This stage will fail because pyproject.toml contains the updated (and unreleased) library version
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))

- bash: |
# Install Azure CLI (if not already present)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Create the apps container in Azurite
az storage container create \
--name apps \
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)"

# Upload all function app packages to the container
FUNCTION_APPS_DIR="$(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }}/tests/consumption_tests/function_apps"
for zipfile in "$FUNCTION_APPS_DIR"/*.zip; do
filename=$(basename "$zipfile")
echo "Uploading $filename..."
az storage blob upload \
--container-name apps \
--name "$filename" \
--file "$zipfile" \
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)" \
--overwrite
done

# Generate a container-level SAS token valid for 1 day
SAS_TOKEN=$(az storage container generate-sas \
--name apps \
--permissions r \
--expiry $(date -u -d '+1 day' +%Y-%m-%dT%H:%M:%SZ) \
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)" \
--output tsv)

echo "##vso[task.setvariable variable=CONTAINER_SAS_TOKEN]$SAS_TOKEN"
env:
AZURE_STORAGE_CONNECTION_STRING: $(AZURE_STORAGE_CONNECTION_STRING)

displayName: 'Setup Function App Packages in Azurite'
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))

- powershell: |
Write-Host "CONTAINER_SAS_TOKEN: $(CONTAINER_SAS_TOKEN)"
displayName: 'Display CONTAINER_SAS_TOKEN variable'

- bash: |
python -m pytest -n auto --dist loadfile -vv --reruns 4 --instafail tests/consumption_tests
env:
AzureWebJobsStorage: $(LinuxStorageConnectionString312)
AzureWebJobsStorage: $(AZURE_STORAGE_CONNECTION_STRING)
_DUMMY_CONT_KEY: $(_DUMMY_CONT_KEY)
CONTAINER_SAS_TOKEN: $(CONTAINER_SAS_TOKEN)
displayName: "Running $(PYTHON_VERSION) Linux Consumption tests"
workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }}
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))

- bash: |
# Cleanup: Stop and remove Azurite container
docker stop azurite-storage || true
docker rm azurite-storage || true
displayName: 'Cleanup Azurite Storage Emulator'
condition: always()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
72 changes: 11 additions & 61 deletions workers/tests/consumption_tests/test_linux_consumption.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,7 @@

_DEFAULT_HOST_VERSION = "4"


class TestLinuxConsumption(TestCase):
"""Test worker behaviors on specific scenarios.

SCM_RUN_FROM_PACKAGE: built function apps are acquired from
-> "Simple Batch" Subscription
-> "AzureFunctionsPythonWorkerCILinuxDevOps" Resource Group
-> "pythonworker<python_major><python_minor>sa" Storage Account
-> "python-worker-lc-apps" Blob Container

For a list of scenario names:
https://pythonworker39sa.blob.core.windows.net/python-worker-lc-apps?restype=container&comp=list
"""

@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -65,6 +53,9 @@ def test_http_no_auth(self):
resp = ctrl.send_request(req)
self.assertEqual(resp.status_code, 200)


@skipIf(sys.version_info.minor != 11,
"Uploaded common libraries are only supported for Python 3.11")
def test_common_libraries(self):
"""A function app with the following requirements.txt:

Expand Down Expand Up @@ -95,8 +86,6 @@ def test_common_libraries(self):
self.assertIn('pyodbc', content)
self.assertIn('requests', content)

@skipIf(sys.version_info.minor in (10, 11),
"Protobuf pinning fails during remote build")
def test_new_protobuf(self):
"""A function app with the following requirements.txt:

Expand Down Expand Up @@ -125,8 +114,6 @@ def test_new_protobuf(self):
self.assertEqual(content['google.protobuf'], '3.15.8')
self.assertEqual(content['grpc'], '1.33.2')

@skipIf(sys.version_info.minor in (10, 11),
"Protobuf pinning fails during remote build")
def test_old_protobuf(self):
"""A function app with the following requirements.txt:

Expand Down Expand Up @@ -230,8 +217,6 @@ def test_pinning_functions_to_older_version(self):
self.assertEqual(resp.status_code, 200)
self.assertIn("Func Version: 1.11.1", resp.text)

@skipIf(sys.version_info.minor != 10,
"This is testing only for python310")
def test_opencensus_with_extensions_enabled(self):
"""A function app with extensions enabled containing the
following libraries:
Expand All @@ -251,8 +236,6 @@ def test_opencensus_with_extensions_enabled(self):
resp = ctrl.send_request(req)
self.assertEqual(resp.status_code, 200)

@skipIf(sys.version_info.minor != 10,
"This is testing only for python310")
def test_opencensus_with_extensions_enabled_init_indexing(self):
"""
A function app with init indexing enabled
Expand All @@ -269,43 +252,7 @@ def test_opencensus_with_extensions_enabled_init_indexing(self):
resp = ctrl.send_request(req)
self.assertEqual(resp.status_code, 200)

@skipIf(sys.version_info.minor != 9,
"This is testing only for python39 where extensions"
"enabled by default")
def test_reload_variables_after_timeout_error(self):
"""
A function app with HTTPtrigger which has a function timeout of
20s. The app as a sleep of 30s which should trigger a timeout
"""
with LinuxConsumptionWebHostController(_DEFAULT_HOST_VERSION,
self._py_version) as ctrl:
ctrl.assign_container(env={
"AzureWebJobsStorage": self._storage,
"SCM_RUN_FROM_PACKAGE": self._get_blob_url(
"TimeoutError"),
PYTHON_ISOLATE_WORKER_DEPENDENCIES: "1"
})
req = Request('GET', f'{ctrl.url}/api/hello')
resp = ctrl.send_request(req)
self.assertEqual(resp.status_code, 500)

sleep(2)
logs = ctrl.get_container_logs()
self.assertRegex(
logs,
r"Applying prioritize_customer_dependencies: "
r"worker_dependencies_path: \/azure-functions-host\/"
r"workers\/python\/.*?\/LINUX\/X64,"
r" customer_dependencies_path: \/home\/site\/wwwroot\/"
r"\.python_packages\/lib\/site-packages, working_directory:"
r" \/home\/site\/wwwroot, Linux Consumption: True,"
r" Placeholder: False")
self.assertNotIn("Failure Exception: ModuleNotFoundError",
logs)

@skipIf(sys.version_info.minor != 9,
"This is testing only for python39 where extensions"
"enabled by default")
def test_reload_variables_after_oom_error(self):
"""
A function app with HTTPtrigger mocking error code 137
Expand Down Expand Up @@ -338,7 +285,7 @@ def test_reload_variables_after_oom_error(self):
logs)

@skipIf(sys.version_info.minor != 10,
"This is testing only for python310")
"Pydantic dependencies that are only compatible with Python 3.10")
def test_http_v2_fastapi_streaming_upload_download(self):
"""
A function app using http v2 fastapi extension with streaming upload and
Expand Down Expand Up @@ -377,7 +324,10 @@ def generate_random_bytes_stream():
streamed_data, b'streamingtestingresponseisreturned')

def _get_blob_url(self, scenario_name: str) -> str:
return (
f'https://pythonworker{self._py_shortform}sa.blob.core.windows.net/'
f'python-worker-lc-apps/{scenario_name}{self._py_shortform}.zip'
)
base_url = "http://host.docker.internal:10000/devstoreaccount1/apps"

container_sas_token = os.getenv('CONTAINER_SAS_TOKEN')
if not container_sas_token:
raise RuntimeError('Environment variable CONTAINER_SAS_TOKEN is '
'required before running Linux Consumption test')
return f"{base_url}/{scenario_name}.zip?{container_sas_token}"
Loading
Loading