Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -373,3 +373,7 @@ env/

# Auto-generated build artifacts
src/templates/finops-hub-copilot-studio/knowledge/query-catalog.md
.gate/
todo/
done/
release/scloud-occurrence-report.md
7 changes: 6 additions & 1 deletion docs-mslearn/toolkit/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: FinOps toolkit changelog
description: Review the latest features and enhancements in the FinOps toolkit, including updates to FinOps hubs, Power BI reports, and more.
author: MSBrett
ms.author: brettwil
ms.date: 04/04/2026
ms.date: 04/06/2026
ms.topic: reference
ms.service: finops
ms.subservice: finops-toolkit
Expand Down Expand Up @@ -54,13 +54,18 @@ _Released March 2026_
### [FinOps hubs](hubs/finops-hubs-overview.md) v14

- **Added**
- Added [Microsoft Sovereign Cloud](/azure/azure-sovereign-clouds/microsoft-sovereign-cloud) support with environment-aware DNS suffix handling for Azure Government, Azure China, and other sovereign environments ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)).
- Added [Copilot Studio agent template](hubs/configure-ai-copilot-studio.md) with instructions, schema reference, query catalog, and weekly report guide for creating a FinOps Hub Agent in Microsoft Copilot Studio using the Kusto Query MCP Server.
- **Changed**
- Improved deployment UI to consolidate hub mode selection into a single radio button group with four mutually exclusive options: None (storage only for Power BI reports), Azure Data Explorer, Microsoft Fabric, or Remote Hub ([#1929](https://github.com/microsoft/finops-toolkit/issues/1929)).
- 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.
- **Fixed**
- Fixed hardcoded Kusto DNS suffix to use an environment-aware lookup map with correct values for all supported clouds ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)).
- Fixed incorrect Azure China ADX DNS suffix (`kusto.chinacloudapi.cn` → `kusto.windows.cn`) ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)).
- Fixed `createUiDefinition.json` storage URL validation to accept sovereign cloud storage suffixes ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)).
- Fixed `gitapp.hub.com` typo in ADF linked service URL ([#2072](https://github.com/microsoft/finops-toolkit/pull/2072)).
- Fixed Init-DataFactory deployment script failing when an Event Grid subscription is already provisioning by checking subscription status before attempting subscribe/unsubscribe and polling separately for completion ([#1996](https://github.com/microsoft/finops-toolkit/issues/1996)).
- Added row count check in `msexports_ExecuteETL` pipeline to fix error when export files have no rows ([#1535](https://github.com/microsoft/finops-toolkit/issues/1535)).

Expand Down
6 changes: 3 additions & 3 deletions src/templates/finops-hub/createUiDefinition.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@
"name": "remoteHubStorageUri",
"type": "Microsoft.Common.TextBox",
"label": "Remote hub storage URI",
"toolTip": "Data Lake storage endpoint from the remote hub storage account. Copy from the storage account Settings > Endpoints > Data Lake storage. Example: https://myremotehub.dfs.core.windows.net/",
"toolTip": "Data Lake storage endpoint from the remote hub storage account. Copy from the storage account Settings > Endpoints > Data Lake storage. Example: https://myremotehub.dfs.core.windows.net/ (endpoint suffix varies by cloud)",
"constraints": {
"required": "[equals(basics('analyticsBackend').analyticsEngine, 'remote')]",
"regex": "^https://.*\\.dfs\\.core\\.windows\\.net/?$",
"validationMessage": "Must be a valid Data Lake storage endpoint URL in the format: https://storageaccount.dfs.core.windows.net/"
"regex": "^https://.*\\.dfs\\.core\\.[a-z.]+/?$",
"validationMessage": "Must be a valid Data Lake storage endpoint URL (e.g., https://storageaccount.dfs.core.windows.net/ for Azure public cloud)"
},
"visible": "[equals(basics('analyticsBackend').analyticsEngine, 'remote')]"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,13 @@ var useFabric = !empty(fabricQueryUri)
var useAzure = !useFabric && !empty(clusterName)

// cSpell:ignore ftkver, privatelink
var dataExplorerPrivateDnsZoneName = replace('privatelink.${app.hub.location}.${replace(environment().suffixes.storage, 'core', 'kusto')}', '..', '.')
var dataExplorerDnsSuffixLookup = {
AzureCloud: 'kusto.windows.net'
AzureUSGovernment: 'kusto.usgovcloudapi.net'
AzureChinaCloud: 'kusto.windows.cn'
}
var dataExplorerDnsSuffix = dataExplorerDnsSuffixLookup[?environment().name] ?? replace(environment().suffixes.storage, 'core', 'kusto')
var dataExplorerPrivateDnsZoneName = replace('privatelink.${app.hub.location}.${dataExplorerDnsSuffix}', '..', '.')

// Actual = Minimum(ClusterMaximumConcurrentOperations, Number of nodes in cluster * Maximum(1, Core count per node * CoreUtilizationCoefficient))
var ingestionCapacity = {
Expand Down Expand Up @@ -219,7 +225,7 @@ var dataExplorerIngestionCapacity = useFabric

// WORKAROUND: Direct property access fails on cluster updates due to ARM bug
// See: https://github.com/Azure/azure-resource-manager-templates/issues/[issue-number]
var dataExplorerUri = useFabric ? fabricQueryUri : 'https://${cluster.name}.${app.hub.location}.kusto.windows.net'
var dataExplorerUri = useFabric ? fabricQueryUri : 'https://${cluster.name}.${app.hub.location}.${dataExplorerDnsSuffix}'

//==============================================================================
// Resources
Expand Down Expand Up @@ -546,7 +552,7 @@ resource dataFactoryVNet 'Microsoft.DataFactory/factories/managedVirtualNetworks
#disable-next-line BCP318 // Null safety warning for conditional resource access // Null safety warning for conditional resource access // Null safety warning for conditional resource access
privateLinkResourceId: cluster.id
fqdns: [
'https://${replace(clusterName, '_', '-')}.${app.hub.location}.kusto.windows.net'
'https://${replace(clusterName, '_', '-')}.${app.hub.location}.${dataExplorerDnsSuffix}'
]
}
}
Expand Down Expand Up @@ -594,19 +600,14 @@ resource linkedService_dataExplorer 'Microsoft.DataFactory/factories/linkedservi
}
}

// GitHub repository linked service for FTK open data
// GitHub repository linked service for FTK release files
resource linkedService_ftkRepo 'Microsoft.DataFactory/factories/linkedservices@2018-06-01' = {
name: 'ftkRepo'
parent: dataFactory
properties: {
type: 'HttpServer'
parameters: {
filePath: {
type: 'string'
}
}
typeProperties: {
url: '@concat(\'https://gitapp.hub.com/microsoft/finops-toolkit/\', linkedService().filePath)'
url: 'https://github.com/microsoft/finops-toolkit/'
enableServerCertificateValidation: true
authenticationType: 'Anonymous'
}
Expand Down
Loading