serverless / serverless-azure-functions

Serverless Azure Functions Plugin – Add Azure Functions support to the Serverless Framework
MIT License
266 stars 162 forks source link

Skip APIM ARM deployment #476

Open Rapol opened 4 years ago

Rapol commented 4 years ago

This is a Feature Proposal

Description

We would like to add an option to exclude the APIM resource in the ARM template when using the type(consumption, premium, ase) deployment.

We have multiple function apps reusing resources (app service plan, apim, storage accounts, etc) in a resource group. This has been working for us nicely but we encountered an issue with APIM. We needed to set the APIM in a VNET. Both of these were created via scripts outside of serverless. When we reference the APIM name in the serverless config it works perfectly for APIM and function app integration but since serverless doesn't know about the VNET the resulting ARM template wipes out the VNET configuration.

I forked the repo and made a branch with the changes we were envisioning but I haven't tested it yet. https://github.com/Rapol/serverless-azure-functions/commit/3b1e09d113871ee7fcaaed3c07124b6a7935d074

Another option would be to add APIM VNET configuration into the apim section in the provider and update the default APIM template to reflect this. For our use case it sounds better to deploy the APIM and VNET configuration outside of serverless and just use serverless to update the APIM endpoint integration with the function apps.

arsenvlad commented 4 years ago

I am also trying to see if one APIM can be used with multiple separate function apps. @Rapol when you tried re-using the APIM, did you notice it also overwriting the API and backend definitions or have those stayed OK for you and only VNET config was wiped out?

Rapol commented 4 years ago

The apim definitions stayed even after deployments of different sls projects. Only the vnet config was wiped out. I suppose the backend definitions cannot be named the same across sls projects, that might overwrite them.

Our sls config imports a config that has the name of the resources (apim, storage accounts, etc). This will make the azure plugin to use the same resources across sls projects. Note that the apim config below has a skipArmTemplate property which is part of the fork I posted in the original issue. This will tell the plugin to not add the APIM to the ARM template but it will still update the APIM endpoints since thats done via the azure cli and not ARM. Keep in mind that now you will need to deploy the APIM individually if skipArmTemplate = true.

provider:
  name: azure
  runtime: nodejs10.x
  tenantId: ${self:custom.config.tenantId}
  os: linux
  resourceGroup: ${opt:rg, self:custom.config.resourceGroup}
  region: ${opt:region, 'East US 2'}
  stage: ${opt:stage, 'dev'}
  subscriptionId: ${self:custom.config.subscriptionId}
  type: premium
  appServicePlan:
    name: ${self:custom.config.servicePlanName}
    sku:
      tier: ElasticPremium
      name: EP1
  appInsights:
    name: ${self:custom.config.appInsightsName}
  functionApp:
    name: ${self:custom.config.functionAppName}
  storageAccount:
    name: ${self:custom.config.storageName}
  apim:
    # Name of a previously deployed APIM
    name: ${self:custom.config.apimName}
    skipArmTemplate: true
    sku:
      name: ${self:custom.config.apimSku}
      capacity: 1
    apis:
      - name: users-api
    ....
arsenvlad commented 4 years ago

Are you putting each of the separate functions app under a different API name (e.g. users-api in your sample above)?

Rapol commented 4 years ago

Yep, each serverless project (function app) represents an API service. Some of our sls projects have one or more APIM APIs but we havent tried to reuse them across projects

sandip-exemplar commented 4 years ago

I am having the same issue if you want to re-use the API across serverless services it overwrites previous service deployment.

I have 2 function Apps pointing to same base path organization. In my serverless service I am referencing same API configuration with different back-end. But, new service deployment overwrites previous service deployment.

apis:

- name: ${self:provider.prefix}-${self:provider.stage}-api

I am referencing above API config in both services

Rapol commented 4 years ago

If you have two serverless projects updating the same api path:

Product service serverless project

apis:
      - name: users-api
      ...

User service serverless project

apis:
      - name: users-api
      ...

You might want to refactor your serverless projects to not redefine APIM apis across projects.

I'm assuming that the azure plugin performs a PUT and overwrites the users-api APIM API definition. I'm not entirely sure on the inner workings of the plugin but that would be my hunch of what it is doing. If it performs a PATCH, once you remove an API path that you do not longer need it would leave it in the APIM which is not something that we would want to do. So I assume the library is working as expected but collaborators might want to shine on this.