Export/Import Azure API Management Developer Portal Configurations
Asked Answered
B

3

6

Microsoft has released a new developer portal for Azure API Management.

I'm looking for a way to export all the files and configurations from an API Developer portal and be able to import it to another one. So, I can apply the same customization to all my APIM instances.

Is there way to achieve that?

Barbecue answered 5/12, 2019 at 17:59 Comment(1)
Any solution for this question?Flowers
P
1

You could use Git Repository to export and import configuration.

In the local Git repository, portalStyles folder contains the configuration for the developer portal customizations in the service instance.

enter image description here

Note: Developer portal entities other than styles cannot be configured using Git.

Pelion answered 6/12, 2019 at 3:21 Comment(0)
B
0

I tried Entire API's are imported Successfully but Not Portal styles and UI design so for that any procedure is there ?

Balbo answered 31/12, 2019 at 11:27 Comment(2)
Is it an answer?Boddie
Any solution for this question?Flowers
B
-1

Using the Git Repository will import most configurations, but that won't cover the Developer Portal styles. This Microsoft article describes how you can import a Developer Portal from one APIM to another:

https://learn.microsoft.com/en-us/azure/api-management/automate-portal-deployments

Here's the script from Microsoft's Github (accessible in the article)

/**
 * This script automates deployments between developer portal instances.
 * In order to run it, you need to:
 * 
 * 1) Clone the api-management-developer-portal repository:
 *    git clone https://github.com/Azure/api-management-developer-portal.git
 * 
 * 2) Install NPM  packages:
 *    npm install
 * 
 * 3) Run this script with a valid combination of arguments:
 *    node ./migrate ^
 *    --sourceSubscriptionId "< your subscription ID >" ^
 *    --sourceResourceGroupName "< your resource group name >" ^
 *    --sourceServiceName "< your service name >" ^
 *    --sourceTenantId "< optional (needed if source and destination is in different subscription) source tenant ID >" ^
 *    --sourceServicePrincipal "< optional (needed if source and destination is in different subscription) source service principal or user name. >" ^
 *    --sourceServicePrincipalSecret "< optional (needed if source and destination is in different subscription) secret or password for service principal or az login for the source apim. >" ^
 *    --destSubscriptionId "< your subscription ID >" ^
 *    --destResourceGroupName "< your resource group name >" ^
 *    --destServiceName "< your service name >"
 *    --destTenantId "< optional (needed if source and destination is in different subscription) destination tenant ID >"
 *    --destServicePrincipal "< optional (needed if source and destination is in different subscription)destination service principal or user name. >"
 *    --destServicePrincipalSecret "< optional (needed if source and destination is in different subscription) secret or password for service principal or az login for the destination. >"
 * 
 * Auto-publishing is not supported for self-hosted versions, so make sure you publish the portal (for example, locally)
 * and upload the generated static files to your hosting after the migration is completed.
 * 
 * You can specify the SAS tokens directly (via sourceToken and destToken), or you can supply an identifier and key,
 * and the script will generate tokens that expire in 1 hour. (via sourceId, sourceKey, destId, destKey)
 */

const { ImporterExporter } = require('./utils.js');

const yargs = require('yargs')
    .example(`node ./migrate ^ \r
    *    --sourceSubscriptionId "< your subscription ID > \r
    *    --sourceResourceGroupName "< your resource group name > \r
    *    --sourceServiceName "< your service name > \r
    *    --sourceTenantId "< optional (needed if source and destination is in different subscription) source tenant ID > \r
    *    --sourceServicePrincipal "< optional (needed if source and destination is in different subscription) source service principal or user name. > \r
    *    --sourceServicePrincipalSecret "< optional (needed if source and destination is in different subscription) secret or password for service principal or az login for the source apim. > \r
    *    --destSubscriptionId "< your subscription ID > \r
    *    --destResourceGroupName "< your resource group name > \r
    *    --destServiceName "< your service name > \r
    *    --destTenantId "< optional (needed if source and destination is in different subscription) destination tenant ID > \r
    *    --destServicePrincipal "< optional (needed if source and destination is in different subscription) destination service principal or user name. > \r
    *    --destServicePrincipalSecret "< optional (needed if source and destination is in different subscription) secret or password for service principal or az login for the destination. >\n`)
    .option('sourceSubscriptionId', {
        type: 'string',
        description: 'Azure subscription ID.',
        demandOption: true
    })
    .option('sourceResourceGroupName', {
        type: 'string',
        description: 'Azure resource group name.',
        demandOption: true
    })
    .option('sourceServiceName', {
        type: 'string',
        description: 'API Management service name.',
        demandOption: true
    })
    .option('sourceTenantId', {
        type: 'string',
        description: 'source tenant ID.',
        demandOption: false
    })
    .option('sourceServicePrincipal', {
        type: 'string',
        description: 'source service principal ID.',
        demandOption: false
    })
    .option('sourceServicePrincipalSecret', {
        type: 'string',
        description: 'source service principal secret.',
        demandOption: false
    })
    .option('destSubscriptionId', {
        type: 'string',
        description: 'Azure subscription ID.',
        demandOption: true
    })
    .option('destResourceGroupName', {
        type: 'string',
        description: 'Azure resource group name.',
        demandOption: true
    })
    .option('destServiceName', {
        type: 'string',
        description: 'API Management service name.',
        demandOption: true
    })
    .option('destTenantId', {
        type: 'string',
        description: ' destination tenantId.',
        demandOption: false
    })
    .option('destServicePrincipal', {
        type: 'string',
        description: 'destination service principal or user name.',
        demandOption: false
    })
    .option('destServicePrincipalSecret', {
        type: 'string',
        description: 'destination service principal secret.',
        demandOption: false
    })
    .help()
    .argv;

async function migrate() {
    try {
        const sourceImporterExporter = new ImporterExporter(yargs.sourceSubscriptionId, yargs.sourceResourceGroupName, yargs.sourceServiceName, yargs.sourceTenantId, yargs.sourceServicePrincipal, yargs.sourceServicePrincipalSecret);
        await sourceImporterExporter.export();

        const destImporterExporter = new ImporterExporter(yargs.destSubscriptionId, yargs.destResourceGroupName, yargs.destServiceName, yargs.destTenantId, yargs.destServicePrincipal, yargs.destServicePrincipalSecret);
        await destImporterExporter.cleanup();
        await destImporterExporter.import();

        await destImporterExporter.publish();
    } 
    catch (error) {
        throw new Error(`Unable to complete migration. ${error.message}`);
    }
}

migrate()
    .then(() => {
        console.log("DONE");
        process.exit(0);
    })
    .catch(error => {
        console.error(error.message);
        process.exit(1);
    });
Biagio answered 1/12, 2023 at 1:27 Comment(1)
A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it is there, then quote the most relevant part of the page you are linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Siege

© 2022 - 2024 — McMap. All rights reserved.