question

ShervinMirsaeidi-4877 avatar image
0 Votes"
ShervinMirsaeidi-4877 asked ShervinMirsaeidi-4877 commented

Creating a azure Python or C# function dynamically using Azure Rest API

Hi Team,

I have been trying to follow the documentation :

https://docs.microsoft.com/en-us/rest/api/appservice/webapps/createfunction

to create azure function using Azure Rest API. I have not been able to create a C# or Python HTTP trigger function using the API. After some research I found a solution to a question that was posted on these forms but that one is showing example for creating a JavaScript function. The following is the link to that questing on Microsoft form :

https://social.msdn.microsoft.com/Forums/en-US/f4c91356-4de4-481c-83dc-7974f9ab1aae/creating-a-function-dynamically-using-azure-rest-api?forum=AzureFunctions

Can you please provide a example similar to the question above but creating simple python or C# Azure HTTP Trigger Function using this rest API similar to above example?

Thanks for your time

azure-functions
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

MayankBargali-MSFT avatar image
1 Vote"
MayankBargali-MSFT answered

Hi @ShervinMirsaeidi-4877

Welcome to Microsoft Q&A! Thanks for posting the question.

You can modify the request body as per your requirement as mentioned in the Create Function REST API document. For your reference sharing the request body that I have tested at my end for creating the HTTP trigger function.

Request Body for C# HTTP Trigger Function:

 {
    "properties":{
       "files":{
          "run.csx":"#r \"Newtonsoft.Json\"\r\n\r\nusing System.Net;\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing Microsoft.Extensions.Primitives;\r\nusing Newtonsoft.Json;\r\n\r\npublic static async Task<IActionResult> Run(HttpRequest req, ILogger log)\r\n{\r\n    log.LogInformation(\"C# HTTP trigger function processed a request.\");\r\n\r\n    string name = req.Query[\"name\"];\r\n\r\n    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();\r\n    dynamic data = JsonConvert.DeserializeObject(requestBody);\r\n    name = name ?? data?.name;\r\n\r\n    string responseMessage = string.IsNullOrEmpty(name)\r\n        ? \"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.\"\r\n                : $\"Hello, {name}. This HTTP triggered function executed successfully.\";\r\n\r\n            return new OkObjectResult(responseMessage);\r\n}\r\n"
       },
       "config":{
          "bindings":[
             {
                "authLevel":"function",
                "name":"req",
                "type":"httpTrigger",
                "direction":"in",
                "methods":[
                   "get",
                   "post"
                ]
             },
             {
                "name":"$return",
                "type":"http",
                "direction":"out"
             }
          ]
       }
    }
 }

Request Body for Python HTTP Trigger Function:

 {
    "properties":{
       "files":{
          "__init__.py":"import logging\nimport azure.functions as func\n\n\ndef main(req: func.HttpRequest) -> func.HttpResponse:\n    logging.info('Python HTTP trigger function processed a request.')\n\t\n    name = req.params.get('name')\n    if not name:\n        try:\n            req_body = req.get_json()\n        except ValueError:\n            pass\n        else:\n            name = req_body.get('name')\n\n    if name:\n        return func.HttpResponse(f\"Hello, {name}. This HTTP triggered function executed successfully.\")\n    else:\n        return func.HttpResponse(\n             \"This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.\",\n             status_code=200\n        )\n"
       },
       "config":{
          "bindings":[
             {
                "authLevel":"function",
                "name":"req",
                "type":"httpTrigger",
                "direction":"in",
                "methods":[
                   "get",
                   "post"
                ]
             },
             {
                "name":"$return",
                "type":"http",
                "direction":"out"
             }
          ]
       }
    }
 }

Hope the above helps. Feel free to get back to me if you need any assistance.

Please 'Accept as answer' and ‘Upvote’ if it helped so that it can help others in the community looking for help on similar topics.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

ShervinMirsaeidi-4877 avatar image
0 Votes"
ShervinMirsaeidi-4877 answered MayankBargali-MSFT commented

@MayankBargali-MSFT

