Skip to content
Closed
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
2 changes: 1 addition & 1 deletion docs-mslearn/toolkit/hubs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Did this guide give you the answers you needed? If not, ask a question in the di
Let us know how we're doing with a quick review. We use these reviews to improve and expand FinOps tools and resources.

> [!div class="nextstepaction"]
> [Give feedback](https://portal.azure.com/#view/HubsExtension/InProductFeedbackBlade/extensionName/FinOpsToolkit/cesQuestion/How%20easy%20or%20hard%20is%20it%20to%20use%20FinOps%20hubs%3F/cvaQuestion/How%20valuable%20are%20FinOps%20hubs%3F/surveyId/FTK0.10/bladeName/Hubs/featureName/Compatibility)
> [Give feedback](https://portal.azure.com/#view/HubsExtension/InProductFeedbackBlade/extensionName/FinOpsToolkit/cesQuestion/How%20easy%20or%20hard%20is%20it%20to%20use%20FinOps%20hubs%3F/cvaQuestion/How%20valuable%20are%20FinOps%20hubs%3F/surveyId/FTK0.9/bladeName/Hubs/featureName/Compatibility)

If you're looking for something specific, vote for an existing or create a new idea. Share ideas with others to get more votes. We focus on ideas with the most votes.

Expand Down
56 changes: 56 additions & 0 deletions docs-mslearn/toolkit/hubs/configure-clouds.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Configure Google Cloud data ingestion for FinOps hubs
description: Connect FinOps hubs to Google Cloud billing accounts to monitor cross-cloud cost and usage from a single pane of glass.
author: flanakin
ms.author: micflan
ms.date: 04/28/2025
ms.topic: how-to
ms.service: finops
ms.subservice: finops-toolkit
ms.reviewer: micflan
# customer intent: As a FinOps toolkit user, I want to learn about how to connect FinOps hubs to my Google Cloud billing accounts so that I can monitor cross-cloud cost and usage.
---

<!-- markdownlint-disable-next-line MD025 -->
# Configure Google Cloud data ingestion

Connect FinOps hubs to your Google Cloud billing accounts to monitor your cross-cloud cost and usage from a single pane of glass. FinOps hubs uses Azure Data Factory to pull cost and usage from configured clouds. All reports and dashboards work as-is and will immediately include cross-cloud data.

<br>

## Prerequisites

Before you begin, you must have:

- [Deployed a FinOps hub instance](finops-hubs-overview.md#create-a-new-hub).

This walkthrough will trigger the following indirect costs:

- Additional Data Factory cost for ingesting additional data.

<br>

## Configure Google Cloud data ingestion

TODO

<br>

## Give feedback

Let us know how we're doing with a quick review. We use these reviews to improve and expand FinOps tools and resources.

> [!div class="nextstepaction"]
> [Give feedback](https://portal.azure.com/#view/HubsExtension/InProductFeedbackBlade/extensionName/FinOpsToolkit/cesQuestion/How%20easy%20or%20hard%20is%20it%20to%20use%20FinOps%20hubs%3F/cvaQuestion/How%20valuable%20are%20FinOps%20hubs%3F/surveyId/FTK0.9/bladeName/Hubs/featureName/ConfigureScopes)

If you're looking for something specific, vote for an existing or create a new idea. Share ideas with others to get more votes. We focus on ideas with the most votes.

> [!div class="nextstepaction"]
> [Vote on or suggest ideas](https://github.com/microsoft/finops-toolkit/issues?q=is%3Aissue%20is%3Aopen%20label%3A%22Tool%3A%20FinOps%20hubs%22%20sort%3Areactions-%2B1-desc)

## Related content

- [Connect to Power BI](../power-bi/setup.md)
- [Learn more](finops-hubs-overview.md#why-finops-hubs)

<br>
2 changes: 1 addition & 1 deletion docs-mslearn/toolkit/hubs/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ To upgrade FinOps hubs 0.8 to 0.9:
Let us know how we're doing with a quick review. We use these reviews to improve and expand FinOps tools and resources.

> [!div class="nextstepaction"]
> [Give feedback](https://portal.azure.com/#view/HubsExtension/InProductFeedbackBlade/extensionName/FinOpsToolkit/cesQuestion/How%20easy%20or%20hard%20is%20it%20to%20use%20FinOps%20hubs%3F/cvaQuestion/How%20valuable%20are%20FinOps%20hubs%3F/surveyId/FTK0.10/bladeName/Hubs/featureName/Upgrade)
> [Give feedback](https://portal.azure.com/#view/HubsExtension/InProductFeedbackBlade/extensionName/FinOpsToolkit/cesQuestion/How%20easy%20or%20hard%20is%20it%20to%20use%20FinOps%20hubs%3F/cvaQuestion/How%20valuable%20are%20FinOps%20hubs%3F/surveyId/FTK0.9/bladeName/Hubs/featureName/Upgrade)

If you're looking for something specific, vote for an existing or create a new idea. Share ideas with others to get more votes. We focus on ideas with the most votes.

Expand Down
24 changes: 21 additions & 3 deletions src/powershell/Private/Invoke-Rest.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,30 @@ function Invoke-Rest
$ver = 'unknown'
try { $ver = Get-VersionNumber } catch {}

$arm = (Get-AzContext).Environment.ResourceManagerUrl
Write-Verbose -Message "Get access token for the $Method $Uri request"

if ($Uri -like '/*')
{
$accessToken = (Get-AzAccessToken -AsSecureString).Token | ConvertFrom-SecureString -AsPlainText
$arm = (Get-AzContext).Environment.ResourceManagerUrl
$fullUri = $arm.Trim('/') + '/' + $Uri.Trim('/')
}
elseif ($Uri -like 'https://api.powerbi.com/*')
{
$accessToken = (Get-AzAccessToken -AsSecureString -ResourceUrl 'https://graph.microsoft.com').Token | ConvertFrom-SecureString -AsPlainText
$fullUri = $Uri
}
else
{
$accessToken = (Get-AzAccessToken -AsSecureString -ResourceUrl "https://$($Uri.Split('/')[2])").Token | ConvertFrom-SecureString -AsPlainText
$fullUri = $Uri
}

$params = @{
Method = $Method
Uri = $arm.Trim('/') + '/' + $Uri.Trim('/')
Uri = $fullUri
Headers = @{
Authorization = "Bearer $((Get-AzAccessToken -AsSecureString).Token | ConvertFrom-SecureString -AsPlainText)"
Authorization = "Bearer $accessToken"
ClientType = "FinOpsToolkit.PowerShell.$CommandName@$ver"
"Content-Type" = 'application/json'
"x-ms-command-name" = "FinOpsToolkit.PowerShell.$CommandName@$ver"
Expand Down
67 changes: 67 additions & 0 deletions src/powershell/Public/Initialize-FinOpsHubFabricWorkspace.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

<#
.SYNOPSIS
Deploys a FinOps hub instance.

.DESCRIPTION
The Initialize-FinOpsHubFabricWorkspace command either creates a new or updates an existing FinOps hub instance by deploying an Azure Resource Manager deployment template. The FinOps hub template is downloaded from GitHub.

Initialize-FinOpsHubFabricWorkspace calls Initialize-FinOpsHubDeployment before deploying the template.

.PARAMETER Name
Required. Name of the hub. Used to ensure unique resource names.

.PARAMETER ResourceGroupName
Required. Name of the resource group to deploy to. Will be created if it doesn't exist.

.PARAMETER WorkspaceId
Required. The Microsoft Fabric workspace ID to grant Data Factory access to.

.EXAMPLE
Initialize-FinOpsHubFabricWorkspace -Name MyHub -ResourceGroupName MyNewResourceGroup -WorkspaceId 00000000-0000-0000-0000-000000000000

Grants the FinOps hub Data Factory instance access to the specified Microsoft Fabric workspace.

.LINK
https://aka.ms/ftk/Initialize-FinOpsHubFabricWorkspace
#>
function Initialize-FinOpsHubFabricWorkspace
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "")]
[CmdletBinding(SupportsShouldProcess)]
param
(
[Parameter(Position = 0)]
[string]
$Name = '*',

[Parameter()]
[string]
$ResourceGroupName = '*',

[Parameter(Required = $true)]
[string]
$WorkspaceId
)

$hubId = "/subscriptions/$($context.Subscription.Id)/resourceGroups/$ResourceGroupName/providers/Microsoft.Cloud/hubs/$Name"

Write-Verbose -Message "Get Data Factory instance for $Name hub instance in the $ResourceGroupName resource group"
$adf = Get-AzDataFactoryV2 -ResourceGroupName ftk-mf-fabric | Where-Object { $_.Tags['cm-resource-parent'] -like $hubId }

if (-not $adf)
{
throw ($LocalizedData.HubFabricWorkspace_Initialize_DataFactoryNotFound -f $Name, $ResourceGroupName)
}

Invoke-Rest `
-Method POST `
-Uri "https://api.powerbi.com/v1.0/myorg/groups/$WorkspaceId/users" `
-Body (@{
"identifier" = $adf.Identity.PrincipalId
"groupUserAccessRight" = "Admin"
} | ConvertTo-Json) `
-CommandName 'Initialize-FinOpsHubFabricWorkspace'
}
3 changes: 2 additions & 1 deletion src/powershell/en-US/FinOpsToolkit.strings.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ ConvertFrom-StringData -StringData @'

Hub_Deploy_Deploy = Deploying FinOps hub '{0}' to resource group '{1}'.
Hub_Deploy_TemplateNotFound = Could not find template 'main.bicep' at path '{0}'.
Hub_Deploy_02to011 = Version 0.2 is not supported for Azure Gov and Azure China due to FOCUS exports not being available in Cost Management yet. Using version 0.1.1 instead.
Hub_Deploy_02to021 = Version 0.2 is not supported due to a bug in the deployment template. Using version 0.3 instead.
Hub_Remove_Failed = FinOps hub could not be deleted. {0}.
Hub_Remove_NotFound = FinOps hub '{0}' not found.

HubFabricWorkspace_Initialize_DataFactoryNotFound = Data Factory instance not found for the '{0}' FinOps hub instance in the '{1}' resource group.

HubProviders_Register_AlreadyRegistered = Resource provider {0} is already registered.
HubProviders_Register_Register = Registering resource provider {0}.
HubProviders_Register_RegisterError = Error registering resource provider: {0}.
Expand Down
16 changes: 14 additions & 2 deletions src/templates/finops-hub/modules/dataFactory.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ var storageRbacRoles = [
'18d7d88d-d35e-4fb5-a5c3-7773c20a72d9' // User Access Administrator https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#user-access-administrator
]

var schemaFolderPath = 'schemas'

//==============================================================================
// Resources
//==============================================================================
Expand Down Expand Up @@ -830,7 +832,7 @@ module trigger_ExportManifestAdded 'hub-event-trigger.bicep' = {
dataFactoryName: dataFactory.name
triggerName: exportManifestAddedTriggerName

// TODO: Replace pipeline with event: 'Microsoft.CostManagement.Exports.ManifestAdded'
// TODO: Replace pipeline with event: 'Microsoft.FinOpsToolkit.CostManagement.ExportManifestAdded'
pipelineName: pipeline_ExecuteExportsETL.name
pipelineParameters: {
folderPath: '@triggerBody().folderPath'
Expand Down Expand Up @@ -3449,7 +3451,7 @@ resource pipeline_ExecuteExportsETL 'Microsoft.DataFactory/factories/pipelines@2
value: '@variables(\'schemaFile\')'
type: 'Expression'
}
folderPath: '${configContainerName}/schemas'
folderPath: '${configContainerName}/${schemaFolderPath}'
}
}
fieldList: ['exists']
Expand Down Expand Up @@ -5114,3 +5116,13 @@ output resourceId string = dataFactory.id

@description('The Name of the Azure Data Factory instance.')
output name string = dataFactory.name

@description('The name of the config container dataset.')
output configDatasetName string = dataset_config.name

@description('The folder path of the schema folder in the config container.')
output schemaContainerName string = configContainerName

@description('The folder path of the schema folder in the config container.')
output schemaFolderPath string = schemaFolderPath

Loading
Loading