skip to Main Content

I have an Azure Function App already created and I want to deploy a python function with Azure DevOps pipeline. The issue is that the pipeline runs without errors but the function is not created. Instead, in the App Files of the Function App, I see that in the wwwroot folder there is the ImpervaWAFCloudSentinelConn folder with all its contents as well as a default host.json.

Here is the pipeline I run:

trigger:
  - none

resources:
  - repo: self

variables:
  azureSubscription: "<my-service-connection>"
  functionAppName: "<my-function-app-name>"
  resourceGroupName: "<my-rg>"


stages:
  - stage: Build
    displayName: Build Function App
    jobs:
      - job: Build
        displayName: Build Code
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: UsePythonVersion@0
            inputs:
              versionSpec: '3.8'
              addToPath: true
              architecture: 'x64'
          - bash: |
              pip install --target="./.python_packages/lib/site-packages" -r ./src/ImpervaWAFCloudSentinelConn/requirements.txt
          - task: ArchiveFiles@2
            inputs:
              rootFolderOrFile: '$(System.DefaultWorkingDirectory)/src/ImpervaWAFCloudSentinelConn'
              archiveFile: '$(Build.ArtifactStagingDirectory)/build$(Build.BuildId).zip'
          - task: PublishBuildArtifacts@1
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)/build$(Build.BuildId).zip'
              artifactName: drop
  - stage: Deploy
    displayName: Deploy Code to Function App
    jobs:
      - job: Deploy
        displayName: Deploy Code to Function App
        pool: DevOps VMSS Agents
        steps:
          - task: DownloadPipelineArtifact@2
            inputs:
              buildType: 'current'
              artifactName: drop
              targetPath: $(System.DefaultWorkingDirectory)
          - task: AzureFunctionApp@2
            inputs:
              connectedServiceNameARM: $(azureSubscription) # string. Alias: azureSubscription. Required. Azure Resource Manager connection.
              appType: 'functionAppLinux' # Required. App type.
              appName: $(functionAppName) # Required. Azure Functions App name.
              resourceGroupName: $(resourceGroupName)
              package: '$(System.DefaultWorkingDirectory)/**/*.zip'
              runtimeStack: 'PYTHON|3.8'
              deploymentMethod: 'runFromPackage'


The application that I’m trying to deploy on the function app is the one mentioned in the documentation here.

The file structure of the git repository is the following:

- pipelines/ 
     -- azure-pipelines-src.yaml 
- src/ 
     -- ImpervaWAFCloudSentinelConn/ 
         --- host.json 
         --- proxies.json 
         --- requirements.txt 
         --- ImpervaWAFCloudSentinelConnector/ 
            ---- __init__.py 
            ---- function.json 
            ---- state_manager.py

2

