5

We're looking to automate the process of importing a function definition into our CD process with every deployment of our azure functions. Within the azure portal, there is a very straightforward way to import a function definition through the UI, but their doesn't appear to be any api/cli/powershell library to automate this process.

Azure Portal Function app import

We have managed to create a workaround which involves keeping our function app definitions up to date using the C# OpenApi library and then using the az apim import cli command as part of our deployment pipeline but it feels like extra work keeping the OpenApi definition up to date and accurate on every endpoint of our function and it would be preferable to automate what the portal is doing under the hood when you import a function app (this does not require an openapi definition being kept up to date in source code). Any help would be greatly appreciated.

We are using Azure Devops for our CI/CD pipelines and releases.

Ben
  • 2,058
  • 9
  • 29
  • 39

1 Answers1

1

You've got a few options for this. You didn't specify if you already have some existing infrastructure CI tools, but I'm most familiar with doing this in terraform.

Tutorial on how to setup terraform into your pipeline.

Once you have terraform integrated you can easily add API definitions into your APIM instance. And link that up to your function backend.

Article and some code samples from it:

resource "azurerm_api_management_backend" "example" {
  name                = "example-backend"
  resource_group_name = data.azurerm_resource_group.example.name
  api_management_name = data.azurerm_api_management.example.name
  protocol            = "http"
  url                 = "https://${azurerm_function_app.example.name}.azurewebsites.net/api/"

  credentials {
    header = {
      "x-functions-key" = "${data.azurerm_function_app_host_keys.example.default_function_key}"
    }
  }
}

resource "azurerm_api_management_api" "example" {
  name                = "example-api"
  resource_group_name = data.azurerm_resource_group.example.name
  api_management_name = data.azurerm_api_management.example.name
  revision            = "1"
  display_name        = "Example API"
  path                = "example"
  protocols           = ["https"]

  import {
    content_format = "openapi"
    content_value  = file("${path.module}/FuncOpenAPI3.yml")
  }
}

resource "azurerm_api_management_api_policy" "example" {
  api_name            = azurerm_api_management_api.example.name
  api_management_name = azurerm_api_management_api.example.api_management_name
  resource_group_name = azurerm_api_management_api.example.resource_group_name

  xml_content = <<XML
<policies>
  <inbound>
    <base/>
    <set-backend-service backend-id="example-backend" />
  </inbound>
</policies>
XML
}

Now as you can see in this article it talks about importing an OpenApi file to define the actual api. There isn't a great way to do this automatically, but there is a way using swagger's built in tofile tool:

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="dotnet tool restore" />
    <Exec Command="dotnet swagger tofile --output swagger.json $(OutputPath)\$(AssemblyName).dll v1 " />
</Target>

When you run your build in your pipeline this file will be generated and then you can reference it in your infrastructure stage to use that OpenAPI file to automatically generate that API in APIM.

Chase
  • 2,206
  • 1
  • 13
  • 17
  • I like the idea of generating the openapi file from the cli rather than having to reference the one that gets deployed as part of our function app. Do you have any idea how Microsoft is doing this under the hood without the requirement of including swashbuckle attributes to the function app? Our function app has about 35 endpoints and keeping the swagger definition correct via those attributes can sometimes be a challenge and often gets missed in our PR's and it would be awesome if we could somehow get that behavior without manually keeping them up to date. – Ben Jul 12 '22 at 18:26
  • When executing `swagger tofile --output swagger.generated.json my.dll v1` I've next error `The specified runtimeconfig.json [.\my.runtimeconfig.json] does not exist`. Is there anything I could do to fix it? – H. Pauwelyn Aug 17 '23 at 09:15