Skip to content

Commit 14d3f4e

Browse files
fix: Consumption tests fixes (#1717)
* Consumption tests fix * Updated blob name * Uncommenting LC tests * Updated imports * Updated tests to run on an emulator * Added sas token * Fixed syntax error * upload one zip, verify, run one test * logging variables * change base url * run all tests * only run 3.13, test with loader.install() * Removed protobuf tests * Removing debugging changes * Updating pipeline to run tests on all versions * Skipping 3.13 tests * Flake8 fixes --------- Co-authored-by: Victoria Hall <victoriahall@microsoft.com>
1 parent 8a42602 commit 14d3f4e

File tree

11 files changed

+234
-178
lines changed

11 files changed

+234
-178
lines changed

eng/ci/integration-tests.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ extends:
4747
dependsOn: []
4848
jobs:
4949
- template: /eng/templates/official/jobs/ci-e2e-tests.yml@self
50-
# Skipping consumption tests till pipeline is fixed
51-
# - stage: RunLCTests
52-
# dependsOn: []
53-
# jobs:
54-
# - template: /eng/templates/official/jobs/ci-lc-tests.yml@self
50+
- stage: RunLCTests
51+
dependsOn: []
52+
jobs:
53+
- template: /eng/templates/official/jobs/ci-lc-tests.yml@self

eng/templates/official/jobs/ci-lc-tests.yml

Lines changed: 85 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,34 @@ jobs:
1212

1313
strategy:
1414
matrix:
15-
Python37:
16-
PYTHON_VERSION: '3.7'
17-
Python38:
18-
PYTHON_VERSION: '3.8'
19-
Python39:
20-
PYTHON_VERSION: '3.9'
21-
Python310:
22-
PYTHON_VERSION: '3.10'
23-
Python311:
24-
PYTHON_VERSION: '3.11'
25-
15+
Python39:
16+
PYTHON_VERSION: '3.9'
17+
Python310:
18+
PYTHON_VERSION: '3.10'
19+
Python311:
20+
PYTHON_VERSION: '3.11'
21+
Python312:
22+
PYTHON_VERSION: '3.12'
2623
steps:
2724
- task: UsePythonVersion@0
2825
inputs:
2926
versionSpec: $(PYTHON_VERSION)
27+
28+
- bash: |
29+
# Start Azurite storage emulator in the background
30+
docker run -d -p 10000:10000 -p 10001:10001 -p 10002:10002 \
31+
--name azurite-storage \
32+
mcr.microsoft.com/azure-storage/azurite:latest \
33+
azurite --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0
34+
35+
# Wait for Azurite to be ready
36+
sleep 5
37+
38+
# Verify Azurite is running
39+
docker ps | grep azurite-storage
40+
displayName: 'Start Azurite Storage Emulator'
41+
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
42+
3043
- bash: |
3144
python -m pip install --upgrade pip
3245
python -m pip install -U -e ${{ parameters.PROJECT_DIRECTORY }}/[dev]
@@ -36,11 +49,69 @@ jobs:
3649
displayName: 'Install dependencies and the worker'
3750
# Skip the installation stage for SDK and Extensions release branches. This stage will fail because pyproject.toml contains the updated (and unreleased) library version
3851
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
52+
53+
- bash: |
54+
# Install Azure CLI (if not already present)
55+
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
56+
57+
# Create the apps container in Azurite
58+
az storage container create \
59+
--name apps \
60+
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)"
61+
62+
# Upload all function app packages to the container
63+
FUNCTION_APPS_DIR="$(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }}/tests/consumption_tests/function_app_zips"
64+
for zipfile in "$FUNCTION_APPS_DIR"/*.zip; do
65+
filename=$(basename "$zipfile")
66+
echo "Uploading $filename..."
67+
az storage blob upload \
68+
--container-name apps \
69+
--name "$filename" \
70+
--file "$zipfile" \
71+
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)" \
72+
--overwrite
73+
done
74+
75+
# Generate a container-level SAS token valid for 1 day
76+
SAS_TOKEN=$(az storage container generate-sas \
77+
--name apps \
78+
--permissions r \
79+
--expiry $(date -u -d '+1 day' +%Y-%m-%dT%H:%M:%SZ) \
80+
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)" \
81+
--output tsv)
82+
83+
echo "##vso[task.setvariable variable=CONTAINER_SAS_TOKEN]$SAS_TOKEN"
84+
85+
# List blobs in the container to verify uploads
86+
echo "Verifying uploaded blobs in 'apps' container..."
87+
az storage blob list \
88+
--container-name apps \
89+
--connection-string "$(AZURE_STORAGE_CONNECTION_STRING)" \
90+
--output table
91+
92+
env:
93+
AZURE_STORAGE_CONNECTION_STRING: $(AZURE_STORAGE_CONNECTION_STRING)
94+
95+
displayName: 'Setup Function App Packages in Azurite'
96+
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
97+
98+
- powershell: |
99+
Write-Host "CONTAINER_SAS_TOKEN: $(CONTAINER_SAS_TOKEN)"
100+
displayName: 'Display CONTAINER_SAS_TOKEN variable'
101+
39102
- bash: |
40-
python -m pytest -n auto --dist loadfile -vv --reruns 4 --instafail tests/consumption_tests
103+
python -m pytest -n auto --dist loadfile -vv --instafail tests/consumption_tests
41104
env:
42-
AzureWebJobsStorage: $(LinuxStorageConnectionString312)
105+
AzureWebJobsStorage: $(AZURE_STORAGE_CONNECTION_STRING)
43106
_DUMMY_CONT_KEY: $(_DUMMY_CONT_KEY)
107+
CONTAINER_SAS_TOKEN: $(CONTAINER_SAS_TOKEN)
44108
displayName: "Running $(PYTHON_VERSION) Linux Consumption tests"
45109
workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }}
46-
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
110+
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
111+
112+
- bash: |
113+
# Cleanup: Stop and remove Azurite container
114+
docker stop azurite-storage || true
115+
docker rm azurite-storage || true
116+
displayName: 'Cleanup Azurite Storage Emulator'
117+
condition: always()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
324 KB
Binary file not shown.
2.82 MB
Binary file not shown.
Binary file not shown.

workers/tests/consumption_tests/test_linux_consumption.py

Lines changed: 13 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,21 @@
33
import os
44
import sys
55
from time import sleep
6-
from unittest import TestCase, skipIf
7-
8-
from requests import Request
9-
from tests.utils.testutils_lc import LinuxConsumptionWebHostController
6+
from unittest import TestCase, skip, skipIf
107

118
from azure_functions_worker.constants import (
129
PYTHON_ENABLE_DEBUG_LOGGING,
1310
PYTHON_ENABLE_INIT_INDEXING,
1411
PYTHON_ENABLE_WORKER_EXTENSIONS,
1512
PYTHON_ISOLATE_WORKER_DEPENDENCIES,
1613
)
14+
from requests import Request
15+
from tests.utils.testutils_lc import LinuxConsumptionWebHostController
1716

1817
_DEFAULT_HOST_VERSION = "4"
1918

2019

2120
class TestLinuxConsumption(TestCase):
22-
"""Test worker behaviors on specific scenarios.
23-
24-
SCM_RUN_FROM_PACKAGE: built function apps are acquired from
25-
-> "Simple Batch" Subscription
26-
-> "AzureFunctionsPythonWorkerCILinuxDevOps" Resource Group
27-
-> "pythonworker<python_major><python_minor>sa" Storage Account
28-
-> "python-worker-lc-apps" Blob Container
29-
30-
For a list of scenario names:
31-
https://pythonworker39sa.blob.core.windows.net/python-worker-lc-apps?restype=container&comp=list
32-
"""
3321

3422
@classmethod
3523
def setUpClass(cls):
@@ -65,6 +53,8 @@ def test_http_no_auth(self):
6553
resp = ctrl.send_request(req)
6654
self.assertEqual(resp.status_code, 200)
6755

56+
@skipIf(sys.version_info.minor != 11,
57+
"Uploaded common libraries are only supported for Python 3.11")
6858
def test_common_libraries(self):
6959
"""A function app with the following requirements.txt:
7060
@@ -95,66 +85,6 @@ def test_common_libraries(self):
9585
self.assertIn('pyodbc', content)
9686
self.assertIn('requests', content)
9787

98-
@skipIf(sys.version_info.minor in (10, 11),
99-
"Protobuf pinning fails during remote build")
100-
def test_new_protobuf(self):
101-
"""A function app with the following requirements.txt:
102-
103-
azure-functions==1.7.0
104-
protobuf==3.15.8
105-
grpcio==1.33.2
106-
107-
should return 200 after importing all libraries.
108-
"""
109-
with LinuxConsumptionWebHostController(_DEFAULT_HOST_VERSION,
110-
self._py_version) as ctrl:
111-
ctrl.assign_container(env={
112-
"AzureWebJobsStorage": self._storage,
113-
"SCM_RUN_FROM_PACKAGE": self._get_blob_url("NewProtobuf"),
114-
PYTHON_ISOLATE_WORKER_DEPENDENCIES: "1"
115-
})
116-
req = Request('GET', f'{ctrl.url}/api/HttpTrigger')
117-
resp = ctrl.send_request(req)
118-
self.assertEqual(resp.status_code, 200)
119-
120-
content = resp.json()
121-
122-
# Worker always picks up the SDK version bundled with the image
123-
# Version of the packages are inconsistent due to isolation's bug
124-
self.assertEqual(content['azure.functions'], '1.7.0')
125-
self.assertEqual(content['google.protobuf'], '3.15.8')
126-
self.assertEqual(content['grpc'], '1.33.2')
127-
128-
@skipIf(sys.version_info.minor in (10, 11),
129-
"Protobuf pinning fails during remote build")
130-
def test_old_protobuf(self):
131-
"""A function app with the following requirements.txt:
132-
133-
azure-functions==1.5.0
134-
protobuf==3.8.0
135-
grpcio==1.27.1
136-
137-
should return 200 after importing all libraries.
138-
"""
139-
with LinuxConsumptionWebHostController(_DEFAULT_HOST_VERSION,
140-
self._py_version) as ctrl:
141-
ctrl.assign_container(env={
142-
"AzureWebJobsStorage": self._storage,
143-
"SCM_RUN_FROM_PACKAGE": self._get_blob_url("OldProtobuf"),
144-
PYTHON_ISOLATE_WORKER_DEPENDENCIES: "1"
145-
})
146-
req = Request('GET', f'{ctrl.url}/api/HttpTrigger')
147-
resp = ctrl.send_request(req)
148-
self.assertEqual(resp.status_code, 200)
149-
150-
content = resp.json()
151-
152-
# Worker always picks up the SDK version bundled with the image
153-
# Version of the packages are inconsistent due to isolation's bug
154-
self.assertIn(content['azure.functions'], '1.5.0')
155-
self.assertIn(content['google.protobuf'], '3.8.0')
156-
self.assertIn(content['grpc'], '1.27.1')
157-
15888
def test_debug_logging_disabled(self):
15989
"""An HttpTrigger function app with 'azure-functions' library
16090
should return 200 and by default customer debug logging should be
@@ -230,8 +160,6 @@ def test_pinning_functions_to_older_version(self):
230160
self.assertEqual(resp.status_code, 200)
231161
self.assertIn("Func Version: 1.11.1", resp.text)
232162

233-
@skipIf(sys.version_info.minor != 10,
234-
"This is testing only for python310")
235163
def test_opencensus_with_extensions_enabled(self):
236164
"""A function app with extensions enabled containing the
237165
following libraries:
@@ -251,8 +179,6 @@ def test_opencensus_with_extensions_enabled(self):
251179
resp = ctrl.send_request(req)
252180
self.assertEqual(resp.status_code, 200)
253181

254-
@skipIf(sys.version_info.minor != 10,
255-
"This is testing only for python310")
256182
def test_opencensus_with_extensions_enabled_init_indexing(self):
257183
"""
258184
A function app with init indexing enabled
@@ -269,43 +195,6 @@ def test_opencensus_with_extensions_enabled_init_indexing(self):
269195
resp = ctrl.send_request(req)
270196
self.assertEqual(resp.status_code, 200)
271197

272-
@skipIf(sys.version_info.minor != 9,
273-
"This is testing only for python39 where extensions"
274-
"enabled by default")
275-
def test_reload_variables_after_timeout_error(self):
276-
"""
277-
A function app with HTTPtrigger which has a function timeout of
278-
20s. The app as a sleep of 30s which should trigger a timeout
279-
"""
280-
with LinuxConsumptionWebHostController(_DEFAULT_HOST_VERSION,
281-
self._py_version) as ctrl:
282-
ctrl.assign_container(env={
283-
"AzureWebJobsStorage": self._storage,
284-
"SCM_RUN_FROM_PACKAGE": self._get_blob_url(
285-
"TimeoutError"),
286-
PYTHON_ISOLATE_WORKER_DEPENDENCIES: "1"
287-
})
288-
req = Request('GET', f'{ctrl.url}/api/hello')
289-
resp = ctrl.send_request(req)
290-
self.assertEqual(resp.status_code, 500)
291-
292-
sleep(2)
293-
logs = ctrl.get_container_logs()
294-
self.assertRegex(
295-
logs,
296-
r"Applying prioritize_customer_dependencies: "
297-
r"worker_dependencies_path: \/azure-functions-host\/"
298-
r"workers\/python\/.*?\/LINUX\/X64,"
299-
r" customer_dependencies_path: \/home\/site\/wwwroot\/"
300-
r"\.python_packages\/lib\/site-packages, working_directory:"
301-
r" \/home\/site\/wwwroot, Linux Consumption: True,"
302-
r" Placeholder: False")
303-
self.assertNotIn("Failure Exception: ModuleNotFoundError",
304-
logs)
305-
306-
@skipIf(sys.version_info.minor != 9,
307-
"This is testing only for python39 where extensions"
308-
"enabled by default")
309198
def test_reload_variables_after_oom_error(self):
310199
"""
311200
A function app with HTTPtrigger mocking error code 137
@@ -337,8 +226,7 @@ def test_reload_variables_after_oom_error(self):
337226
self.assertNotIn("Failure Exception: ModuleNotFoundError",
338227
logs)
339228

340-
@skipIf(sys.version_info.minor != 10,
341-
"This is testing only for python310")
229+
@skip("Flaky test.")
342230
def test_http_v2_fastapi_streaming_upload_download(self):
343231
"""
344232
A function app using http v2 fastapi extension with streaming upload and
@@ -377,7 +265,10 @@ def generate_random_bytes_stream():
377265
streamed_data, b'streamingtestingresponseisreturned')
378266

379267
def _get_blob_url(self, scenario_name: str) -> str:
380-
return (
381-
f'https://pythonworker{self._py_shortform}sa.blob.core.windows.net/'
382-
f'python-worker-lc-apps/{scenario_name}{self._py_shortform}.zip'
383-
)
268+
base_url = "http://172.17.0.1:10000/devstoreaccount1/apps"
269+
270+
container_sas_token = os.getenv('CONTAINER_SAS_TOKEN')
271+
if not container_sas_token:
272+
raise RuntimeError('Environment variable CONTAINER_SAS_TOKEN is '
273+
'required before running Linux Consumption test')
274+
return f"{base_url}/{scenario_name}.zip?{container_sas_token}"

0 commit comments

Comments
 (0)