1

I’ve spent days trying to deploy a function app using Terraform. It makes use of the requests python module.

I’ve narrowed the problem down to Azure not importing python modules in the requirements.txt. file.

To test, I created a simple httptrigger function app that simply returns a url parameter. My deployment script zips the directories and deploys the app using terraform. All is well and everything works as expected.

But, if change my python script (__init__.py) to import the python modules “urllib3” and/or “requests,” The function fails, even though the simple python script doesn’t actually use any methods or classes from the modules. There are no errors when deploying the function. It fails when called from the url.

I verified that the modules are listed in the requirements.txt file.

And just to be sure, if I comment out the import requests and urllib3, everything works.

Any advice or suggestions would be greatly appreciated.

Simple test script (__init__.py):

import logging
import azure.functions as func
# function fails with the following line.  Works if commented out.
import urllib3



def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    target = req.params.get('target')
    if target:
        return func.HttpResponse("Pretending to use " + target, status_code = 503)
    else:
        return func.HttpResponse("No Taget Specified", status_code = 400)

requirements.txt (Updated 7/15)

azure-functions==1.2.1
future==0.18.2
pefile==2019.4.18
PyInstaller==3.6
pylint==2.5.3
pywin32-ctypes==0.2.0
PyYAML==5.3.1
urllib3==1.25.9
requests==2.24.1

Update 7/16: Terraform file:

variable "prefix" {
    type = "string"
    default = "jis"
}

variable "location" {
    type = "string"
    default = "eastus"
}

variable "environment" {
    type = "string"
    default = "dev"
}

variable "functionapp" {
    type = "string"
    default = "./testit.zip"
}

resource "random_string" "storage_name" {
    length = 24
    upper = false
    lower = true
    number = true
    special = false
}

provider "azurerm" {
  version = "~>2.1.0"
  features {}
}

# Create Storage Account

resource "azurerm_resource_group" "rg" {
    name = "${var.prefix}-${var.environment}"
    location = "${var.location}"
}

resource "azurerm_storage_account" "storage" {
    name = "${random_string.storage_name.result}"
    resource_group_name = "${azurerm_resource_group.rg.name}"
    location = "${var.location}"
    account_tier = "Standard"
    account_replication_type = "LRS"
}

resource "azurerm_storage_container" "deployments" {
    name = "function-releases"
    storage_account_name = "${azurerm_storage_account.storage.name}"
    container_access_type = "private"
}

# upload zip file

resource "azurerm_storage_blob" "appcode" {
    name = "functionapp.zip"
    storage_account_name = "${azurerm_storage_account.storage.name}"
    storage_container_name = "${azurerm_storage_container.deployments.name}"
    type = "Block"
    source = "${var.functionapp}"
}

# Create function app

data "azurerm_storage_account_sas" "sas" {
    connection_string = "${azurerm_storage_account.storage.primary_connection_string}"
    https_only = true
    start = "2020-07-10"
    expiry = "2023-12-31"
    resource_types {
        object = true
        container = false
        service = false
    }
    services {
        blob = true
        queue = false
        table = false
        file = false
    }
    permissions {
        read = true
        write = false
        delete = false
        list = false
        add = false
        create = false
        update = false
        process = false
    }
}

resource "azurerm_app_service_plan" "asp" {
    name = "${var.prefix}-plan"
    resource_group_name = "${azurerm_resource_group.rg.name}"
    location = "${var.location}"
    kind = "Linux"
    reserved = true
    sku {
        tier = "Dynamic"
        size = "Y1"
    }
}

resource "azurerm_function_app" "functions" {
    name = "${var.prefix}-${var.environment}"
    location = "${var.location}"
    resource_group_name = "${azurerm_resource_group.rg.name}"
    app_service_plan_id = "${azurerm_app_service_plan.asp.id}"
    storage_connection_string = "${azurerm_storage_account.storage.primary_connection_string}"
    version = "~2"

    app_settings = {
        https_only = true
        FUNCTIONS_WORKER_RUNTIME = "python"
        WEBSITE_NODE_DEFAULT_VERSION = "~10"
        FUNCTION_APP_EDIT_MODE = "readonly"
        HASH = "${base64encode(filesha256("${var.functionapp}"))}"
        WEBSITE_RUN_FROM_PACKAGE = "https://${azurerm_storage_account.storage.name}.blob.core.windows.net/${azurerm_storage_container.deployments.name}/${azurerm_storage_blob.appcode.name}${data.azurerm_storage_account_sas.sas.sas}"
    }
}

# 
5
  • Hi! Can you include the error messages / stack trace printed after running the test script? Commented Jul 14, 2020 at 20:17
  • The only error message I get is "this page isn't working" code 500 Commented Jul 15, 2020 at 13:47
  • @RonTrunk how are you publishing your app content in your function app? Are you also using Terraform for that? If so, could you share some of the config for us to see exactly what publishing process is it going through. Typically, Azure Functions tools do a "build" step (to add your dependencies) before publish or during publish. I doubt terraform does that. I can provide workarounds if you share your terraform deployment file. Commented Jul 16, 2020 at 5:44
  • Is this post helpful to your problem ? Please refer to the last comment in the post. Commented Jul 16, 2020 at 8:27
  • @AnkitKumar I included the terraform config. I guess I'm not including the publishing step. Commented Jul 16, 2020 at 12:32

2 Answers 2

4

After some struggling, I figured out the problem. Thanks to @HuryShen and @AnkitKumar for pointing me in the right direction.

I did not include the modules urllib3 and requests in the function zip file. They need to be installed to the <funcname>.python_packages/lib/site-packages directory. The easiest way to do that (from the requirements.txt file) is

pip install  --target="azure/.python_packages/lib/site-packages"  -r requirements.txt

Once the modules are downloaded, they can be included in the zip file. After that, the terraform script works fine.

Sign up to request clarification or add additional context in comments.

Comments

0

It may be a version compatibility problem.

The versions of urllib3 and requests that you are using are from June 2018, the others (did not check all) appear to be latest versions.

Any reason why you need to use the older versions?

1 Comment

I read somewhere (can't remember where) that there were some compatibility issues and these were the recommended versions. But I have now updated requirements.txt with latest versions (see edited answer). Same result. If I import only urllib3, for example. It still fails.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.