Hi Mayank,

Thank you for your response. This is exactly what I was looking for. However I believe there is a bug for creating the "init.py" azure function. When I copy paste your request body and send a put request I get a status code "201" for both the C# and Python Azure Function. However when I navigate to azure portal to test the HTTP Trigger function, it runs successfully for the C# one but for the Python I can see the "init.py" script and when I click "Test/Run" in azure portal. The response is "404 Not Found" and when I refresh the page seems like the "init.py" script disappears. Also when I navigate back to the "Functions" page under the Function App using the portal, the newly created function disappears when I click refresh. Have you tried testing the Python function after creation? Or you just assumed it was working when you got the created status code "201" response. Seems that there is some issues with the Python one. I will provide all the screen shots of what I observed. Also sometimes when you create the Python function. It creates it on the portal but when you click it, there is no script. Also sometimes the script names changes to "WarmUp" , than disappears after clicking refresh few times using the Azure portal. Can you please let me know if you notice the same issue on your end. Also if there is something that I missed. I can also provide you a video reproducing's what I have explained above. I did not want to expose my subscription ID and other info in the video. I have attached the screenshots below :

97315-screenshot-1.png97306-screenshot-2.png97268-screenshot-3.png97227-screenshot-4.png97259-screenshot-5.png97250-screenshot-6.png



screenshot-1.png (106.7 KiB)
screenshot-2.png (60.6 KiB)
screenshot-3.png (75.0 KiB)
screenshot-4.png (72.5 KiB)
screenshot-5.png (28.0 KiB)
screenshot-6.png (47.5 KiB)
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@ShervinMirsaeidi-4877 Yes, I have executed the python function (under webapp plans) when I have dynamically created them using REST API. Looking into your configuration I have tested the same in the consumption plan and observe the same behavior as you have mentioned. But this works fine in the webapp plans. I will check with my team if this is supported.

In the meanwhile, I also want to check your requirement what is the use case where you want to create the function dynamically?

1 Vote 1 ·

@ShervinMirsaeidi-4877 In consumption sku there is no persistent storage by default. So contents will be lost when the workers recycle. If you need to create a function for the consumption plan then you need to define (WEBSITE_CONTENTAZUREFILECONNECTIONSTRING, WEBSITE_CONTENTSHARE app settings). I have tested creating a python function once I have defined these two settings in my application settings of the function app.

0 Votes 0 ·

@MayankBargali-MSFT

I cannot get this to work. Looking at this following document (https://docs.microsoft.com/en-us/azure/azure-functions/functions-infrastructure-as-code),
it says for consumption plan you cannot add WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE for Linux. When I try to create function app from portal it says you cannot create a python function app on windows. Only option is Linux. Is the documentation above outdated? Or am I missing something? What I'm trying to accomplish is to first create a Python function app hosted on consumption plan using ARM template, than programmatically add simple Python function under it. I have tried to create a Python function app from UI or ARM template hosted on Consumption plan but have had not luck. Perhaps could you provide me the ARM template for creating a Python Function App hosted on Consumption plan, given I have already created a resource group? Or perhaps guide me in right direction?

Thanks again

0 Votes 0 ·

@ShervinMirsaeidi-4877 Is it possible to create new Microsoft Q&A issue so it can be tracked better and the community can assist you.

0 Votes 0 ·
ShervinMirsaeidi-4877 avatar image
0 Votes"
ShervinMirsaeidi-4877 answered ShervinMirsaeidi-4877 commented

@MayankBargali-MSFT

You are correct, I just tried it using the "App Service Plan" and it works. There is not specific use case. I'm working on a web app that will be used by a manufacturing company, and we want allow them to upload Python or C# scripts which will run against there data. This means they will use Angular web app to upload text scripts and I will use a C# back end to create azure functions using REST API. Given the Azure Function App that was previously created. Pretty much I will hard code everything for the PUT request except the text script that they will upload using a text area for example. I could not find any NuGet packages that I can import into my C# backend that I can use to create Azure Functions on a previously created Azure Function App. The only solution I found was to use REST API. These scripts will need to be able to be executed at any time triggered from web app, also I plan to use Application Insights to check some status, logs and performance via REST API. I figured the best option would be HTTP Trigger Function App that I can call when user clicks run from my web app. Also I could not find anything that I can use to stop a single Azure Function once its started. The only option I can find is a REST API end point which will stop the Azure Function App which contains all the Azure Functions. What I need is to be able to stop a single Azure Function, for example the Python "Function1" that I have posted above.

Please let me know if there are any other options that would simply my flow. Or if you have any other suggestions.

One last thing, could you please also provide examples on how I would pass the applications insights "Instrumentation Key" for Python or C# function using the rest API given I have enabled application insight for the Azure Function App. Like what would the request body look like?

I will now accept your answer.

Once again thank you for your time

· 9
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@ShervinMirsaeidi-4877 For simple use cases your solution would work but for a complex python script where it has a dependencies library, this might not work. If you deploy any python script then if there are any dependencies then you define it in requirements.txt
In that case, you need to find alternatives to install these dependencies and if it is possible using Management API. Not every operation that is supported from the portal would be available using the Management API as some might be a preview or have complex properties/objects or not available. But you can always take a fiddler or F12 traces to verify what is the management API that is being called when you perform any operation from the portal.

<1/3>

1 Vote 1 ·

Wow thank you, all this information is very helpful. Now I get good understanding of potential problems I will run into in the future. Couple more questions came up after looking at your response :

1) Is the dependency issue the same for C# as well? For more complex scripts that require NuGet

