├── .devcontainer └── devcontainer.json ├── .github ├── CODE_OF_CONDUCT.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── images ├── api-center.png ├── gbb.png ├── import-bian.png ├── import-from-aws.png ├── import-from-azure-apim.png ├── import-from-gcp.png ├── import-from-generic-openapi.png ├── import-from-git.png ├── import-from-ibm.png ├── import-from-k8s.png ├── import-from-kong.png ├── import-from-mulesoft.png └── toolchain.png ├── labs ├── import-bian │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-bian.ipynb │ ├── main.bicep │ └── spectral.yaml ├── import-from-aws │ ├── Petstore.json │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── get-rest-api.json │ ├── get-rest-apis.json │ ├── get-stage.json │ ├── import-from-aws.ipynb │ └── main.bicep ├── import-from-azure-apim │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-azure-apim.ipynb │ └── main.bicep ├── import-from-gcp │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-gcp.ipynb │ └── main.bicep ├── import-from-generic-openapi │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-generic-openapi.ipynb │ ├── main.bicep │ └── petstore.yaml ├── import-from-git │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-git.ipynb │ └── main.bicep ├── import-from-ibm │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-ibm.ipynb │ └── main.bicep ├── import-from-k8s │ ├── README.MD │ └── clean-up-resources.ipynb ├── import-from-kong │ ├── README.MD │ ├── clean-up-resources.ipynb │ ├── import-from-kong.ipynb │ └── main.bicep └── import-from-mulesoft │ ├── README.MD │ ├── account_environment_list.json │ ├── api-mgr_api_list.json │ ├── clean-up-resources.ipynb │ ├── import-from-mulesoft.ipynb │ ├── main.bicep │ └── runtime-mgr-application_describe.json └── tools └── delete-all-apis.ipynb /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Universal API Center Dev Container", 3 | "image": "mcr.microsoft.com/vscode/devcontainers/dotnet:8.0-jammy", 4 | "hostRequirements": { 5 | "cpus": 4 6 | }, 7 | "features": { 8 | "ghcr.io/devcontainers/features/azure-cli:1": { 9 | "installBicep": true, 10 | "version": "latest" 11 | }, 12 | "ghcr.io/devcontainers/features/python:1": { 13 | "installTools": true, 14 | "version": "os-provided" 15 | }, 16 | "ghcr.io/stuartleeks/dev-container-features/azure-cli-persistence:0": {}, 17 | "ghcr.io/azure/azure-dev/azd:0": { 18 | "version": "stable" 19 | }, 20 | "ghcr.io/devcontainers/features/git:1": { 21 | "version": "latest" 22 | } 23 | }, 24 | "waitFor": "onCreateCommand", 25 | "updateContentCommand": "", 26 | "postCreateCommand": "", 27 | "customizations": { 28 | "codespaces": { 29 | "openFiles": [] 30 | }, 31 | "vscode": { 32 | "extensions": [ 33 | "ms-vscode.azure-account", 34 | "ms-azuretools.azure-dev", 35 | "ms-azuretools.vscode-apimanagement", 36 | "apidev.azure-api-center", 37 | "ms-azuretools.vscode-azurefunctions", 38 | "ms-kubernetes-tools.vscode-aks-tools", 39 | "ms-azuretools.vscode-azurecontainerapps", 40 | "ms-azuretools.vscode-azureappservice", 41 | "ms-azuretools.vscode-azurelogicapps", 42 | "ms-azuretools.vscode-azurestaticwebapps", 43 | "ms-toolsai.jupyter", 44 | "ms-python.python", 45 | "ms-dotnettools.dotnet-interactive-vscode", 46 | "github.copilot", 47 | "github.copilot-chat", 48 | "humao.rest-client", 49 | "evilz.vscode-reveal" 50 | ] 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | > Please provide us with the following information: 5 | > --------------------------------------------------------------- 6 | 7 | ### This issue is for a: (mark with an `x`) 8 | ``` 9 | - [ ] bug report -> please search issues before submitting 10 | - [ ] feature request 11 | - [ ] documentation issue or request 12 | - [ ] regression (a behavior that used to work and stopped in a new release) 13 | ``` 14 | 15 | ### Minimal steps to reproduce 16 | > 17 | 18 | ### Any log messages given by the failure 19 | > 20 | 21 | ### Expected/desired behavior 22 | > 23 | 24 | ### OS and Version? 25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?) 26 | 27 | ### Versions 28 | > 29 | 30 | ### Mention any other details that might be useful 31 | 32 | > --------------------------------------------------------------- 33 | > Thanks! We'll be in touch soon. 34 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | * ... 4 | 5 | ## Does this introduce a breaking change? 6 | 7 | ``` 8 | [ ] Yes 9 | [ ] No 10 | ``` 11 | 12 | ## Pull Request Type 13 | What kind of change does this Pull Request introduce? 14 | 15 | 16 | ``` 17 | [ ] Bugfix 18 | [ ] Feature 19 | [ ] Code style update (formatting, local variables) 20 | [ ] Refactoring (no functional changes, no api changes) 21 | [ ] Documentation content changes 22 | [ ] Other... Please describe: 23 | ``` 24 | 25 | ## How to Test 26 | * Get the code 27 | 28 | ``` 29 | git clone [repo-address] 30 | cd [repo-name] 31 | git checkout [branch-name] 32 | npm install 33 | ``` 34 | 35 | * Test the code 36 | 37 | ``` 38 | ``` 39 | 40 | ## What to Check 41 | Verify that the following are valid 42 | * ... 43 | 44 | ## Other Information 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | .azure/ 10 | .temp/ 11 | 12 | labs-in-progress/ 13 | params.json 14 | 15 | # Distribution / packaging 16 | .Python 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | pip-wheel-metadata/ 30 | share/python-wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | MANIFEST 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .nox/ 50 | .coverage 51 | .coverage.* 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | *.cover 56 | *.py,cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | db.sqlite3-journal 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | env/ 114 | venv/ 115 | ENV/ 116 | env.bak/ 117 | venv.bak/ 118 | 119 | # Spyder project settings 120 | .spyderproject 121 | .spyproject 122 | 123 | # Rope project settings 124 | .ropeproject 125 | 126 | # mkdocs documentation 127 | /site 128 | 129 | # mypy 130 | .mypy_cache/ 131 | .dmypy.json 132 | dmypy.json 133 | 134 | # Pyre type checker 135 | .pyre/ -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to universal-api-center 2 | 3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 5 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 6 | 7 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 8 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 9 | provided by the bot. You will only need to do this once across all repos using our CLA. 10 | 11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 14 | 15 | - [Code of Conduct](#coc) 16 | - [Issues and Bugs](#issue) 17 | - [Feature Requests](#feature) 18 | - [Submission Guidelines](#submit) 19 | 20 | ## Code of Conduct 21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 22 | 23 | ## Found an Issue? 24 | If you find a bug in the source code or a mistake in the documentation, you can help us by 25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Want a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | 33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 34 | 35 | ## Submission Guidelines 36 | 37 | ### Submitting an Issue 38 | Before you submit an issue, search the archive, maybe your question was already answered. 39 | 40 | If your issue appears to be a bug, and hasn't been reported, open a new issue. 41 | Help us to maximize the effort we can spend fixing issues and adding new 42 | features, by not reporting duplicate issues. Providing the following information will increase the 43 | chances of your issue being dealt with quickly: 44 | 45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps 46 | * **Version** - what version is affected (e.g. 0.1.2) 47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you 48 | * **Browsers and Operating System** - is this a problem with all browsers? 49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps 50 | * **Related Issues** - has a similar issue been reported before? 51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be 52 | causing the problem (line of code or commit) 53 | 54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new]. 55 | 56 | ### Submitting a Pull Request (PR) 57 | Before you submit your Pull Request (PR) consider the following guidelines: 58 | 59 | * Search the repository (https://github.com/Azure-Samples/universal-api-center/pulls) for an open or closed PR 60 | that relates to your submission. You don't want to duplicate effort. 61 | 62 | * Make your changes in a new git fork: 63 | 64 | * Commit your changes using a descriptive commit message 65 | * Push your fork to GitHub: 66 | * In GitHub, create a pull request 67 | * If we suggest changes then: 68 | * Make the required updates. 69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request): 70 | 71 | ```shell 72 | git rebase master -i 73 | git push -f 74 | ``` 75 | 76 | That's it! Thank you for your contribution! 77 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Universal API Center 2 | 3 | MIT License 4 | 5 | Copyright (c) Microsoft Corporation. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | [![Open Source Love](https://firstcontributions.github.io/open-source-badges/badges/open-source-v1/open-source.svg)](https://github.com/firstcontributions/open-source-badges) 4 | 5 | ## Contents 6 | 1. [🌐 Universal API Center](#-universal-api-center) 7 | 2. [🧪 Labs](#-labs) 8 | 3. [🚀 Getting started](#-getting-started) 9 | 7. [🥇 Other Resources](#-other-resources) 10 | 11 | In the current era of digital transformation, organizations are increasingly adopting cloud-based technologies and incorporating microservice patterns, which has been a catalyst in significantly escalating the use of Application Programming Interfaces (APIs). The application of these APIs stretches across a diverse array of platforms, various environments, and different architectural designs, which suggests a gradual evolution in technological infrastructure that is crucial in sustaining a prosperous business landscape. 12 | 13 | However, organisations struggling to adapt to this API proliferation, face three major challenges: 14 | - The first is the complex task of identifying APIs due to a proliferation of platforms, API Gateways and other tools implemented by disparate teams and environments, forming a complicated maze and creating significant obstacles for modern organisations. 15 | - Secondly, each API, which enables varied functionalities across multiple environments and platforms, carries its own unique set of quality standards. This evolving and diverse API landscape spawns a complex management area for IT departments, particularly while managing multiple versions and embodiments of APIs, resembling a daunting trap requiring extensive effort to manage an overwhelming number of API variations. 16 | - Thirdly, the recent spike in security attacks directed at APIs, pose a significant concern for today's enterprises. The arrival of concealed or 'shadow' APIs introduces potential security risks, obliging companies to conduct exhaustive forensic evaluations to determine potential damage and strategize appropriate mitigation tactics. Thus, mitigating these security risks demands proper API Governance and ongoing threat monitoring capabilities to safeguard an organisation's digital ecosystem. 17 | 18 | 19 | ## 🌐 Universal API Center 20 | ![Universal API Center](images/api-center.png) 21 | 22 | 🚀 We are pleased to introduce the API Center, a new Azure service designed to address the various complexities associated with API proliferation. This ground-breaking solution will empower businesses with a reliable, seamless approach to overcoming these challenges, paving the way for enhanced operational efficiencies and productivity. 23 | 24 | The API Center provides a centralized platform for discovering, reusing, and governing all of your APIs. It establishes a structured and systematic inventory of your organization's APIs, irrespective of their type, lifecycle stage, or deployment location. Further, it accommodatively provides related information such as version specifics, API definition files, and shared metadata. Utilizing the API Center, various stakeholders within your organization including API program managers, IT administrators, application developers, and API developers can smoothly discover, reuse, and govern APIs. 25 | 26 | ### Benefits 27 | - Having a robust inventory of APIs within an organization's framework is crucial as it fosters effective communication and collaboration between API program managers and developers. This not only amplifies the quality and reusability of APIs but also amplifies their security and compliance. Ultimately, this strategic approach leads to an advantageous uptick in developer productivity. 28 | - Enhancing your organization's API governance offers a crucial advantage. It allows API program managers and IT administrators to maintain comprehensive oversight of the API creation and utilization within their organization. This enhanced visibility promotes adherence to organizational standards by facilitating the definition of custom metadata and the analysis of API definitions. This in turn enables the enforcement of conformance to API style guidelines, thereby improving the overall API management. 29 | - API Center enhances API discovery, enabling organizations to promote API reuse and optimize developer productivity by assisting both program managers and developers in identifying API inventory and filtering with both built-in and bespoke metadata properties. Moreover, the API Center expedites API consumption to further boost developer efficiency, safeguarding secure and organizationally compliant usage of APIs. 30 | 31 | To expedite the realization of the above benefits, we have constructed a variety of labs demonstrating the seamless cataloguing of APIs from diverse gateways and sources. This step is integral in our goal to establish a truly **Universal API center**. 32 | 33 | 34 | ## 🧪 Labs 35 | 36 | The labs, structured as Jupyter notebooks, offer thorough guidance on utilizing PowerShell scripts in conjunction with Azure CLI commands. These comprehensive instructions cover diverse functionalities, including importing, and discovering APIs. 37 | 38 | > [!TIP] 39 | > You can apply the supplied Powershell scripts across various platforms, including Windows, Linux, and Mac, to construct automation workflows, continuous integration, and continuous delivery pipelines, among other procedures. This facilitates the enhancement of productivity and efficiency within your operations. 40 | 41 | | | | | | 42 | | ---- | ----- | ----------- | -- | 43 | | [Import from generic OpenAPI](labs/import-from-generic-openapi/import-from-generic-openapi.ipynb) | [![image](images/import-from-generic-openapi.png)](labs/import-from-generic-openapi/import-from-generic-openapi.ipynb) | Playground to experiment importing APIs in the OpenAPI specification into API Center. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Azure CLI]((https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest)) to import the APIs. | [💬](../../issues/2 "Discussion") | 44 | | [Import from Azure API Management](labs/import-from-azure-apim/import-from-azure-apim.ipynb) | [![image](images/import-from-azure-apim.png)](labs/import-from-azure-apim/import-from-azure-apim.ipynb) | Playground to experiment importing APIs from Azure APIM into API Center. We start by creating APIM and API Center instances using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Azure CLI]((https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest)) to import the APIs from APIM. | [💬](../../issues/3 "Discussion") | 45 | | [Import from Amazon API Gateway](labs/import-from-aws/import-from-aws.ipynb) | [![image](images/import-from-aws.png)](labs/import-from-aws/import-from-aws.ipynb) | Playground to experiment importing APIs from Amazon API Gateway. We will use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. | [💬](../../issues/4 "Discussion") | 46 | | [Import from Apigee](labs/import-from-gcp/import-from-gcp.ipynb) | [![image](images/import-from-gcp.png)](labs/import-from-gcp/import-from-gcp.ipynb) | Playground to experiment importing APIs from Apigee. We will use the [GCP CLI](https://cloud.google.com/sdk/docs/install-sdk) to export the Apigee APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. | [💬](../../issues/5 "Discussion") | 47 | | [Import from Kong](labs/import-from-kong/import-from-kong.ipynb) | [![image](images/import-from-kong.png)](labs/import-from-kong/import-from-kong.ipynb) | Playground to experiment importing APIs from Kong API Gateway. We will use the [Kong Admin API](https://docs.konghq.com/gateway/api/admin-oss/latest) to export Kong services and import them into API Center. | [💬](../../issues/6 "Discussion") | 48 | | [Import from Mulesoft](labs/import-from-mulesoft/import-from-mulesoft.ipynb) | [![image](images/import-from-mulesoft.png)](labs/import-from-mulesoft/import-from-mulesoft.ipynb) | Playground to experiment importing APIs from the MuleSoft Anypoint platform. We will use the [Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. | [💬](../../issues/7 "Discussion") | 49 | | [Import from IBM](labs/import-from-ibm/import-from-ibm.ipynb) | [![image](images/import-from-ibm.png)](labs/import-from-ibm/import-from-ibm.ipynb) | Playground to experiment bulk importing APIs from IBM API Connect into API Center | | 50 | | [Import from Git](labs/import-from-git/import-from-git.ipynb) | [![image](images/import-from-git.png)](labs/import-from-git/import-from-git.ipynb) | Playground to experiment importing APIs in the OpenAPI specification into API Center by crawling Git repositories. | [💬](../../issues/9 "Discussion") | 51 | | [Import BIAN](labs/import-bian/import-bian.ipynb) | [![image](images/import-bian.png)](labs/import-bian/import-bian.ipynb) | Playground to experiment importing Banking Industry Architecture Network (BIAN) APIs from [their GitHub repo](https://github.com/bian-official/public). | | 52 | 53 | 54 | 55 | 56 | 57 | > [!TIP] 58 | > Kindly use [the feedback discussion](../../discussions/1) so that we can continuously improve with your experiences, suggestions, ideas or lab requests. 59 | 60 | ## 🚀 Getting Started 61 | 62 | [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/Azure-Samples/universal-api-center/tree/main) 63 | 64 | 65 | ### Prerequisites 66 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 67 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 68 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 69 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 70 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 71 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 72 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 73 | 74 | ### Quickstart 75 | 1. Clone this repo and configure your local machine with the prerequisites. Or just create a [GitHub Codespace](https://codespaces.new/Azure-Samples/universal-api-center/tree/main) and run it on the browser or in VS Code. 76 | 2. Navigate through the available labs and select one that best suits your needs. For starters we recommend the [import from generic OpenAPI](labs/import-from-generic-openapi/import-from-generic-openapi.ipynb). 77 | 3. Open the notebook and run the provided steps. 78 | 4. Tailor the experiment according to your requirements. If you wish to contribute to our collective work, we would appreciate your [submission of a pull request](CONTRIBUTING.MD). 79 | 80 | > [!NOTE] 81 | > 🪲 Please feel free to open a new [issue](../../issues/new) if you find something that should be fixed or enhanced. 82 | 83 | ## 🥇 Other resources 84 | 85 | - [API Center Overview video](https://www.youtube.com/watch?v=Y9K3Fx2TpCo) 86 | - [API Center documentation](https://learn.microsoft.com/en-us/azure/api-center/) 87 | - [Self-host Your Azure API Center Portal](https://github.com/Azure/APICenter-Portal-Starter) 88 | - [Analyze your API Specs with Azure API Center](https://github.com/Azure/APICenter-Analyzer) 89 | - [Govern SAP APIs living in various API Management gateways in a single place with Azure API Center](https://community.sap.com/t5/technology-blogs-by-members/govern-sap-apis-living-in-various-api-management-gateways-in-a-single-place/ba-p/13682483) 90 | 91 | > We believe that there may be valuable content that we are currently unaware of. We would greatly appreciate any suggestions or recommendations to enhance this list. 92 | 93 | ### 🌐 WW GBB initiative 94 | 95 | ![GBB](images/gbb.png) 96 | 97 | ### Disclaimer 98 | > [!IMPORTANT] 99 | > This software is provided for demonstration purposes only. It is not intended to be relied upon for any purpose. The creators of this software make no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability or availability with respect to the software or the information, products, services, or related graphics contained in the software for any purpose. Any reliance you place on such information is therefore strictly at your own risk. 100 | 101 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 102 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 103 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 104 | 105 | Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft’s Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party’s policies. 106 | 107 | -------------------------------------------------------------------------------- /images/api-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/api-center.png -------------------------------------------------------------------------------- /images/gbb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/gbb.png -------------------------------------------------------------------------------- /images/import-bian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-bian.png -------------------------------------------------------------------------------- /images/import-from-aws.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-aws.png -------------------------------------------------------------------------------- /images/import-from-azure-apim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-azure-apim.png -------------------------------------------------------------------------------- /images/import-from-gcp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-gcp.png -------------------------------------------------------------------------------- /images/import-from-generic-openapi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-generic-openapi.png -------------------------------------------------------------------------------- /images/import-from-git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-git.png -------------------------------------------------------------------------------- /images/import-from-ibm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-ibm.png -------------------------------------------------------------------------------- /images/import-from-k8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-k8s.png -------------------------------------------------------------------------------- /images/import-from-kong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-kong.png -------------------------------------------------------------------------------- /images/import-from-mulesoft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/import-from-mulesoft.png -------------------------------------------------------------------------------- /images/toolchain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure-Samples/universal-api-center/21e4e9280a4d3dc5c6558717aa69abe6bfbb4671/images/toolchain.png -------------------------------------------------------------------------------- /labs/import-bian/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import the Banking Industry Architecture Network (BIAN) APIs 4 | ![image](../../images/import-bian.png) 5 | 6 | Playground to experiment importing BIAN APIs from the GitHub repo. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Prerequisites 11 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 12 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 13 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 14 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 15 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 16 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 17 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 18 | - Install [Spectral CLI](https://github.com/stoplightio/spectral) 19 | 20 | ### 🚀 Get started 21 | Proceed by opening the [Jupyter notebook](import-bian.ipynb), and follow the steps provided. 22 | 23 | ### 🗑️ Clean up resources 24 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 25 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-bian/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-bian/import-bian.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import the Banking Industry Architecture Network (BIAN) APIs\n", 10 | "![image](../../images/import-bian.png)\n", 11 | "\n", 12 | "Playground to experiment importing BIAN APIs from the GitHub repo.\n", 13 | "\n", 14 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 15 | "\n", 16 | "### Prerequisites\n", 17 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 18 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 19 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 20 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 21 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 22 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 23 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n", 24 | "- Install [Spectral CLI](https://github.com/stoplightio/spectral)\n" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "### 0️⃣ Initialize notebook variables\n", 32 | "\n", 33 | "- Resources will be suffixed by a unique string based on your subscription id\n", 34 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": { 41 | "dotnet_interactive": { 42 | "language": "pwsh" 43 | }, 44 | "polyglot_notebook": { 45 | "kernelName": "pwsh" 46 | }, 47 | "vscode": { 48 | "languageId": "polyglot-notebook" 49 | } 50 | }, 51 | "outputs": [], 52 | "source": [ 53 | "\n", 54 | "$sourceRepo = \"https://github.com/bian-official/public\"\n", 55 | "$maxAPIsToImport = 10\n", 56 | "\n", 57 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 58 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 59 | "$resourceGroupLocation = \"westeurope\"\n", 60 | "$apicResourceNamePrefix = \"apic\"\n", 61 | "$apicResourceSku = \"free\"\n", 62 | "$apicResourceTags = @{\n", 63 | " \"lab\" = $deploymentName\n", 64 | "}\n", 65 | "\n", 66 | "# the following metadata will be created during the deployment\n", 67 | "$metadata = @(\n", 68 | ")\n", 69 | "\n", 70 | "# the following environment(s) will be created during the deployment\n", 71 | "$environments = @(\n", 72 | ")\n", 73 | "\n", 74 | "\n", 75 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 76 | ] 77 | }, 78 | { 79 | "cell_type": "markdown", 80 | "metadata": {}, 81 | "source": [ 82 | "### 1️⃣ Create the Azure Resource Group\n", 83 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 84 | ] 85 | }, 86 | { 87 | "cell_type": "code", 88 | "execution_count": null, 89 | "metadata": { 90 | "dotnet_interactive": { 91 | "language": "pwsh" 92 | }, 93 | "polyglot_notebook": { 94 | "kernelName": "pwsh" 95 | }, 96 | "vscode": { 97 | "languageId": "polyglot-notebook" 98 | } 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 103 | "\n", 104 | "if ($LASTEXITCODE -ne 0) {\n", 105 | " Write-Output $resourceGroupOutput\n", 106 | "} else {\n", 107 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 108 | "}" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 116 | "\n", 117 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": null, 123 | "metadata": { 124 | "dotnet_interactive": { 125 | "language": "pwsh" 126 | }, 127 | "polyglot_notebook": { 128 | "kernelName": "pwsh" 129 | }, 130 | "vscode": { 131 | "languageId": "polyglot-notebook" 132 | } 133 | }, 134 | "outputs": [], 135 | "source": [ 136 | "$bicepParameters = @{\n", 137 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 138 | " \"contentVersion\" = \"1.0.0.0\"\n", 139 | " \"parameters\" = @{\n", 140 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 141 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 142 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 143 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 144 | " }\n", 145 | "}\n", 146 | "\n", 147 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 148 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 149 | "\n", 150 | "# Execute the Azure CLI command to create the deployment\n", 151 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 152 | "\n" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "### 3️⃣ Get the deployment outputs\n", 160 | "\n", 161 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": { 168 | "dotnet_interactive": { 169 | "language": "pwsh" 170 | }, 171 | "polyglot_notebook": { 172 | "kernelName": "pwsh" 173 | }, 174 | "vscode": { 175 | "languageId": "polyglot-notebook" 176 | } 177 | }, 178 | "outputs": [], 179 | "source": [ 180 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 181 | "if ($LASTEXITCODE -ne 0) {\n", 182 | " Write-Output $deploymentOutput\n", 183 | "} else {\n", 184 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 185 | "}\n", 186 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "### 4️⃣ Clone the repo\n", 194 | "\n", 195 | "Creates a local copy of the specific repository or branch within a repository.\n" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": { 202 | "dotnet_interactive": { 203 | "language": "pwsh" 204 | }, 205 | "polyglot_notebook": { 206 | "kernelName": "pwsh" 207 | }, 208 | "vscode": { 209 | "languageId": "polyglot-notebook" 210 | } 211 | }, 212 | "outputs": [], 213 | "source": [ 214 | "git clone $sourceRepo \".temp\"" 215 | ] 216 | }, 217 | { 218 | "cell_type": "markdown", 219 | "metadata": {}, 220 | "source": [ 221 | "### 5️⃣ Crawl APIs and register each one of them in API Center\n", 222 | "\n", 223 | "[Registers](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-register) each valid API in the cloned repo." 224 | ] 225 | }, 226 | { 227 | "cell_type": "code", 228 | "execution_count": null, 229 | "metadata": { 230 | "dotnet_interactive": { 231 | "language": "pwsh" 232 | }, 233 | "polyglot_notebook": { 234 | "kernelName": "pwsh" 235 | }, 236 | "vscode": { 237 | "languageId": "polyglot-notebook" 238 | } 239 | }, 240 | "outputs": [], 241 | "source": [ 242 | "$results = @()\n", 243 | "\n", 244 | "$files = Get-ChildItem -Path \".temp\\release12.0.0\\semantic-apis\\oas3\\yamls\" -Recurse -File\n", 245 | "\n", 246 | "$counter = 0\n", 247 | "foreach ($file in $files) {\n", 248 | " if ($file.Extension -eq \".yaml\" || $file.Extension -eq \".yml\" || $file.Extension -eq \".json\") {\n", 249 | " $fileSize = $file.Length\n", 250 | " $filePath = $file.FullName\n", 251 | " $lintintProblemsJson = spectral lint $filePath --ruleset spectral.yaml -f json \n", 252 | " $lintintProblems = $lintintProblemsJson | ConvertFrom-Json\n", 253 | " $lintingErrors = 0\n", 254 | " $lintingWarnings = 0\n", 255 | " foreach ($problem in $lintintProblems) {\n", 256 | " if ($problem.severity -eq 0) {\n", 257 | " $lintingErrors++\n", 258 | " } elseif ($problem.severity -eq 1) {\n", 259 | " $lintingWarnings++\n", 260 | " }\n", 261 | " }\n", 262 | " Write-Output \"👉🏻 Registering: $filePath\"\n", 263 | " $registerOutput = az apic api register -g $resourceGroupName -n $apicResourceName -l $filePath 2>&1\n", 264 | " $registeredAPI = [ordered] @{ \n", 265 | " Name = $file.Name \n", 266 | " File = $file.FullName \n", 267 | " Extension = $file.Extension \n", 268 | " Size = $file.Length\n", 269 | " Errors = $lintingErrors\n", 270 | " Warnings = $lintingWarnings\n", 271 | " API = if ($registerOutput -match \"API was created successfully\") {\"OK\"} else {\"ERROR\"}\n", 272 | " Version = if ($registerOutput -match \"API version was created successfully\") {\"OK\"} else {\"ERROR\"}\n", 273 | " Definition = if ($registerOutput -match \"API specification was created successfully\") {\"OK\"} else {\"ERROR\"}\n", 274 | " Output = $registerOutput | Out-String\n", 275 | " } \n", 276 | " $results += New-Object PSObject -Property $registeredAPI\n", 277 | " $counter++\n", 278 | " if ($counter -ge $maxAPIsToImport) {\n", 279 | " Write-Output \"🚫 Max APIs to import reached. Done for now.\"\n", 280 | " break\n", 281 | " }\n", 282 | " }\n", 283 | "}\n", 284 | "Write-Output \"✅ $counter APIs imported.\"\n", 285 | "\n", 286 | "$results | export-csv -Path .temp/result.csv -NoTypeInformation -Delimiter \";\"\n" 287 | ] 288 | }, 289 | { 290 | "cell_type": "markdown", 291 | "metadata": {}, 292 | "source": [ 293 | "### 7️⃣ Discover the APIs that were just imported\n", 294 | "\n", 295 | "You can discover the APIs with fhe following methods:\n", 296 | "- With the Azure Portal\n", 297 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 298 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 299 | "- With the CLI, the service REST API and more\n", 300 | "\n", 301 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": null, 307 | "metadata": { 308 | "dotnet_interactive": { 309 | "language": "pwsh" 310 | }, 311 | "polyglot_notebook": { 312 | "kernelName": "pwsh" 313 | }, 314 | "vscode": { 315 | "languageId": "polyglot-notebook" 316 | } 317 | }, 318 | "outputs": [], 319 | "source": [ 320 | "az apic api list -g $resourceGroupName -n $apicResourceName --query \"[].{Name:name, Title:title, ContactEmail:contacts[0].email}\" -o table" 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "metadata": {}, 326 | "source": [ 327 | "### 🗑️ Clean up resources\n", 328 | "\n", 329 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 330 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 331 | ] 332 | } 333 | ], 334 | "metadata": { 335 | "kernelspec": { 336 | "display_name": ".NET (C#)", 337 | "language": "C#", 338 | "name": ".net-csharp" 339 | }, 340 | "language_info": { 341 | "codemirror_mode": { 342 | "name": "ipython", 343 | "version": 3 344 | }, 345 | "file_extension": ".py", 346 | "mimetype": "text/x-python", 347 | "name": "python", 348 | "nbconvert_exporter": "python", 349 | "pygments_lexer": "ipython3", 350 | "version": "3.11.9" 351 | }, 352 | "polyglot_notebook": { 353 | "kernelInfo": { 354 | "defaultKernelName": "csharp", 355 | "items": [ 356 | { 357 | "aliases": [], 358 | "name": "csharp" 359 | } 360 | ] 361 | } 362 | } 363 | }, 364 | "nbformat": 4, 365 | "nbformat_minor": 2 366 | } 367 | -------------------------------------------------------------------------------- /labs/import-bian/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-bian/spectral.yaml: -------------------------------------------------------------------------------- 1 | extends: spectral:oas 2 | 3 | -------------------------------------------------------------------------------- /labs/import-from-aws/Petstore.json: -------------------------------------------------------------------------------- 1 | { 2 | "openapi" : "3.0.1", 3 | "info" : { 4 | "title" : "PetStore", 5 | "description" : "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints", 6 | "version" : "2024-05-02" 7 | }, 8 | "servers" : [ { 9 | "url" : "https://2q3nwrw1r0.execute-api.eu-north-1.amazonaws.com/{basePath}", 10 | "variables" : { 11 | "basePath" : { 12 | "default" : "production" 13 | } 14 | } 15 | } ], 16 | "paths" : { 17 | "/pets" : { 18 | "get" : { 19 | "parameters" : [ { 20 | "name" : "type", 21 | "in" : "query", 22 | "schema" : { 23 | "type" : "string" 24 | } 25 | }, { 26 | "name" : "page", 27 | "in" : "query", 28 | "schema" : { 29 | "type" : "string" 30 | } 31 | } ], 32 | "responses" : { 33 | "200" : { 34 | "description" : "200 response", 35 | "headers" : { 36 | "Access-Control-Allow-Origin" : { 37 | "schema" : { 38 | "type" : "string" 39 | } 40 | } 41 | }, 42 | "content" : { 43 | "application/json" : { 44 | "schema" : { 45 | "$ref" : "#/components/schemas/Pets" 46 | } 47 | } 48 | } 49 | } 50 | } 51 | }, 52 | "post" : { 53 | "operationId" : "CreatePet", 54 | "requestBody" : { 55 | "content" : { 56 | "application/json" : { 57 | "schema" : { 58 | "$ref" : "#/components/schemas/NewPet" 59 | } 60 | } 61 | }, 62 | "required" : true 63 | }, 64 | "responses" : { 65 | "200" : { 66 | "description" : "200 response", 67 | "headers" : { 68 | "Access-Control-Allow-Origin" : { 69 | "schema" : { 70 | "type" : "string" 71 | } 72 | } 73 | }, 74 | "content" : { 75 | "application/json" : { 76 | "schema" : { 77 | "$ref" : "#/components/schemas/NewPetResponse" 78 | } 79 | } 80 | } 81 | } 82 | } 83 | }, 84 | "options" : { 85 | "responses" : { 86 | "200" : { 87 | "description" : "200 response", 88 | "headers" : { 89 | "Access-Control-Allow-Origin" : { 90 | "schema" : { 91 | "type" : "string" 92 | } 93 | }, 94 | "Access-Control-Allow-Methods" : { 95 | "schema" : { 96 | "type" : "string" 97 | } 98 | }, 99 | "Access-Control-Allow-Headers" : { 100 | "schema" : { 101 | "type" : "string" 102 | } 103 | } 104 | }, 105 | "content" : { 106 | "application/json" : { 107 | "schema" : { 108 | "$ref" : "#/components/schemas/Empty" 109 | } 110 | } 111 | } 112 | } 113 | } 114 | } 115 | }, 116 | "/pets/{petId}" : { 117 | "get" : { 118 | "operationId" : "GetPet", 119 | "parameters" : [ { 120 | "name" : "petId", 121 | "in" : "path", 122 | "required" : true, 123 | "schema" : { 124 | "type" : "string" 125 | } 126 | } ], 127 | "responses" : { 128 | "200" : { 129 | "description" : "200 response", 130 | "headers" : { 131 | "Access-Control-Allow-Origin" : { 132 | "schema" : { 133 | "type" : "string" 134 | } 135 | } 136 | }, 137 | "content" : { 138 | "application/json" : { 139 | "schema" : { 140 | "$ref" : "#/components/schemas/Pet" 141 | } 142 | } 143 | } 144 | } 145 | } 146 | }, 147 | "options" : { 148 | "parameters" : [ { 149 | "name" : "petId", 150 | "in" : "path", 151 | "required" : true, 152 | "schema" : { 153 | "type" : "string" 154 | } 155 | } ], 156 | "responses" : { 157 | "200" : { 158 | "description" : "200 response", 159 | "headers" : { 160 | "Access-Control-Allow-Origin" : { 161 | "schema" : { 162 | "type" : "string" 163 | } 164 | }, 165 | "Access-Control-Allow-Methods" : { 166 | "schema" : { 167 | "type" : "string" 168 | } 169 | }, 170 | "Access-Control-Allow-Headers" : { 171 | "schema" : { 172 | "type" : "string" 173 | } 174 | } 175 | }, 176 | "content" : { 177 | "application/json" : { 178 | "schema" : { 179 | "$ref" : "#/components/schemas/Empty" 180 | } 181 | } 182 | } 183 | } 184 | } 185 | } 186 | }, 187 | "/" : { 188 | "get" : { 189 | "responses" : { 190 | "200" : { 191 | "description" : "200 response", 192 | "headers" : { 193 | "Content-Type" : { 194 | "schema" : { 195 | "type" : "string" 196 | } 197 | } 198 | }, 199 | "content" : { } 200 | } 201 | } 202 | } 203 | } 204 | }, 205 | "components" : { 206 | "schemas" : { 207 | "Pets" : { 208 | "type" : "array", 209 | "items" : { 210 | "$ref" : "#/components/schemas/Pet" 211 | } 212 | }, 213 | "Empty" : { 214 | "type" : "object" 215 | }, 216 | "NewPetResponse" : { 217 | "type" : "object", 218 | "properties" : { 219 | "pet" : { 220 | "$ref" : "#/components/schemas/Pet" 221 | }, 222 | "message" : { 223 | "type" : "string" 224 | } 225 | } 226 | }, 227 | "Pet" : { 228 | "type" : "object", 229 | "properties" : { 230 | "id" : { 231 | "type" : "integer" 232 | }, 233 | "type" : { 234 | "type" : "string" 235 | }, 236 | "price" : { 237 | "type" : "number" 238 | } 239 | } 240 | }, 241 | "NewPet" : { 242 | "type" : "object", 243 | "properties" : { 244 | "type" : { 245 | "$ref" : "#/components/schemas/PetType" 246 | }, 247 | "price" : { 248 | "type" : "number" 249 | } 250 | } 251 | }, 252 | "PetType" : { 253 | "type" : "string", 254 | "enum" : [ "dog", "cat", "fish", "bird", "gecko" ] 255 | } 256 | } 257 | } 258 | } -------------------------------------------------------------------------------- /labs/import-from-aws/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Amazon API Gateway 4 | ![image](../../images/import-from-aws.png) 5 | 6 | Playground to experiment importing APIs from Amazon API Gateway. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 13 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 14 | - Register APIs using the OpenAPI spec exported from AWS API Gateway. 15 | - Create deployments for each AWS API Gateway stage. 16 | - Search and discover the APIs registered in API Center. 17 | 18 | ### Prerequisites 19 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 20 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 21 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 22 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 23 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 24 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 25 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 26 | - Install or update to the latest [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 27 | - [Setup](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html) the AWS CLI to interact with AWS services 28 | 29 | ### 🚀 Get started 30 | Proceed by opening the [Jupyter notebook](import-from-aws.ipynb), and follow the steps provided. 31 | 32 | ### 🗑️ Clean up resources 33 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 34 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-aws/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-aws/get-rest-api.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2q3nwrw1r0", 3 | "name": "PetStore", 4 | "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints", 5 | "createdDate": "2024-05-02T21:54:38+01:00", 6 | "apiKeySource": "HEADER", 7 | "endpointConfiguration": { 8 | "types": [ 9 | "REGIONAL" 10 | ] 11 | }, 12 | "tags": { 13 | "dataClassification": "Confidential", 14 | "department": "HR" 15 | }, 16 | "disableExecuteApiEndpoint": false, 17 | "rootResourceId": "o66v41060e" 18 | } -------------------------------------------------------------------------------- /labs/import-from-aws/get-rest-apis.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "id": "2q3nwrw1r0", 5 | "name": "PetStore", 6 | "description": "Your first API with Amazon API Gateway. This is a sample API that integrates via HTTP with our demo Pet Store endpoints", 7 | "createdDate": "2024-05-02T21:54:38+01:00", 8 | "apiKeySource": "HEADER", 9 | "endpointConfiguration": { 10 | "types": [ 11 | "REGIONAL" 12 | ] 13 | }, 14 | "disableExecuteApiEndpoint": false, 15 | "rootResourceId": "o66v41060e" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /labs/import-from-aws/get-stage.json: -------------------------------------------------------------------------------- 1 | { 2 | "deploymentId": "g97923", 3 | "stageName": "production", 4 | "description": "Production Stage", 5 | "cacheClusterEnabled": false, 6 | "cacheClusterSize": "0.5", 7 | "cacheClusterStatus": "NOT_AVAILABLE", 8 | "methodSettings": { 9 | "*/*": { 10 | "metricsEnabled": false, 11 | "dataTraceEnabled": false, 12 | "throttlingBurstLimit": -1, 13 | "throttlingRateLimit": -1.0, 14 | "cachingEnabled": false, 15 | "cacheTtlInSeconds": 300, 16 | "cacheDataEncrypted": false, 17 | "requireAuthorizationForCacheControl": true, 18 | "unauthorizedCacheControlHeaderStrategy": "SUCCEED_WITH_RESPONSE_HEADER" 19 | } 20 | }, 21 | "tracingEnabled": false, 22 | "createdDate": "2024-05-02T21:56:07+01:00", 23 | "lastUpdatedDate": "2024-05-02T23:02:23+01:00" 24 | } -------------------------------------------------------------------------------- /labs/import-from-aws/import-from-aws.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import from Amazon API Gateway\n", 10 | "![image](../../images/import-from-aws.png)\n", 11 | "\n", 12 | "Playground to experiment importing APIs from Amazon API Gateway. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center.\n", 13 | "\n", 14 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 15 | "\n", 16 | "### Learning Objectives - Upon completing this lab, you should be able to:\n", 17 | "- Deploy Azure API Center using Bicep.\n", 18 | "- Configure the API Center metadata scheme for APIs, Environments and Deployments.\n", 19 | "- Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest).\n", 20 | "- Register APIs using the OpenAPI spec exported from AWS API Gateway.\n", 21 | "- Create deployments for each AWS API Gateway stage. \n", 22 | "- Search and discover the APIs registered in API Center.\n", 23 | "\n", 24 | "### Prerequisites\n", 25 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 26 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 27 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 28 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 29 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 30 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 31 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n", 32 | "- Install or update to the latest [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)\n", 33 | "- [Setup](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html) the AWS CLI to interact with AWS services" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "### 0️⃣ Initialize notebook variables\n", 41 | "\n", 42 | "- Resources will be suffixed by a unique string based on your subscription id\n", 43 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "dotnet_interactive": { 51 | "language": "pwsh" 52 | }, 53 | "polyglot_notebook": { 54 | "kernelName": "pwsh" 55 | }, 56 | "vscode": { 57 | "languageId": "polyglot-notebook" 58 | } 59 | }, 60 | "outputs": [], 61 | "source": [ 62 | "\n", 63 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 64 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 65 | "$resourceGroupLocation = \"westeurope\"\n", 66 | "$apicResourceNamePrefix = \"apic\"\n", 67 | "$apicResourceSku = \"free\"\n", 68 | "$apicResourceTags = @{\n", 69 | " \"lab\" = $deploymentName\n", 70 | "}\n", 71 | "\n", 72 | "# the following metadata will be created during the deployment\n", 73 | "$metadata = @(\n", 74 | " @{\n", 75 | " \"name\" = 'createdDate'\n", 76 | " \"schema\" = '{\"title\":\"createdDate\",\"description\":\"Date when the API was created\",\"type\":\"string\"}'\n", 77 | " \"assignedTo\" = @(\n", 78 | " @{\n", 79 | " \"entity\" = 'api'\n", 80 | " \"required\" = $false\n", 81 | " },\n", 82 | " @{\n", 83 | " \"entity\" = 'deployment'\n", 84 | " \"required\" = $false\n", 85 | " }\n", 86 | " )\n", 87 | " },\n", 88 | " @{\n", 89 | " \"name\" = 'rootResourceId'\n", 90 | " \"schema\" = '{\"title\":\"rootResourceId\",\"description\":\"API Gateway resource id\",\"type\":\"string\"}'\n", 91 | " \"assignedTo\" = @(\n", 92 | " @{\n", 93 | " \"entity\" = 'api'\n", 94 | " \"required\" = $false\n", 95 | " }\n", 96 | " )\n", 97 | " },\n", 98 | " @{\n", 99 | " \"name\" = 'dataClassification'\n", 100 | " \"schema\" = '{\"title\":\"dataClassification\",\"description\":\"Classification of the Data that will transit in the API\",\"type\":\"string\"}'\n", 101 | " \"assignedTo\" = @(\n", 102 | " @{\n", 103 | " \"entity\" = 'api'\n", 104 | " \"required\" = $false\n", 105 | " }\n", 106 | " )\n", 107 | " },\n", 108 | " @{\n", 109 | " \"name\" = 'department'\n", 110 | " \"schema\" = '{\"title\":\"department\",\"description\":\"Department associated with the API\",\"type\":\"string\"}'\n", 111 | " \"assignedTo\" = @(\n", 112 | " @{\n", 113 | " \"entity\" = 'api'\n", 114 | " \"required\" = $false\n", 115 | " }\n", 116 | " )\n", 117 | " }\n", 118 | ")\n", 119 | "\n", 120 | "# the following environment(s) will be created during the deployment\n", 121 | "$environments = @(\n", 122 | " @{\n", 123 | " \"title\" = 'production'\n", 124 | " \"kind\" = 'production'\n", 125 | " \"description\" = 'Production Stage'\n", 126 | " \"server\" = @{\n", 127 | " \"type\" = 'AWS API Gateway' \n", 128 | " \"managementPortalUri\" = 'https://console.aws.amazon.com/apigateway/'\n", 129 | " }\n", 130 | " \"onboarding\" = @{\n", 131 | " \"developerPortalUri\" = ''\n", 132 | " \"instructions\" = ''\n", 133 | " }\n", 134 | " \"customProperties\" = @{ \n", 135 | " }\n", 136 | " },\n", 137 | " @{\n", 138 | " \"title\" = 'development'\n", 139 | " \"kind\" = 'development'\n", 140 | " \"description\" = 'Development Stage'\n", 141 | " \"server\" = @{\n", 142 | " \"type\" = 'AWS API Gateway' \n", 143 | " \"managementPortalUri\" = 'https://console.aws.amazon.com/apigateway/'\n", 144 | " }\n", 145 | " \"onboarding\" = @{\n", 146 | " \"developerPortalUri\" = ''\n", 147 | " \"instructions\" = ''\n", 148 | " }\n", 149 | " \"customProperties\" = @{ \n", 150 | " }\n", 151 | " }\n", 152 | ")\n", 153 | "\n", 154 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "### 1️⃣ Create the Azure Resource Group\n", 162 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": { 169 | "dotnet_interactive": { 170 | "language": "pwsh" 171 | }, 172 | "polyglot_notebook": { 173 | "kernelName": "pwsh" 174 | }, 175 | "vscode": { 176 | "languageId": "polyglot-notebook" 177 | } 178 | }, 179 | "outputs": [], 180 | "source": [ 181 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 182 | "\n", 183 | "if ($LASTEXITCODE -ne 0) {\n", 184 | " Write-Output $resourceGroupOutput\n", 185 | "} else {\n", 186 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 187 | "}" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 195 | "\n", 196 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": { 203 | "dotnet_interactive": { 204 | "language": "pwsh" 205 | }, 206 | "polyglot_notebook": { 207 | "kernelName": "pwsh" 208 | }, 209 | "vscode": { 210 | "languageId": "polyglot-notebook" 211 | } 212 | }, 213 | "outputs": [], 214 | "source": [ 215 | "$bicepParameters = @{\n", 216 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 217 | " \"contentVersion\" = \"1.0.0.0\"\n", 218 | " \"parameters\" = @{\n", 219 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 220 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 221 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 222 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 223 | " }\n", 224 | "}\n", 225 | "\n", 226 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 227 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 228 | "\n", 229 | "# Execute the Azure CLI command to create the deployment\n", 230 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 231 | "\n" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "### 3️⃣ Get the deployment outputs\n", 239 | "\n", 240 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": { 247 | "dotnet_interactive": { 248 | "language": "pwsh" 249 | }, 250 | "polyglot_notebook": { 251 | "kernelName": "pwsh" 252 | }, 253 | "vscode": { 254 | "languageId": "polyglot-notebook" 255 | } 256 | }, 257 | "outputs": [], 258 | "source": [ 259 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 260 | "if ($LASTEXITCODE -ne 0) {\n", 261 | " Write-Output $deploymentOutput\n", 262 | "} else {\n", 263 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 264 | "}\n", 265 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"" 266 | ] 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "metadata": {}, 271 | "source": [ 272 | "### 4️⃣ Export the APIs from AWS API Gateway and Register in API Center\n", 273 | "\n", 274 | "We will start to list all the REST APIs, then for each API we will export the OpenAPI spec, update the metadata and then create deployments for each environment.\n", 275 | "\n", 276 | "Note: this script supports REST APIs. For HTTP APIs you should adapt the script to use the [equivalent commands](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/index.html)." 277 | ] 278 | }, 279 | { 280 | "cell_type": "code", 281 | "execution_count": null, 282 | "metadata": { 283 | "dotnet_interactive": { 284 | "language": "pwsh" 285 | }, 286 | "polyglot_notebook": { 287 | "kernelName": "pwsh" 288 | }, 289 | "vscode": { 290 | "languageId": "polyglot-notebook" 291 | } 292 | }, 293 | "outputs": [], 294 | "source": [ 295 | "\n", 296 | "# comment one of the following lines to use the real AWS API Gateway or the local file\n", 297 | "#$restAPIsJson = aws apigateway get-rest-apis --output json\n", 298 | "$restAPIsJson = Get-Content -Raw 'get-rest-apis.json'\n", 299 | "\n", 300 | "$restAPIs = $restAPIsJson | ConvertFrom-Json\n", 301 | "foreach ($restAPI in $restAPIs.items) {\n", 302 | " $restAPIId = $restAPI.name\n", 303 | "\n", 304 | " # comment one of the following lines to use the real AWS API Gateway or the local file\n", 305 | " #$restAPIJson = aws apigateway get-rest-api --rest-api-id $restAPIId --output json\n", 306 | " $restAPIJson = Get-Content -Raw 'get-rest-api.json' \n", 307 | "\n", 308 | " $restAPI = $restAPIJson | ConvertFrom-Json\n", 309 | "\n", 310 | " # uncomment the following line to export from AWS API Gateway instead of using the local file\n", 311 | " # aws apigateway get-export --rest-api-id 2q3nwrw1r0 --stage-name production --export-type oas30 $restAPIId.json\n", 312 | "\n", 313 | " write-output \"👉🏻 Registering API $restAPIId\"\n", 314 | " az apic api register -g $resourceGroupName -n $apicResourceName -l $restAPIId\".json\"\n", 315 | "\n", 316 | " $apiCustomProperties = @{ \n", 317 | " \"createdDate\" = $restAPI.createdDate \n", 318 | " \"rootResourceId\" = $restAPI.rootResourceId\n", 319 | " \"department\" = $restAPI.tags.department\n", 320 | " \"dataClassification\" = $restAPI.tags.dataClassification\n", 321 | " }\n", 322 | " $apiCustomPropertiesJson = ConvertTo-Json -InputObject $apiCustomProperties -Depth 10 -Compress\n", 323 | " write-output \"👉🏻 Updating API $restAPIId metadata\"\n", 324 | " az apic api update -g $resourceGroupName -n $apicResourceName --api-id $restAPIId --custom-properties $apiCustomPropertiesJson.replace('\"','\\\"') \n", 325 | "\n", 326 | " $openAPIJson = Get-Content -Raw $restAPIId\".json\"\n", 327 | " $openAPI = $openAPIJson | ConvertFrom-Json\n", 328 | " $version = $openAPI.info.version\n", 329 | " $runtimeUri = $openAPI.servers[0].url\n", 330 | "\n", 331 | " foreach ($environment in $environments) {\n", 332 | " $environmentName = $environment.title\n", 333 | "\n", 334 | " # comment one of the following lines to use the real AWS API Gateway or the local file\n", 335 | " # $stageJson = aws apigateway get-stage --stage-name $environmentName --rest-api-id $restAPIId\n", 336 | " $stageJson = Get-Content -Raw 'get-stage.json'\n", 337 | " \n", 338 | " $stage = $stageJson | ConvertFrom-Json\n", 339 | " $deploymentId = $stage.deploymentId\n", 340 | " $deploymentDescription = $stage.description\n", 341 | " $server = $('{\\\"runtimeUri\\\":[\\\"' + $runtimeUri.replace('{basePath}', $environmentName) + '\\\"]}')\n", 342 | "\n", 343 | " $deploymentCustomProperties = @{\n", 344 | " \"createdDate\" = $stage.createdDate\n", 345 | " }\n", 346 | " $deploymentCustomPropertiesJson = ConvertTo-Json -InputObject $deploymentCustomProperties -Depth 10 -Compress\n", 347 | " write-output \"👉🏻 Creating $environmentName deployment for API $restAPIId\"\n", 348 | " az apic api deployment create -g $resourceGroupName -n $apicResourceName --deployment-id $environmentName\"-\"$deploymentId `\n", 349 | " --title $deploymentId --description $deploymentDescription --api-id $restAPIId `\n", 350 | " --environment-id \"/workspaces/default/environments/$environmentName\" `\n", 351 | " --definition-id \"/workspaces/default/apis/$restAPIId/versions/$version/definitions/openapi\" `\n", 352 | " --server $server `\n", 353 | " --custom-properties $deploymentCustomPropertiesJson.replace('\"','\\\"') \n", 354 | " }\n", 355 | "}" 356 | ] 357 | }, 358 | { 359 | "cell_type": "markdown", 360 | "metadata": {}, 361 | "source": [ 362 | "### 5️⃣ Discover the APIs that were just imported\n", 363 | "\n", 364 | "You can discover the APIs with fhe following methods:\n", 365 | "- With the Azure Portal\n", 366 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 367 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 368 | "- With the CLI, the service REST API and more\n", 369 | "\n", 370 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": { 377 | "dotnet_interactive": { 378 | "language": "pwsh" 379 | }, 380 | "polyglot_notebook": { 381 | "kernelName": "pwsh" 382 | }, 383 | "vscode": { 384 | "languageId": "polyglot-notebook" 385 | } 386 | }, 387 | "outputs": [], 388 | "source": [ 389 | "az apic api list -g $resourceGroupName -n $apicResourceName --query \"[].{Name:name, Title:title, Kind:kind, ContactEmail:contacts[0].email}\" -o table" 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": {}, 395 | "source": [ 396 | "### 🗑️ Clean up resources\n", 397 | "\n", 398 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 399 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 400 | ] 401 | } 402 | ], 403 | "metadata": { 404 | "kernelspec": { 405 | "display_name": ".NET (C#)", 406 | "language": "C#", 407 | "name": ".net-csharp" 408 | }, 409 | "language_info": { 410 | "codemirror_mode": { 411 | "name": "ipython", 412 | "version": 3 413 | }, 414 | "file_extension": ".py", 415 | "mimetype": "text/x-python", 416 | "name": "python", 417 | "nbconvert_exporter": "python", 418 | "pygments_lexer": "ipython3", 419 | "version": "3.11.9" 420 | }, 421 | "polyglot_notebook": { 422 | "kernelInfo": { 423 | "defaultKernelName": "csharp", 424 | "items": [ 425 | { 426 | "aliases": [], 427 | "name": "csharp" 428 | } 429 | ] 430 | } 431 | } 432 | }, 433 | "nbformat": 4, 434 | "nbformat_minor": 2 435 | } 436 | -------------------------------------------------------------------------------- /labs/import-from-aws/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-azure-apim/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Azure API Management 4 | ![image](../../images/import-from-azure-apim.png) 5 | 6 | Playground to experiment importing APIs from Azure APIM into API Center. We start by creating APIM and API Center instances using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Azure CLI]((https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest)) to import the APIs from APIM. 7 | 8 | ### Prerequisites 9 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 10 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 11 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 12 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 13 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 14 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 15 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 16 | 17 | ### 🚀 Get started 18 | Proceed by opening the [Jupyter notebook](import-from-azure-apim.ipynb), and follow the steps provided. 19 | 20 | ### 🗑️ Clean up resources 21 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 22 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-azure-apim/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [ 27 | { 28 | "name": "stdout", 29 | "output_type": "stream", 30 | "text": [ 31 | "✅ Resource group lab-import-from-azure-apim deleted ⌚ 00:29:58\r\n" 32 | ] 33 | } 34 | ], 35 | "source": [ 36 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 37 | "$resourceGroupName = \"lab-$deploymentName\"\n", 38 | "\n", 39 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 40 | "if ($LASTEXITCODE -ne 0) {\n", 41 | " Write-Output $deleteOutput\n", 42 | "} else {\n", 43 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 44 | "}\n" 45 | ] 46 | } 47 | ], 48 | "metadata": { 49 | "kernelspec": { 50 | "display_name": "Python 3", 51 | "language": "python", 52 | "name": "python3" 53 | }, 54 | "language_info": { 55 | "codemirror_mode": { 56 | "name": "ipython", 57 | "version": 3 58 | }, 59 | "file_extension": ".py", 60 | "mimetype": "text/x-python", 61 | "name": "python", 62 | "nbconvert_exporter": "python", 63 | "pygments_lexer": "ipython3", 64 | "version": "3.11.9" 65 | } 66 | }, 67 | "nbformat": 4, 68 | "nbformat_minor": 2 69 | } 70 | -------------------------------------------------------------------------------- /labs/import-from-azure-apim/import-from-azure-apim.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import from Azure API Management\n", 10 | "![image](../../images/import-from-azure-apim.png)\n", 11 | "\n", 12 | "Playground to experiment importing APIs from Azure APIM into API Center. We start by creating APIM and API Center instances using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Azure CLI]((https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest)) to import the APIs from APIM.\n", 13 | "\n", 14 | "▶️ Set the kernel to `.NET Interactive` before running the PowerShell scripts.\n", 15 | "\n", 16 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 17 | "\n", 18 | "### Learning Objectives - Upon completing this lab, you should be able to:\n", 19 | "- Deploy Azure API Management and Azure API Center using Bicep. With a role assignment allowing API Center to read APIs from APIM.\n", 20 | "- Deploy sample APIs in APIM.\n", 21 | "- Configure the API Center metadata scheme for APIs, Environments and Deployments.\n", 22 | "- Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest).\n", 23 | "- Execute the [import-from-apim](https://learn.microsoft.com/en-us/cli/azure/apic/service?view=azure-cli-latest#az-apic-service-import-from-apim) command.\n", 24 | "- List the APIs imported.\n", 25 | "\n", 26 | "### Prerequisites\n", 27 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 28 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 29 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 30 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 31 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 32 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 33 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n", 34 | "- [Register the Microsoft.ApiCenter provider](https://learn.microsoft.com/en-us/azure/api-center/set-up-api-center-azure-cli#register-the-microsoftapicenter-provider)\n", 35 | "\n", 36 | "The [Oficial documentation](https://learn.microsoft.com/en-us/azure/api-center/import-api-management-apis?tabs=portal) describes in detail the process." 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "### 0️⃣ Initialize notebook variables\n", 44 | "\n", 45 | "- Resources will be suffixed by a unique string based on your subscription id\n", 46 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": { 53 | "dotnet_interactive": { 54 | "language": "pwsh" 55 | }, 56 | "polyglot_notebook": { 57 | "kernelName": "pwsh" 58 | }, 59 | "vscode": { 60 | "languageId": "polyglot-notebook" 61 | } 62 | }, 63 | "outputs": [], 64 | "source": [ 65 | "\n", 66 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 67 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 68 | "$resourceGroupLocation = \"westeurope\"\n", 69 | "$apicResourceNamePrefix = \"apic\"\n", 70 | "$apicResourceSku = \"free\"\n", 71 | "$apicResourceTags = @{\n", 72 | " \"lab\" = $deploymentName\n", 73 | "}\n", 74 | "$apimResourceNamePrefix = \"apim\"\n", 75 | "$apimResourceLocation = \"westeurope\"\n", 76 | "$apimResourceSku = \"Basicv2\"\n", 77 | "\n", 78 | "# the following metadata will be created during the deployment\n", 79 | "$metadata = @(\n", 80 | " @{\n", 81 | " \"name\" = 'termsOfService'\n", 82 | " \"schema\" = '{\"title\":\"termsOfService\",\"description\":\"The terms of service URL for using the API\",\"type\":\"string\",\"format\":\"uri\"}'\n", 83 | " \"assignedTo\" = @(\n", 84 | " @{\n", 85 | " \"entity\" = 'api'\n", 86 | " \"required\" = $false\n", 87 | " }\n", 88 | " )\n", 89 | " },\n", 90 | " @{\n", 91 | " \"name\" = 'externalDocs'\n", 92 | " \"schema\" = '{\"title\":\"externalDocs\",\"description\":\"External Documents that describe the API\",\"type\":\"object\",\"properties\":{\"description\":{\"title\":\"description\",\"description\":\"Description of the External Documents\",\"type\":\"string\"},\"url\":{\"title\":\"url\",\"description\":\"The URL to reference the external documents\",\"type\":\"string\",\"format\":\"uri\"}},\"required\":[\"url\"]}'\n", 93 | " \"assignedTo\" = @(\n", 94 | " @{\n", 95 | " \"entity\" = 'api'\n", 96 | " \"required\" = $false\n", 97 | " }\n", 98 | " )\n", 99 | " },\n", 100 | " @{\n", 101 | " \"name\" = 'sourceControl'\n", 102 | " \"schema\" = '{\"title\":\"sourceControl\",\"description\":\"Source Control Info\",\"type\":\"object\",\"properties\":{\"type\":{\"type\":\"string\",\"title\":\"type\",\"description\":\"Source Control System type\",\"oneOf\":[{\"const\":\"GitHub\",\"description\":\"\"},{\"const\":\"GitLab\",\"description\":\"\"},{\"const\":\"Bitbucket\",\"description\":\"\"},{\"const\":\"Other\",\"description\":\"\"}]},\"repository\":{\"title\":\"repository\",\"description\":\"URL for the repository\",\"type\":\"string\",\"format\":\"uri\"},\"url\":{\"title\":\"url\",\"description\":\"Full URL for the API definition stored in the source control system\",\"type\":\"string\",\"format\":\"uri\"}},\"required\":[\"type\",\"repository\",\"url\"]}'\n", 103 | " \"assignedTo\" = @(\n", 104 | " @{\n", 105 | " \"entity\" = 'api'\n", 106 | " \"required\" = $false\n", 107 | " }\n", 108 | " )\n", 109 | " },\n", 110 | " @{\n", 111 | " \"name\" = 'securitySchemes'\n", 112 | " \"schema\" = '{\"title\":\"securitySchemes\",\"description\":\"API Security Schemes\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"name\":{\"title\":\"name\",\"description\":\"Name of the API Security Scheme\",\"type\":\"string\"},\"type\":{\"type\":\"string\",\"title\":\"type\",\"description\":\"The Type of the API Security Scheme\",\"oneOf\":[{\"const\":\"http\",\"description\":\"Basic, Bearer and other HTTP authentications schemes\"},{\"const\":\"apiKey\",\"description\":\"API keys and cookie authentication\"},{\"const\":\"oauth2\",\"description\":\"OAuth 2.0 is the industry-standard protocol for authorization.\"},{\"const\":\"openIdConnect \",\"description\":\"OpenID Connect Discovery\"}]},\"authorizationurl\":{\"title\":\"authorizationUrl\",\"type\":\"string\",\"format\":\"uri\"}},\"required\":[\"name\",\"type\"]}}'\n", 113 | " \"assignedTo\" = @(\n", 114 | " @{\n", 115 | " \"entity\" = 'deployment'\n", 116 | " \"required\" = $false\n", 117 | " }\n", 118 | " )\n", 119 | " },\n", 120 | " @{\n", 121 | " \"name\" = 'host'\n", 122 | " \"schema\" = '{\"title\":\"host\",\"description\":\"The name of the host that is hosting the API\",\"type\":\"string\"}'\n", 123 | " \"assignedTo\" = @(\n", 124 | " @{\n", 125 | " \"entity\" = 'environment'\n", 126 | " \"required\" = $false\n", 127 | " }\n", 128 | " )\n", 129 | " }\n", 130 | ")\n", 131 | "\n", 132 | "# the following environment(s) will be created during the deployment\n", 133 | "$environments = @(\n", 134 | " @{\n", 135 | " \"title\" = 'prod'\n", 136 | " \"kind\" = 'production'\n", 137 | " \"description\" = 'Production Environment'\n", 138 | " \"server\" = @{\n", 139 | " \"type\" = 'Kubernetes' \n", 140 | " \"managementPortalUri\" = 'https://swagger.io/tools/swaggerhub/'\n", 141 | " }\n", 142 | " \"onboarding\" = @{\n", 143 | " \"developerPortalUri\" = 'https://swagger.io/tools/swaggerhub/features/swaggerhub-portal/'\n", 144 | " \"instructions\" = 'Sign in and access the developer portal to get started with the API'\n", 145 | " }\n", 146 | " \"customProperties\" = @{ \n", 147 | " }\n", 148 | " }\n", 149 | ")\n", 150 | "\n", 151 | "$environmentCustomProperties = @{\n", 152 | " \"host\" = \"petstore3.swagger.io\"\n", 153 | "}\n", 154 | "\n", 155 | "$apiCustomProperties = @{\n", 156 | " \"termsOfService\" = \"http://swagger.io/terms/\"\n", 157 | " \"externalDocs\" = @{\n", 158 | " \"description\" = \"Find out more about Swagger\"\n", 159 | " \"url\" = \"http://swagger.io\"\n", 160 | " }\n", 161 | " \"sourceControl\" = @{\n", 162 | " \"type\" = \"GitHub\"\n", 163 | " \"repository\" = \"https://github.com/swagger-api/swagger-petstore\"\n", 164 | " \"url\" = \"https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml\"\n", 165 | " }\n", 166 | "}\n", 167 | "\n", 168 | "$deploymentCustomProperties = @{\n", 169 | " \"securitySchemes\" = @(\n", 170 | " @{\n", 171 | " \"name\" = \"petstore_auth\"\n", 172 | " \"type\" = \"oauth2\"\n", 173 | " \"authorizationurl\" = \"https://petstore3.swagger.io/oauth/authorize\"\n", 174 | " }\n", 175 | " )\n", 176 | "}\n", 177 | "\n", 178 | "$apisConfig = @(\n", 179 | " @{\n", 180 | " \"name\" = 'petstore'\n", 181 | " \"type\" = 'http'\n", 182 | " \"revision\" = '1-0-20-SNAPSHOT'\n", 183 | " \"revisionDescription\" = '1.0.20-SNAPSHOT'\n", 184 | " \"displayName\" = 'Petstore'\n", 185 | " \"description\" = 'Sample Pet Store Server'\n", 186 | " 'contact' = @{\n", 187 | " 'name' = 'API Team'\n", 188 | " 'email' = 'apiteam@swagger.io'\n", 189 | " 'url' = 'http://swagger.io'\n", 190 | " }\n", 191 | " 'license' = @{\n", 192 | " 'name' = 'Apache 2.0'\n", 193 | " 'url' = 'http://www.apache.org/licenses/LICENSE-2.0.html'\n", 194 | " }\n", 195 | " 'format' = 'openapi-link'\n", 196 | " \"path\" = 'petstore'\n", 197 | " 'termsOfServiceUrl' = 'http://swagger.io/terms/'\n", 198 | " \"serviceUrl\" = 'https://petstore3.swagger.io/api/v3'\n", 199 | " \"specURL\" = 'https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml'\n", 200 | " },\n", 201 | " @{\n", 202 | " \"name\" = 'openai'\n", 203 | " \"type\" = 'http'\n", 204 | " \"revision\" = '2024-02-01'\n", 205 | " \"revisionDescription\" = '2024-02-01'\n", 206 | " \"displayName\" = 'OpenAI'\n", 207 | " \"description\" = 'OpenAI inference API'\n", 208 | " 'contact' = @{\n", 209 | " 'name' = 'OpenAI Team'\n", 210 | " 'email' = 'openai@microsoft.com'\n", 211 | " 'url' = 'http://www.microsoft.com'\n", 212 | " }\n", 213 | " 'license' = @{\n", 214 | " 'name' = 'MIT License'\n", 215 | " 'url' = 'Http://opensource.org/licenses/MIT'\n", 216 | " }\n", 217 | " 'format' = 'openapi-link'\n", 218 | " \"path\" = 'openai'\n", 219 | " 'termsOfServiceUrl' = 'https://learn.microsoft.com/en-us/legal/cognitive-services/openai/code-of-conduct'\n", 220 | " \"serviceUrl\" = 'https://your-resource-name.openai.azure.com'\n", 221 | " \"specURL\" = 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/stable/2024-02-01/inference.json'\n", 222 | " }\n", 223 | ")\n", 224 | "\n", 225 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 226 | ] 227 | }, 228 | { 229 | "cell_type": "markdown", 230 | "metadata": {}, 231 | "source": [ 232 | "### 1️⃣ Create the Azure Resource Group\n", 233 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": { 240 | "dotnet_interactive": { 241 | "language": "pwsh" 242 | }, 243 | "polyglot_notebook": { 244 | "kernelName": "pwsh" 245 | }, 246 | "vscode": { 247 | "languageId": "polyglot-notebook" 248 | } 249 | }, 250 | "outputs": [], 251 | "source": [ 252 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 253 | "\n", 254 | "if ($LASTEXITCODE -ne 0) {\n", 255 | " Write-Output $resourceGroupOutput\n", 256 | "} else {\n", 257 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 258 | "}" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 266 | "\n", 267 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": null, 273 | "metadata": { 274 | "dotnet_interactive": { 275 | "language": "pwsh" 276 | }, 277 | "polyglot_notebook": { 278 | "kernelName": "pwsh" 279 | }, 280 | "vscode": { 281 | "languageId": "polyglot-notebook" 282 | } 283 | }, 284 | "outputs": [], 285 | "source": [ 286 | "$bicepParameters = @{\n", 287 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 288 | " \"contentVersion\" = \"1.0.0.0\"\n", 289 | " \"parameters\" = @{\n", 290 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 291 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 292 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 293 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 294 | " \"apimResourceNamePrefix\" = @{ \"value\" = $apimResourceNamePrefix }\n", 295 | " \"apimResourceLocation\" = @{ \"value\" = $apimResourceLocation }\n", 296 | " \"apimResourceSku\" = @{ \"value\" = $apimResourceSku }\n", 297 | " \"apisConfig\" = @{ \"value\" = $apisConfig }\n", 298 | " }\n", 299 | "}\n", 300 | "\n", 301 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 302 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 303 | "\n", 304 | "# Execute the Azure CLI command to create the deployment\n", 305 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 306 | "\n" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "### 3️⃣ Get the deployment outputs\n", 314 | "\n", 315 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": null, 321 | "metadata": { 322 | "dotnet_interactive": { 323 | "language": "pwsh" 324 | }, 325 | "polyglot_notebook": { 326 | "kernelName": "pwsh" 327 | }, 328 | "vscode": { 329 | "languageId": "polyglot-notebook" 330 | } 331 | }, 332 | "outputs": [], 333 | "source": [ 334 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 335 | "if ($LASTEXITCODE -ne 0) {\n", 336 | " Write-Output $deploymentOutput\n", 337 | "} else {\n", 338 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 339 | "}\n", 340 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"\n", 341 | "\n", 342 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apimResourceId.value -o json\n", 343 | "if ($LASTEXITCODE -ne 0) {\n", 344 | " Write-Output $deploymentOutput\n", 345 | "} else {\n", 346 | " $apimResourceId = $deploymentOutput | ConvertFrom-Json\n", 347 | "}\n", 348 | "Write-Output \"👉🏻 API Management id: $apimResourceId\"" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "### 4️⃣ Update the environment metadata\n", 356 | "\n", 357 | "We will [update the enviroment](https://learn.microsoft.com/en-us/cli/azure/apic/environment?view=azure-cli-latest#az-apic-environment-update) with the `custom properties` defined in the variable `environmentCustomProperties`" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "dotnet_interactive": { 365 | "language": "pwsh" 366 | }, 367 | "polyglot_notebook": { 368 | "kernelName": "pwsh" 369 | }, 370 | "vscode": { 371 | "languageId": "polyglot-notebook" 372 | } 373 | }, 374 | "outputs": [], 375 | "source": [ 376 | "$environmentCustomPropertiesJson = ConvertTo-Json -InputObject $environmentCustomProperties -Depth 10 -Compress\n", 377 | "az apic environment update -g $resourceGroupName -s $apicResourceName --environment-id \"prod\" `\n", 378 | " --custom-properties $environmentCustomPropertiesJson.replace('\"','\\\"')" 379 | ] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "metadata": {}, 384 | "source": [ 385 | "### 5️⃣ Import the Azure API Management APIs into Azure API Center\n", 386 | "\n", 387 | "We will use the [import-from-apim](https://learn.microsoft.com/en-us/cli/azure/apic/service?view=azure-cli-latest#az-apic-service-import-from-apim) command with the wildcard to import all the APIs." 388 | ] 389 | }, 390 | { 391 | "cell_type": "code", 392 | "execution_count": null, 393 | "metadata": { 394 | "dotnet_interactive": { 395 | "language": "pwsh" 396 | }, 397 | "polyglot_notebook": { 398 | "kernelName": "pwsh" 399 | }, 400 | "vscode": { 401 | "languageId": "polyglot-notebook" 402 | } 403 | }, 404 | "outputs": [], 405 | "source": [ 406 | "az apic service import-from-apim -g $resourceGroupName -s $apicResourceName --source-resource-ids \"$apimResourceId/apis/*\"" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "### 6️⃣ Discover the APIs that were just imported\n", 414 | "\n", 415 | "You can discover the APIs with fhe following methods:\n", 416 | "- With the Azure Portal\n", 417 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 418 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 419 | "- With the CLI, the service REST API and more\n", 420 | "\n", 421 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": null, 427 | "metadata": { 428 | "dotnet_interactive": { 429 | "language": "pwsh" 430 | }, 431 | "polyglot_notebook": { 432 | "kernelName": "pwsh" 433 | }, 434 | "vscode": { 435 | "languageId": "polyglot-notebook" 436 | } 437 | }, 438 | "outputs": [], 439 | "source": [ 440 | "az apic api list -g $resourceGroupName -s $apicResourceName --query \"[].{Name:name, Title:title, Kind:kind, ContantEmail:contacts[0].email}\" -o table" 441 | ] 442 | }, 443 | { 444 | "cell_type": "markdown", 445 | "metadata": {}, 446 | "source": [ 447 | "### 🗑️ Clean up resources\n", 448 | "\n", 449 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 450 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 451 | ] 452 | } 453 | ], 454 | "metadata": { 455 | "kernelspec": { 456 | "display_name": "Python 3", 457 | "language": "python", 458 | "name": "python3" 459 | }, 460 | "language_info": { 461 | "codemirror_mode": { 462 | "name": "ipython", 463 | "version": 3 464 | }, 465 | "file_extension": ".py", 466 | "mimetype": "text/x-python", 467 | "name": "python", 468 | "nbconvert_exporter": "python", 469 | "pygments_lexer": "ipython3", 470 | "version": "3.11.9" 471 | } 472 | }, 473 | "nbformat": 4, 474 | "nbformat_minor": 2 475 | } 476 | -------------------------------------------------------------------------------- /labs/import-from-azure-apim/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | @description('The prefix name of the API Management resource') 18 | param apimResourceNamePrefix string 19 | 20 | @description('Location for the APIM resource') 21 | param apimResourceLocation string = resourceGroup().location 22 | 23 | @description('The pricing tier of this API Management service') 24 | @allowed([ 25 | 'Consumption' 26 | 'Developer' 27 | 'Basic' 28 | 'Basicv2' 29 | 'Standard' 30 | 'Standardv2' 31 | 'Premium' 32 | ]) 33 | param apimResourceSku string = 'Consumption' 34 | 35 | @description('The instance size of this API Management service.') 36 | @allowed([ 37 | 0 38 | 1 39 | 2 40 | ]) 41 | param apimResourceSkuCount int = 1 42 | 43 | @description('The email address of the owner of the service') 44 | param apimPublisherEmail string = 'noreply@microsoft.com' 45 | 46 | @description('The name of the owner of the service') 47 | param apimPublisherName string = 'Microsoft' 48 | 49 | @description('List of API resources to create.') 50 | param apisConfig array = [] 51 | 52 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 53 | 54 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 55 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 56 | location: apicResourceLocation 57 | tags: apicResourceTags 58 | identity: { 59 | type: 'SystemAssigned' 60 | } 61 | } 62 | 63 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 64 | name: metadata.name 65 | parent: apic 66 | properties: { 67 | schema: metadata.schema 68 | assignedTo: [for assignedTo in metadata.assignedTo: { 69 | deprecated: false 70 | entity: assignedTo.entity 71 | required: assignedTo.required 72 | } 73 | ] 74 | } 75 | }] 76 | 77 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 78 | name: 'default' 79 | parent: apic 80 | } 81 | 82 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 83 | name: environment.title 84 | parent: apicWorkspace 85 | properties: { 86 | customProperties: environment.customProperties 87 | description: environment.description 88 | kind: environment.kind 89 | onboarding: { 90 | developerPortalUri: [ 91 | environment.onboarding.developerPortalUri 92 | ] 93 | instructions: environment.onboarding.instructions 94 | } 95 | server: { 96 | managementPortalUri: [ 97 | environment.server.managementPortalUri 98 | ] 99 | type: environment.server.type 100 | } 101 | title: environment.title 102 | } 103 | }] 104 | 105 | resource apimService 'Microsoft.ApiManagement/service@2023-05-01-preview' = { 106 | name: '${apimResourceNamePrefix}-${resourceSuffix}' 107 | location: apimResourceLocation 108 | sku: { 109 | name: apimResourceSku 110 | capacity: (apimResourceSku == 'Consumption') ? 0 : ((apimResourceSku == 'Developer') ? 1 : apimResourceSkuCount) 111 | } 112 | properties: { 113 | publisherEmail: apimPublisherEmail 114 | publisherName: apimPublisherName 115 | } 116 | identity: { 117 | type: 'SystemAssigned' 118 | } 119 | } 120 | 121 | var roleDefinitionID = resourceId('Microsoft.Authorization/roleDefinitions', '71522526-b88f-4d52-b57f-d31fc3546d0d') // API Management Service Reader Role 122 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { 123 | scope: apimService 124 | name: guid(subscription().id, resourceGroup().id, apimService.name, roleDefinitionID) 125 | properties: { 126 | roleDefinitionId: roleDefinitionID 127 | principalId: apic.identity.principalId 128 | principalType: 'ServicePrincipal' 129 | } 130 | } 131 | 132 | resource apiResource 'Microsoft.ApiManagement/service/apis@2023-05-01-preview' = [for (api, i) in apisConfig: if(length(apisConfig) > 0) { 133 | name: api.name 134 | parent: apimService 135 | properties: { 136 | apiRevision: api.revision 137 | apiRevisionDescription: api.revisionDescription 138 | apiType: api.type 139 | description: api.description 140 | displayName: api.displayName 141 | contact: { 142 | email: api.contact.email 143 | name: api.contact.name 144 | url: api.contact.url 145 | } 146 | license: { 147 | name: api.license.name 148 | url: api.license.url 149 | } 150 | format: api.format 151 | path: api.path 152 | serviceUrl: api.serviceUrl 153 | protocols: [ 154 | 'https' 155 | ] 156 | subscriptionKeyParameterNames: { 157 | header: 'api-key' 158 | query: 'api-key' 159 | } 160 | subscriptionRequired: true 161 | termsOfServiceUrl: api.termsOfServiceUrl 162 | type: api.type 163 | value: api.specURL 164 | } 165 | }] 166 | 167 | 168 | output apicResourceId string = apic.id 169 | output apicResourceName string = apic.name 170 | output apicResourcePrincipalId string = apic.identity.principalId 171 | 172 | output apimResourceId string = apimService.id 173 | output apimResourceName string = apimService.name 174 | -------------------------------------------------------------------------------- /labs/import-from-gcp/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Apigee API Management 4 | ![image](../../images/import-from-gcp.png) 5 | 6 | Playground to experiment importing APIs from Apigee. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [GCP CLI](https://cloud.google.com/sdk/docs/install-sdk) to export the Apigee APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Import environments from Apigee 13 | - Import APIs from Apigee 14 | - Import API deployments from Apigee 15 | - Search and discover the APIs registered in API Center. 16 | 17 | ### Prerequisites 18 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 19 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 20 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 21 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 22 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 23 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 24 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 25 | - Install or update to the latest [GCP CLI](https://cloud.google.com/sdk/docs/install-sdk) and set your Apigee project 26 | -------------------------------------------------------------------------------- /labs/import-from-gcp/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-gcp/import-from-gcp.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import from Apigee API Management\n", 10 | "![image](../../images/import-from-gcp.png)\n", 11 | "\n", 12 | "Playground to experiment importing APIs from Apigee. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [GCP CLI](https://cloud.google.com/sdk/docs/install-sdk) to export the Apigee APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center.\n", 13 | "\n", 14 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 15 | "\n", 16 | "### Learning Objectives - Upon completing this lab, you should be able to:\n", 17 | "- Deploy Azure API Center using Bicep.\n", 18 | "- Import environments from Apigee\n", 19 | "- Import APIs from Apigee\n", 20 | "- Import API deployments from Apigee\n", 21 | "- Search and discover the APIs registered in API Center.\n", 22 | "\n", 23 | "### Prerequisites\n", 24 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 25 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 26 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 27 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 28 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 29 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 30 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n", 31 | "- Install or update to the latest [GCP CLI](https://cloud.google.com/sdk/docs/install-sdk) and set your Apigee project\n" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "### 0️⃣ Initialize notebook variables\n", 39 | "\n", 40 | "- Resources will be suffixed by a unique string based on your subscription id\n", 41 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": null, 47 | "metadata": { 48 | "dotnet_interactive": { 49 | "language": "pwsh" 50 | }, 51 | "polyglot_notebook": { 52 | "kernelName": "pwsh" 53 | }, 54 | "vscode": { 55 | "languageId": "polyglot-notebook" 56 | } 57 | }, 58 | "outputs": [], 59 | "source": [ 60 | "\n", 61 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 62 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 63 | "$resourceGroupLocation = \"westeurope\"\n", 64 | "$apicResourceNamePrefix = \"apic\"\n", 65 | "$apicResourceSku = \"free\"\n", 66 | "$apicResourceTags = @{\n", 67 | " \"lab\" = $deploymentName\n", 68 | "}\n", 69 | "\n", 70 | "# the following metadata will be created during the Bicep deployment\n", 71 | "$metadata = @(\n", 72 | " @{\n", 73 | " \"name\" = 'createdAt'\n", 74 | " \"schema\" = '{\"title\":\"createdAt\",\"description\":\"When the API was created in Apigee\",\"type\":\"string\"}'\n", 75 | " \"assignedTo\" = @(\n", 76 | " @{\n", 77 | " \"entity\" = 'api'\n", 78 | " \"required\" = $false\n", 79 | " }\n", 80 | " )\n", 81 | " },\n", 82 | " @{\n", 83 | " \"name\" = 'deployStartTime'\n", 84 | " \"schema\" = '{\"title\":\"deployStartTime\",\"description\":\"When the API was deployed in Apigee\",\"type\":\"string\"}'\n", 85 | " \"assignedTo\" = @(\n", 86 | " @{\n", 87 | " \"entity\" = 'deployment'\n", 88 | " \"required\" = $false\n", 89 | " }\n", 90 | " )\n", 91 | " }\n", 92 | ")\n", 93 | "\n", 94 | "# the following environment(s) will be created during the deployment\n", 95 | "$environments = @(\n", 96 | ")\n", 97 | "\n", 98 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 99 | ] 100 | }, 101 | { 102 | "cell_type": "markdown", 103 | "metadata": {}, 104 | "source": [ 105 | "### 1️⃣ Create the Azure Resource Group\n", 106 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": { 113 | "dotnet_interactive": { 114 | "language": "pwsh" 115 | }, 116 | "polyglot_notebook": { 117 | "kernelName": "pwsh" 118 | }, 119 | "vscode": { 120 | "languageId": "polyglot-notebook" 121 | } 122 | }, 123 | "outputs": [], 124 | "source": [ 125 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 126 | "\n", 127 | "if ($LASTEXITCODE -ne 0) {\n", 128 | " Write-Output $resourceGroupOutput\n", 129 | "} else {\n", 130 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 131 | "}" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 139 | "\n", 140 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 141 | ] 142 | }, 143 | { 144 | "cell_type": "code", 145 | "execution_count": null, 146 | "metadata": { 147 | "dotnet_interactive": { 148 | "language": "pwsh" 149 | }, 150 | "polyglot_notebook": { 151 | "kernelName": "pwsh" 152 | }, 153 | "vscode": { 154 | "languageId": "polyglot-notebook" 155 | } 156 | }, 157 | "outputs": [], 158 | "source": [ 159 | "$bicepParameters = @{\n", 160 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 161 | " \"contentVersion\" = \"1.0.0.0\"\n", 162 | " \"parameters\" = @{\n", 163 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 164 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 165 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 166 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 167 | " }\n", 168 | "}\n", 169 | "\n", 170 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 171 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 172 | "\n", 173 | "# Execute the Azure CLI command to create the deployment\n", 174 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 175 | "\n" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "### 3️⃣ Get the deployment outputs\n", 183 | "\n", 184 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": { 191 | "dotnet_interactive": { 192 | "language": "pwsh" 193 | }, 194 | "polyglot_notebook": { 195 | "kernelName": "pwsh" 196 | }, 197 | "vscode": { 198 | "languageId": "polyglot-notebook" 199 | } 200 | }, 201 | "outputs": [], 202 | "source": [ 203 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 204 | "if ($LASTEXITCODE -ne 0) {\n", 205 | " Write-Output $deploymentOutput\n", 206 | "} else {\n", 207 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 208 | "}\n", 209 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "metadata": {}, 215 | "source": [ 216 | "### 4️⃣ Get and import Apigee environments\n", 217 | "\n", 218 | "We will start by [getting the environments from Apigee](https://cloud.google.com/sdk/gcloud/reference/apigee) and create the environments in API Center\n" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": { 225 | "dotnet_interactive": { 226 | "language": "pwsh" 227 | }, 228 | "polyglot_notebook": { 229 | "kernelName": "pwsh" 230 | }, 231 | "vscode": { 232 | "languageId": "polyglot-notebook" 233 | } 234 | }, 235 | "outputs": [], 236 | "source": [ 237 | "\n", 238 | "$apigeeEnvironmentsJson = gcloud apigee environments list --format=json\n", 239 | "$apigeeEnvironments = $apigeeEnvironmentsJson | ConvertFrom-Json\n", 240 | "foreach ($environment in $apigeeEnvironments) {\n", 241 | " Write-Output \"👉🏻 Creating environment $environment\"\n", 242 | " az apic environment create -g $resourceGroupName -s $apicResourceName --environment-id $environment --title $environment --type \"production\" `\n", 243 | " --server '{\\\"type\\\":\\\"Apigee API Management\\\"}'\n", 244 | "}\n" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "### 5️⃣ Import the Apigee APIs into API Center\n", 252 | "\n", 253 | "Get the APIs from Apigee and register in API Center with version and definition." 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": { 260 | "dotnet_interactive": { 261 | "language": "pwsh" 262 | }, 263 | "polyglot_notebook": { 264 | "kernelName": "pwsh" 265 | }, 266 | "vscode": { 267 | "languageId": "polyglot-notebook" 268 | } 269 | }, 270 | "outputs": [], 271 | "source": [ 272 | "$apigeeAPIsJson = gcloud apigee apis list --format=json\n", 273 | "$apigeeAPIs = $apigeeAPIsJson | ConvertFrom-Json\n", 274 | "foreach ($apigeeAPI in $apigeeAPIs) {\n", 275 | " $apiJson = gcloud apigee apis describe $apigeeAPI --format=json\n", 276 | " $api = $apiJson | ConvertFrom-Json\n", 277 | "\n", 278 | " $apiCustomProperties = @{\n", 279 | " \"createdAt\" = $api.metaData.createdAt\n", 280 | " }\n", 281 | "\n", 282 | " $apiName = $api.name\n", 283 | " if ($api.metaData.subType -eq \"PROXY\") {\n", 284 | " $apiCustomPropertiesJson = ConvertTo-Json -InputObject $apiCustomProperties -Depth 10 -Compress\n", 285 | " write-output \"👉🏻 Creating API $apiName\"\n", 286 | " az apic api create -g $resourceGroupName -s $apicResourceName --api-id $apiName --type REST `\n", 287 | " --title $apiName `\n", 288 | " --custom-properties $apiCustomPropertiesJson.replace('\"','\\\"')\n", 289 | " foreach ($revision in $api.revision) {\n", 290 | " write-output \"👉🏻 Creating version $revision of API $apiName\"\n", 291 | " az apic api version create -g $resourceGroupName -s $apicResourceName --api-id $apiName --version-id \"v-$revision\" --title \"Version $revision\" `\n", 292 | " --lifecycle-stage \"production\"\n", 293 | "\n", 294 | " write-output \"👉🏻 Creating definition for version $revision of API $apiName\"\n", 295 | " az apic api definition create -g $resourceGroupName -s $apicResourceName --api-id $apiName `\n", 296 | " --version-id \"v-$revision\" --definition-id \"openapi\" --title \"OpenAPI\" --description \"OpenAPI spec\" \n", 297 | "\n", 298 | " }\n", 299 | " }\n", 300 | "}\n", 301 | "\n" 302 | ] 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "metadata": {}, 307 | "source": [ 308 | "### 6️⃣ Import the Apigee API Deployments into API Center\n", 309 | "\n", 310 | "Get the Deployments from Apigee and create them in API Center" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": { 317 | "dotnet_interactive": { 318 | "language": "pwsh" 319 | }, 320 | "polyglot_notebook": { 321 | "kernelName": "pwsh" 322 | }, 323 | "vscode": { 324 | "languageId": "polyglot-notebook" 325 | } 326 | }, 327 | "outputs": [], 328 | "source": [ 329 | "$apigeeDeploymentsListJson = gcloud apigee deployments list --format=json\n", 330 | "$apigeeDeploymentsList = $apigeeDeploymentsListJson | ConvertFrom-Json\n", 331 | "foreach ($apigeeDeployment in $apigeeDeploymentsList) {\n", 332 | " $apiName = $apigeeDeployment.apiProxy\n", 333 | " $envName = $apigeeDeployment.environment\n", 334 | " $apigeeDeploymentJson = gcloud apigee deployments describe --api=$apiName --environment=$envName --format=json\n", 335 | "\n", 336 | " $apigeeDeployment = $apigeeDeploymentJson | ConvertFrom-Json\n", 337 | "\n", 338 | " $deploymentCustomProperties = @{\n", 339 | " \"deployStartTime\" = $apigeeDeployment.deployStartTime\n", 340 | " }\n", 341 | "\n", 342 | " $deploymentCustomPropertiesJson = ConvertTo-Json -InputObject $deploymentCustomProperties -Depth 10 -Compress\n", 343 | " $revision = $apigeeDeployment.revision\n", 344 | " write-output \"👉🏻 Creating deployment for version $revision of API $apiName\"\n", 345 | " az apic api deployment create -g $resourceGroupName -s $apicResourceName --deployment-id \"$apiName-deployment\" `\n", 346 | " --title \"$apiName Deployment\" --api-id $apiName `\n", 347 | " --environment-id \"/workspaces/default/environments/$envName\" `\n", 348 | " --definition-id \"/workspaces/default/apis/another-petstore/versions/v-$revision/definitions/openapi\" `\n", 349 | " --server '{\\\"runtimeUri\\\":[\\\"\\\"]}' `\n", 350 | " --custom-properties $deploymentCustomPropertiesJson.replace('\"','\\\"')\n", 351 | "}" 352 | ] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "metadata": {}, 357 | "source": [ 358 | "### 7️⃣ Discover the APIs that were just imported\n", 359 | "\n", 360 | "You can discover the APIs with fhe following methods:\n", 361 | "- With the Azure Portal\n", 362 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 363 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 364 | "- With the CLI, the service REST API and more\n", 365 | "\n", 366 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": { 373 | "dotnet_interactive": { 374 | "language": "pwsh" 375 | }, 376 | "polyglot_notebook": { 377 | "kernelName": "pwsh" 378 | }, 379 | "vscode": { 380 | "languageId": "polyglot-notebook" 381 | } 382 | }, 383 | "outputs": [], 384 | "source": [ 385 | "az apic api list -g $resourceGroupName -s $apicResourceName --query \"[].{Name:name, Title:title, Kind:kind, ContactEmail:contacts[0].email}\" -o table" 386 | ] 387 | }, 388 | { 389 | "cell_type": "markdown", 390 | "metadata": {}, 391 | "source": [ 392 | "### 🗑️ Clean up resources\n", 393 | "\n", 394 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 395 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 396 | ] 397 | } 398 | ], 399 | "metadata": { 400 | "kernelspec": { 401 | "display_name": "Python 3", 402 | "language": "python", 403 | "name": "python3" 404 | }, 405 | "language_info": { 406 | "codemirror_mode": { 407 | "name": "ipython", 408 | "version": 3 409 | }, 410 | "file_extension": ".py", 411 | "mimetype": "text/x-python", 412 | "name": "python", 413 | "nbconvert_exporter": "python", 414 | "pygments_lexer": "ipython3", 415 | "version": "3.11.9" 416 | } 417 | }, 418 | "nbformat": 4, 419 | "nbformat_minor": 2 420 | } 421 | -------------------------------------------------------------------------------- /labs/import-from-gcp/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-generic-openapi/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Generic OpenAPI lab 4 | ![image](../../images/import-from-generic-openapi.png) 5 | 6 | Playground to experiment importing APIs in the OpenAPI specification into API Center. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Azure CLI]((https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest)) to import the APIs. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 13 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 14 | - Create an enviroment with custom metadata properties 15 | - Register an API using the OpenAPI spec as the source of truth and assign API metadata properties. 16 | - Register an API with individual commands to have full control over all the properties. 17 | - Search and discover the APIs registered in API Center. 18 | 19 | ### Prerequisites 20 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 21 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 22 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 23 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 24 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 25 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 26 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 27 | 28 | ### 🚀 Get started 29 | Proceed by opening the [Jupyter notebook](import-from-generic-openapi.ipynb), and follow the steps provided. 30 | 31 | ### 🗑️ Clean up resources 32 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 33 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-generic-openapi/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-generic-openapi/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-git/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Git version control system 4 | ![image](../../images/import-from-git.png) 5 | 6 | Playground to experiment importing APIs in the OpenAPI specification into API Center by crawling Git repositories. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 13 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 14 | - Create an enviroment with custom metadata properties 15 | - Register an API using the OpenAPI spec as the source of truth and assign API metadata properties. 16 | - Register an API with individual commands to have full control over all the properties. 17 | - Search and discover the APIs registered in API Center. 18 | 19 | ### Prerequisites 20 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 21 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 22 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 23 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 24 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 25 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 26 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 27 | - Install [OpenAPI spec validator tool](https://openapi-spec-validator.readthedocs.io/en/latest/index.html) 28 | 29 | ### 🚀 Get started 30 | Proceed by opening the [Jupyter notebook](import-from-generic-openapi.ipynb), and follow the steps provided. 31 | 32 | ### 🗑️ Clean up resources 33 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 34 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-git/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-git/import-from-git.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import from Git version control system\n", 10 | "![image](../../images/import-from-git.png)\n", 11 | "\n", 12 | "Playground to experiment importing APIs in the OpenAPI specification into API Center by crawling Git repositories.\n", 13 | "\n", 14 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 15 | "\n", 16 | "### Learning Objectives - Upon completing this lab, you should be able to:\n", 17 | "- Deploy Azure API Center using Bicep.\n", 18 | "- Configure the API Center metadata scheme for APIs, Environments and Deployments.\n", 19 | "- Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest).\n", 20 | "- Create an enviroment with custom metadata properties \n", 21 | "- Register an API using the OpenAPI spec as the source of truth and assign API metadata properties.\n", 22 | "- Register an API with individual commands to have full control over all the properties. \n", 23 | "- Search and discover the APIs registered in API Center.\n", 24 | "\n", 25 | "### Prerequisites\n", 26 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 27 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 28 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 29 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 30 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 31 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 32 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n", 33 | "- Install [OpenAPI spec validator tool](https://openapi-spec-validator.readthedocs.io/en/latest/index.html)\n" 34 | ] 35 | }, 36 | { 37 | "cell_type": "markdown", 38 | "metadata": {}, 39 | "source": [ 40 | "### 0️⃣ Initialize notebook variables\n", 41 | "\n", 42 | "- Resources will be suffixed by a unique string based on your subscription id\n", 43 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "dotnet_interactive": { 51 | "language": "pwsh" 52 | }, 53 | "polyglot_notebook": { 54 | "kernelName": "pwsh" 55 | }, 56 | "vscode": { 57 | "languageId": "polyglot-notebook" 58 | } 59 | }, 60 | "outputs": [], 61 | "source": [ 62 | "\n", 63 | "$sourceRepo = \"https://github.com/APIs-guru/openapi-directory\"\n", 64 | "$maxAPIsToImport = 150\n", 65 | "\n", 66 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 67 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 68 | "$resourceGroupLocation = \"westeurope\"\n", 69 | "$apicResourceNamePrefix = \"apic\"\n", 70 | "$apicResourceSku = \"free\"\n", 71 | "$apicResourceTags = @{\n", 72 | " \"lab\" = $deploymentName\n", 73 | "}\n", 74 | "\n", 75 | "# the following metadata will be created during the deployment\n", 76 | "$metadata = @(\n", 77 | ")\n", 78 | "\n", 79 | "# the following environment(s) will be created during the deployment\n", 80 | "$environments = @(\n", 81 | ")\n", 82 | "\n", 83 | "\n", 84 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "### 1️⃣ Create the Azure Resource Group\n", 92 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": { 99 | "dotnet_interactive": { 100 | "language": "pwsh" 101 | }, 102 | "polyglot_notebook": { 103 | "kernelName": "pwsh" 104 | }, 105 | "vscode": { 106 | "languageId": "polyglot-notebook" 107 | } 108 | }, 109 | "outputs": [], 110 | "source": [ 111 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 112 | "\n", 113 | "if ($LASTEXITCODE -ne 0) {\n", 114 | " Write-Output $resourceGroupOutput\n", 115 | "} else {\n", 116 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 117 | "}" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 125 | "\n", 126 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": null, 132 | "metadata": { 133 | "dotnet_interactive": { 134 | "language": "pwsh" 135 | }, 136 | "polyglot_notebook": { 137 | "kernelName": "pwsh" 138 | }, 139 | "vscode": { 140 | "languageId": "polyglot-notebook" 141 | } 142 | }, 143 | "outputs": [], 144 | "source": [ 145 | "$bicepParameters = @{\n", 146 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 147 | " \"contentVersion\" = \"1.0.0.0\"\n", 148 | " \"parameters\" = @{\n", 149 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 150 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 151 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 152 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 153 | " }\n", 154 | "}\n", 155 | "\n", 156 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 157 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 158 | "\n", 159 | "# Execute the Azure CLI command to create the deployment\n", 160 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 161 | "\n" 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "### 3️⃣ Get the deployment outputs\n", 169 | "\n", 170 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": null, 176 | "metadata": { 177 | "dotnet_interactive": { 178 | "language": "pwsh" 179 | }, 180 | "polyglot_notebook": { 181 | "kernelName": "pwsh" 182 | }, 183 | "vscode": { 184 | "languageId": "polyglot-notebook" 185 | } 186 | }, 187 | "outputs": [], 188 | "source": [ 189 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 190 | "if ($LASTEXITCODE -ne 0) {\n", 191 | " Write-Output $deploymentOutput\n", 192 | "} else {\n", 193 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 194 | "}\n", 195 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "### 4️⃣ Clone the repo\n", 203 | "\n", 204 | "Creates a local copy of the specific repository or branch within a repository.\n" 205 | ] 206 | }, 207 | { 208 | "cell_type": "code", 209 | "execution_count": null, 210 | "metadata": { 211 | "dotnet_interactive": { 212 | "language": "pwsh" 213 | }, 214 | "polyglot_notebook": { 215 | "kernelName": "pwsh" 216 | }, 217 | "vscode": { 218 | "languageId": "polyglot-notebook" 219 | } 220 | }, 221 | "outputs": [], 222 | "source": [ 223 | "git clone $sourceRepo \".temp\"" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "### 5️⃣ Crawl APIs and register each one of them in API Center\n", 231 | "\n", 232 | "[Registers](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-register) each valid API in the cloned repo." 233 | ] 234 | }, 235 | { 236 | "cell_type": "code", 237 | "execution_count": null, 238 | "metadata": { 239 | "dotnet_interactive": { 240 | "language": "pwsh" 241 | }, 242 | "polyglot_notebook": { 243 | "kernelName": "pwsh" 244 | }, 245 | "vscode": { 246 | "languageId": "polyglot-notebook" 247 | } 248 | }, 249 | "outputs": [], 250 | "source": [ 251 | "\n", 252 | "$files = Get-ChildItem -Path \".temp\" -Recurse -File\n", 253 | "\n", 254 | "$counter = 0\n", 255 | "foreach ($file in $files) {\n", 256 | " if ($file.Extension -eq \".yaml\" || $file.Extension -eq \".yml\" || $file.Extension -eq \".json\") {\n", 257 | " $fileSize = $file.Length\n", 258 | " $filePath = $file.FullName\n", 259 | " $validationOutput = openapi-spec-validator $filePath\n", 260 | " if ($LASTEXITCODE -ne 0) {\n", 261 | " Write-Output \"🚫 File: $filePath failed validation againts OpenAPI 2.0 (aka Swagger), OpenAPI 3.0 or OpenAPI 3.1 specification\"\n", 262 | " } else { \n", 263 | " $counter++\n", 264 | " Write-Output \"👉🏻 Registering: $filePath\"\n", 265 | " az apic api register -g $resourceGroupName -s $apicResourceName -l $filePath\n", 266 | " } \n", 267 | " if ($counter -ge $maxAPIsToImport) {\n", 268 | " Write-Output \"🚫 Max APIs to import reached. Done for now.\"\n", 269 | " break\n", 270 | " }\n", 271 | " }\n", 272 | "}\n", 273 | "Write-Output \"✅ $counter APIs imported.\"\n", 274 | "\n" 275 | ] 276 | }, 277 | { 278 | "cell_type": "markdown", 279 | "metadata": {}, 280 | "source": [ 281 | "### 7️⃣ Discover the APIs that were just imported\n", 282 | "\n", 283 | "You can discover the APIs with fhe following methods:\n", 284 | "- With the Azure Portal\n", 285 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 286 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 287 | "- With the CLI, the service REST API and more\n", 288 | "\n", 289 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": { 296 | "dotnet_interactive": { 297 | "language": "pwsh" 298 | }, 299 | "polyglot_notebook": { 300 | "kernelName": "pwsh" 301 | }, 302 | "vscode": { 303 | "languageId": "polyglot-notebook" 304 | } 305 | }, 306 | "outputs": [], 307 | "source": [ 308 | "az apic api list -g $resourceGroupName -s $apicResourceName --query \"[].{Name:name, Title:title, ContactEmail:contacts[0].email}\" -o table" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": {}, 314 | "source": [ 315 | "### 🗑️ Clean up resources\n", 316 | "\n", 317 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 318 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 319 | ] 320 | } 321 | ], 322 | "metadata": { 323 | "kernelspec": { 324 | "display_name": "Python 3", 325 | "language": "python", 326 | "name": "python3" 327 | }, 328 | "language_info": { 329 | "codemirror_mode": { 330 | "name": "ipython", 331 | "version": 3 332 | }, 333 | "file_extension": ".py", 334 | "mimetype": "text/x-python", 335 | "name": "python", 336 | "nbconvert_exporter": "python", 337 | "pygments_lexer": "ipython3", 338 | "version": "3.11.9" 339 | } 340 | }, 341 | "nbformat": 4, 342 | "nbformat_minor": 2 343 | } 344 | -------------------------------------------------------------------------------- /labs/import-from-git/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-ibm/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from IBM® API Connect 4 | 5 | ![image](../../images/import-from-ibm.png) 6 | 7 | Playground to experiment bulk importing APIs from IBM API Connect. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [IBM API Connect Tooklit](https://www.ibm.com/docs/en/api-connect/10.0.8?topic=tool-overview-command-line) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. 8 | 9 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 10 | 11 | ### Learning Objectives - Upon completing this lab, you should be able to 12 | 13 | - Deploy Azure API Center using Bicep. 14 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 15 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 16 | - Register APIs using the OpenAPI spec exported from IBM API Connect. 17 | - Create deployments for each IBM API Connect Gateway. 18 | - Search and discover the APIs registered in API Center. 19 | 20 | ### Prerequisites 21 | 22 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 23 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 24 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 25 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 26 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 27 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 28 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 29 | - Install or update to the latest [IBM API Connect Toolkit](https://www.ibm.com/docs/en/api-connect/10.0.8?topic=configuration-installing-toolkit) 30 | - [Logging in to a management server](https://www.ibm.com/docs/en/api-connect/10.0.8?topic=tool-logging-in-management-server) 31 | 32 | ### 🚀 Get started 33 | 34 | Proceed by opening the [Jupyter notebook](import-from-ibm.ipynb), and follow the steps provided. 35 | 36 | ### 🗑️ Clean up resources 37 | 38 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 39 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. 40 | -------------------------------------------------------------------------------- /labs/import-from-ibm/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-ibm/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-k8s/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Kubernetes 4 | ![image](../../images/import-from-k8s.png) 5 | 6 | Work in progress 7 | 8 | ### Prerequisites 9 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 10 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 11 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 12 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 13 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 14 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 15 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 16 | 17 | ### 🚀 Get started 18 | Proceed by opening the [Jupyter notebook](import-from-k8s.ipynb), and follow the steps provided. 19 | 20 | ### 🗑️ Clean up resources 21 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 22 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-k8s/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-kong/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from Kong API Gateway 4 | ![image](../../images/import-from-kong.png) 5 | 6 | Playground to experiment importing APIs from Kong API Gateway. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Kong Admin API](https://docs.konghq.com/gateway/api/admin-oss/latest) to export Kong services and import them into API Center. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 13 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 14 | - Create an enviroment with custom metadata properties 15 | - Register an API using the OpenAPI spec as the source of truth and assign API metadata properties. 16 | - Register an API with individual commands to have full control over all the properties. 17 | - Search and discover the APIs registered in API Center. 18 | 19 | ### Prerequisites 20 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 21 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 22 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 23 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 24 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 25 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 26 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 27 | 28 | ### 🚀 Get started 29 | Proceed by opening the [Jupyter notebook](import-from-generic-openapi.ipynb), and follow the steps provided. 30 | 31 | ### 🗑️ Clean up resources 32 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 33 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-kong/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-kong/import-from-kong.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# API Center ❤️ all APIs\n", 8 | "\n", 9 | "## Import from Kong API Gateway\n", 10 | "![image](../../images/import-from-kong.png)\n", 11 | "\n", 12 | "Playground to experiment importing APIs from Kong API Gateway. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Kong Admin API](https://docs.konghq.com/gateway/api/admin-oss/latest) to export Kong services and import them into API Center.\n", 13 | "\n", 14 | "💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more.\n", 15 | "\n", 16 | "### Learning Objectives - Upon completing this lab, you should be able to:\n", 17 | "- Deploy Azure API Center using Bicep.\n", 18 | "- Configure the API Center metadata scheme for APIs, Environments and Deployments.\n", 19 | "- Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest).\n", 20 | "- Create an enviroment with custom metadata properties \n", 21 | "- Register an API using the OpenAPI spec as the source of truth and assign API metadata properties.\n", 22 | "- Register an API with individual commands to have full control over all the properties. \n", 23 | "- Search and discover the APIs registered in API Center.\n", 24 | "\n", 25 | "### Prerequisites\n", 26 | "- Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download)\n", 27 | "- Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/)\n", 28 | "- Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace\n", 29 | "- Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell)\n", 30 | "- Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command.\n", 31 | "- [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions\n", 32 | "- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively)\n" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "### 0️⃣ Initialize notebook variables\n", 40 | "\n", 41 | "- Resources will be suffixed by a unique string based on your subscription id\n", 42 | "- Adjust the APIC location parameter according your preferences and [region availability.](https://learn.microsoft.com/en-us/azure/api-center/overview#available-regions) \n" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": { 49 | "dotnet_interactive": { 50 | "language": "pwsh" 51 | }, 52 | "polyglot_notebook": { 53 | "kernelName": "pwsh" 54 | }, 55 | "vscode": { 56 | "languageId": "polyglot-notebook" 57 | } 58 | }, 59 | "outputs": [], 60 | "source": [ 61 | "\n", 62 | "$kongAdminAPIUrl = \"http://localhost:8001\"\n", 63 | "\n", 64 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 65 | "$resourceGroupName = \"lab-$deploymentName\" # change the name to match your naming style\n", 66 | "$resourceGroupLocation = \"westeurope\"\n", 67 | "$apicResourceNamePrefix = \"apic\"\n", 68 | "$apicResourceSku = \"free\"\n", 69 | "$apicResourceTags = @{\n", 70 | " \"lab\" = $deploymentName\n", 71 | "}\n", 72 | "\n", 73 | "# the following metadata will be created during the deployment\n", 74 | "$metadata = @(\n", 75 | " @{\n", 76 | " \"name\" = 'kongVersion'\n", 77 | " \"schema\" = '{\"title\":\"kongVersion\",\"description\":\"The Kong API Gateway version\",\"type\":\"string\"}'\n", 78 | " \"assignedTo\" = @(\n", 79 | " @{\n", 80 | " \"entity\" = 'environment'\n", 81 | " \"required\" = $false\n", 82 | " }\n", 83 | " )\n", 84 | " },\n", 85 | " @{\n", 86 | " \"name\" = 'kongEdition'\n", 87 | " \"schema\" = '{\"title\":\"kongEdition\",\"description\":\"The Kong API Gateway edition\",\"type\":\"string\"}'\n", 88 | " \"assignedTo\" = @(\n", 89 | " @{\n", 90 | " \"entity\" = 'environment'\n", 91 | " \"required\" = $false\n", 92 | " }\n", 93 | " )\n", 94 | " },\n", 95 | " @{\n", 96 | " \"name\" = 'konnectMode'\n", 97 | " \"schema\" = '{\"title\":\"konnectMode\",\"description\":\"Using Kong Konnectn\",\"type\":\"boolean\"}'\n", 98 | " \"assignedTo\" = @(\n", 99 | " @{\n", 100 | " \"entity\" = 'environment'\n", 101 | " \"required\" = $false\n", 102 | " }\n", 103 | " )\n", 104 | " },\n", 105 | " @{\n", 106 | " \"name\" = 'upstreamHost'\n", 107 | " \"schema\" = '{\"title\":\"host\",\"description\":\"Upstream server\",\"type\":\"string\"}'\n", 108 | " \"assignedTo\" = @(\n", 109 | " @{\n", 110 | " \"entity\" = 'api'\n", 111 | " \"required\" = $false\n", 112 | " }\n", 113 | " )\n", 114 | " },\n", 115 | " @{\n", 116 | " \"name\" = 'apiEnabled'\n", 117 | " \"schema\" = '{\"title\":\"apiEnabled\",\"description\":\"The API is enabled\",\"type\":\"boolean\"}'\n", 118 | " \"assignedTo\" = @(\n", 119 | " @{\n", 120 | " \"entity\" = 'api'\n", 121 | " \"required\" = $false\n", 122 | " }\n", 123 | " )\n", 124 | " },\n", 125 | " @{\n", 126 | " \"name\" = 'tags'\n", 127 | " \"schema\" = '{\"title\":\"tags\",\"description\":\"API tags\",\"type\":\"array\",\"items\":{\"type\":\"string\"}}'\n", 128 | " \"assignedTo\" = @(\n", 129 | " @{\n", 130 | " \"entity\" = 'api'\n", 131 | " \"required\" = $false\n", 132 | " }\n", 133 | " )\n", 134 | " },\n", 135 | " @{\n", 136 | " \"name\" = 'protocol'\n", 137 | " \"schema\" = '{\"title\":\"protocol\",\"description\":\"The API deployment protocol\",\"type\":\"boolean\"}'\n", 138 | " \"assignedTo\" = @(\n", 139 | " @{\n", 140 | " \"entity\" = 'deployment'\n", 141 | " \"required\" = $false\n", 142 | " }\n", 143 | " )\n", 144 | " } \n", 145 | ")\n", 146 | "\n", 147 | "\n", 148 | "# the following environment(s) will be created during the deployment\n", 149 | "$environments = @(\n", 150 | " @{\n", 151 | " \"title\" = 'dev'\n", 152 | " \"kind\" = 'development'\n", 153 | " \"description\" = 'Dev Environment'\n", 154 | " \"server\" = @{\n", 155 | " \"type\" = 'Kong API Gateway' \n", 156 | " \"managementPortalUri\" = 'https://localhost:8002/'\n", 157 | " }\n", 158 | " \"onboarding\" = @{\n", 159 | " \"developerPortalUri\" = ''\n", 160 | " \"instructions\" = ''\n", 161 | " }\n", 162 | " \"customProperties\" = @{ \n", 163 | " }\n", 164 | " }\n", 165 | ")\n", 166 | "\n", 167 | "\n", 168 | "\n", 169 | "Write-Output \"✅ Variables initialized ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n" 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "metadata": {}, 175 | "source": [ 176 | "### 1️⃣ Create the Azure Resource Group\n", 177 | "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": { 184 | "dotnet_interactive": { 185 | "language": "pwsh" 186 | }, 187 | "polyglot_notebook": { 188 | "kernelName": "pwsh" 189 | }, 190 | "vscode": { 191 | "languageId": "polyglot-notebook" 192 | } 193 | }, 194 | "outputs": [], 195 | "source": [ 196 | "$resourceGroupOutput = az group create --name $resourceGroupName --location $resourceGroupLocation\n", 197 | "\n", 198 | "if ($LASTEXITCODE -ne 0) {\n", 199 | " Write-Output $resourceGroupOutput\n", 200 | "} else {\n", 201 | " Write-Output \"✅ Azure Resource Grpup $resourceGroupName created ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 202 | "}" 203 | ] 204 | }, 205 | { 206 | "cell_type": "markdown", 207 | "metadata": {}, 208 | "source": [ 209 | "### 2️⃣ Create deployment using 🦾 Bicep\n", 210 | "\n", 211 | "This lab uses [Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": { 218 | "dotnet_interactive": { 219 | "language": "pwsh" 220 | }, 221 | "polyglot_notebook": { 222 | "kernelName": "pwsh" 223 | }, 224 | "vscode": { 225 | "languageId": "polyglot-notebook" 226 | } 227 | }, 228 | "outputs": [], 229 | "source": [ 230 | "$bicepParameters = @{\n", 231 | " \"`$schema\" = \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\"\n", 232 | " \"contentVersion\" = \"1.0.0.0\"\n", 233 | " \"parameters\" = @{\n", 234 | " \"apicResourceNamePrefix\" = @{ \"value\" = $apicResourceNamePrefix }\n", 235 | " \"apicResourceTags\" = @{ \"value\" = $apicResourceTags }\n", 236 | " \"apicMetadataSchema\" = @{ \"value\" = $metadata }\n", 237 | " \"apicEnvironments\" = @{ \"value\" = $environments }\n", 238 | " }\n", 239 | "}\n", 240 | "\n", 241 | "$bicepParametersJson = ConvertTo-Json -InputObject $bicepParameters -Depth 10\n", 242 | "Set-Content -Path \"params.json\" -Value $bicepParametersJson\n", 243 | "\n", 244 | "# Execute the Azure CLI command to create the deployment\n", 245 | "az deployment group create --name $deploymentName --resource-group $resourceGroupName --template-file \"main.bicep\" --parameters \"params.json\"\n", 246 | "\n" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "### 3️⃣ Get the deployment outputs\n", 254 | "\n", 255 | "We will set the `apicResourceName` variable with the value that was returned from the deployment " 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "dotnet_interactive": { 263 | "language": "pwsh" 264 | }, 265 | "polyglot_notebook": { 266 | "kernelName": "pwsh" 267 | }, 268 | "vscode": { 269 | "languageId": "polyglot-notebook" 270 | } 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "$deploymentOutput = az deployment group show --name $deploymentName -g $resourceGroupName --query properties.outputs.apicResourceName.value -o json\n", 275 | "if ($LASTEXITCODE -ne 0) {\n", 276 | " Write-Output $deploymentOutput\n", 277 | "} else {\n", 278 | " $apicResourceName = $deploymentOutput | ConvertFrom-Json\n", 279 | "}\n", 280 | "Write-Output \"👉🏻 API Center name: $apicResourceName\"" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "### 4️⃣ Update the environment metadata\n", 288 | "\n", 289 | "We will [update the enviroment](https://learn.microsoft.com/en-us/cli/azure/apic/environment?view=azure-cli-latest#az-apic-environment-update) with the Kong configuration" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": { 296 | "dotnet_interactive": { 297 | "language": "pwsh" 298 | }, 299 | "polyglot_notebook": { 300 | "kernelName": "pwsh" 301 | }, 302 | "vscode": { 303 | "languageId": "polyglot-notebook" 304 | } 305 | }, 306 | "outputs": [], 307 | "source": [ 308 | "$config = Invoke-RestMethod -Uri $kongAdminAPIUrl/ -Method Get\n", 309 | "$environmentCustomProperties = @{\n", 310 | " \"kongVersion\" = $config.version\n", 311 | " \"kongEdition\" = $config.edition\n", 312 | " \"konnectMode\" = $config.configuration.konnect_mode\n", 313 | "}\n", 314 | "\n", 315 | "$environmentCustomPropertiesJson = ConvertTo-Json -InputObject $environmentCustomProperties -Depth 10 -Compress\n", 316 | "\n", 317 | "az apic environment update -g $resourceGroupName -s $apicResourceName --environment-id \"dev\" `\n", 318 | " --custom-properties $environmentCustomPropertiesJson.replace('\"','\\\"')" 319 | ] 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "metadata": {}, 324 | "source": [ 325 | "### 5️⃣ Retrieves the Kong services and import into API Center\n", 326 | "\n", 327 | "It uses the [Kong Admin API](https://docs.konghq.com/gateway/latest/get-started/services-and-routes/) to retrieve the services and then the Azure CLI to import the APIs into API Center." 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "metadata": { 334 | "dotnet_interactive": { 335 | "language": "pwsh" 336 | }, 337 | "polyglot_notebook": { 338 | "kernelName": "pwsh" 339 | }, 340 | "vscode": { 341 | "languageId": "polyglot-notebook" 342 | } 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "\n", 347 | "$services = Invoke-RestMethod -Uri $kongAdminAPIUrl/services -Method Get\n", 348 | "\n", 349 | "foreach ($service in $services.data) {\n", 350 | " $apiCustomProperties = @{\n", 351 | " \"upstreamHost\" = $service.host\n", 352 | " \"apiEnabled\" = $service.enabled\n", 353 | " \"tags\" = $service.tags\n", 354 | " }\n", 355 | "\n", 356 | " $apiId = $service.name\n", 357 | " $apiName = $service.name\n", 358 | " $apiVersionId = \"1-0\"\n", 359 | " $apiVersionName = \"1.0\"\n", 360 | " $definitionId = \"openapi\"\n", 361 | "\n", 362 | " $apiCustomPropertiesJson = ConvertTo-Json -InputObject $apiCustomProperties -Depth 10 -Compress\n", 363 | " write-output \"👉🏻 Creating API $apiName\"\n", 364 | " az apic api create -g $resourceGroupName -s $apicResourceName --api-id $apiId --type REST `\n", 365 | " --title $apiName `\n", 366 | " --custom-properties $apiCustomPropertiesJson.replace('\"','\\\"')\n", 367 | "\n", 368 | " write-output \"👉🏻 Creating version $apiVersion of API $apiName\"\n", 369 | " az apic api version create -g $resourceGroupName -s $apicResourceName --api-id $apiId --version-id $apiVersionId `\n", 370 | " --title $apiVersionName --lifecycle-stage \"development\"\n", 371 | "\n", 372 | " write-output \"👉🏻 Creating definition for version $apiVersion of API $apiName\"\n", 373 | " az apic api definition create -g $resourceGroupName -s $apicResourceName --api-id $apiId `\n", 374 | " --version-id $apiVersionId --definition-id $definitionId --title \"OpenAPI\" --description \"OpenAPI spec\" \n", 375 | "\n", 376 | " $deploymentCustomProperties = @{\n", 377 | " \"protocol\" = $service.protocol\n", 378 | " }\n", 379 | " \n", 380 | " $deploymentCustomPropertiesJson = ConvertTo-Json -InputObject $deploymentCustomProperties -Depth 10 -Compress\n", 381 | " write-output \"👉🏻 Creating deployment for the API $apiName\"\n", 382 | " az apic api deployment create -g $resourceGroupName -s $apicResourceName --deployment-id \"deployment\" `\n", 383 | " --title \"Development deployment\" --description \"Development deployment.\" --api-id $apiId `\n", 384 | " --environment-id \"/workspaces/default/environments/dev\" `\n", 385 | " --definition-id \"/workspaces/default/apis/another-petstore/versions/$apiVersionId/definitions/$definitionId\" `\n", 386 | " --server '{\\\"runtimeUri\\\":[\\\"http://localhost:8000\\\"]}' `\n", 387 | " --custom-properties $deploymentCustomPropertiesJson.replace('\"','\\\"')\n", 388 | "\n", 389 | "\n", 390 | "}" 391 | ] 392 | }, 393 | { 394 | "cell_type": "markdown", 395 | "metadata": {}, 396 | "source": [ 397 | "### 6️⃣ Discover the APIs that were just imported\n", 398 | "\n", 399 | "You can discover the APIs with fhe following methods:\n", 400 | "- With the Azure Portal\n", 401 | "- With the [self-hosted API Center Portal](https://learn.microsoft.com/en-us/azure/api-center/enable-api-center-portal)\n", 402 | "- With the [VS Code extension](https://learn.microsoft.com/en-us/azure/api-center/use-vscode-extension-copilot) that is integrated with GitHub Copilot Chat.\n", 403 | "- With the CLI, the service REST API and more\n", 404 | "\n", 405 | "Here we will use the [list command](https://learn.microsoft.com/en-us/cli/azure/apic/api?view=azure-cli-latest#az-apic-api-list) to display the APIs that we have just imported. \n" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": null, 411 | "metadata": { 412 | "dotnet_interactive": { 413 | "language": "pwsh" 414 | }, 415 | "polyglot_notebook": { 416 | "kernelName": "pwsh" 417 | }, 418 | "vscode": { 419 | "languageId": "polyglot-notebook" 420 | } 421 | }, 422 | "outputs": [], 423 | "source": [ 424 | "az apic api list -g $resourceGroupName -s $apicResourceName --query \"[].{Name:name, Title:title, Kind:kind, ContactEmail:contacts[0].email}\" -o table" 425 | ] 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "metadata": {}, 430 | "source": [ 431 | "### 🗑️ Clean up resources\n", 432 | "\n", 433 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.\n", 434 | "Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that." 435 | ] 436 | } 437 | ], 438 | "metadata": { 439 | "kernelspec": { 440 | "display_name": "Python 3", 441 | "language": "python", 442 | "name": "python3" 443 | }, 444 | "language_info": { 445 | "codemirror_mode": { 446 | "name": "ipython", 447 | "version": 3 448 | }, 449 | "file_extension": ".py", 450 | "mimetype": "text/x-python", 451 | "name": "python", 452 | "nbconvert_exporter": "python", 453 | "pygments_lexer": "ipython3", 454 | "version": "3.11.9" 455 | } 456 | }, 457 | "nbformat": 4, 458 | "nbformat_minor": 2 459 | } 460 | -------------------------------------------------------------------------------- /labs/import-from-kong/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-mulesoft/README.MD: -------------------------------------------------------------------------------- 1 | # API Center ❤️ all APIs 2 | 3 | ## Import from MuleSoft API Manager 4 | ![image](../../images/import-from-mulesoft.png) 5 | 6 | Playground to experiment importing APIs from the MuleSoft Anypoint platform. We start by creating an API Center instance using [Bicep resource definition](https://learn.microsoft.com/en-us/azure/templates/microsoft.apicenter/services?pivots=deployment-language-bicep) and then we will use the [Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/) to export the APIs and the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) to import the APIs into API Center. 7 | 8 | 💡 Every step outlined below leverages the power of PowerShell scripts. This is designed so you can seamlessly integrate them into your automation workflows, CI/CD pipelines, webhooks, and more. 9 | 10 | ### Learning Objectives - Upon completing this lab, you should be able to: 11 | - Deploy Azure API Center using Bicep. 12 | - Configure the API Center metadata scheme for APIs, Environments and Deployments. 13 | - Understand the Azure CLI commands to manage Azure API Center. [Full list of commands available here](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest). 14 | - Create an enviroment with custom metadata properties 15 | - Register an API using the OpenAPI spec as the source of truth and assign API metadata properties. 16 | - Register an API with individual commands to have full control over all the properties. 17 | - Search and discover the APIs registered in API Center. 18 | 19 | ### Prerequisites 20 | - Install or update to the latest [.NET 8 SDK](https://dotnet.microsoft.com/en-us/download) 21 | - Install or update to the latest [Visual Studio Code](https://code.visualstudio.com/) 22 | - Install the [Polyglot Notebooks extension](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.dotnet-interactive-vscode) from the VS Code marketplace 23 | - Install or update to the latest [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell) 24 | - Install or update to the latest [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). The Azure API Center extension will automatically install the first time you run an [az apic](https://learn.microsoft.com/en-us/cli/azure/apic?view=azure-cli-latest) command. 25 | - [An Azure Subscription](https://azure.microsoft.com/en-us/free/) with Contributor permissions 26 | - [Sign in to Azure with Azure CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-interactively) 27 | - [Install and configure the MuleSoft Anypoint Platform CLI](https://docs.mulesoft.com/anypoint-cli/latest/) 28 | 29 | ### 🚀 Get started 30 | Proceed by opening the [Jupyter notebook](import-from-generic-openapi.ipynb), and follow the steps provided. 31 | 32 | ### 🗑️ Clean up resources 33 | When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered. 34 | Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that. -------------------------------------------------------------------------------- /labs/import-from-mulesoft/account_environment_list.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "environment-id1", 4 | "name": "Design", 5 | "organizationId": "organizationid-guid", 6 | "isProduction": false, 7 | "type": "design", 8 | "clientId": "clientid-guid", 9 | "arcNamespace": null 10 | }, 11 | { 12 | "id": "environment-id2", 13 | "name": "Sandbox", 14 | "organizationId": "organizationid-guid", 15 | "isProduction": false, 16 | "type": "sandbox", 17 | "clientId": "clientid2-guid", 18 | "arcNamespace": null 19 | } 20 | ] -------------------------------------------------------------------------------- /labs/import-from-mulesoft/api-mgr_api_list.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "audit": { 4 | "created": { 5 | "date": "2024-05-03T09:49:53.908Z" 6 | }, 7 | "updated": {} 8 | }, 9 | "masterOrganizationId": "5c887b3a-13a5-4808-97ae-2fae71667035", 10 | "organizationId": "5c887b3a-13a5-4808-97ae-2fae71667035", 11 | "id": 19461143, 12 | "instanceLabel": null, 13 | "groupId": "5c887b3a-13a5-4808-97ae-2fae71667035", 14 | "assetId": "petstore", 15 | "assetVersion": "1.0.0", 16 | "productVersion": "v1", 17 | "description": null, 18 | "tags": [], 19 | "order": 1, 20 | "providerId": null, 21 | "deprecated": false, 22 | "lastActiveDate": "2024-05-03T12:37:12.354Z", 23 | "endpointUri": null, 24 | "environmentId": "e66fe03d-f76e-41eb-8b6e-cc5456e11466", 25 | "isPublic": false, 26 | "stage": "release", 27 | "technology": "mule4", 28 | "status": "active", 29 | "deployment": { 30 | "audit": { 31 | "created": {}, 32 | "updated": {} 33 | }, 34 | "applicationId": "26f72364-8300-4c74-b706-5a7d172a6aa6", 35 | "targetId": "cloudhub-us-east-2", 36 | "expectedStatus": "deployed" 37 | }, 38 | "lastActiveDelta": 48, 39 | "pinned": false, 40 | "activeContractsCount": 0, 41 | "autodiscoveryInstanceName": "v1:19461143" 42 | } 43 | ] -------------------------------------------------------------------------------- /labs/import-from-mulesoft/clean-up-resources.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### 🗑️ Clean up resources\n", 8 | "\n", 9 | "When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": { 16 | "dotnet_interactive": { 17 | "language": "pwsh" 18 | }, 19 | "polyglot_notebook": { 20 | "kernelName": "pwsh" 21 | }, 22 | "vscode": { 23 | "languageId": "polyglot-notebook" 24 | } 25 | }, 26 | "outputs": [], 27 | "source": [ 28 | "$deploymentName = Split-Path -Path (Get-Location) -Leaf\n", 29 | "$resourceGroupName = \"lab-$deploymentName\"\n", 30 | "\n", 31 | "$deleteOutput = az group delete --name $resourceGroupName -y\n", 32 | "if ($LASTEXITCODE -ne 0) {\n", 33 | " Write-Output $deleteOutput\n", 34 | "} else {\n", 35 | " Write-Output \"✅ Resource group $resourceGroupName deleted ⌚ $(Get-Date -Format 'HH:mm:ss')\"\n", 36 | "}\n" 37 | ] 38 | } 39 | ], 40 | "metadata": { 41 | "kernelspec": { 42 | "display_name": "Python 3", 43 | "language": "python", 44 | "name": "python3" 45 | }, 46 | "language_info": { 47 | "codemirror_mode": { 48 | "name": "ipython", 49 | "version": 3 50 | }, 51 | "file_extension": ".py", 52 | "mimetype": "text/x-python", 53 | "name": "python", 54 | "nbconvert_exporter": "python", 55 | "pygments_lexer": "ipython3", 56 | "version": "3.11.9" 57 | } 58 | }, 59 | "nbformat": 4, 60 | "nbformat_minor": 2 61 | } 62 | -------------------------------------------------------------------------------- /labs/import-from-mulesoft/main.bicep: -------------------------------------------------------------------------------- 1 | 2 | @description('The prefix name of the API Center resource') 3 | param apicResourceNamePrefix string 4 | 5 | @description('Location for the API Center resource') 6 | param apicResourceLocation string = resourceGroup().location 7 | 8 | @description('Tags for the API Center resource') 9 | param apicResourceTags object 10 | 11 | @description('API Center Metadata Schema') 12 | param apicMetadataSchema array = [] 13 | 14 | @description('API Center Environments') 15 | param apicEnvironments array = [] 16 | 17 | 18 | var resourceSuffix = uniqueString(subscription().id, resourceGroup().id) 19 | 20 | resource apic 'Microsoft.ApiCenter/services@2024-03-01' = { 21 | name: '${apicResourceNamePrefix}-${resourceSuffix}' 22 | location: apicResourceLocation 23 | tags: apicResourceTags 24 | identity: { 25 | type: 'SystemAssigned' 26 | } 27 | } 28 | 29 | resource apicMetadata 'Microsoft.ApiCenter/services/metadataSchemas@2024-03-01' = [for metadata in apicMetadataSchema: { 30 | name: metadata.name 31 | parent: apic 32 | properties: { 33 | schema: metadata.schema 34 | assignedTo: [for assignedTo in metadata.assignedTo: { 35 | deprecated: false 36 | entity: assignedTo.entity 37 | required: assignedTo.required 38 | } 39 | ] 40 | } 41 | }] 42 | 43 | resource apicWorkspace 'Microsoft.ApiCenter/services/workspaces@2024-03-01' existing = { 44 | name: 'default' 45 | parent: apic 46 | } 47 | 48 | resource symbolicname 'Microsoft.ApiCenter/services/workspaces/environments@2024-03-01' = [for environment in apicEnvironments: { 49 | name: environment.title 50 | parent: apicWorkspace 51 | properties: { 52 | customProperties: environment.customProperties 53 | description: environment.description 54 | kind: environment.kind 55 | onboarding: { 56 | developerPortalUri: [ 57 | environment.onboarding.developerPortalUri 58 | ] 59 | instructions: environment.onboarding.instructions 60 | } 61 | server: { 62 | managementPortalUri: [ 63 | environment.server.managementPortalUri 64 | ] 65 | type: environment.server.type 66 | } 67 | title: environment.title 68 | } 69 | }] 70 | 71 | output apicResourceId string = apic.id 72 | output apicResourceName string = apic.name 73 | output apicResourcePrincipalId string = apic.identity.principalId 74 | 75 | -------------------------------------------------------------------------------- /labs/import-from-mulesoft/runtime-mgr-application_describe.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "26f72364-8300-4c74-b706-5a7d172a6aa6", 3 | "name": "proxyapp", 4 | "creationDate": 1714729803866, 5 | "lastModifiedDate": 1714733433281, 6 | "target": { 7 | "provider": "MC", 8 | "targetId": "cloudhub-us-east-2", 9 | "deploymentSettings": { 10 | "http": { 11 | "inbound": { 12 | "publicUrl": "https://proxyapp-ojrtol.5sc6y6-3.usa-e2.cloudhub.io", 13 | "lastMileSecurity": false, 14 | "forwardSslSession": false 15 | } 16 | }, 17 | "runtimeVersion": "4.6.2:5e-java8", 18 | "runtimeReleaseChannel": "EDGE", 19 | "disableAmLogForwarding": false, 20 | "anypointMonitoringScope": "app", 21 | "sidecars": { 22 | "anypoint-monitoring": { 23 | "image": "auto", 24 | "resources": { 25 | "cpu": { 26 | "limit": "50m", 27 | "reserved": "0m" 28 | }, 29 | "memory": { 30 | "limit": "50Mi", 31 | "reserved": "50Mi" 32 | } 33 | } 34 | } 35 | }, 36 | "runtime": { 37 | "version": "4.6.2:5e-java8", 38 | "releaseChannel": "EDGE", 39 | "java": "8" 40 | } 41 | }, 42 | "replicas": 1 43 | }, 44 | "status": "APPLIED", 45 | "application": { 46 | "status": "RUNNING", 47 | "desiredState": "STARTED", 48 | "ref": { 49 | "groupId": "5c887b3a-13a5-4808-97ae-2fae71667035", 50 | "artifactId": "petstore-api-gateway-sample-rest-proxy", 51 | "version": "1.0.0-3.2.0", 52 | "packaging": "jar" 53 | }, 54 | "configuration": { 55 | "mule.agent.application.properties.service": { 56 | "applicationName": "proxyapp", 57 | "properties": { 58 | "anypoint.platform.analytics_base_uri": "https://analytics-ingest.anypoint.mulesoft.com", 59 | "proxy.port": "8081", 60 | "api.version": "v1:19461143", 61 | "proxy.path": "/*", 62 | "implementation.port": "443", 63 | "implementation.api.parser": "AUTO", 64 | "api.name": "groupId:5c887b3a-13a5-4808-97ae-2fae71667035:assetId:petstore", 65 | "anypoint.platform.base_uri": "https://anypoint.mulesoft.com", 66 | "api.id": "19461143", 67 | "implementation.host": "petstore3.swagger.io", 68 | "anypoint.platform.client_id": "d5e19b6219494ed984d592ae13471039", 69 | "validation.strict.queryParams": "false", 70 | "implementation.protocol": "HTTPS", 71 | "validation.disable": "true", 72 | "validation.strict.headers": "false", 73 | "implementation.path": "/api/v3", 74 | "proxy.responseTimeout": "10000" 75 | }, 76 | "secureProperties": { 77 | "anypoint.platform.client_secret": "******" 78 | } 79 | } 80 | }, 81 | "vCores": 0.1 82 | }, 83 | "desiredVersion": "6ea98620-58e8-408b-a23d-098fc4b03f4b", 84 | "replicas": [ 85 | { 86 | "id": "proxyapp-6ffccd7759-jdzz8", 87 | "state": "STARTED", 88 | "deploymentLocation": "cloudhub-us-east-2", 89 | "currentDeploymentVersion": "6ea98620-58e8-408b-a23d-098fc4b03f4b", 90 | "reason": "" 91 | } 92 | ], 93 | "lastSuccessfulVersion": "6ea98620-58e8-408b-a23d-098fc4b03f4b" 94 | } -------------------------------------------------------------------------------- /tools/delete-all-apis.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Tool: delete all APIs\n", 8 | "\n" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "### 0️⃣ Initialize notebook variables\n", 16 | "\n" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": null, 22 | "metadata": { 23 | "dotnet_interactive": { 24 | "language": "pwsh" 25 | }, 26 | "polyglot_notebook": { 27 | "kernelName": "pwsh" 28 | }, 29 | "vscode": { 30 | "languageId": "polyglot-notebook" 31 | } 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "$resourceGroupName = \"\"\n", 36 | "$apicResourceName = \"\"\n" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": { 43 | "dotnet_interactive": { 44 | "language": "pwsh" 45 | }, 46 | "polyglot_notebook": { 47 | "kernelName": "pwsh" 48 | }, 49 | "vscode": { 50 | "languageId": "polyglot-notebook" 51 | } 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "$apiListJson = az apic api list -g $resourceGroupName -n $apicResourceName\n", 56 | "\n", 57 | "$apiList = $apiListJson | ConvertFrom-Json\n", 58 | "foreach ($api in $apiList) {\n", 59 | " $apiName = $api.name\n", 60 | " Write-Output \"👉🏻 Deleting: $apiName\"\n", 61 | " az apic api delete -g $resourceGroupName -n $apicResourceName -y --api-id=$apiName\n", 62 | "}\n" 63 | ] 64 | } 65 | ], 66 | "metadata": { 67 | "kernelspec": { 68 | "display_name": ".NET (C#)", 69 | "language": "C#", 70 | "name": ".net-csharp" 71 | }, 72 | "language_info": { 73 | "codemirror_mode": { 74 | "name": "ipython", 75 | "version": 3 76 | }, 77 | "file_extension": ".py", 78 | "mimetype": "text/x-python", 79 | "name": "python", 80 | "nbconvert_exporter": "python", 81 | "pygments_lexer": "ipython3", 82 | "version": "3.11.9" 83 | }, 84 | "polyglot_notebook": { 85 | "kernelInfo": { 86 | "defaultKernelName": "csharp", 87 | "items": [ 88 | { 89 | "aliases": [], 90 | "name": "csharp" 91 | } 92 | ] 93 | } 94 | } 95 | }, 96 | "nbformat": 4, 97 | "nbformat_minor": 2 98 | } 99 | --------------------------------------------------------------------------------