Miten julkaista jokainen ASP.NET Core Controller omaksi API:ksi Azure API Managementissa

Sami Ovaska | 05.11.2020
Lukuaika 3 min

Tavoite

Tavoitteena on automaattisesti julkaista Azure DevOps pipelinen kautta jokainen ASP.NET Core Controller omaksi API:ksi Azure API Managementiin.

Taustaa

Swashbuckle:a käyttäen voi generoida OpenAPI Specification:in (OAS) ASP.NET Core sovelluksesta. Sen lisäksi on olemassa swagger niminen dotnet työkalu, jonka avulla voi generoida OAS:n komentoriviltä.

dotnet swagger tofile --output swagger.V1.json My.Api\bin\Release\netcoreapp3.1\My.Api.dll V1

Generoitu OAS:n voi importoida API:ksi Azure API Managementiin.

Alla olevassa kuvassa näkyy miltä importoitu API näyttää Azure API managementissa ennenkuin mitään muutoksia on tehty.

APIs imported before any changes done

OAS importointi toimii hienosti, mutta vielä hienompaa olisi jos jokainen API näkyisi myös Azure API Managementissa omana APInaan.

Generoitu OAS sisältää kaikki APIt yhdessä tiedostossa.

"paths": {
  "/api/Users": {...},
  "/api/Users/search": {...},
  "/api/Roles": {...}
}

Serverin osoite on myös mukana generoidussa OAS tiedostossa.

"servers": [
  {
    "url": "http://localhost:10586/"
  }
]

Generoidun OAS tiedoston jakaminen API kohtaisiin OAS tiedostoihin

Rakensin yksinkertaisen komentorivisovelluksen nimeltään SwaggerCli joka

  • lukee generoidun OAS tiedoston
  • poistaa API kohtaiset polut ”paths” noodista (esim. /api/Users ylläolevassa esimerkissä)
  • muuttaa serverin osoitteen niin että se sisältää alkuperäisen API endpointin polun (esim. /api/Users ylläolevassa esimerkissä)
  • tallentaa jokaisen API kohtaisen OAS määrityksen omaan tiedostoon

Esimerkiksi Users API OAS sisältää muutosten jälkeen

"paths": {
  "/": {...},
  "/search": {...},
},
"servers": [
  {
    "url": "http://localhost:10586/api/Users"
  }
]

Kaikki Roles -API kohtainen data on poistettu, ja server url sisältää /api/Users -polun.

Build pipeline

API kohtaiset OAS tiedostot generoidaan build pipelinessä, ja julkaistaan build tuloksina.

Seuraavat muutokset tarvittiin build pipelineen:

  1. dotnet tool swagger lisätty
    1. dotnet tool install Swashbuckle.AspNetCore.Cli --version 5.6.2
  2. SwaggerCli projekti lisätty Solution tiedostoon
  3. Osana pipelineä ajetaan dotnet tool restore
  4. Osana pipelineä buildataan SwaggerCli
  5. Generoidaan OAS käyttäen dotnet tool swagger:iä
  6. Ajetaan SwaggerCli joka jakaa OAS tiedoston API kohtaisiin OAS tiedostoihin
  7. Julkaistaan API kohtaiset OAS tiedostot build tuloksina

Kohdat 5-7 pipeline YAML -tiedostossa:

- task: CmdLine@2
displayName: Create specs directory
inputs:
script: 'mkdir $(Pipeline.Workspace)\specs'

- task: DotNetCoreCLI@2
displayName: 'Generate OpenAPI spec document'
inputs:
command: custom
custom: swagger
arguments: 'tofile --output $(Pipeline.Workspace)\specs\${{parameters.projectName}}.V1.json ${{ parameters.projectName }}.Api\bin\Release\netcoreapp3.1\${{parameters.projectName}}.Api.dll V1'

- task: DotNetCoreCLI@2
displayName: "Divide OpenAPI spec document to API specific documents"
inputs:
command: custom
custom: SwaggerCli\bin\Release\netcoreapp3.1\SwaggerCli.dll
arguments: '--inputFilename $(Pipeline.Workspace)\specs\${{parameters.projectName}}.V1.json --outputPath $(Pipeline.Workspace)\specs'

- task: CmdLine@2
displayName: Delete original OpenAPI spec file
inputs:
script: 'del $(Pipeline.Workspace)\specs\${{parameters.projectName}}.V1.json'

- task: PublishPipelineArtifact@1
displayName: "Publish Artifact: OpenAPI specs"
inputs:
targetPath: '$(Pipeline.Workspace)\specs'
artifactName: 'OpenAPI'

Release pipeline

Jokaista API kohtaista OAS -tiedostoa varten piti lisätä uusi taski Release pipelineen:

- task: AzurePowerShell@4
displayName: Update API Management for Users API
inputs:
azureSubscription: '${{ parameters.azureSubscriptionName }}'
scriptType: 'FilePath'
scriptPath: '$(Pipeline.Workspace)/Deployment/Scripts/Update-ApimOpenAPISpec.ps1'
scriptArguments: '-ResourceGroupName "${{ parameters.resourceGroupName }}" -ServiceName "${{ parameters.apiManagementName }}" -ServiceUrl "${{ parameters.apiManagementServiceUrl }}api/users" -ApiPath "api/users" -ApiName "Users" -SpecificationFilePath $(Pipeline.Workspace)\OpenAPI\Users.${{ parameters.environment }}.json'
errorActionPreference: 'stop'
azurePowerShellVersion: 'latestVersion'

Taski kutsuu alla olevaa PowerShell scriptiä jonka avulla OAS importoidaan Azure API Managementiin:

[CmdletBinding()]
Param(
[string] [Parameter(Mandatory=$true)] $ResourceGroupName,
[string] [Parameter(Mandatory=$true)] $ServiceName,
[string] [Parameter(Mandatory=$true)] $ServiceUrl,
[string] [Parameter(Mandatory=$true)] $ApiPath,
[string] [Parameter(Mandatory=$true)] $ApiName,
[string] [Parameter(Mandatory=$true)] $SpecificationFilePath
)

$apiMgmtContext = New-AzApiManagementContext -ResourceGroupName $ResourceGroupName -ServiceName $ServiceName

$api = Get-AzApiManagementApi -Context $apiMgmtContext -Name $ApiName
if ($null -eq $api) {
$api = New-AzApiManagementApi -Context $apiMgmtContext -Name $ApiName -ServiceUrl $ServiceUrl -Path $ApiPath -Protocols @("https")
}

Import-AzApiManagementApi -Context $apiMgmtContext `
-SpecificationPath $SpecificationFilePath `
-SpecificationFormat 'OpenApi' `
-Path $api.Path `
-ApiId $api.ApiId

Loppusanat

Tältä API:t näyttävät Azure API managementissa muutosten jälkeen.

APIs imported after changes are done

Muutosten jälkeen voin määritellä useamman API Management Productin ja liittää valitut API:t eri Producteihin. Tämä ei ollut mahdollista ilman jokaisen API:n importoimista omaksi API:ksi Azure API Managementin.

Kiitos Twitter käyttäjälle @domze alla olevasta hienosta artikkelista, siitä oli suuri apu tavoitteen saavuttamisessa!

Automating your OpenAPI updates to API Management through your CI/CD pipeline