Answers


  1. Chosen as BEST ANSWER

    If I have the following file structure:

    pipeline/
    ├─ azure-pipeline-src.yaml
    src/
    ├─ ImpervaWAFCloutSentinelConnector/
    │  ├─ __init__.py
    │  ├─ function.json
    │  ├─ state_manager.py
    ├─ host.json
    ├─ proxies.json
    ├─ requirements.txt
    
    

    What I need to do is to create a deployment slot in the Function App and deploy it there. In the end you have to swap with the default slot.

    Here is the pipeline that worked for me:

    trigger:
    - none
    
    variables: 
      azureSubscription: <service-connection-or-subscription-name>
      functionAppName: <function-app-name>
      resourceGroup: <resource-group-name>
      slotName: <slot-name>
    
    stages:
    - stage: Build
      displayName: Build stage
    
      jobs:
      - job: Build
        displayName: Build
        pool:
          vmImage: 'ubuntu-latest'
    
        steps:
        - task: UsePythonVersion@0
          inputs:
            versionSpec: '3.8'
            addToPath: true
            architecture: 'x64'
    
        - bash: |
            if [ -f extensions.csproj ]
            then
                dotnet build extensions.csproj --output ./bin
            fi
            pip install --target="./.python_packages/lib/site-packages" -r ./src/requirements.txt
        - task: ArchiveFiles@2
          displayName: "Archive files"
          inputs:
            rootFolderOrFile: "$(System.DefaultWorkingDirectory)/src"
            includeRootFolder: false
            archiveFile: "$(System.DefaultWorkingDirectory)/src/build$(Build.BuildId).zip"
        - task: PublishBuildArtifacts@1
          inputs:
            PathtoPublish: '$(System.DefaultWorkingDirectory)/src/build$(Build.BuildId).zip'
            artifactName: 'drop'
    
    - stage: Deploy
      displayName: Deploy stage
      dependsOn: Build
      condition: succeeded()
    
      jobs:
      - job: Deploy
        displayName: Deploy
        pool: DevOps VMSS Agents
        steps:
          - task: DownloadPipelineArtifact@2
            inputs:
              buildType: 'current'
              artifactName: drop
              targetPath: $(System.DefaultWorkingDirectory)
          - task: AzureFunctionApp@2
            inputs:
              connectedServiceNameARM: $(azureSubscription)
              appType: 'functionAppLinux'
              appName: $(functionAppName)
              package: '$(System.DefaultWorkingDirectory)/**/*.zip'
              runtimeStack: 'PYTHON|3.8'
              deploymentMethod: 'auto'
              deployToSlotOrASE: true
              resourceGroupName: $(resourceGroup)
              slotName: $(slotName)
          - task: AzureAppServiceManage@0
            inputs:
              azureSubscription: $(azureSubscription)
              Action: 'Swap Slots'
              WebAppName: $(functionAppName)
              ResourceGroupName: $(resourceGroup)
              SourceSlot: $(slotName)
              PreserveVnet: true
    

  2. I tried to deploy the Function from this Imperva Cloud ARM template and the url mentioned in this ARM template for the Function Trigger code files does not contain local.settings.json file, Thus it is causing the Function app to not read the function. As local.settings.json file is necessary for the Function app deployment even if it contains local settings. You can download the Function code from the URL and add local.settings.json in the root level Refer below:-

    local.settings.json:-

    {
        "IsEncrypted": false,
        "Values": {
          "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=valleystrg129;AccountKey=xxxxxm9GXkEbQyVIUtd15vxxxxE7Bxxxxxxx;EndpointSuffix=core.windows.net",
          "FUNCTIONS_WORKER_RUNTIME": "python"
        }
      }
    

    Make sure you add a storage account Connection string in AzureWebJobsStorage

    My Function code locally with below format:-

    I sent this code to Azure repository and deployed the Function via Azure DevOps pipeline like below:-

    My Azure DevOps repository:-

    enter image description here

    Selected below option:-

    enter image description here

    trigger:
    - main
    
    variables:
      
      azureSubscription: 'xxxxxxxxx35a6cbaf'
    
      # Function app name
      functionAppName: 'valleyfunc769'
    
      # Agent VM image name
      vmImageName: 'ubuntu-latest'
    
      # Working Directory
      workingDirectory: '$(System.DefaultWorkingDirectory)'
    
    stages:
    - stage: Build
      displayName: Build stage
    
      jobs:
      - job: Build
        displayName: Build
        pool:
          vmImage: $(vmImageName)
    
        steps:
        - bash: |
            if [ -f extensions.csproj ]
            then
                dotnet build extensions.csproj --runtime ubuntu.16.04-x64 --output ./bin
            fi
          workingDirectory: $(workingDirectory)
          displayName: 'Build extensions'
    
        - task: UsePythonVersion@0
          displayName: 'Use Python 3.6'
          inputs:
            versionSpec: 3.10 # Functions V2 supports Python 3.6 as of today
    
        - bash: |
            pip install --target="./.python_packages/lib/site-packages" -r ./requirements.txt
          workingDirectory: $(workingDirectory)
          displayName: 'Install application dependencies'
    
        - task: ArchiveFiles@2
          displayName: 'Archive files'
          inputs:
            rootFolderOrFile: '$(workingDirectory)'
            includeRootFolder: false
            archiveType: zip
            archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
            replaceExistingArchive: true
    
        - publish: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
          artifact: drop
    
    - stage: Deploy
      displayName: Deploy stage
      dependsOn: Build
      condition: succeeded()
    
      jobs:
      - deployment: Deploy
        displayName: Deploy
        environment: 'development'
        pool:
          vmImage: $(vmImageName)
    
        strategy:
          runOnce:
            deploy:
    
              steps:
              - task: AzureFunctionApp@1
                displayName: 'Azure functions app deploy'
                inputs:
                  azureSubscription: '$(azureSubscription)'
                  appType: functionAppLinux
                  appName: $(functionAppName)
                  package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
    

    Output:-

    enter image description here

    Function is visible and got deployed successfully like below:-

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search