Conversation
- Replace hardcoded .kusto.windows.net with environment-aware lookup map covering AzureCloud, AzureUSGovernment, AzureChinaCloud with fallback heuristic for unknown clouds - Fix China ADX suffix: kusto.windows.cn (not kusto.chinacloudapi.cn) - Add openDataBaseUrl parameter for sovereign open-data ingestion (main.bicep → hub.bicep → Analytics/app.bicep) - Auto-skip ADF GitHub resources when open data is local storage - Fix createUiDefinition regex to accept all cloud storage suffixes - Replace 27 hardcoded portal.azure.com URLs in dashboard.json with build-time variable token - Add -PortalUrl parameter to Build-Toolkit.ps1 - Clear hardcoded clusterUri in dashboard.json (user configures post-import) - Fix gitapp.hub.com typo in ADF linked service URL - Add SOVEREIGN-CLOUD-GUIDE.md: deployment workflow, suffix inventory, prerequisites, verified against Microsoft Learn docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add deploy-sovereign.md: Microsoft Learn how-to guide for sovereign cloud deployments (US Government, China, other sovereign environments) - deploy-sovereign.md follows deploy.md conventions: front matter, tab selectors, admonitions, nextstepaction blocks, related content Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| - Data Explorer SKU and retention settings are now only visible when Azure Data Explorer mode is selected. | ||
| - Added typed metadata contracts between hub apps to formalize dependency management and enable compile-time verification of inter-app interfaces. | ||
| - **Added** | ||
| - Added sovereign cloud deployment support for Azure US Government, Azure China (21Vianet), and other sovereign environments ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)). |
There was a problem hiding this comment.
| - Added sovereign cloud deployment support for Azure US Government, Azure China (21Vianet), and other sovereign environments ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)). | |
| - Added sovereign cloud deployment support for Azure Government, Azure China, and other [Microsoft Sovereign Cloud](/industry/sovereign-cloud/overview/microsoft-sovereign-cloud) environments ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)). |
| - Remote Hub configuration (storage URI, storage key, and purge protection) is now displayed in the Basics tab when Remote Hub mode is selected, making the mutual exclusivity clear. | ||
| - Data Explorer SKU and retention settings are now only visible when Azure Data Explorer mode is selected. | ||
| - Added typed metadata contracts between hub apps to formalize dependency management and enable compile-time verification of inter-app interfaces. | ||
| - **Added** |
There was a problem hiding this comment.
Added should go above Changed
|
|
||
| # How to deploy FinOps hubs to sovereign clouds | ||
|
|
||
| This article explains how to deploy FinOps hubs to sovereign Azure clouds, including Azure US Government, Azure China (21Vianet), and other sovereign environments. Bicep's `environment()` function compiles to an ARM runtime expression that resolves in the target cloud, so templates built on any workstation deploy correctly to any cloud. No cross-compilation is needed. This article helps you: |
There was a problem hiding this comment.
Aligning to official terms...
| This article explains how to deploy FinOps hubs to sovereign Azure clouds, including Azure US Government, Azure China (21Vianet), and other sovereign environments. Bicep's `environment()` function compiles to an ARM runtime expression that resolves in the target cloud, so templates built on any workstation deploy correctly to any cloud. No cross-compilation is needed. This article helps you: | |
| This article explains how to deploy FinOps hubs to [Microsoft Sovereign Clouds](/industry/sovereign-cloud/overview/microsoft-sovereign-cloud), including Azure Government, Azure China, and other sovereign environments. Bicep's `environment()` function compiles to an ARM runtime expression that resolves in the target cloud, so templates built on any workstation deploy correctly to any cloud. No cross-compilation is needed. This article helps you: |
|
|
||
| # How to deploy FinOps hubs to sovereign clouds | ||
|
|
||
| This article explains how to deploy FinOps hubs to sovereign Azure clouds, including Azure US Government, Azure China (21Vianet), and other sovereign environments. Bicep's `environment()` function compiles to an ARM runtime expression that resolves in the target cloud, so templates built on any workstation deploy correctly to any cloud. No cross-compilation is needed. This article helps you: |
There was a problem hiding this comment.
Given this is end user documentation, I don't think we need to call out the Bicep caveat.
| | Cloud | Environment name | Portal URL | Status | | ||
| |-------|-----------------|------------|--------| | ||
| | Azure Commercial | `AzureCloud` | `portal.azure.com` | ✅ Fully supported | | ||
| | Azure US Government | `AzureUSGovernment` | `portal.azure.us` | ✅ Fully supported | | ||
| | Azure China (21Vianet) | `AzureChinaCloud` | `portal.azure.cn` | ✅ Fully supported | | ||
| | Other sovereign clouds | *(verify with your environment)* | *(verify with your environment)* | ⚠️ Supported with parameter overrides | |
There was a problem hiding this comment.
Where is the system of record for "Environment name"? We don't include "US" in Azure Gov, so I'm questioning that column. What is the purpose of that column at all? How will it be used? I would recomment getting rid of it unless we explicitly need it.
| | Cloud | Environment name | Portal URL | Status | | |
| |-------|-----------------|------------|--------| | |
| | Azure Commercial | `AzureCloud` | `portal.azure.com` | ✅ Fully supported | | |
| | Azure US Government | `AzureUSGovernment` | `portal.azure.us` | ✅ Fully supported | | |
| | Azure China (21Vianet) | `AzureChinaCloud` | `portal.azure.cn` | ✅ Fully supported | | |
| | Other sovereign clouds | *(verify with your environment)* | *(verify with your environment)* | ⚠️ Supported with parameter overrides | | |
| | Cloud | Portal URL | Status | | |
| |-------|------------|--------| | |
| | Azure Commercial | `portal.azure.com` | ✅ Fully supported | | |
| | Azure Government | `portal.azure.us` | ✅ Fully supported | | |
| | Azure China | `portal.azure.cn` | ✅ Fully supported | | |
| | Others | *(verify with your environment)* | ⚠️ Supported with parameter overrides | |
Fwiw, I don't actually know what value this table brings. Everything is supported the same way, right?
| @description('Optional. Base URL to use for FinOps Toolkit open data CSV files. Override this to point to a hub storage path when the CSV files are pre-loaded into the hub storage account. Default: The current FinOps Toolkit GitHub open-data path for this build.') | ||
| param openDataBaseUrl string = contains(loadTextContent('modules/fx/ftkver.txt'), '-dev') | ||
| ? 'https://raw.githubusercontent.com/microsoft/finops-toolkit/refs/heads/dev/src/open-data' | ||
| : 'https://raw.githubusercontent.com/microsoft/finops-toolkit/refs/tags/${loadTextContent('modules/fx/ftktag.txt')}/src/open-data' |
There was a problem hiding this comment.
Let's simplify this. If we want to offer deploying to storage, then let's just make that a boolean. This just makes it more difficult to set it up by requiring people to find the URL.
| @description('Optional. Base URL to use for FinOps Toolkit open data CSV files. Override this to point to a hub storage path when the CSV files are pre-loaded into the hub storage account. Default: The current FinOps Toolkit GitHub open-data path for this build.') | ||
| param openDataBaseUrl string = contains(loadTextContent('modules/fx/ftkver.txt'), '-dev') | ||
| ? 'https://raw.githubusercontent.com/microsoft/finops-toolkit/refs/heads/dev/src/open-data' | ||
| : 'https://raw.githubusercontent.com/microsoft/finops-toolkit/refs/tags/${loadTextContent('modules/fx/ftktag.txt')}/src/open-data' |
There was a problem hiding this comment.
Roland has raise a concern about how these files aren't getting updated over time. We should consider that before we make a substantive change to how we ingest the data to ensure we're accounting for keeping them updated for people. Maybe a separate deployment/app?
| // GitHub repository linked service for FTK open data | ||
| resource linkedService_ftkRepo 'Microsoft.DataFactory/factories/linkedservices@2018-06-01' = { | ||
| // GitHub repository linked service for FTK release files | ||
| resource linkedService_ftkRepo 'Microsoft.DataFactory/factories/linkedservices@2018-06-01' = if (!useLocalOpenData) { |
There was a problem hiding this comment.
Should we just always push the files to storage rather than using GitHub as the source? I prefer not from a cost perspective, but that would simplify this by only offering one approach.
| - **Added** | ||
| - Added sovereign cloud deployment support for Azure US Government, Azure China (21Vianet), and other sovereign environments ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)). | ||
| - Added `openDataBaseUrl` parameter to support open-data ingestion from a local storage account in sovereign environments without internet access. | ||
| - Added `-PortalUrl` parameter to `Build-Toolkit.ps1` for sovereign cloud dashboard feedback links. |
There was a problem hiding this comment.
nit: Do internal build script changes go into the changelog? 🤔 Not opposed to it. But it's a level of detail our customers generally shouldn't need.
| - Fixed incorrect China ADX DNS suffix derivation (`kusto.chinacloudapi.cn` → `kusto.windows.cn`). | ||
| - Fixed `createUiDefinition.json` storage URL validation to accept all cloud storage suffixes. |
There was a problem hiding this comment.
As far as I can tell, these changes sound like AI fixes within the PR, not fixing something that was already there.
| - Fixed incorrect China ADX DNS suffix derivation (`kusto.chinacloudapi.cn` → `kusto.windows.cn`). | |
| - Fixed `createUiDefinition.json` storage URL validation to accept all cloud storage suffixes. |
|
@@MSBrett: you have some new feedback! Please review and resolve all comments and I'll let reviewers know by removing the |
flanakin
left a comment
There was a problem hiding this comment.
🤖 [AI][Claude] PR Review
Summary: Well-structured sovereign cloud support with clean Kusto DNS suffix handling, proper conditional resource deployment, and thorough documentation. One minor suggestion below.
💡 Suggestions (1)
ftkGitTagvariable is now only consumed by the conditionaldataset_ftkReleaseFileresource — consider adding a comment noting this dependency.
| @@ -135,15 +140,22 @@ var HUB_DB = 'Hub' | |||
| var INGESTION_DB = 'Ingestion' | |||
|
|
|||
| var ftkGitTag = loadTextContent('../../fx/ftktag.txt') // cSpell:ignore ftktag | |||
There was a problem hiding this comment.
🤖 [AI][Claude] 💡 Suggestion
With the ftkReleaseUri refactor, ftkGitTag is now only consumed by dataset_ftkReleaseFile (line 667), which is gated behind !useLocalOpenData. When deploying with local open data, this variable becomes unused dead code. Consider adding a brief comment noting the conditional dependency, e.g.:
| var ftkGitTag = loadTextContent('../../fx/ftktag.txt') // cSpell:ignore ftktag | |
| var ftkGitTag = loadTextContent('../../fx/ftktag.txt') // cSpell:ignore ftktag // Only used by ftkReleaseFile dataset when !useLocalOpenData |
Summary
Adds sovereign cloud support to FinOps Hubs, enabling deployment to Azure US Government, Azure China (21Vianet), and other sovereign environments.
Changes
Bicep template changes (
src/templates/finops-hub/).kusto.windows.netwith an environment-aware lookup map covering AzureCloud, AzureUSGovernment, and AzureChinaCloud, with areplace()fallback heuristic for unknown clouds. Fixes an incorrect China suffix (kusto.chinacloudapi.cn→kusto.windows.cn).openDataBaseUrlparameter (threaded throughmain.bicep→hub.bicep→Analytics/app.bicep) so sovereign environments without internet access can point to a local storage account instead of GitHub.openDataBaseUrlpoints to the hub's own storage account.createUiDefinition.jsonregex to accept storage suffixes from all clouds (not just.windows.net).portal.azure.comURLs indashboard.jsonwith a build-time$$defined-portal-url$$token.clusterUri— users configure it to their cluster after import.-PortalUrlparameter toBuild-Toolkit.ps1(defaults tohttps://portal.azure.com).gitapp.hub.comtypo in ADF linked service URL →github.com.Documentation (
docs-mslearn/toolkit/hubs/)deploy-sovereign.md: New Microsoft Learn how-to guide covering build, open-data preparation, deployment, and dashboard configuration for sovereign clouds. Followsdeploy.mdconventions (front matter, tab selectors, admonitions, related content).Testing
bicep build main.bicep).kusto.windows.net,portal.azure.com,logic.azure.com, orgitapp.hub.comin changed filesChecklist
src/templates/finops-hub/onlydeploy-sovereign.mdmatchesdeploy.mdformat conventions