The Azure API Management (APIM) Developer Portal is shipped with the default theme. Many customers choose to change it to reflect the corporate branding and to present the APIs in a custom way.
Technically the portal is based on the Paperbits framework which allows for redesigning the portal within the browser. The whole contents are stored in a JSON file and the images are hosted on the internal blob storage of API Management.
In the real world, we often have multiple APIM environments (DEV, STG, PROD, …) which raises the question of how to migrate the Developer Portal from one environment to another. In this article, we’ll show how to do that with Azure DevOps.
This article will show you how to create an Azure DevOps (YAML) pipeline and use the APIM Developer Portal tools to migrate the portal contents.
Azure APIM Developer Portal is an open-source project that along with the portal files contains also the migration tools. Currently, there are two versions of the tools (v2 and v3) but in the article, we’ll use the latest version that is located in the “scripts.v3” folder. The folder contains several Node.js scripts and batch files for the migration.
Note that in this folder you can find the migrate.js and migrate.bat files that allow us to migrate the portal with only one command. It worked well when I did the migration locally where my Azure account had enough permissions to proceed with the migration. However, in my Azure DevOps environment, I had only Service connections for the source and destination (target) subscriptions so the migration had to be done in another way. Instead of one migrate command we’ll use multiple commands that allow us to proceed step-by-step with the migration.
The commands we’ll need to execute are (in that order) :
Fair enough, let’s create an Azure DevOps pipeline with those commands to proceed with the migration.
Now let’s see how to create the YAML pipeline. As mentioned earlier, we need to execute three commands – capture, cleanup and generate. The pipeline has to capture the data from the source APIM Developer Portal, clean up the destination (portal) and generate contents for the destination APIM Developer Portal. Recently a new option (–publish true) was added to the generate command. With this option, we can publish the portal just after the contents generation.
As the migration tools are implemented in NodeJs, the first task in the pipeline will be the installation of the Node.js JavaScript runtime.
The source code below contains the Azure DevOps pipeline (YAML). It will execute all the tasks necessary for the migration of the Azure API Management Developer portal from one APIM instance to another. I’ll explain all the pipeline variables later in the article.
name: APIM_DeveloperPortalMigration trigger: none variables: location: northeurope sourceServiceConnection: <source_service_connection> destServiceConnection: <destination_service_connection> sourceSubscriptionId: <source_subscription_id> destSubscriptionId: <destination_subscription_id> sourceResourceGroupName: <source_apim_instance_resource_group> destResourceGroupName: <destination_apim_instnace_resource_group> sourceServiceName: <source_apim_instance_name> destServiceName: <destination_apim_instance_name> jobs: # All tasks on APIM Developer portal pipeline - job: Deploy_APIM_Developer_Portal displayName: Deploy APIM Developer portal from one APIM instance to another APIM instance Migration pool: vmImage: ubuntu-latest timeoutInMinutes: 90 steps: - task: Npm@1 displayName: Npm Install command inputs: command: "install" workingDir: 'portal/scripts.v3' - task: AzureCLI@2 displayName: Capturing source portal inputs: azureSubscription: $(sourceServiceConnection) scriptType: 'pscore' workingDirectory: 'portal/scripts.v3' scriptLocation: 'inlineScript' inlineScript: 'node ./capture --subscriptionId $(sourceSubscriptionId) --resourceGroupName $(sourceResourceGroupName) --serviceName $(sourceServiceName)' - task: AzureCLI@2 displayName: Cleaning up destination portal inputs: azureSubscription: $(destServiceConnection) scriptType: 'pscore' workingDirectory: 'portal/scripts.v3' scriptLocation: 'inlineScript' inlineScript: 'node ./cleanup --subscriptionId $(destSubscriptionId) --resourceGroupName $(destResourceGroupName) --serviceName $(destServiceName)' - task: AzureCLI@2 displayName: Generating destination portal inputs: azureSubscription: $(destServiceConnection) scriptType: 'pscore' workingDirectory: 'portal/scripts.v3' scriptLocation: 'inlineScript' inlineScript: 'node ./generate --publish true --subscriptionId $(destSubscriptionId) --resourceGroupName $(destResourceGroupName) --serviceName $(destServiceName)'
The following parameters (in angle brackets) should be specified:
<source_service_connection> – service connection in Azure DevOps, for accessing resources in the source subscription
<destination_service_connection> – service connection in Azure DevOps, for accessing resources in the destination subscription
<source_subscription_id> – subscription id of the source APIM instance
<destination_subscription_id> – subscription id of the destination APIM instance
<source_apim_instance_resource_group> – resource group name of the source APIM instance
<destination_apim_instnace_resource_group> – resource group name of the destination APIM instance
<source_apim_instance_name> – name of the source APIM instance
<destination_apim_instance_name> – name of the destination APIM instance
Let’s prepare a workspace in the Azure DevOps repository. First, I’ve created a “portal” folder where we’ll keep all portal-related files and migration tools. I’ve cloned the APIM Developer portal GitHub repository to my local disk and then I’ve copied the “scripts.v3” folder.
Then I’ve created my Azure DevOps YAML pipeline and pushed it to the portal folder.
Finally, I have committed and pushed the files to the Azure DevOps repository so the structure on the Azure DevOps repository looks something like this:
After the files are in the Azure DevOps repository, all you need is to find the YAML pipeline file in the Azure DevOps and execute it. If everything is configured correctly and the service connections have sufficient permissions, the portal content will be migrated between the Azure APIM instances.
It might happen that the destination portal should use the different URLs (custom domains) that are attributed by default to the APIM instance. In that case, we can enrich our pipeline with one more task and call the updatecontenturl command:
- task: AzureCLI@2 displayName: Updating destination urls inputs: azureSubscription: $(destServiceConnection) scriptType: 'pscore' workingDirectory: 'portal/scripts.v3' scriptLocation: 'inlineScript' inlineScript: 'node ./updatecontenturl --subscriptionId $(destSubscriptionId) --resourceGroupName $(destResourceGroupName) --serviceName $(destServiceName) --existingEnvUrls $(existingEnvUrls) --destEnvUrls $(destEnvUrls)'
We’ll also need to add two new variables to the variable list:
If multiple URLs are specified, the number and order of URLs must match the existing and destination URL list.
That’s it! The latest version of the tools has made the migration process easier than it was some time ago. The source files of the migration commands are well documented, so do not hesitate the check them.