Deploy Azure Function and expose it using API Management

In this article, you will learn how to deploy Azure Function and expose it using API Management. You find a sample Azure Function and deployment pipeline. The azure function is written in dotnet 7.0 and Azure Function v4.

This is the next post in the Network Series, you can find all posts in this series. Just a small recap, in the Network series, I show you how to expose Rest APIs through Azure API Management. All dependencies are connected using private endpoints.

As always, all source codes can be found at the beginning of the article, you can find it here. If you don’t know how to set up a pipeline, all answers are below!

Before you can use the pipeline from this article, you need to deploy Azure components from the Network Series scenario. In order to do that go to Rest API with Private Endpoint, exposed to API Management by Terraform to download terraform sources and ready-to-go pipelines.

Sample Azure Function exposes only one method with get and post. Additionally, there is an open API endpoint, used for APIM import.

The deployment pipeline consists of three stages:

So firstly you need to set up variables in the build-and-deploy-function.yaml pipeline. Set values for variables with # mark:

pool: Default

  buildConfiguration: 'Release'
  functionAppName: '#FUNCTION_NAME#'
  azureSubscription: '#SERIVCE_CONNECTION_NAME#'
  apimResourceGroup: '#APIM_RG#'
  apimName: '#APIM_NAME#'
  apimServiceName: '#APIM_SERVICE_NAME#'
  apimPath: '#APIM_SERVICE_PATH'
  specificationUrl: '#FUNCTION_URL#/api/swagger.json'
  serviceUrl: '#FUNCTION_URL#/api'
  specificationFormat: 'OpenApiJson'  
  productName: SampleFunctionApiProduct
  productNameId: SampleFunctionApiProduct
  projectPath: "**/SampleFunction/**/*.csproj"

Take a look at the below parameter, you can find it on the top pipeline:

pool: Default

In Azure DevOps, the Default pool is intended for self-hosted agents. We need it because this solution is isolated on the network level. If you want to know more details, you can get in here: Rest API with Private Endpoint, exposed to API Management by Terraform.

Build Azure Function

Azure Function is built with DotNetCoreCLI@2 task:

- task: DotNetCoreCLI@2
  displayName: Build
    command: 'build'
    projects: '$(projectPath)'
    arguments: --configuration $(buildConfiguration)

After the build, we have to publish Azure Function and create Artifact for the next stages:

- task: DotNetCoreCLI@2
  displayName: Publish
    command: 'publish'
    publishWebProjects: false
    projects: '$(projectPath)'
    arguments: '--configuration $(buildConfiguration) --output $(build.artifactstagingdirectory)'
    zipAfterPublish: True

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact'
    PathtoPublish: '$(build.artifactstagingdirectory)'

Deploy Azure Function

When an artefact is published, we can jump to the Deploy stage:

- stage: Deploy
  displayName: 'Deploy function'
  dependsOn: Build
  condition: succeeded()
    - deployment: Deploy
      displayName: Deploy function
      environment: Azureway
              - task: AzureFunctionApp@1
                displayName: 'Deploy Azure Function'
                  azureSubscription: '$(azureSubscription)'
                  appType: functionAppLinux
                  appName: $(functionAppName)       
                  runtimeStack: 'DOTNET-ISOLATED|7.0'            
                  package: '$(Pipeline.Workspace)/drop/'
                  deploymentMethod: 'zipDeploy'

Pay attention to the following settings:

  • dependsOn and condition – ensure that the previous step was successful
  • runtimeStack – specify what is the runtime of the Azure Function
  • package – path to the Artifact
  • deploymentMethod – in the publish task we set zipAfterPublish flag to ‘true’, so we need to set deploymentMethod to ‘zipDeploy’

API Management and Azure Function integration

Before we update API Management, we have to wait for Azure Function to update the definition. I add 3 minutes of sleep before the APIM update will execute.

To deploy Azure Function to the API Management we have to:

Get API revision

If we want to import new versions of the API, we need to set new revisions for each deployment.

currentApiRevision=$(az apim api revision list --resource-group $APIMRESOURCEGROUP --service-name $APIMNAME --api-id $APIMSERVICENAME | jq '.[0].apiRevision' ) 
parsedApiRevision=$(echo $currentApiRevision | tr -d '"')
nextApiRevision=$(($parsedApiRevision + 1))

Create/get product

Contains one or more APIs, defines a usage quota, and the terms of use.

az apim product create --resource-group $APIMRESOURCEGROUP  --service-name $APIMNAME --product-id $PRODUCTNAMEID --product-name $d --subscription-required true --approval-required false --state "published"

Add our API to the product

az apim product api add --resource-group $APIMRESOURCEGROUP --service-name $APIMNAME --product-id $PRODUCTNAMEID --api-id $APIMSERVICENAME

Import API from OpenApi definition, hosted by Azure Function

az apim api import -g $APIMRESOURCEGROUP --service-name $APIMNAME --path $APIMPATH --service-url $SERVICEURL --specification-url $SPECIFICATIONURL --specification-format $SPECIFICATIONFORMAT --api-type http --api-revision $nextApiRevision --api-id $APIMSERVICENAME --subscription-required false

Create a release of the revision, to publish the newest changes.

az apim api release create --resource-group $APIMRESOURCEGROUP --service-name $APIMNAME --api-id $APIMSERVICENAME --release-id MyRelease_$nextApiRevision --api-revision $nextApiRevision

Complete integration between API Management and Azure Function you can find here.

The above API Management deployment is valid for all Rest APIs for which you can expose OpenAPI documents, for example, swagger. You need to remember to give some time between deployment and updating your API because you need a new version of the API to be available.

I hope this article was useful for you 🙂 Check out more articles from this series:

Leave a Reply

Your email address will not be published. Required fields are marked *