2)
A) when you say define it in "requirements.txt"? Is that another attribute on the request body? Cause I do not see it looking at the documentation (https://docs.microsoft.com/en-us/rest/api/appservice/webapps/createfunction)

B) If so could you provide example of what the payload looks like for requiremtn.txt for python and C# request body. For example adding Azure.Messaging.EventHubs rest API service to C# or PythonFunction

3) Does step 2 above is part of the process for using "Management API" option you mentioned for dependency injection? Or this option is a alternative option to the "requirements.txt" you posted above.

Once again I appreciate your time


0 Votes 0 ·

Also I found this document about the assemblies are automatically added by the Azure Functions hosting environment for C#
(https://docs.microsoft.com/en-us/answers/questions/107470/how-to-add-reference-to-directives-in-azure-functi.html)


I assume some of the basic libraries for Python are in the hosting environment as well. If so, what is the list if the libraries added by default? Such as "requests", "NumPy" etc...

0 Votes 0 ·

@ShervinMirsaeidi-4877 Yes basic library should be there but I will suggest you to test it first with a different use case/library. Yes, the directive should help in most of the cases but not necessarily. AFAIK requirement text file should be created not sure if the dependencies will be loaded as this needs to be tested to confirm and might not be supported. One more thing to note that if the app ever gets deployed using Run-From-Package that will take precedence and the functions created using the rest API will no longer be available inside the app. We recommend using Run-From-Package for perf. reasons as well.


1 Vote 1 ·
Show more comments

In the case where you want to disable a particular function, you can leverage the same API and update the property "isDisabled" to true or false and see if it helps while creating/updating the function. Alternatively, you can use the below endpoint to enable and disable a particular function.
https://management.azure.com/subscriptions/{subscriptionID}/resourceGroups/{resourcegroupname}/providers/Microsoft.Web/sites/{sitename}/functions/{functionappname}/properties/state?api-version=2018-11-01

Request Body:
{"properties":"disabled"}
OR
{"properties":"enabled"}

<2/3>

1 Vote 1 ·

@MayankBargali-MSFT

II tried your first solution of passing the "isDisabled" attribute as true under the "properties" object but it does not seem to disable the function. However your second solution of calling that specific endpoint and passing the "properties" as "disabled" does work. But this solution means I need to make a extra call after I update/create function. I wanted to attach my C# HTTP trigger function request body just to make sure I have not missed anything.

Thanks again for your time106024-csharphttpfunction.txt


0 Votes 0 ·