FabricTools.psm1
#Region './Private/Get-FabricUri.ps1' -1 <# .SYNOPSIS Internal function to connect to Fabric and setup the uri and headers for commands. .DESCRIPTION Internal function to connect to Fabric and setup the uri and headers for commands. Requires the Workspace and DataWarehouse GUIDs to connect to. .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER WorkspaceGUID This is the workspace GUID in which the data warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the data warehouse which we want to retrieve restore points for. .PARAMETER BatchId The BatchId to use for the request. If this is set then the batches endpoint will be used. .EXAMPLE Get-FabricUri -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Connects to the specified Fabric Data Warehouse and sets up the headers and uri for future commands. .EXAMPLE Get-FabricUri -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' -BatchId 'GUID-GUID-GUID-GUID' Connects to the specified Fabric Data Warehouse and sets up the headers and uri for checking the progress of an operation with a specific batchId. #> function Get-FabricUri { param ( $BaseUrl = 'api.powerbi.com', [parameter(Mandatory)] [String]$WorkspaceGUID, [parameter(Mandatory)] [String]$DataWarehouseGUID, [String]$BatchId ) try { $headers = Get-PowerBIAccessToken } catch { try { Stop-PSFFunction -Message ('Not able to get a token - execute Connect-PowerBIServiceAccount manually first') -EnableException # Write-PSFMessage -Level Warning -Message ('Not able to get a token - will execute Connect-PowerBIServiceAccount') #TODO: This doesn't work the first time - is it waiting for response? # $conn = Connect-PowerBIServiceAccount # if($conn) { # Write-PSFMessage -Level Info -Message ('Successfully connected to PowerBI') # } } catch { throw 'Not able to get a token - manually try and run Connect-PowerBIServiceAccount' } } if($BatchId) { $Uri = ('https://{0}/v1.0/myorg/groups/{1}/datawarehouses/{2}/batches/{3}' -f $baseurl, $workspaceGUID, $dataWarehouseGUID, $BatchId) $method = 'Get' } else { $Uri = ('https://{0}/v1.0/myorg/groups/{1}/datawarehouses/{2}/' -f $baseurl, $workspaceGUID, $dataWarehouseGUID) $method = 'Post' } return @{ Uri = $Uri Headers = $headers Method = $method ContentType = 'application/json' } #TODO: Change this to be a saved config property? } #EndRegion './Private/Get-FabricUri.ps1' 76 #Region './Private/Get-FileDefinitionParts.ps1' -1 function Get-FileDefinitionParts { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$sourceDirectory ) try { if (-Not (Test-Path $sourceDirectory)) { Write-Message -Message "The specified source directory does not exist: $sourceDirectory" -Level Error throw } # Get all files from the directory recursively Write-Message -Message "Get all files from the directory recursively" -Level Debug $fileList = Get-ChildItem -Path $sourceDirectory -File -Recurse # Initialize the output JSON object $jsonObject = @{ parts = @() } # Loop through the files to create parts dynamically Write-Message -Message "Loop through the files to create parts dynamically" -Level Debug foreach ($file in $fileList) { $relativePath = $file.FullName.Substring($sourceDirectory.Length + 1) -replace "\\", "/" Write-Message -Message "File found: $relativePath" -Level Debug Write-Message -Message "Starting encode to base64" -Level Debug $base64Content = Convert-ToBase64 -filePath $file.FullName Write-Message -Message "Adding part to json object" -Level Debug $jsonObject.parts += @{ path = $relativePath payload = $base64Content payloadType = "InlineBase64" } } Write-Message -Message "Loop through the files finished" -Level Debug return $jsonObject Write-Message -Message "Parts returned" -Level Debug } catch { # Step 4: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "An error occurred while getting file definition parts: $errorDetails" -Level Error throw "An error occurred while encoding to Base64: $_" } } # Example usage #$sourceDirectory = "C:\temp\API\Notebook" #Get-FileParts -sourceDirectory $sourceDirectory #$fileParts = Get-FileParts -sourceDirectory $sourceDirectory #$fileParts | ConvertTo-Json -Depth 10 #EndRegion './Private/Get-FileDefinitionParts.ps1' 58 #Region './Private/Set-FabConfig.ps1' -1 # this is a workaround to get the variables set for now # TODO: change to use PSFConfig? $script:FabricSession = [ordered]@{ BaseApiUrl = 'https://api.fabric.microsoft.com/v1' ResourceUrl = 'https://api.fabric.microsoft.com' FabricToken = $null HeaderParams = $null ContentType = @{'Content-Type' = "application/json" } KustoURL = "https://api.kusto.windows.net" AccessToken = $null } $script:AzureSession = [ordered]@{ BaseApiUrl = "https://management.azure.com" AccessToken = $null Token = $null HeaderParams = $null } $script:PowerBI = [ordered]@{ BaseApiUrl = "https://api.powerbi.com/v1.0/myorg" } $FabricTools = @{ FeatureFlags = @{ AutoRenewExpiredToken = $true } } $FabricConfig = @{ BaseUrl = "https://api.fabric.microsoft.com/v1" ResourceUrl = "https://api.fabric.microsoft.com" FabricHeaders = @{} TenantIdGlobal = "" TokenExpiresOn = "" } #EndRegion './Private/Set-FabConfig.ps1' 38 #Region './Private/Test-TokenExpired.ps1' -1 <# .SYNOPSIS Checks if the Fabric token is expired and logs appropriate messages. .DESCRIPTION The `Test-TokenExpired` function checks the expiration status of the Fabric token stored in the `$FabricConfig.TokenExpiresOn` variable. If the token is expired, it logs an error message and provides guidance for refreshing the token. Otherwise, it logs that the token is still valid. .PARAMETER FabricConfig The configuration object containing the token expiration details. .EXAMPLE Test-TokenExpired -FabricConfig $config Checks the token expiration status using the provided `$config` object. .NOTES - Ensure the `FabricConfig` object includes a valid `TokenExpiresOn` property of type `DateTimeOffset`. - Requires the `Write-Message` function for logging. .AUTHOR Tiago Balabuch #> function Test-TokenExpired { [CmdletBinding()] param () Confirm-FabricAuthToken | Out-Null Write-Message -Message "Validating token..." -Level Debug try { # Ensure required properties have valid values if ([string]::IsNullOrWhiteSpace($FabricConfig.TenantIdGlobal) -or [string]::IsNullOrWhiteSpace($FabricConfig.TokenExpiresOn)) { Write-Message -Message "Token details are missing. Please run 'Set-FabricApiHeaders' to configure them." -Level Error throw "MissingTokenDetailsException: Token details are missing." } # Convert the TokenExpiresOn value to a DateTime object if ($FabricConfig.TokenExpiresOn.GetType() -eq [datetimeoffset]) { $tokenExpiryDate = $FabricConfig.TokenExpiresOn } else { $tokenExpiryDate = [datetimeoffset]::Parse($FabricConfig.TokenExpiresOn) } # Check if the token is expired if ($tokenExpiryDate -le [datetimeoffset]::Now) { Write-Message -Message "Your authentication token has expired. Please sign in again to refresh your session." -Level Warning #throw "TokenExpiredException: Token has expired." #Set-FabricApiHeaders -tenantId $FabricConfig.TenantIdGlobal } # Log valid token status Write-Message -Message "Token is still valid. Expiry time: $($tokenExpiryDate.ToString("u"))" -Level Debug } catch [System.FormatException] { Write-Message -Message "Invalid 'TokenExpiresOn' format in the FabricConfig object. Ensure it is a valid datetime string." -Level Error throw "FormatException: Invalid TokenExpiresOn value." } catch { # Log unexpected errors with details Write-Message -Message "An unexpected error occurred: $_" -Level Error throw $_ } Write-Message -Message "Token validation completed." -Level Debug } #EndRegion './Private/Test-TokenExpired.ps1' 67 #Region './Private/Write-Message.ps1' -1 <# .SYNOPSIS Logs messages with different severity levels to the console and optionally to a file. .DESCRIPTION The `Write-Message` function provides a unified way to log messages with levels such as Info, Error, Alert, Verbose, and Debug. It supports logging to the console with color-coded messages and optionally writing logs to a file with timestamps. .PARAMETER Message The message to log. Supports pipeline input. .PARAMETER Level Specifies the log level. Supported values are Info, Error, Alert, Verbose, and Debug. .PARAMETER LogFile (Optional) Specifies a file path to write the log messages to. If not provided, messages are only written to the console. .EXAMPLE Write-Message -Message "This is an info message." -Level Info Logs an informational message to the console. .EXAMPLE Write-Message -Message "Logging to file." -Level Info -LogFile "C:\Logs\MyLog.txt" Logs an informational message to the console and writes it to a file. .EXAMPLE "Pipeline message" | Write-Message -Level Alert Logs a message from the pipeline with an Alert level. .NOTES Author: Tiago Balabuch #> function Write-Message { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [string]$Message, [Parameter()] [ValidateSet("Message","Info", "Error", "Warning","Critical", "Verbose", "Debug", IgnoreCase = $true)] [string]$Level = "Info", [Parameter()] [string]$LogFile ) process { try { # Format timestamp $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" # Construct log message $logMessage = "[$timestamp] [$Level] $Message" # Write log message to console with colors switch ($Level) { "Message" { Write-Host $logMessage -ForegroundColor White } "Info" { Write-Host $logMessage -ForegroundColor Green } "Error" { Write-Host $logMessage -ForegroundColor Red } "Warning" { Write-Host $logMessage -ForegroundColor Yellow } "Critical" { Write-Host $logMessage -ForegroundColor Red } "Verbose" { Write-Verbose $logMessage } "Debug" { Write-Debug $logMessage } } # Optionally write log message to a file if ($LogFile) { try { Add-Content -Path $LogFile -Value $logMessage -Encoding UTF8 } catch { # Catch and log any errors when writing to file Write-Host "[ERROR] Failed to write to log file '$LogFile': $_" -ForegroundColor Red } } } catch { Write-Host "[ERROR] An unexpected error occurred: $_" -ForegroundColor Red } } } #EndRegion './Private/Write-Message.ps1' 85 #Region './Public/Capacity/Get-FabricCapacities.ps1' -1 <# .SYNOPSIS This function retrieves all resources of type "Microsoft.Fabric/capacities" from all resource groups in a given subscription or all subscriptions if no subscription ID is provided. .DESCRIPTION The Get-AllFabricCapacities function is used to retrieve all resources of type "Microsoft.Fabric/capacities" from all resource groups in a given subscription or all subscriptions if no subscription ID is provided. It uses the Az module to interact with Azure. .PARAMETER subscriptionID An optional parameter that specifies the subscription ID. If this parameter is not provided, the function will retrieve resources from all subscriptions. .EXAMPLE Get-AllFabricCapacities -subscriptionID "12345678-1234-1234-1234-123456789012" This command retrieves all resources of type "Microsoft.Fabric/capacities" from all resource groups in the subscription with the ID "12345678-1234-1234-1234-123456789012". .EXAMPLE Get-AllFabricCapacities This command retrieves all resources of type "Microsoft.Fabric/capacities" from all resource groups in all subscriptions. .NOTES Alias: Get-AllFabCapacities #> function Get-FabricCapacities { # Define aliases for the function for flexibility. # Define parameters for the function Param ( # Optional parameter for subscription ID [Parameter(Mandatory = $false)] [string]$subscriptionID ) # Initialize an array to store the results $res = @() Get-FabricAuthToken | Out-Null # If a subscription ID is provided if ($subscriptionID) { # Set the context to the provided subscription ID Set-AzContext -SubscriptionId $subscriptionID | Out-Null # Get all resource groups in the subscription $rgs = Get-AzResourceGroup # For each resource group, get all resources of type "Microsoft.Fabric/capacities" foreach ($r in $rgs) { # Get all resources of type "Microsoft.Fabric/capacities" and add them to the results array $res += Get-AzResource -ResourceGroupName $r.ResourceGroupName -resourcetype "Microsoft.Fabric/capacities" -ErrorAction SilentlyContinue } } else { # If no subscription ID is provided, get all subscriptions $subscriptions = Get-AzSubscription # For each subscription, set the context to the subscription ID foreach ($sub in $subscriptions) { # Set the context to the subscription ID Set-AzContext -SubscriptionId $sub.id | Out-Null # Get all resource groups in the subscription $rgs = Get-AzResourceGroup # For each resource group, get all resources of type "Microsoft.Fabric/capacities" foreach ($r in $rgs) { # Get all resources of type "Microsoft.Fabric/capacities" and add them to the results array $res += Get-AzResource -ResourceGroupName $r.ResourceGroupName -ResourceType "Microsoft.Fabric/capacities" -ErrorAction SilentlyContinue } } } # Return the results return $res } #EndRegion './Public/Capacity/Get-FabricCapacities.ps1' 76 #Region './Public/Capacity/Get-FabricCapacity.ps1' -1 <# .SYNOPSIS Retrieves capacity details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves capacity details from a specified workspace using either the provided capacityId or capacityName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER capacityId The unique identifier of the capacity to retrieve. This parameter is optional. .PARAMETER capacityName The name of the capacity to retrieve. This parameter is optional. .EXAMPLE Get-FabricCapacity -capacityId "capacity-12345" This example retrieves the capacity details for the capacity with ID "capacity-12345". .EXAMPLE Get-FabricCapacity -capacityName "MyCapacity" This example retrieves the capacity details for the capacity named "MyCapacity". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricCapacity { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$capacityId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$capacityName ) try { # Handle ambiguous input if ($capacityId -and $capacityName) { Write-Message -Message "Both 'capacityId' and 'capacityName' were provided. Please specify only one." -Level Error return $null } # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URL $apiEndpointURI = "capacities" # Invoke the Fabric API to retrieve capacity details $apiParams = @{ Uri = $apiEndpointURI Method = 'Get' } $capacities = (Invoke-FabricAPIRequest @apiParams).Value # Filter results based on provided parameters $response = if ($capacityId) { $capacities | Where-Object { $_.Id -eq $capacityId } } elseif ($capacityName) { $capacities | Where-Object { $_.DisplayName -eq $capacityName } } else { # No filter, return all capacities Write-Message -Message "No filter specified. Returning all capacities." -Level Debug return $capacities } # Handle results if ($response) { Write-Message -Message "Capacity found matching the specified criteria." -Level Debug return $response } else { Write-Message -Message "No capacity found matching the specified criteria." -Level Warning return $null } } catch { # Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve capacity. Error: $errorDetails" -Level Error return $null } } #EndRegion './Public/Capacity/Get-FabricCapacity.ps1' 89 #Region './Public/Capacity/Get-FabricCapacityRefreshables.ps1' -1 function Get-FabricCapacityRefreshables { <# .SYNOPSIS Retrieves the top refreshable capacities for the tenant. .DESCRIPTION The Get-FabricCapacityRefreshables function retrieves the top refreshable capacities for the tenant. It supports multiple aliases for flexibility. .PARAMETER top The number of top refreshable capacities to retrieve. This is a mandatory parameter. .EXAMPLE Get-FabricCapacityRefreshables -top 5 This example retrieves the top 5 refreshable capacities for the tenant. .NOTES The function retrieves the PowerBI access token and makes a GET request to the PowerBI API to retrieve the top refreshable capacities. It then returns the 'value' property of the response, which contains the capacities. #> # This function retrieves the top refreshable capacities for the tenant. # Define aliases for the function for flexibility. [Alias("Get-FabCapacityRefreshables")] # Define a mandatory parameter for the number of top refreshable capacities to retrieve. Param ( [Parameter(Mandatory = $false)] [string]$top = 5 ) Confirm-FabricAuthToken | Out-Null # Make a GET request to the PowerBI API to retrieve the top refreshable capacities. # The function returns the 'value' property of the response. return (Invoke-RestMethod -uri "$($PowerBI.BaseApiUrl)/capacities/refreshables?`$top=$top" -Headers $FabricSession.HeaderParams -Method GET).value } #EndRegion './Public/Capacity/Get-FabricCapacityRefreshables.ps1' 37 #Region './Public/Capacity/Get-FabricCapacitySkus.ps1' -1 function Get-FabricCapacitySkus { <# .SYNOPSIS Retrieves the fabric capacity information. .DESCRIPTION This function makes a GET request to the Fabric API to retrieve the tenant settings. .PARAMETER subscriptionID Specifies the subscription ID for the Azure subscription. .PARAMETER ResourceGroupName Specifies the name of the resource group in which the Fabric capacity is located. .PARAMETER capacity Specifies the capacity to retrieve information for. If not provided, all capacities will be retrieved. .EXAMPLE Get-FabricCapacitySkus -capacity "exampleCapacity" Retrieves the fabric capacity information for the specified capacity. #> # Define aliases for the function for flexibility. Param( [Parameter(Mandatory = $true)] [string]$subscriptionID, [Parameter(Mandatory = $true)] [string]$ResourceGroupName, [Parameter(Mandatory = $true)] [string]$capacity ) Confirm-FabricAuthToken | Out-Null #GET https://management.azure.com/subscriptions/548B7FB7-3B2A-4F46-BB02-66473F1FC22C/resourceGroups/TestRG/providers/Microsoft.Fabric/capacities/azsdktest/skus?api-version=2023-11-01 $uri = "$($AzureSession.BaseApiUrl)/subscriptions/$subscriptionID/resourceGroups/$ResourceGroupName/providers/Microsoft.Fabric/capacities/$capacity/skus?api-version=2023-11-01" $result = Invoke-RestMethod -Headers $AzureSession.HeaderParams -Uri $uri -Method GET return $result.value } #EndRegion './Public/Capacity/Get-FabricCapacitySkus.ps1' 43 #Region './Public/Capacity/Get-FabricCapacityState.ps1' -1 function Get-FabricCapacityState { <# .SYNOPSIS Retrieves the state of a specific capacity. .DESCRIPTION The Get-FabricCapacityState function retrieves the state of a specific capacity. It supports multiple aliases for flexibility. .PARAMETER subscriptionID The ID of the subscription. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER resourcegroup The resource group. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER capacity The capacity. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .EXAMPLE Get-FabricCapacityState -subscriptionID "your-subscription-id" -resourcegroupID "your-resource-group" -capacityID "your-capacity" This example retrieves the state of a specific capacity given the subscription ID, resource group, and capacity. .NOTES The function checks if the Azure token is null. If it is, it connects to the Azure account and retrieves the token. It then defines the headers for the GET request and the URL for the GET request. Finally, it makes the GET request and returns the response. #> # This function retrieves the state of a specific capacity. # Define aliases for the function for flexibility. [Alias("Get-FabCapacityState")] # Define mandatory parameters for the subscription ID, resource group, and capacity. Param ( [Parameter(Mandatory = $true)] [string]$subscriptionID, [Parameter(Mandatory = $true)] [string]$resourcegroup, [Parameter(Mandatory = $true)] [string]$capacity ) Confirm-FabricAuthToken | Out-Null # Define the URL for the GET request. $getCapacityState = "$($AzureSession.BaseApiUrl)/subscriptions/$subscriptionID/resourceGroups/$resourcegroup/providers/Microsoft.Fabric/capacities/$capacity/?api-version=2022-07-01-preview" # Make the GET request and return the response. return Invoke-RestMethod -Method GET -Uri $getCapacityState -Headers $script:AzureSession.HeaderParams -ErrorAction Stop } #EndRegion './Public/Capacity/Get-FabricCapacityState.ps1' 49 #Region './Public/Capacity/Get-FabricCapacityTenantOverrides.ps1' -1 function Get-FabricCapacityTenantOverrides { <# .SYNOPSIS Retrieves the tenant overrides for all capacities. .DESCRIPTION The Get-FabricCapacityTenantOverrides function retrieves the tenant overrides for all capacities. It supports multiple aliases for flexibility. .PARAMETER authToken The authentication token used to authorize the request. If not provided, the function will retrieve the token using the Get-FabricAuthToken function. .EXAMPLE Get-FabricCapacityTenantOverrides This example retrieves the tenant overrides for all capacities. .NOTES The function retrieves the PowerBI access token and makes a GET request to the Fabric API to retrieve the tenant overrides for all capacities. It then returns the response of the GET request. #> # This function retrieves the tenant overrides for all capacities. # Define aliases for the function for flexibility. [Alias("Get-FabCapacityTenantOverrides")] Param ( ) Confirm-FabricAuthToken | Out-Null # Make a GET request to the Fabric API to retrieve the tenant overrides for all capacities. # The function returns the response of the GET request. return Invoke-RestMethod -uri "$($FabricSession.BaseApiUrl)/admin/capacities/delegatedTenantSettingOverrides" -Headers $FabricSession.HeaderParams -Method GET } #EndRegion './Public/Capacity/Get-FabricCapacityTenantOverrides.ps1' 34 #Region './Public/Capacity/Get-FabricCapacityWorkload.ps1' -1 function Get-FabricCapacityWorkload { <# .SYNOPSIS Retrieves the workloads for a specific capacity. .DESCRIPTION The Get-FabricCapacityWorkload function retrieves the workloads for a specific capacity. It supports multiple aliases for flexibility. .PARAMETER capacityID The ID of the capacity. This is a mandatory parameter. .PARAMETER authToken The authentication token to access the PowerBI API. If not provided, the function will retrieve the token using the Get-FabricAuthToken function. .EXAMPLE Get-FabricCapacityWorkload -capacityID "your-capacity-id" -authToken "your-auth-token" This example retrieves the workloads for a specific capacity given the capacity ID and authentication token. .NOTES The function retrieves the PowerBI access token and makes a GET request to the PowerBI API to retrieve the workloads for the specified capacity. It then returns the 'value' property of the response, which contains the workloads. #> # This function retrieves the workloads for a specific capacity. # Define aliases for the function for flexibility. [Alias("Get-FabCapacityWorkload")] # Define a mandatory parameter for the capacity ID. Param ( [Parameter(Mandatory = $true)] [string]$capacityID ) Confirm-FabricAuthToken | Out-Null # Make a GET request to the PowerBI API to retrieve the workloads for the specified capacity. # The function returns the 'value' property of the response. return (Invoke-RestMethod -uri "$($PowerBI.BaseApiUrl)/capacities/$capacityID/Workloads" -Headers $FabricSession.HeaderParams -Method GET).value } #https://learn.microsoft.com/en-us/rest/api/power-bi/capacities/get-workloads #EndRegion './Public/Capacity/Get-FabricCapacityWorkload.ps1' 43 #Region './Public/Capacity/Resume-FabricCapacity.ps1' -1 function Resume-FabricCapacity { <# .SYNOPSIS Resumes a capacity. .DESCRIPTION The Resume-FabricCapacity function resumes a capacity. It supports multiple aliases for flexibility. .PARAMETER subscriptionID The the ID of the subscription. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER resourcegroup The resource group. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER capacity The capacity. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .EXAMPLE Resume-FabricCapacity -subscriptionID "your-subscription-id" -resourcegroupID "your-resource-group" -capacityID "your-capacity" This example resumes a capacity given the subscription ID, resource group, and capacity. .NOTES The function defines parameters for the subscription ID, resource group, and capacity. If the 'azToken' environment variable is null, it connects to the Azure account and sets the 'azToken' environment variable. It then defines the headers for the request, defines the URI for the request, and makes a GET request to the URI. #> # This function resumes a capacity. # Define aliases for the function for flexibility. [Alias("Resume-FabCapacity")] [CmdletBinding(SupportsShouldProcess)] # Define parameters for the subscription ID, resource group, and capacity. Param ( [Parameter(Mandatory = $true)] [string]$subscriptionID, [Parameter(Mandatory = $true)] [string]$resourcegroup, [Parameter(Mandatory = $true)] [string]$capacity ) Confirm-FabricAuthToken | Out-Null # Define the URI for the request. $resumeCapacity = "$($AzureSession.BaseApiUrl)/subscriptions/$subscriptionID/resourceGroups/$resourcegroup/providers/Microsoft.Fabric/capacities/$capacity/resume?api-version=2022-07-01-preview" # Make a GET request to the URI and return the response. if ($PSCmdlet.ShouldProcess("Resume capacity $capacity")) { return Invoke-RestMethod -Method POST -Uri $resumeCapacity -Headers $script:AzureSession.HeaderParams -ErrorAction Stop } } #EndRegion './Public/Capacity/Resume-FabricCapacity.ps1' 53 #Region './Public/Capacity/Suspend-FabricCapacity.ps1' -1 # This function suspends a capacity. function Suspend-FabricCapacity { <# .SYNOPSIS Suspends a capacity. .DESCRIPTION The Suspend-FabricCapacity function suspends a capacity. It supports multiple aliases for flexibility. .PARAMETER subscriptionID The ID of the subscription. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER resourcegroup The resource group. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .PARAMETER capacity The the capacity. This is a mandatory parameter. This is a parameter found in Azure, not Fabric. .EXAMPLE Suspend-FabricCapacity -subscriptionID "your-subscription-id" -resourcegroupID "your-resource-group" -capacityID "your-capacity" This example suspends a capacity given the subscription ID, resource group, and capacity. .NOTES The function defines parameters for the subscription ID, resource group, and capacity. If the 'azToken' environment variable is null, it connects to the Azure account and sets the 'azToken' environment variable. It then defines the headers for the request, defines the URI for the request, and makes a GET request to the URI. #> # Define aliases for the function for flexibility. [Alias("Suspend-PowerBICapacity", "Suspend-FabCapacity")] [CmdletBinding(SupportsShouldProcess)] # Define parameters for the subscription ID, resource group, and capacity. Param ( [Parameter(Mandatory = $true)] [string]$subscriptionID, [Parameter(Mandatory = $true)] [string]$resourcegroup, [Parameter(Mandatory = $true)] [string]$capacity ) Confirm-FabricAuthToken | Out-Null # Define the URI for the request. $suspendCapacity = "$($AzureSession.BaseApiUrl)/subscriptions/$subscriptionID/resourceGroups/$resourcegroup/providers/Microsoft.Fabric/capacities/$capacity/suspend?api-version=2023-11-01" # Make a GET request to the URI and return the response. if ($PSCmdlet.ShouldProcess("Suspend capacity $capacity")) { return Invoke-RestMethod -Method POST -Uri $suspendCapacity -Headers $script:AzureSession.HeaderParams -ErrorAction Stop } } #EndRegion './Public/Capacity/Suspend-FabricCapacity.ps1' 53 #Region './Public/Config/Get-FabricConfig.ps1' -1 <# .SYNOPSIS Gets the configuration for use with all functions in the PSFabricTools module. .DESCRIPTION Gets the configuration for use with all functions in the PSFabricTools module. .PARAMETER ConfigName The name of the configuration to retrieve. .EXAMPLE PS> Get-FabricConfig Gets all the configuration values for the PSFabricTools module and outputs them .EXAMPLE PS> Get-FabricConfig -ConfigName BaseUrl Gets the BaseUrl configuration value for the PSFabricTools module. #> function Get-FabricConfig { param ( [String]$ConfigName ) if ($ConfigName) { Get-PSFConfig -Module PSFabricTools -Name $ConfigName } else { Get-PSFConfig -Module PSFabricTools } } #EndRegion './Public/Config/Get-FabricConfig.ps1' 33 #Region './Public/Config/Set-FabricConfig.ps1' -1 <# .SYNOPSIS Register the configuration for use with all functions in the PSFabricTools module. .DESCRIPTION Register the configuration for use with all functions in the PSFabricTools module. .PARAMETER WorkspaceGUID This is the workspace GUID in which the Data Warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the Data Warehouse which we want to retrieve restore points for. .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER SkipPersist If set, the configuration will not be persisted to the registry. .EXAMPLE PS> Set-FabricConfig -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Registers the specified Fabric Data Warehouse configuration for use with all functions in the PSFabricTools module. .EXAMPLE PS> Set-FabricConfig -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' -SkipPersist Registers the specified Fabric Data Warehouse configuration for use with all functions in the PSFabricTools module - but does not persist the values, only uses them for the current session. #> function Set-FabricConfig { [CmdletBinding(SupportsShouldProcess)] param ( [String]$WorkspaceGUID, [String]$DataWarehouseGUID, $BaseUrl = 'api.powerbi.com', [switch]$SkipPersist ) if ($PSCmdlet.ShouldProcess("Setting Fabric Configuration")) { if ($BaseUrl) { Set-PSFConfig -Module PSFabricTools -Name BaseUrl -Value $BaseUrl } if ($WorkspaceGUID) { Set-PSFConfig -Module PSFabricTools -Name WorkspaceGUID -Value $WorkspaceGUID } if ($DataWarehouseGUID) { Set-PSFConfig -Module PSFabricTools -Name DataWarehouseGUID -Value $DataWarehouseGUID } # Register the config values in the registry if skip persist is not set if (-not $SkipPersist) { Register-PSFConfig -Module PSFabricTools -Scope SystemMandatory } } } #EndRegion './Public/Config/Set-FabricConfig.ps1' 62 #Region './Public/Confirm-FabricAuthToken.ps1' -1 <# .SYNOPSIS Check whether the Fabric API authentication token is set and not expired and reset it if necessary. .DESCRIPTION The Confirm-FabricAuthToken function retrieves the Fabric API authentication token. If the token is not already set, it calls the Set-FabricAuthToken function to set it. It then outputs the token. .EXAMPLE Confirm-FabricAuthToken This command retrieves the Fabric API authentication token. .INPUTS None. You cannot pipe inputs to this function. .OUTPUTS Returns object as Get-FabricDebugInfo function .NOTES #> function Confirm-FabricAuthToken { [CmdletBinding()] param ( ) Write-Verbose "Check if session is established and token not expired." # Check if the Fabric token is already set if (!$FabricSession.FabricToken -or !$AzureSession.AccessToken) { Write-Output "Confirm-FabricAuthToken::Set-FabricAuthToken" Set-FabricAuthToken | Out-Null } $now = (Get-Date) $s = Get-FabricDebugInfo if ($FabricSession.AccessToken.ExpiresOn -lt $now ) { Write-Output "Confirm-FabricAuthToken::Set-FabricAuthToken#1" Set-FabricAuthToken -reset | Out-Null } if ($s.AzureSession.AccessToken.ExpiresOn -lt $now ) { Write-Output "Confirm-FabricAuthToken::Set-FabricAuthToken#2" Set-FabricAuthToken -reset | Out-Null } $s = Get-FabricDebugInfo return $s } #EndRegion './Public/Confirm-FabricAuthToken.ps1' 51 #Region './Public/Connect-FabricAccount.ps1' -1 function Connect-FabricAccount { <# .SYNOPSIS Connects to the Fabric WebAPI. .DESCRIPTION Connects to the Fabric WebAPI by using the cmdlet Connect-AzAccount. This function retrieves the authentication token for the Fabric API and sets up the headers for API calls. .PARAMETER TenantId The TenantId of the Azure Active Directory tenant you want to connect to and in which your Fabric Capacity is. .EXAMPLE Connect-FabricAccount ` -TenantID '12345678-1234-1234-1234-123456789012' .NOTES Revsion History: - 2024-12-22 - FGE: Added Verbose Output .LINK Connect-AzAccount https://learn.microsoft.com/de-de/powershell/module/az.accounts/connect-azaccount?view=azps-12.4.0 #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TenantId ) begin { } process { Write-Verbose "Connect to Azure Account" Connect-AzAccount -TenantId $TenantId | Out-Null Write-Verbose "Get authentication token" $FabricSession.FabricToken = (Get-AzAccessToken -ResourceUrl $FabricSession.ResourceUrl).Token Write-Verbose "Token: $($FabricSession.FabricToken)" Write-Verbose "Setup headers for API calls" $FabricSession.HeaderParams = @{'Authorization' = "Bearer {0}" -f $FabricSession.FabricToken } Write-Verbose "HeaderParams: $($FabricSession.HeaderParams)" } end { } } #EndRegion './Public/Connect-FabricAccount.ps1' 56 #Region './Public/Copy Job/Get-FabricCopyJob.ps1' -1 function Get-FabricCopyJob { <# .SYNOPSIS Retrieves CopyJob details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves CopyJob details from a specified workspace using either the provided CopyJobId or CopyJob. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the CopyJob exists. This parameter is mandatory. .PARAMETER CopyJobId The unique identifier of the CopyJob to retrieve. This parameter is optional. .PARAMETER CopyJob The name of the CopyJob to retrieve. This parameter is optional. .EXAMPLE FabricCopyJob -WorkspaceId "workspace-12345" -CopyJobId "CopyJob-67890" This example retrieves the CopyJob details for the CopyJob with ID "CopyJob-67890" in the workspace with ID "workspace-12345". .EXAMPLE FabricCopyJob -WorkspaceId "workspace-12345" -CopyJob "My CopyJob" This example retrieves the CopyJob details for the CopyJob named "My CopyJob" in the workspace with ID "workspace-12345". .NOTES Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$CopyJob ) try { # Handle ambiguous input if ($CopyJobId -and $CopyJob) { Write-Message -Message "Both 'CopyJobId' and 'CopyJob' were provided. Please specify only one." -Level Error return $null } # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URL $apiEndpointURI = "workspaces/{0}/copyJobs" -f $WorkspaceId # Invoke the Fabric API to retrieve capacity details $apiParams = @{ Uri = $apiEndpointURI Method = 'Get' } $copyJobs = Invoke-FabricAPIRequest @apiParams # Filter results based on provided parameters $response = if ($CopyJobId) { $copyJobs | Where-Object { $_.Id -eq $CopyJobId } } elseif ($CopyJob) { $copyJobs | Where-Object { $_.DisplayName -eq $CopyJob } } else { # Return all CopyJobs if no filter is provided Write-Message -Message "No filter provided. Returning all CopyJobs." -Level Debug $copyJobs } # Step 9: Handle results if ($response) { Write-Message -Message "CopyJob found matching the specified criteria." -Level Debug return $response } else { Write-Message -Message "No CopyJob found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve CopyJob. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/Get-FabricCopyJob.ps1' 98 #Region './Public/Copy Job/Get-FabricCopyJobDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a Copy Job from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the Copy Job's content or metadata from a workspace. It supports both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the Copy Job definition is to be retrieved. .PARAMETER CopyJobId (Mandatory) The unique identifier of the Copy Job whose definition needs to be retrieved. .PARAMETER CopyJobFormat (Optional) Specifies the format of the Copy Job definition. For example, 'json' or 'xml'. .EXAMPLE Get-FabricCopyJobDefinition -WorkspaceId "12345" -CopyJobId "67890" Retrieves the definition of the Copy Job with ID `67890` from the workspace with ID `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. - Logs detailed information for debugging purposes. #> function Get-FabricCopyJobDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CopyJobId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobFormat ) try { # Step 1: Validate authentication token before proceeding. Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving the Copy Job definition. $apiEndpointUrl = "workspaces/{0}/copyJobs/{1}/getDefinition" -f $WorkspaceId, $CopyJobId # Step 3: Append the format query parameter if specified by the user. if ($CopyJobFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $CopyJobFormat } Write-Message -Message "Constructed API Endpoint URL: $apiEndpointUrl" -Level Debug # Step 4: Execute the API request to retrieve the Copy Job definition. $apiParams = @{ Uri = $apiEndpointUrl Method = 'POST' } $response = Invoke-FabricAPIRequest @apiParams # Step 5: Return the API response containing the Copy Job definition. return $response } catch { # Step 6: Capture and log detailed error information for troubleshooting. $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Copy Job definition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/Get-FabricCopyJobDefinition.ps1' 76 #Region './Public/Copy Job/New-FabricCopyJob.ps1' -1 <# .SYNOPSIS Creates a new copy job in a specified Microsoft Fabric workspace. .DESCRIPTION Sends a POST request to the Microsoft Fabric API to create a new copy job in the specified workspace. Supports optional parameters for description and definition files. .PARAMETER WorkspaceId The unique identifier of the workspace where the copy job will be created. Mandatory. .PARAMETER CopyJobName The name of the copy job to be created. Mandatory. .PARAMETER CopyJobDescription Optional description for the copy job. .PARAMETER CopyJobPathDefinition Optional file path to the copy job definition JSON file. .PARAMETER CopyJobPathPlatformDefinition Optional file path to the platform definition file. .EXAMPLE New-FabricCopyJob -WorkspaceId "workspace-12345" -CopyJobName "New Copy Job" -CopyJobDescription "Description of the new copy job" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricCopyJob { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$CopyJobName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointURI = "workspaces/{0}/copyJobs" -f $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $CopyJobName } if ($CopyJobDescription) { $body.description = $CopyJobDescription } # Step 4: Add copy job definition file content if provided if ($CopyJobPathDefinition) { $CopyJobEncodedContent = Convert-ToBase64 -filePath $CopyJobPathDefinition if (-not [string]::IsNullOrEmpty($CopyJobEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "copyjob-content.json" payload = $CopyJobEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Copy Job definition." -Level Error return $null } } #Step 5: Add platform definition file content if provided if ($CopyJobPathPlatformDefinition) { $CopyJobEncodedPlatformContent = Convert-ToBase64 -filePath $CopyJobPathPlatformDefinition if (-not [string]::IsNullOrEmpty($CopyJobEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $CopyJobEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if($PSCmdlet.ShouldProcess($apiEndpointURI, "Create Copy Job")) { # Step 6: Make the API request $apiParams = @{ Uri = $apiEndpointURI Method = 'Post' Body = $bodyJson } $response = Invoke-FabricAPIRequest @apiParams } Write-Message -Message "Copy Job created successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Copy Job. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/New-FabricCopyJob.ps1' 147 #Region './Public/Copy Job/Remove-FabricCopyJob.ps1' -1 <# .SYNOPSIS Deletes a Copy Job from a specified Microsoft Fabric workspace. .DESCRIPTION This function performs a DELETE operation on the Microsoft Fabric API to remove a Copy Job from the specified workspace using the provided WorkspaceId and CopyJobId parameters. .PARAMETER WorkspaceId The unique identifier of the workspace containing the Copy Job to be deleted. .PARAMETER CopyJobId The unique identifier of the Copy Job to delete. .EXAMPLE Remove-FabricCopyJob -WorkspaceId "workspace-12345" -CopyJobId "copyjob-67890" Deletes the Copy Job with ID "copyjob-67890" from the workspace with ID "workspace-12345". .NOTES - Requires the `$FabricConfig` global configuration, which must include `BaseUrl` and `FabricHeaders`. - Ensures token validity by invoking `Test-TokenExpired` before making the API request. Author: Tiago Balabuch #> function Remove-FabricCopyJob { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CopyJobId ) try { # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URI $apiEndpointURI = "workspaces/{0}/copyJobs/{1}" -f $WorkspaceId, $CopyJobId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug if($PSCmdlet.ShouldProcess($apiEndpointURI, "Delete Copy Job")) { # Make the API request $apiParams = @{ Uri = $apiEndpointURI Method = 'DELETE' } $response = Invoke-FabricAPIRequest @apiParams } Write-Message -Message "Copy Job '$CopyJobId' deleted successfully from workspace '$WorkspaceId'." -Level Info return $response } catch { # Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Copy Job '$CopyJobId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/Remove-FabricCopyJob.ps1' 64 #Region './Public/Copy Job/Update-FabricCopyJob.ps1' -1 <# .SYNOPSIS Updates an existing Copy Job in a specified Microsoft Fabric workspace. .DESCRIPTION Sends a PATCH request to the Microsoft Fabric API to update an existing Copy Job in the specified workspace. Allows updating the Copy Job's name and optionally its description. .PARAMETER WorkspaceId The unique identifier of the workspace containing the Copy Job. This parameter is mandatory. .PARAMETER CopyJobId The unique identifier of the Copy Job to be updated. This parameter is mandatory. .PARAMETER CopyJobName The new name for the Copy Job. This parameter is mandatory. .PARAMETER CopyJobDescription An optional new description for the Copy Job. .EXAMPLE Update-FabricCopyJob -WorkspaceId "workspace-12345" -CopyJobId "copyjob-67890" -CopyJobName "Updated Copy Job" -CopyJobDescription "Updated description" Updates the Copy Job with ID "copyjob-67890" in the workspace "workspace-12345" with a new name and description. .NOTES - Requires the `$FabricConfig` global configuration, which includes `BaseUrl` and `FabricHeaders`. - Ensures token validity by calling `Test-TokenExpired` before making the API request. Author: Tiago Balabuch #> function Update-FabricCopyJob { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CopyJobId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$CopyJobName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobDescription ) try { # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URI $apiEndpointURI = "{0}/workspaces/{1}/copyJobs/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $CopyJobId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Construct the request body $body = @{ displayName = $CopyJobName } if ($CopyJobDescription) { $body.description = $CopyJobDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Update Copy Job")) { # Step 4: Make the API request $response = Invoke-FabricAPIRequest ` -Headers $FabricConfig.FabricHeaders ` -BaseURI $apiEndpointURI ` -method Patch ` -body $bodyJson } Write-Message -Message "Copy Job '$CopyJobName' updated successfully!" -Level Info return $response } catch { # Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Copy Job. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/Update-FabricCopyJob.ps1' 98 #Region './Public/Copy Job/Update-FabricCopyJobDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a Copy Job in a Microsoft Fabric workspace. .DESCRIPTION This function updates the content or metadata of a Copy Job within a Microsoft Fabric workspace. The Copy Job content and platform-specific definitions can be provided as file paths, which will be encoded as Base64 and sent in the request. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace containing the Copy Job. .PARAMETER CopyJobId (Mandatory) The unique identifier of the Copy Job to be updated. .PARAMETER CopyJobPathDefinition (Mandatory) The file path to the Copy Job content definition file. The file content will be encoded as Base64. .PARAMETER CopyJobPathPlatformDefinition (Optional) The file path to the platform-specific definition file for the Copy Job. The file content will be encoded as Base64. .EXAMPLE Update-FabricCopyJobDefinition -WorkspaceId "12345" -CopyJobId "67890" -CopyJobPathDefinition "C:\CopyJobs\CopyJob.ipynb" Updates the content of the Copy Job with ID `67890` in the workspace `12345` using the specified Copy Job file. .EXAMPLE Update-FabricCopyJobDefinition -WorkspaceId "12345" -CopyJobId "67890" -CopyJobPathDefinition "C:\CopyJobs\CopyJob.ipynb" -CopyJobPathPlatformDefinition "C:\CopyJobs\Platform.json" Updates both the content and platform-specific definition of the Copy Job with ID `67890` in the workspace `12345`. .NOTES - Requires the `$FabricConfig` global configuration, which must include `BaseUrl` and `FabricHeaders`. - Validates token expiration using `Test-TokenExpired` before making the API request. - Encodes file content as Base64 before sending it to the Fabric API. - Logs detailed messages for debugging and error handling. Author: Tiago Balabuch #> function Update-FabricCopyJobDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CopyJobId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CopyJobPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CopyJobPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/copyJobs/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $CopyJobId if ($CopyJobPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($CopyJobPathDefinition) { $CopyJobEncodedContent = Convert-ToBase64 -filePath $CopyJobPathDefinition if (-not [string]::IsNullOrEmpty($CopyJobEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "copyjob-content.json" payload = $CopyJobEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Copy Job definition." -Level Error return $null } } if ($CopyJobPathPlatformDefinition) { $CopyJobEncodedPlatformContent = Convert-ToBase64 -filePath $CopyJobPathPlatformDefinition if (-not [string]::IsNullOrEmpty($CopyJobEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $CopyJobEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Copy Job Definition")) { # Step 4: Make the API request $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointUrl ` -Headers $FabricConfig.FabricHeaders ` -Method Post ` -Body $bodyJson } Write-Message -Message "Copy Job updated successfully!" -Level Info return $response } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Copy Job. Error: $errorDetails" -Level Error } } #EndRegion './Public/Copy Job/Update-FabricCopyJobDefinition.ps1' 134 #Region './Public/Dashboard/Get-FabricDashboard.ps1' -1 <# .SYNOPSIS Retrieves dashboards from a specified workspace. .DESCRIPTION This function retrieves all dashboards from a specified workspace using the provided WorkspaceId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The ID of the workspace from which to retrieve dashboards. This parameter is mandatory. .EXAMPLE Get-FabricDashboard -WorkspaceId "12345" This example retrieves all dashboards from the workspace with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricDashboard { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URL $apiEndpointURI = "workspaces/{0}/dashboards" -f $WorkspaceId # Invoke the Fabric API to retrieve capacity details $apiParams = @{ Uri = $apiEndpointURI Method = 'Get' } $Dashboards = Invoke-FabricAPIRequest @apiParams return $Dashboards } catch { # Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Dashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/Dashboard/Get-FabricDashboard.ps1' 55 #Region './Public/Data Pipeline/Get-FabricDataPipeline.ps1' -1 function Get-FabricDataPipeline { <# .SYNOPSIS Retrieves data pipelines from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves all data pipelines from a specified workspace using either the provided Data PipelineId or Data PipelineName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Data Pipeline exists. This parameter is mandatory. .PARAMETER DataPipelineId The unique identifier of the Data Pipeline to retrieve. This parameter is optional. .PARAMETER DataPipelineName The name of the Data Pipeline to retrieve. This parameter is optional. .EXAMPLE Get-FabricData Pipeline -WorkspaceId "workspace-12345" -Data PipelineId "Data Pipeline-67890" This example retrieves the Data Pipeline details for the Data Pipeline with ID "Data Pipeline-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricData Pipeline -WorkspaceId "workspace-12345" -Data PipelineName "My Data Pipeline" This example retrieves the Data Pipeline details for the Data Pipeline named "My Data Pipeline" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DataPipelineId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$DataPipelineName ) try { # Step 1: Handle ambiguous input if ($DataPipelineId -and $DataPipelineName) { Write-Message -Message "Both 'DataPipelineId' and 'DataPipelineName' were provided. Please specify only one." -Level Error return $null } # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URL $apiEndpointURI = ("workspaces/{0}/dataPipelines" -f $WorkspaceId) # Invoke the Fabric API to retrieve data pipeline details $DataPipelines = (Invoke-FabricAPIRequest -uri $apiEndpointURI -Method Get).Value # Filter results based on provided parameters $response = if ($DataPipelineId) { $DataPipelines | Where-Object { $_.Id -eq $DataPipelineId } } elseif ($DataPipelineName) { $DataPipelines | Where-Object { $_.DisplayName -eq $DataPipelineName } } else { # Return all DataPipelines if no filter is provided Write-Message -Message "No filter provided. Returning all DataPipelines." -Level Debug $DataPipelines } # Handle results if ($response) { Write-Message -Message "DataPipeline found matching the specified criteria." -Level Debug return $response } else { Write-Message -Message "No DataPipeline found matching the provided criteria." -Level Warning return $null } } catch { # Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve DataPipeline. Error: $errorDetails" -Level Error } } #EndRegion './Public/Data Pipeline/Get-FabricDataPipeline.ps1' 93 #Region './Public/Data Pipeline/New-FabricDataPipeline.ps1' -1 <# .SYNOPSIS Creates a new DataPipeline in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new DataPipeline in the specified workspace. It supports optional parameters for DataPipeline description and path definitions for the DataPipeline content. .PARAMETER WorkspaceId The unique identifier of the workspace where the DataPipeline will be created. .PARAMETER DataPipelineName The name of the DataPipeline to be created. .PARAMETER DataPipelineDescription An optional description for the DataPipeline. .EXAMPLE New-FabricDataPipeline -WorkspaceId "workspace-12345" -DataPipelineName "New DataPipeline" This example creates a new DataPipeline named "New DataPipeline" in the workspace with ID "workspace-12345" and uploads the definition file from the specified path. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricDataPipeline { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$DataPipelineName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DataPipelineDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointURI = ("workspaces/{0}/dataPipelines" -f $WorkspaceId) Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $DataPipelineName } if ($DataPipelineDescription) { $body.description = $DataPipelineDescription } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Create DataPipeline")) { # Step 4: Make the API request $apiParams = @{ Uri = $apiEndpointURI method = 'Post' body = $bodyJson } $response = Invoke-FabricAPIRequest @apiParams } Write-Message -Message "Data Pipeline created successfully!" -Level Info return $response } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create DataPipeline. Error: $errorDetails" -Level Error } } #EndRegion './Public/Data Pipeline/New-FabricDataPipeline.ps1' 93 #Region './Public/Data Pipeline/Remove-FabricDataPipeline.ps1' -1 <# .SYNOPSIS Removes a DataPipeline from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove a DataPipeline from the specified workspace using the provided WorkspaceId and DataPipelineId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the DataPipeline will be removed. .PARAMETER DataPipelineId The unique identifier of the DataPipeline to be removed. .EXAMPLE Remove-FabricDataPipeline -WorkspaceId "workspace-12345" -DataPipelineId "pipeline-67890" This example removes the DataPipeline with ID "pipeline-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricDataPipeline { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DataPipelineId ) try { # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API URI $apiEndpointURI = "{0}/workspaces/{1}/dataPipelines/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $DataPipelineId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Delete DataPipeline")) { # Make the API request $response = Invoke-FabricAPIRequest ` -Headers $FabricConfig.FabricHeaders ` -BaseURI $apiEndpointURI ` -method Delete } Write-Message -Message "DataPipeline '$DataPipelineId' deleted successfully from workspace '$WorkspaceId'." -Level Info return $response } catch { # Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete DataPipeline '$DataPipelineId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Data Pipeline/Remove-FabricDataPipeline.ps1' 68 #Region './Public/Data Pipeline/Update-FabricDataPipeline.ps1' -1 <# .SYNOPSIS Updates an existing DataPipeline in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing DataPipeline in the specified workspace. It supports optional parameters for DataPipeline description. .PARAMETER WorkspaceId The unique identifier of the workspace where the DataPipeline exists. This parameter is optional. .PARAMETER DataPipelineId The unique identifier of the DataPipeline to be updated. This parameter is mandatory. .PARAMETER DataPipelineName The new name of the DataPipeline. This parameter is mandatory. .PARAMETER DataPipelineDescription An optional new description for the DataPipeline. .EXAMPLE Update-FabricDataPipeline -WorkspaceId "workspace-12345" -DataPipelineId "pipeline-67890" -DataPipelineName "Updated DataPipeline" -DataPipelineDescription "Updated description" This example updates the DataPipeline with ID "pipeline-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricDataPipeline { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DataPipelineId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$DataPipelineName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DataPipelineDescription ) try { # Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API URL $apiEndpointURI = "{0}/workspaces/{1}/dataPipelines/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $DataPipelineId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Construct the request body $body = @{ displayName = $DataPipelineName } if ($DataPipelineDescription) { $body.description = $DataPipelineDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Update DataPipeline")) { # Make the API request $response = Invoke-FabricAPIRequest ` -Headers $FabricConfig.FabricHeaders ` -BaseURI $apiEndpointURI ` -method Patch ` -body $bodyJson } Write-Message -Message "DataPipeline '$DataPipelineName' updated successfully!" -Level Info return $response } catch { # Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update DataPipeline. Error: $errorDetails" -Level Error } } #EndRegion './Public/Data Pipeline/Update-FabricDataPipeline.ps1' 99 #Region './Public/Datamart/Get-FabricDatamart.ps1' -1 function Get-FabricDatamart { <# .SYNOPSIS Retrieves datamarts from a specified workspace. .DESCRIPTION This function retrieves all datamarts from a specified workspace using the provided WorkspaceId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The ID of the workspace from which to retrieve datamarts. This parameter is mandatory. .PARAMETER datamartId The ID of the specific datamart to retrieve. This parameter is optional. .PARAMETER datamartName The name of the specific datamart to retrieve. This parameter is optional. .EXAMPLE Get-FabricDatamart -WorkspaceId "12345" This example retrieves all datamarts from the workspace with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$datamartId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$datamartName ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $apiEndpointURI = "workspaces/{0}/Datamarts" -f $WorkspaceId $apiParams = @{ Uri = $apiEndpointURI method = 'Get' } $Datamarts = Invoke-FabricAPIRequest @apiParams # Step 9: Filter results based on provided parameters $response = if ($datamartId) { $Datamarts | Where-Object { $_.Id -eq $datamartId } } elseif ($datamartName) { $Datamarts | Where-Object { $_.DisplayName -eq $datamartName } } else { # No filter, return all datamarts Write-Message -Message "No filter specified. Returning all datamarts." -Level Debug return $Datamarts } # Step 10: Handle results if ($response) { Write-Message -Message "Datamart found matching the specified criteria." -Level Debug return $response } else { Write-Message -Message "No Datamart found matching the specified criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Datamart. Error: $errorDetails" -Level Error } } #EndRegion './Public/Datamart/Get-FabricDatamart.ps1' 85 #Region './Public/Domain/Add-FabricDomainWorkspaceAssignmentByCapacity.ps1' -1 <# .SYNOPSIS Assigns workspaces to a Fabric domain based on specified capacities. .DESCRIPTION The `Add-FabricDomainWorkspaceAssignmentByCapacity` function assigns workspaces to a Fabric domain using a list of capacity IDs by making a POST request to the relevant API endpoint. .PARAMETER DomainId The unique identifier of the Fabric domain to which the workspaces will be assigned. .PARAMETER CapacitiesIds An array of capacity IDs used to assign workspaces to the domain. .EXAMPLE Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId "12345" -CapacitiesIds @("capacity1", "capacity2") Assigns workspaces to the domain with ID "12345" based on the specified capacities. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricDomainWorkspaceAssignmentByCapacity { [CmdletBinding()] [Alias("Assign-FabricDomainWorkspaceByCapacity")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [array]$CapacitiesIds ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/assignWorkspacesByCapacities" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ capacitiesIds = $CapacitiesIds } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Assigning domain workspaces by capacity completed successfully!" -Level Info return $response } 202 { Write-Message -Message "Assigning domain workspaces by capacity is in progress for domain '$DomainId'." -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug return $operationStatus } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Error occurred while assigning workspaces by capacity for domain '$DomainId'. Details: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Add-FabricDomainWorkspaceAssignmentByCapacity.ps1' 113 #Region './Public/Domain/Add-FabricDomainWorkspaceAssignmentById.ps1' -1 <# .SYNOPSIS Assigns workspaces to a specified domain in Microsoft Fabric by their IDs. .DESCRIPTION The `Add-FabricDomainWorkspaceAssignmentById` function sends a request to assign multiple workspaces to a specified domain using the provided domain ID and an array of workspace IDs. .PARAMETER DomainId The ID of the domain to which workspaces will be assigned. This parameter is mandatory. .PARAMETER WorkspaceIds An array of workspace IDs to be assigned to the domain. This parameter is mandatory. .EXAMPLE Add-FabricDomainWorkspaceAssignmentById -DomainId "12345" -WorkspaceIds @("ws1", "ws2", "ws3") Assigns the workspaces with IDs "ws1", "ws2", and "ws3" to the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricDomainWorkspaceAssignmentById { [CmdletBinding()] [Alias("Assign-FabricDomainWorkspaceById")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [array]$WorkspaceIds ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/assignWorkspaces" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ workspacesIds = $WorkspaceIds } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Successfully assigned workspaces to the domain with ID '$DomainId'." -Level Info } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to assign workspaces to the domain with ID '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Add-FabricDomainWorkspaceAssignmentById.ps1' 84 #Region './Public/Domain/Add-FabricDomainWorkspaceAssignmentByPrincipal.ps1' -1 <# .SYNOPSIS Assigns workspaces to a domain based on principal IDs in Microsoft Fabric. .DESCRIPTION The `Add-FabricDomainWorkspaceAssignmentByPrincipal` function sends a request to assign workspaces to a specified domain using a JSON object of principal IDs and types. .PARAMETER DomainId The ID of the domain to which workspaces will be assigned. This parameter is mandatory. .PARAMETER PrincipalIds An array representing the principals with their `id` and `type` properties. Must contain a `principals` key with an array of objects. .EXAMPLE $PrincipalIds = @( @{id = "813abb4a-414c-4ac0-9c2c-bd17036fd58c"; type = "User"}, @{id = "b5b9495c-685a-447a-b4d3-2d8e963e6288"; type = "User"} ) Add-FabricDomainWorkspaceAssignmentByPrincipal -DomainId "12345" -PrincipalIds $principals Assigns the workspaces based on the provided principal IDs and types. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricDomainWorkspaceAssignmentByPrincipal { [CmdletBinding()] [Alias("Assign-FabricDomainWorkspaceByPrincipal")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] #[hashtable]$PrincipalIds # Must contain a JSON array of principals with 'id' and 'type' properties [System.Object]$PrincipalIds ) try { # Step 1: Ensure each principal contains 'id' and 'type' foreach ($principal in $PrincipalIds) { if (-not ($principal.ContainsKey('id') -and $principal.ContainsKey('type'))) { throw "Each principal object must contain 'id' and 'type' properties." } } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/assignWorkspacesByPrincipals" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Message # Step 4: Construct the request body $body = @{ principals = $PrincipalIds } # Convert the PrincipalIds to JSON $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 5: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 6: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Assigning domain workspaces by principal completed successfully!" -Level Info return $response } 202 { Write-Message -Message "Assigning domain workspaces by principal is in progress for domain '$DomainId'." -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug return $operationStatus } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to assign domain workspaces by principals. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Add-FabricDomainWorkspaceAssignmentByPrincipal.ps1' 119 #Region './Public/Domain/Add-FabricDomainWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Bulk assigns roles to principals for workspaces in a Fabric domain. .DESCRIPTION The `AssignFabricDomainWorkspaceRoleAssignment` function performs bulk role assignments for principals in a specific Fabric domain. It sends a POST request to the relevant API endpoint. .PARAMETER DomainId The unique identifier of the Fabric domain where roles will be assigned. .PARAMETER DomainRole The role to assign to the principals. Must be one of the following: - `Admins` - `Contributors` .PARAMETER PrincipalIds An array of principals to assign roles to. Each principal must include: - `id`: The identifier of the principal. - `type`: The type of the principal (e.g., `User`, `Group`). .EXAMPLE AssignFabricDomainWorkspaceRoleAssignment -DomainId "12345" -DomainRole "Admins" -PrincipalIds @(@{id="user1"; type="User"}, @{id="group1"; type="Group"}) Assigns the `Admins` role to the specified principals in the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricDomainWorkspaceRoleAssignment { [CmdletBinding()] [Alias("Assign-FabricDomainWorkspaceRoleAssignment")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Admins', 'Contributors')] [string]$DomainRole, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [array]$PrincipalIds # Array with 'id' and 'type' ) try { # Step 1: Validate PrincipalIds structure foreach ($principal in $PrincipalIds) { if (-not ($principal.id -and $principal.type)) { throw "Invalid principal detected: Each principal must include 'id' and 'type' properties. Found: $principal" } } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/roleAssignments/bulkAssign" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Construct the request body $body = @{ type = $DomainRole principals = $PrincipalIds } $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 5: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 6: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Bulk role assignment for domain '$DomainId' completed successfully!" -Level Info } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to bulk assign roles in domain '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Add-FabricDomainWorkspaceRoleAssignment.ps1' 103 #Region './Public/Domain/Get-FabricDomain.ps1' -1 <# .SYNOPSIS Retrieves domain information from Microsoft Fabric, optionally filtering by domain ID, domain name, or only non-empty domains. .DESCRIPTION The `Get-FabricDomain` function allows retrieval of domains in Microsoft Fabric, with optional filtering by domain ID or name. Additionally, it can filter to return only non-empty domains. .PARAMETER DomainId (Optional) The ID of the domain to retrieve. .PARAMETER DomainName (Optional) The display name of the domain to retrieve. .PARAMETER NonEmptyDomainsOnly (Optional) If set to `$true`, only domains containing workspaces will be returned. .EXAMPLE Get-FabricDomain -DomainId "12345" Fetches the domain with ID "12345". .EXAMPLE Get-FabricDomain -DomainName "Finance" Fetches the domain with the display name "Finance". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricDomain { [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DomainName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$NonEmptyDomainsOnly = $false ) try { # Step 1: Handle ambiguous input if ($DomainId -and $DomainName) { Write-Message -Message "Both 'DomainId' and 'DomainName' were provided. Please specify only one." -Level Error return @() } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL with filtering logic $apiEndpointUrl = "{0}/admin/domains" -f $FabricConfig.BaseUrl if ($NonEmptyDomainsOnly) { $apiEndpointUrl = "{0}?nonEmptyOnly=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle empty response if (-not $response) { Write-Message -Message "No data returned from the API." -Level Warning return $null } # Step 7: Filter results based on provided parameters $domains = if ($DomainId) { $response.domains | Where-Object { $_.Id -eq $DomainId } } elseif ($DomainName) { $response.domains | Where-Object { $_.DisplayName -eq $DomainName } } else { # Return all domains if no filter is provided Write-Message -Message "No filter provided. Returning all domains." -Level Debug return $response.domains } # Step 8: Handle results if ($domains) { return $domains } else { Write-Message -Message "No domain found matching the provided criteria." -Level Warning return $null } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Get-FabricDomain.ps1' 119 #Region './Public/Domain/Get-FabricDomainWorkspace.ps1' -1 <# .SYNOPSIS Retrieves the workspaces associated with a specific domain in Microsoft Fabric. .DESCRIPTION The `Get-FabricDomainWorkspace` function fetches the workspaces for the given domain ID. .PARAMETER DomainId The ID of the domain for which to retrieve workspaces. .EXAMPLE Get-FabricDomainWorkspace -DomainId "12345" Fetches workspaces for the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricDomainWorkspace { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/workspaces" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle empty response if (-not $response) { Write-Message -Message "No data returned from the API." -Level Warning return $null } # Step 6: Handle results if ($response) { return $response.value } else { Write-Message -Message "No workspace found for the '$DomainId'." -Level Warning return $null } } catch { # Step 7: Capture and log error details $errorDetails = Get-ErrorResponse($_.Exception) Write-Message -Message "Failed to retrieve domain workspaces. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Get-FabricDomainWorkspace.ps1' 79 #Region './Public/Domain/New-FabricDomain.ps1' -1 <# .SYNOPSIS Creates a new Fabric domain. .DESCRIPTION The `Add-FabricDomain` function creates a new domain in Microsoft Fabric by making a POST request to the relevant API endpoint. .PARAMETER DomainName The name of the domain to be created. Must only contain alphanumeric characters, underscores, and spaces. .PARAMETER DomainDescription A description of the domain to be created. .PARAMETER ParentDomainId (Optional) The ID of the parent domain, if applicable. .EXAMPLE Add-FabricDomain -DomainName "Finance" -DomainDescription "Finance data domain" -ParentDomainId "12345" Creates a "Finance" domain under the parent domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricDomain { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$DomainName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DomainDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ParentDomainId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the request body $apiEndpointUrl = "{0}/admin/domains" -f $FabricConfig.BaseUrl Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Construct the request body $body = @{ displayName = $DomainName } if ($DomainDescription) { $body.description = $DomainDescription } if ($ParentDomainId) { $body.parentDomainId = $ParentDomainId } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($DomainName, "Create Domain")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Domain '$DomainName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Domain '$DomainName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create domain. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/New-FabricDomain.ps1' 144 #Region './Public/Domain/Remove-FabricDomain.ps1' -1 <# .SYNOPSIS Deletes a Fabric domain by its ID. .DESCRIPTION The `Remove-FabricDomain` function removes a specified domain from Microsoft Fabric by making a DELETE request to the relevant API endpoint. .PARAMETER DomainId The unique identifier of the domain to be deleted. .EXAMPLE Remove-FabricDomain -DomainId "12345" Deletes the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricDomain { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Domain")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Domain '$DomainId' deleted successfully!" -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete domain '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Remove-FabricDomain.ps1' 75 #Region './Public/Domain/Remove-FabricDomainWorkspaceAssignment.ps1' -1 <# .SYNOPSIS Unassign workspaces from a specified Fabric domain. .DESCRIPTION The `Unassign -FabricDomainWorkspace` function allows you to Unassign specific workspaces from a given Fabric domain or unassign all workspaces if no workspace IDs are specified. It makes a POST request to the relevant API endpoint for this operation. .PARAMETER DomainId The unique identifier of the Fabric domain. .PARAMETER WorkspaceIds (Optional) An array of workspace IDs to unassign. If not provided, all workspaces will be unassigned. .EXAMPLE Remove-FabricDomainWorkspaceAssignment -DomainId "12345" Unassigns all workspaces from the domain with ID "12345". .EXAMPLE Remove-FabricDomainWorkspaceAssignment -DomainId "12345" -WorkspaceIds @("workspace1", "workspace2") Unassigns the specified workspaces from the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricDomainWorkspaceAssignment { [CmdletBinding(SupportsShouldProcess)] [Alias("Unassign-FabricDomainWorkspace")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [array]$WorkspaceIds ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL # Determine the API endpoint URL based on the presence of WorkspaceIds $endpointSuffix = if ($WorkspaceIds) { "unassignWorkspaces" } else { "unassignAllWorkspaces" } $apiEndpointUrl = "{0}/admin/domains/{1}/{2}" -f $FabricConfig.BaseUrl, $DomainId, $endpointSuffix Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body (if needed) $bodyJson = if ($WorkspaceIds) { $body = @{ workspacesIds = $WorkspaceIds } $body | ConvertTo-Json -Depth 2 } else { $null } Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($DomainId, "Unassign Workspaces")) { # Step 4: Make the API request to unassign specific workspaces $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Successfully unassigned workspaces to the domain with ID '$DomainId'." -Level Info } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to unassign workspaces to the domain with ID '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Remove-FabricDomainWorkspaceAssignment.ps1' 114 #Region './Public/Domain/Remove-FabricDomainWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Bulk unUnassign roles to principals for workspaces in a Fabric domain. .DESCRIPTION The `AssignFabricDomainWorkspaceRoleAssignment` function performs bulk role assignments for principals in a specific Fabric domain. It sends a POST request to the relevant API endpoint. .PARAMETER DomainId The unique identifier of the Fabric domain where roles will be assigned. .PARAMETER DomainRole The role to assign to the principals. Must be one of the following: - `Admins` - `Contributors` .PARAMETER PrincipalIds An array of principals to assign roles to. Each principal must include: - `id`: The identifier of the principal. - `type`: The type of the principal (e.g., `User`, `Group`). .EXAMPLE AssignFabricDomainWorkspaceRoleAssignment -DomainId "12345" -DomainRole "Admins" -PrincipalIds @(@{id="user1"; type="User"}, @{id="group1"; type="Group"}) Unassign the `Admins` role to the specified principals in the domain with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricDomainWorkspaceRoleAssignment { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [Alias("Unassign-FabricDomainWorkspaceRoleAssignment")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Admins', 'Contributors')] [string]$DomainRole, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [array]$PrincipalIds # Array with 'id' and 'type' ) try { # Step 1: Validate PrincipalIds structure foreach ($principal in $PrincipalIds) { if (-not ($principal.id -and $principal.type)) { throw "Invalid principal detected: Each principal must include 'id' and 'type' properties. Found: $principal" } } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}/roleAssignments/bulkUnassign" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Construct the request body $body = @{ type = $DomainRole principals = $PrincipalIds } $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug if($PSCmdlet.ShouldProcess($DomainId, "Unassign Roles")) { # Step 5: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 6: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Bulk role unassignment for domain '$DomainId' completed successfully!" -Level Info } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to bulk assign roles in domain '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Remove-FabricDomainWorkspaceRoleAssignment.ps1' 106 #Region './Public/Domain/Update-FabricDomain.ps1' -1 <# .SYNOPSIS Updates a Fabric domain by its ID. .DESCRIPTION The `Update-FabricDomain` function modifies a specified domain in Microsoft Fabric using the provided parameters. .PARAMETER DomainId The unique identifier of the domain to be updated. .PARAMETER DomainName The new name for the domain. Must be alphanumeric. .PARAMETER DomainDescription (Optional) A new description for the domain. .PARAMETER DomainContributorsScope (Optional) The contributors' scope for the domain. Accepted values: 'AdminsOnly', 'AllTenant', 'SpecificUsersAndGroups'. .EXAMPLE Update-FabricDomain -DomainId "12345" -DomainName "NewDomain" -DomainDescription "Updated description" -DomainContributorsScope "AdminsOnly" Updates the domain with ID "12345" with a new name, description, and contributors' scope. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricDomain { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DomainId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$DomainName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$DomainDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('AdminsOnly', 'AllTenant', 'SpecificUsersAndGroups')] [string]$DomainContributorsScope ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/admin/domains/{1}" -f $FabricConfig.BaseUrl, $DomainId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $DomainName } if ($DomainDescription) { $body.description = $DomainDescription } if ($DomainContributorsScope) { $body.contributorsScope = $DomainContributorsScope } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($DomainName, "Update Domain")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Domain '$DomainName' updated successfully!" -Level Info return $response } catch { # Step 7: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update domain '$DomainId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Domain/Update-FabricDomain.ps1' 122 #Region './Public/Environment/Get-FabricEnvironment.ps1' -1 function Get-FabricEnvironment { <# .SYNOPSIS Retrieves an environment or a list of environments from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricEnvironment` function sends a GET request to the Fabric API to retrieve environment details for a given workspace. It can filter the results by `EnvironmentName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query environments. .PARAMETER EnvironmentId (Optional) The ID of a specific environment to retrieve. .PARAMETER EnvironmentName (Optional) The name of the specific environment to retrieve. .EXAMPLE Get-FabricEnvironment -WorkspaceId "12345" -EnvironmentName "Development" Retrieves the "Development" environment from workspace "12345". .EXAMPLE Get-FabricEnvironment -WorkspaceId "12345" Retrieves all environments in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Returns the matching environment details or all environments if no filter is provided. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EnvironmentName ) try { # Step 1: Handle ambiguous input if ($EnvironmentId -and $EnvironmentName) { Write-Message -Message "Both 'EnvironmentId' and 'EnvironmentName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $environments = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } $baseApiEndpointUrl = "{0}/workspaces/{1}/environments" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 4: Loop to retrieve data with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $environments += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $environment = if ($EnvironmentId) { $environments | Where-Object { $_.Id -eq $EnvironmentId } } elseif ($EnvironmentName) { $environments | Where-Object { $_.DisplayName -eq $EnvironmentName } } else { # Return all workspaces if no filter is provided Write-Message -Message "No filter provided. Returning all environments." -Level Debug $environments } # Step 9: Handle results if ($environment) { Write-Message -Message "Environment found in the Workspace '$WorkspaceId'." -Level Debug return $environment } else { Write-Message -Message "No environment found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Get-FabricEnvironment.ps1' 155 #Region './Public/Environment/Get-FabricEnvironmentLibrary.ps1' -1 <# .SYNOPSIS Retrieves the list of libraries associated with a specific environment in a Microsoft Fabric workspace. .DESCRIPTION The Get-FabricEnvironmentLibrary function fetches library information for a given workspace and environment using the Microsoft Fabric API. It ensures the authentication token is valid and validates the response to handle errors gracefully. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the environment is located. .PARAMETER EnvironmentId The unique identifier of the environment whose libraries are being queried. .EXAMPLE Get-FabricEnvironmentLibrary -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Retrieves the libraries associated with the specified environment in the given workspace. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. - Uses `Test-TokenExpired` to validate the token before making API calls. Author: Tiago Balabuch #> function Get-FabricEnvironmentLibrary { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/libraries" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle results return $response } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment libraries. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Get-FabricEnvironmentLibrary.ps1' 76 #Region './Public/Environment/Get-FabricEnvironmentSparkCompute.ps1' -1 <# .SYNOPSIS Retrieves the Spark compute details for a specific environment in a Microsoft Fabric workspace. .DESCRIPTION The Get-FabricEnvironmentSparkCompute function communicates with the Microsoft Fabric API to fetch information about Spark compute resources associated with a specified environment. It ensures that the API token is valid and gracefully handles errors during the API call. .PARAMETER WorkspaceId The unique identifier of the workspace containing the target environment. .PARAMETER EnvironmentId The unique identifier of the environment whose Spark compute details are being retrieved. .EXAMPLE Get-FabricEnvironmentSparkCompute -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Retrieves Spark compute details for the specified environment in the given workspace. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. - Uses `Test-TokenExpired` to validate the token before making API calls. Author: Tiago Balabuch #> function Get-FabricEnvironmentSparkCompute { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/sparkcompute" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle results return $response } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment Spark compute. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Get-FabricEnvironmentSparkCompute.ps1' 76 #Region './Public/Environment/Get-FabricEnvironmentStagingLibrary.ps1' -1 <# .SYNOPSIS Retrieves the staging library details for a specific environment in a Microsoft Fabric workspace. .DESCRIPTION The Get-FabricEnvironmentStagingLibrary function interacts with the Microsoft Fabric API to fetch information about staging libraries associated with a specified environment. It ensures token validity and handles API errors gracefully. .PARAMETER WorkspaceId The unique identifier of the workspace containing the target environment. .PARAMETER EnvironmentId The unique identifier of the environment for which staging library details are being retrieved. .EXAMPLE Get-FabricEnvironmentStagingLibrary -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Retrieves the staging libraries for the specified environment in the given workspace. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. - Uses `Test-TokenExpired` to validate the token before making API calls. Author: Tiago Balabuch #> function Get-FabricEnvironmentStagingLibrary { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/libraries" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle results return $response.customLibraries } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment spark compute. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Get-FabricEnvironmentStagingLibrary.ps1' 76 #Region './Public/Environment/Get-FabricEnvironmentStagingSparkCompute.ps1' -1 function Get-FabricEnvironmentStagingSparkCompute { <# .SYNOPSIS Retrieves staging Spark compute details for a specific environment in a Microsoft Fabric workspace. .DESCRIPTION The Get-FabricEnvironmentStagingSparkCompute function interacts with the Microsoft Fabric API to fetch information about staging Spark compute configurations for a specified environment. It ensures token validity and handles API errors gracefully. .PARAMETER WorkspaceId The unique identifier of the workspace containing the target environment. .PARAMETER EnvironmentId The unique identifier of the environment for which staging Spark compute details are being retrieved. .EXAMPLE Get-FabricEnvironmentStagingSparkCompute -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Retrieves the staging Spark compute configurations for the specified environment in the given workspace. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. - Uses `Test-TokenExpired` to validate the token before making API calls. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/sparkcompute" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle results return $response } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve environment spark compute. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Get-FabricEnvironmentStagingSparkCompute.ps1' 76 #Region './Public/Environment/Import-FabricEnvironmentStagingLibrary.ps1' -1 <# .SYNOPSIS Uploads a library to the staging environment in a Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to upload a library to the specified environment staging area for the given workspace. .PARAMETER WorkspaceId The unique identifier of the workspace where the environment exists. .PARAMETER EnvironmentId The unique identifier of the environment where the library will be uploaded. .EXAMPLE Import-FabricEnvironmentStagingLibrary -WorkspaceId "workspace-12345" -EnvironmentId "env-67890" .NOTES - This is not working code. It is a placeholder for future development. Fabric documentation is missing some important details on how to upload libraries. - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Import-FabricEnvironmentStagingLibrary { [CmdletBinding()] [Alias("Upload-FabricEnvironmentStagingLibrary")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/libraries" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Environment staging library uploaded successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to upload environment staging library. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Import-FabricEnvironmentStagingLibrary.ps1' 80 #Region './Public/Environment/New-FabricEnvironment.ps1' -1 <# .SYNOPSIS Creates a new environment in a specified workspace. .DESCRIPTION The `Add-FabricEnvironment` function creates a new environment within a given workspace by making a POST request to the Fabric API. The environment can optionally include a description. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace where the environment will be created. .PARAMETER EnvironmentName (Mandatory) The name of the environment to be created. Only alphanumeric characters, spaces, and underscores are allowed. .PARAMETER EnvironmentDescription (Optional) A description of the environment. .EXAMPLE Add-FabricEnvironment -WorkspaceId "12345" -EnvironmentName "DevEnv" -EnvironmentDescription "Development Environment" Creates an environment named "DevEnv" in workspace "12345" with the specified description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricEnvironment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EnvironmentName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EnvironmentDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EnvironmentName } if ($EnvironmentDescription) { $body.description = $EnvironmentDescription } $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EnvironmentName, "Create Environment")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Environment '$EnvironmentName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Environment '$EnvironmentName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create environment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/New-FabricEnvironment.ps1' 136 #Region './Public/Environment/Publish-FabricEnvironment.ps1' -1 <# .SYNOPSIS Publishes a staging environment in a specified Microsoft Fabric workspace. .DESCRIPTION This function interacts with the Microsoft Fabric API to initiate the publishing process for a staging environment. It validates the authentication token, constructs the API request, and handles both immediate and long-running operations. .PARAMETER WorkspaceId The unique identifier of the workspace containing the staging environment. .PARAMETER EnvironmentId The unique identifier of the staging environment to be published. .EXAMPLE Publish-FabricEnvironment -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Initiates the publishing process for the specified staging environment. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. - Uses `Test-TokenExpired` to validate the token before making API calls. Author: Tiago Balabuch #> function Publish-FabricEnvironment { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/publish" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Publish operation request has been submitted successfully for the environment '$EnvironmentId'!" -Level Info return $response.publishDetails } 202 { Write-Message -Message "Publish operation accepted. Publishing in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create environment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Publish-FabricEnvironment.ps1' 103 #Region './Public/Environment/Remove-FabricEnvironment.ps1' -1 <# .SYNOPSIS Deletes an environment from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricEnvironment` function sends a DELETE request to the Fabric API to remove a specified environment from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the environment to delete. .PARAMETER EnvironmentId (Mandatory) The ID of the environment to be deleted. .EXAMPLE Remove-FabricEnvironment -WorkspaceId "12345" -EnvironmentId "67890" Deletes the environment with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricEnvironment { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Environment")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Environment '$EnvironmentId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete environment '$EnvironmentId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Remove-FabricEnvironment.ps1' 81 #Region './Public/Environment/Remove-FabricEnvironmentStagingLibrary.ps1' -1 function Remove-FabricEnvironmentStagingLibrary { <# .SYNOPSIS Deletes a specified library from the staging environment in a Microsoft Fabric workspace. .DESCRIPTION This function allows for the deletion of a library from the staging environment, one file at a time. It ensures token validity, constructs the appropriate API request, and handles both success and failure responses. .PARAMETER WorkspaceId The unique identifier of the workspace from which the library is to be deleted. .PARAMETER EnvironmentId The unique identifier of the staging environment containing the library. .PARAMETER LibraryName The name of the library to be deleted from the environment. .EXAMPLE Remove-FabricEnvironmentStagingLibrary -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" -LibraryName "library-to-delete" Deletes the specified library from the staging environment in the specified workspace. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. - This function currently supports deleting one library at a time. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LibraryName ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/libraries?libraryToDelete={3}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId, $LibraryName Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Staging Library")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Staging library $LibraryName for the Environment '$EnvironmentId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete environment '$EnvironmentId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Remove-FabricEnvironmentStagingLibrary.ps1' 89 #Region './Public/Environment/Stop-FabricEnvironmentPublish.ps1' -1 <# .SYNOPSIS Cancels the publish operation for a specified environment in Microsoft Fabric. .DESCRIPTION This function sends a cancel publish request to the Microsoft Fabric API for a given environment. It ensures that the token is valid before making the request and handles both successful and error responses. .PARAMETER WorkspaceId The unique identifier of the workspace where the environment exists. .PARAMETER EnvironmentId The unique identifier of the environment for which the publish operation is to be canceled. .EXAMPLE Stop-FabricEnvironmentPublish -WorkspaceId "workspace-12345" -EnvironmentId "environment-67890" Cancels the publish operation for the specified environment. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Stop-FabricEnvironmentPublish { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/cancelPublish" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Cancel Publish")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Publication for environment '$EnvironmentId' has been successfully canceled." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to cancel publication for environment '$EnvironmentId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Stop-FabricEnvironmentPublish.ps1' 83 #Region './Public/Environment/Update-FabricEnvironment.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric Environment. .DESCRIPTION The `Update-FabricEnvironment` function updates the name and/or description of a specified Fabric Environment by making a PATCH request to the API. .PARAMETER EnvironmentId The unique identifier of the Environment to be updated. .PARAMETER EnvironmentName The new name for the Environment. .PARAMETER EnvironmentDescription (Optional) The new description for the Environment. .PARAMETER WorkspaceId The unique identifier of the workspace where the Environment resides. .EXAMPLE Update-FabricEnvironment -EnvironmentId "Environment123" -EnvironmentName "NewEnvironmentName" Updates the name of the Environment with the ID "Environment123" to "NewEnvironmentName". .EXAMPLE Update-FabricEnvironment -EnvironmentId "Environment123" -EnvironmentName "NewName" -EnvironmentDescription "Updated description" Updates both the name and description of the Environment "Environment123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricEnvironment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EnvironmentName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EnvironmentDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EnvironmentName } if ($EnvironmentDescription) { $body.description = $EnvironmentDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EnvironmentId, "Update Environment")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Environment '$EnvironmentName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Environment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Update-FabricEnvironment.ps1' 120 #Region './Public/Environment/Update-FabricEnvironmentStagingSparkCompute.ps1' -1 <# .SYNOPSIS Updates the Spark compute configuration in the staging environment for a given workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the Spark compute settings for a specified environment, including instance pool, driver and executor configurations, and dynamic allocation settings. .PARAMETER WorkspaceId The unique identifier of the workspace where the environment exists. .PARAMETER EnvironmentId The unique identifier of the environment where the Spark compute settings will be updated. .PARAMETER InstancePoolName The name of the instance pool to be used for Spark compute. .PARAMETER InstancePoolType The type of instance pool (either 'Workspace' or 'Capacity'). .PARAMETER DriverCores The number of cores to allocate to the driver. .PARAMETER DriverMemory The amount of memory to allocate to the driver. .PARAMETER ExecutorCores The number of cores to allocate to each executor. .PARAMETER ExecutorMemory The amount of memory to allocate to each executor. .PARAMETER DynamicExecutorAllocationEnabled Boolean flag to enable or disable dynamic executor allocation. .PARAMETER DynamicExecutorAllocationMinExecutors The minimum number of executors when dynamic allocation is enabled. .PARAMETER DynamicExecutorAllocationMaxExecutors The maximum number of executors when dynamic allocation is enabled. .PARAMETER RuntimeVersion The Spark runtime version to use. .PARAMETER SparkProperties A hashtable of additional Spark properties to configure. .EXAMPLE Update-FabricEnvironmentStagingSparkCompute -WorkspaceId "workspace-12345" -EnvironmentId "env-67890" -InstancePoolName "pool1" -InstancePoolType "Workspace" -DriverCores 4 -DriverMemory "16GB" -ExecutorCores 8 -ExecutorMemory "32GB" -DynamicExecutorAllocationEnabled $true -DynamicExecutorAllocationMinExecutors 2 -DynamicExecutorAllocationMaxExecutors 10 -RuntimeVersion "3.1" -SparkProperties @{ "spark.executor.memoryOverhead"="4GB" } .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricEnvironmentStagingSparkCompute { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EnvironmentId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$InstancePoolName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Workspace', 'Capacity')] [string]$InstancePoolType, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DriverCores, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DriverMemory, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$ExecutorCores, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ExecutorMemory, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$DynamicExecutorAllocationEnabled, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMinExecutors, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMaxExecutors, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$RuntimeVersion, [Parameter(Mandatory = $true)] [System.Object]$SparkProperties ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/environments/{2}/staging/sparkcompute" -f $FabricConfig.BaseUrl, $WorkspaceId, $EnvironmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ instancePool = @{ name = $InstancePoolName type = $InstancePoolType } driverCores = $DriverCores driverMemory = $DriverMemory executorCores = $ExecutorCores executorMemory = $ExecutorMemory dynamicExecutorAllocation = @{ enabled = $DynamicExecutorAllocationEnabled minExecutors = $DynamicExecutorAllocationMinExecutors maxExecutors = $DynamicExecutorAllocationMaxExecutors } runtimeVersion = $RuntimeVersion sparkProperties = $SparkProperties } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 4 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EnvironmentId, "Update Environment Staging Spark Compute")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Environment staging Spark compute updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update environment staging Spark compute. Error: $errorDetails" -Level Error } } #EndRegion './Public/Environment/Update-FabricEnvironmentStagingSparkCompute.ps1' 196 #Region './Public/Eventhouse/Get-FabricEventhouse.ps1' -1 function Get-FabricEventhouse { <# .SYNOPSIS Retrieves Fabric Eventhouses .DESCRIPTION Retrieves Fabric Eventhouses. Without the EventhouseName or EventhouseID parameter, all Eventhouses are returned. If you want to retrieve a specific Eventhouse, you can use the EventhouseName or EventhouseID parameter. These parameters cannot be used together. .PARAMETER WorkspaceId Id of the Fabric Workspace for which the Eventhouses should be retrieved. The value for WorkspaceId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .PARAMETER EventhouseName The name of the Eventhouse to retrieve. This parameter cannot be used together with EventhouseID. .PARAMETER EventhouseId The Id of the Eventhouse to retrieve. This parameter cannot be used together with EventhouseName. The value for WorkspaceId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .EXAMPLE Get-FabricEventhouse ` -WorkspaceId '12345678-1234-1234-1234-123456789012' This example will give you all Eventhouses in the Workspace. .EXAMPLE Get-FabricEventhouse ` -WorkspaceId '12345678-1234-1234-1234-123456789012' ` -EventhouseName 'MyEventhouse' This example will give you all Information about the Eventhouse with the name 'MyEventhouse'. .EXAMPLE Get-FabricEventhouse ` -WorkspaceId '12345678-1234-1234-1234-123456789012' ` -EventhouseId '12345678-1234-1234-1234-123456789012' This example will give you all Information about the Eventhouse with the Id '12345678-1234-1234-1234-123456789012'. .EXAMPLE Get-FabricEventhouse ` -WorkspaceId '12345678-1234-1234-1234-123456789012' ` -EventhouseId '12345678-1234-1234-1234-123456789012' ` -Verbose This example will give you all Information about the Eventhouse with the Id '12345678-1234-1234-1234-123456789012'. It will also give you verbose output which is useful for debugging. .LINK https://learn.microsoft.com/en-us/rest/api/fabric/eventhouse/items/list-eventhouses?tabs=HTTP .NOTES TODO: Add functionality to list all Eventhouses in the subscription. To do so fetch all workspaces and then all eventhouses in each workspace. Revsion History: - 2024-11-09 - FGE: Added DisplaName as Alias for EventhouseName - 2024-11-16 - FGE: Added Verbose Output - 2024-11-27 - FGE: Added more Verbose Output #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventhouseName ) try { # Step 1: Handle ambiguous input if ($EventhouseId -and $EventhouseName) { Write-Message -Message "Both 'EventhouseId' and 'EventhouseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $eventhouses = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/eventhouses" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $eventhouses += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $eventhouse = if ($EventhouseId) { $eventhouses | Where-Object { $_.Id -eq $EventhouseId } } elseif ($EventhouseName) { $eventhouses | Where-Object { $_.DisplayName -eq $EventhouseName } } else { # Return all eventhouses if no filter is provided Write-Message -Message "No filter provided. Returning all Eventhouses." -Level Debug $eventhouses } # Step 9: Handle results if ($eventhouse) { Write-Message -Message "Eventhouse found in the Workspace '$WorkspaceId'." -Level Debug return $eventhouse } else { Write-Message -Message "No Eventhouse found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Eventhouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/Get-FabricEventhouse.ps1' 181 #Region './Public/Eventhouse/Get-FabricEventhouseDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of an Eventhouse from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves the definition of an Eventhouse from a specified workspace using the provided EventhouseId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventhouse exists. This parameter is mandatory. .PARAMETER EventhouseId The unique identifier of the Eventhouse to retrieve the definition for. This parameter is optional. .PARAMETER EventhouseFormat The format in which to retrieve the Eventhouse definition. This parameter is optional. .EXAMPLE Get-FabricEventhouseDefinition -WorkspaceId "workspace-12345" -EventhouseId "eventhouse-67890" This example retrieves the definition of the Eventhouse with ID "eventhouse-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricEventhouseDefinition -WorkspaceId "workspace-12345" -EventhouseId "eventhouse-67890" -EventhouseFormat "json" This example retrieves the definition of the Eventhouse with ID "eventhouse-67890" in the workspace with ID "workspace-12345" in JSON format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricEventhouseDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhouseFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventhouses/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventhouseId if ($EventhouseFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $EventhouseFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Eventhouse '$EventhouseId' definition retrieved successfully!" -Level Debug return $response } 202 { Write-Message -Message "Getting Eventhouse '$EventhouseId' definition request accepted. Retrieving in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Eventhouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/Get-FabricEventhouseDefinition.ps1' 123 #Region './Public/Eventhouse/New-FabricEventhouse.ps1' -1 function New-FabricEventhouse { <# .SYNOPSIS Creates a new Eventhouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Eventhouse in the specified workspace. It supports optional parameters for Eventhouse description and path definitions. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventhouse will be created. This parameter is mandatory. .PARAMETER EventhouseName The name of the Eventhouse to be created. This parameter is mandatory. .PARAMETER EventhouseDescription An optional description for the Eventhouse. .PARAMETER EventhousePathDefinition An optional path to the Eventhouse definition file to upload. .PARAMETER EventhousePathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE New-FabricEventhouse -WorkspaceId "workspace-12345" -EventhouseName "New Eventhouse" -EventhouseDescription "Description of the new Eventhouse" This example creates a new Eventhouse named "New Eventhouse" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventhouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhouseDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhousePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhousePathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventhouses" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EventhouseName } if ($EventhouseDescription) { $body.description = $EventhouseDescription } if ($EventhousePathDefinition) { $eventhouseEncodedContent = Convert-ToBase64 -filePath $EventhousePathDefinition if (-not [string]::IsNullOrEmpty($eventhouseEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "EventhouseProperties.json" payload = $eventhouseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Eventhouse definition." -Level Error return $null } } if ($EventhousePathPlatformDefinition) { $eventhouseEncodedPlatformContent = Convert-ToBase64 -filePath $EventhousePathPlatformDefinition if (-not [string]::IsNullOrEmpty($eventhouseEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $eventhouseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EventhouseName, "Create Eventhouse")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Eventhouse '$EventhouseName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Eventhouse '$EventhouseName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Eventhouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/New-FabricEventhouse.ps1' 216 #Region './Public/Eventhouse/Remove-FabricEventhouse.ps1' -1 function Remove-FabricEventhouse { <# .SYNOPSIS Removes an Eventhouse from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an Eventhouse from the specified workspace using the provided WorkspaceId and EventhouseId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the Eventhouse will be removed. .PARAMETER EventhouseId The unique identifier of the Eventhouse to be removed. .PARAMETER EventhouseName The name of the Eventhouse to delete. EventhouseId and EventhouseName cannot be used together. .EXAMPLE Remove-FabricEventhouse -WorkspaceId "workspace-12345" -EventhouseId "eventhouse-67890" This example removes the Eventhouse with ID "eventhouse-67890" from the workspace with ID "workspace-12345". .NOTES Revsion History: - 2024-11-07 - FGE: Implemented SupportShouldProcess - 2024-11-09 - FGE: Added DisplaName as Alias for EventhouseName - 2024-11-27 - FGE: Added Verbose Output .LINK https://learn.microsoft.com/en-us/rest/api/fabric/eventhouse/items/delete-eventhouse?tabs=HTTP - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventhouseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventhouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventhouseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Eventhouse")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle response if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Eventhouse '$EventhouseId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Eventhouse '$EventhouseId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/Remove-FabricEventhouse.ps1' 93 #Region './Public/Eventhouse/Update-FabricEventhouse.ps1' -1 <# .SYNOPSIS Updates an existing Eventhouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing Eventhouse in the specified workspace. It supports optional parameters for Eventhouse description. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventhouse exists. This parameter is optional. .PARAMETER EventhouseId The unique identifier of the Eventhouse to be updated. This parameter is mandatory. .PARAMETER EventhouseName The new name of the Eventhouse. This parameter is mandatory. .PARAMETER EventhouseDescription An optional new description for the Eventhouse. .EXAMPLE Update-FabricEventhouse -WorkspaceId "workspace-12345" -EventhouseId "eventhouse-67890" -EventhouseName "Updated Eventhouse" -EventhouseDescription "Updated description" This example updates the Eventhouse with ID "eventhouse-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricEventhouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventhouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventhouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhouseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventhouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventhouseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EventhouseName } if ($EventhouseDescription) { $body.description = $EventhouseDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess("Eventhouse", "Update")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Eventhouse '$EventhouseName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Eventhouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/Update-FabricEventhouse.ps1' 114 #Region './Public/Eventhouse/Update-FabricEventhouseDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of an existing Eventhouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the definition of an existing Eventhouse in the specified workspace. It supports optional parameters for Eventhouse definition and platform-specific definition. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventhouse exists. This parameter is mandatory. .PARAMETER EventhouseId The unique identifier of the Eventhouse to be updated. This parameter is mandatory. .PARAMETER EventhousePathDefinition An optional path to the Eventhouse definition file to upload. .PARAMETER EventhousePathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE Update-FabricEventhouseDefinition -WorkspaceId "workspace-12345" -EventhouseId "eventhouse-67890" -EventhousePathDefinition "C:\Path\To\EventhouseDefinition.json" This example updates the definition of the Eventhouse with ID "eventhouse-67890" in the workspace with ID "workspace-12345" using the provided definition file. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricEventhouseDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventhouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventhousePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventhousePathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventhouses/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventhouseId #if ($UpdateMetadata -eq $true) { if ($EventhousePathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($EventhousePathDefinition) { $EventhouseEncodedContent = Convert-ToBase64 -filePath $EventhousePathDefinition if (-not [string]::IsNullOrEmpty($EventhouseEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "EventhouseProperties.json" payload = $EventhouseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Eventhouse definition." -Level Error return $null } } if ($EventhousePathPlatformDefinition) { $EventhouseEncodedPlatformContent = Convert-ToBase64 -filePath $EventhousePathPlatformDefinition if (-not [string]::IsNullOrEmpty($EventhouseEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $EventhouseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess("Eventhouse", "Update")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for Eventhouse '$EventhouseId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for Eventhouse '$EventhouseId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Eventhouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventhouse/Update-FabricEventhouseDefinition.ps1' 187 #Region './Public/Eventstream/Get-FabricEventstream.ps1' -1 function Get-FabricEventstream { <# .SYNOPSIS Retrieves an Eventstream or a list of Eventstreams from a specified workspace in Microsoft Fabric. .DESCRIPTION Retrieves Fabric Eventstreams. Without the EventstreamName or EventstreamID parameter, all Eventstreams are returned. If you want to retrieve a specific Eventstream, you can use the EventstreamName or EventstreamID parameter. These parameters cannot be used together. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query Eventstreams. .PARAMETER EventstreamName (Optional) The name of the specific Eventstream to retrieve. .PARAMETER EventstreamId The Id of the Eventstream to retrieve. This parameter cannot be used together with EventstreamName. The value for EventstreamId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .EXAMPLE Get-FabricEventstream -WorkspaceId "12345" -EventstreamName "Development" Retrieves the "Development" Eventstream from workspace "12345". .EXAMPLE Get-FabricEventstream -WorkspaceId "12345" Retrieves all Eventstreams in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventstreamName ) try { # Step 1: Handle ambiguous input if ($EventstreamId -and $EventstreamName) { Write-Message -Message "Both 'EventstreamId' and 'EventstreamName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $continuationToken = $null $eventstreams = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/eventstreams" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $eventstreams += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $eventstream = if ($EventstreamId) { $eventstreams | Where-Object { $_.Id -eq $EventstreamId } } elseif ($EventstreamName) { $eventstreams | Where-Object { $_.DisplayName -eq $EventstreamName } } else { # Return all eventstreams if no filter is provided Write-Message -Message "No filter provided. Returning all Eventstreams." -Level Debug $eventstreams } # Step 9: Handle results if ($eventstream) { Write-Message -Message "Eventstream found matching the specified criteria." -Level Debug return $eventstream } else { Write-Message -Message "No Eventstream found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Eventstream. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/Get-FabricEventstream.ps1' 160 #Region './Public/Eventstream/Get-FabricEventstreamDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a Eventstream from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the Eventstream's content or metadata from a workspace. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the Eventstream definition is to be retrieved. .PARAMETER EventstreamId (Optional)The unique identifier of the Eventstream whose definition needs to be retrieved. .PARAMETER EventstreamFormat Specifies the format of the Eventstream definition. Currently, only 'ipynb' is supported. Default: 'ipynb'. .EXAMPLE Get-FabricEventstreamDefinition -WorkspaceId "12345" -EventstreamId "67890" Retrieves the definition of the Eventstream with ID `67890` from the workspace with ID `12345` in the `ipynb` format. .EXAMPLE Get-FabricEventstreamDefinition -WorkspaceId "12345" Retrieves the definitions of all Eventstreams in the workspace with ID `12345` in the `ipynb` format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricEventstreamDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/Eventstreams/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventstreamId if ($EventstreamFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $EventstreamFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Eventstream '$EventstreamId' definition retrieved successfully!" -Level Info return $response.definition.parts } 202 { Write-Message -Message "Getting Eventstream '$EventstreamId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Eventstream. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/Get-FabricEventstreamDefinition.ps1' 120 #Region './Public/Eventstream/New-FabricEventstream.ps1' -1 function New-FabricEventstream { <# .SYNOPSIS Creates a new Eventstream in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Eventstream in the specified workspace. It supports optional parameters for Eventstream description and path definitions for the Eventstream content. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventstream will be created. .PARAMETER EventstreamName The name of the Eventstream to be created. .PARAMETER EventstreamDescription An optional description for the Eventstream. .PARAMETER EventstreamPathDefinition An optional path to the Eventstream definition file (e.g., .ipynb file) to upload. .PARAMETER EventstreamPathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE #TODO Fix example name Add-FabricEventstream -WorkspaceId "workspace-12345" -EventstreamName "New Eventstream" -EventstreamPathDefinition "C:\Eventstreams\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> #TODO SupportsShouldProcess [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventstreamName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventstreams" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EventstreamName } if ($EventstreamDescription) { $body.description = $EventstreamDescription } if ($EventstreamPathDefinition) { $EventstreamEncodedContent = Convert-ToBase64 -filePath $EventstreamPathDefinition if (-not [string]::IsNullOrEmpty($EventstreamEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "eventstream" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "eventstream.json" payload = $EventstreamEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Eventstream definition." -Level Error return $null } } if ($EventstreamPathPlatformDefinition) { $EventstreamEncodedPlatformContent = Convert-ToBase64 -filePath $EventstreamPathPlatformDefinition if (-not [string]::IsNullOrEmpty($EventstreamEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "eventstream" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $EventstreamEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EventstreamName, "Create Eventstream")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Eventstream '$EventstreamName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Eventstream '$EventstreamName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Eventstream. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/New-FabricEventstream.ps1' 211 #Region './Public/Eventstream/Remove-FabricEventstream.ps1' -1 function Remove-FabricEventstream { <# .SYNOPSIS Deletes an Eventstream from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricEventstream` function sends a DELETE request to the Fabric API to remove a specified Eventstream from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the Eventstream to delete. .PARAMETER EventstreamId (Mandatory) The ID of the Eventstream to be deleted. .PARAMETER EventstreamName The name of the Eventstream to delete. The value for Eventstream is a string. An example of a string is 'MyEventstream'. The name of the Eventstream to delete. The value for Eventstream is a string. .EXAMPLE Remove-FabricEventstream -WorkspaceId "12345" -EventstreamId "67890" Deletes the Eventstream with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventstreamId #TODO Add EventstreamName parameter to validate the name of the Eventstream to delete. ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventstreams/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventstreamId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Eventstream")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Eventstream '$EventstreamId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Eventstream '$EventstreamId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/Remove-FabricEventstream.ps1' 86 #Region './Public/Eventstream/Update-FabricEventstream.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric Eventstream. .DESCRIPTION The `Update-FabricEventstream` function updates the name and/or description of a specified Fabric Eventstream by making a PATCH request to the API. .PARAMETER EventstreamId The unique identifier of the Eventstream to be updated. .PARAMETER EventstreamName The new name for the Eventstream. .PARAMETER EventstreamDescription (Optional) The new description for the Eventstream. .PARAMETER WorkspaceId The unique identifier of the workspace where the Eventstream resides. .EXAMPLE Update-FabricEventstream -EventstreamId "Eventstream123" -EventstreamName "NewEventstreamName" Updates the name of the Eventstream with the ID "Eventstream123" to "NewEventstreamName". .EXAMPLE Update-FabricEventstream -EventstreamId "Eventstream123" -EventstreamName "NewName" -EventstreamDescription "Updated description" Updates both the name and description of the Eventstream "Eventstream123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricEventstream { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventstreamId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$EventstreamName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventstreams/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventstreamId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $EventstreamName } if ($EventstreamDescription) { $body.description = $EventstreamDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EventstreamId, "Update Eventstream")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Eventstream '$EventstreamName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Eventstream. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/Update-FabricEventstream.ps1' 117 #Region './Public/Eventstream/Update-FabricEventstreamDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a Eventstream in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a Eventstream in a Microsoft Fabric workspace. The Eventstream content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the Eventstream resides. .PARAMETER EventstreamId (Mandatory) The unique identifier of the Eventstream to be updated. .PARAMETER EventstreamPathDefinition (Mandatory) The file path to the Eventstream content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER EventstreamPathPlatformDefinition (Optional) The file path to the Eventstream's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER UpdateMetadata (Optional)A boolean flag indicating whether to update the Eventstream's metadata. Default: `$false`. .EXAMPLE Update-FabricEventstreamDefinition -WorkspaceId "12345" -EventstreamId "67890" -EventstreamPathDefinition "C:\Eventstreams\Eventstream.ipynb" Updates the content of the Eventstream with ID `67890` in the workspace `12345` using the specified Eventstream file. .EXAMPLE Update-FabricEventstreamDefinition -WorkspaceId "12345" -EventstreamId "67890" -EventstreamPathDefinition "C:\Eventstreams\Eventstream.ipynb" -UpdateMetadata $true Updates both the content and metadata of the Eventstream with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The Eventstream content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricEventstreamDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventstreamId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$EventstreamPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EventstreamPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/eventstreams/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $EventstreamId if ($EventstreamPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($EventstreamPathDefinition) { $EventstreamEncodedContent = Convert-ToBase64 -filePath $EventstreamPathDefinition if (-not [string]::IsNullOrEmpty($EventstreamEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "eventstream.json" payload = $EventstreamEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Eventstream definition." -Level Error return $null } } if ($EventstreamPathPlatformDefinition) { $EventstreamEncodedPlatformContent = Convert-ToBase64 -filePath $EventstreamPathPlatformDefinition if (-not [string]::IsNullOrEmpty($EventstreamEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $EventstreamEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($EventstreamId, "Update Eventstream")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for Eventstream '$EventstreamId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for Eventstream '$EventstreamId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Eventstream. Error: $errorDetails" -Level Error } } #EndRegion './Public/Eventstream/Update-FabricEventstreamDefinition.ps1' 199 #Region './Public/External Data Share/Get-FabricExternalDataShares.ps1' -1 <# .SYNOPSIS Retrieves External Data Shares details from a specified Microsoft Fabric. .DESCRIPTION This function retrieves External Data Shares details. It handles token validation, constructs the API URL, makes the API request, and processes the response. .EXAMPLE Get-FabricExternalDataShares This example retrieves the External Data Shares details .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricExternalDataShares { [CmdletBinding()] param ( ) try { # Validate authentication token before proceeding Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Construct the API endpoint URI for retrieving external data shares Write-Message -Message "Constructing API endpoint URI..." -Level Debug $apiEndpointURI = "{0}/admin/items/externalDataShares" -f $FabricConfig.BaseUrl, $WorkspaceId # Invoke the API request to retrieve external data shares $externalDataShares = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get # Return the retrieved external data shares Write-Message -Message "Successfully retrieved external data shares." -Level Debug return $externalDataShares } catch { # Capture and log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve External Data Shares. Error: $errorDetails" -Level Error } } #EndRegion './Public/External Data Share/Get-FabricExternalDataShares.ps1' 50 #Region './Public/External Data Share/Revoke-FabricExternalDataShares.ps1' -1 function Revoke-FabricExternalDataShares { <# .SYNOPSIS Retrieves External Data Shares details from a specified Microsoft Fabric. .DESCRIPTION This function retrieves External Data Shares details. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the External Data Shares resides. .PARAMETER ItemId The unique identifier of the item associated with the External Data Shares. .PARAMETER ExternalDataShareId The unique identifier of the External Data Share to be retrieved. .EXAMPLE Get-FabricExternalDataShares This example retrieves the External Data Shares details .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ItemId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ExternalDataShareId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Constructing API endpoint URI..." -Level Debug $apiEndpointURI = "{0}/admin/workspaces/{1}/items/{2}/externalDataShares/{3}/revoke" -f $FabricConfig.BaseUrl, $WorkspaceId, $ItemId, $ExternalDataShareId if ($PSCmdlet.ShouldProcess("$ExternalDataShareId", "revoke")) { $externalDataShares = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Post } # Step 4: Return retrieved data Write-Message -Message "Successfully revoked external data shares." -Level Info return $externalDataShares } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve External Data Shares. Error: $errorDetails" -Level Error } } #EndRegion './Public/External Data Share/Revoke-FabricExternalDataShares.ps1' 74 #Region './Public/Get-AllFabricDatasetRefreshes.ps1' -1 function Get-FabricDatasetRefreshes { <# .SYNOPSIS Retrieves all refreshes for all datasets in all PowerBI workspaces. .DESCRIPTION The Get-FabricDatasetRefreshes function retrieves all refreshes for all datasets in all PowerBI workspaces. It supports multiple aliases for flexibility. .EXAMPLE Get-FabricDatasetRefreshes This example retrieves all refreshes for all datasets in all PowerBI workspaces. .NOTES The function makes a GET request to the PowerBI API to retrieve the refreshes. It loops through each workspace and each dataset in each workspace. If a dataset is refreshable, it retrieves the refreshes for the dataset and selects the most recent one. It then creates a PSCustomObject with information about the refresh and adds it to an array of refreshes. Finally, it returns the array of refreshes. #> # This function retrieves all refreshes for all datasets in all PowerBI workspaces. # Define aliases for the function for flexibility. Confirm-FabricAuthToken | Out-Null # Retrieve all PowerBI workspaces. $wsps = Get-FabricWorkspace # Initialize an array to store the refreshes. $refs = @() # Loop through each workspace. foreach ($w in $wsps) { # Get a list of all the datasets in the workspace. $d = Get-FabricDataset -workspaceid $w.Id -ErrorAction SilentlyContinue # Loop through each dataset. foreach ($di in $d) { # Check if the dataset is refreshable. if ($di.isrefreshable ) { # Get a list of all the refreshes for the dataset. $results = (Invoke-PowerBIRestMethod -Method get -Url ("datasets/" + $di.id + "/Refreshes") | ConvertFrom-Json) # Select the most recent refresh. $results.value[0] # Create a PSCustomObject with the information about the refresh. $refresh = [PSCustomObject] @{ Clock = Get-Date # Current date and time. Workspace = $w.name # Name of the workspace. Dataset = $di.Name # Name of the dataset. refreshtype = $results.value[0].refreshType # Type of the refresh. startTime = $results.value[0].startTime # Start time of the refresh. endTime = $results.value[0].endTime # End time of the refresh. status = $results.value[0].status # Status of the refresh. ErrorMessage = $results.value[0].serviceExceptionJson # Error message of the refresh, if any. } # Add the refresh to the array of refreshes. $refs += $refresh } } } # Return the array of refreshes. return $refs } #EndRegion './Public/Get-AllFabricDatasetRefreshes.ps1' 58 #Region './Public/Get-FabricAPIClusterURI.ps1' -1 function Get-FabricAPIclusterURI { <# .SYNOPSIS Retrieves the cluster URI for the tenant. .DESCRIPTION The Get-FabricAPIclusterURI function retrieves the cluster URI for the tenant. It supports multiple aliases for flexibility. .EXAMPLE Get-FabricAPIclusterURI This example retrieves the cluster URI for the tenant. .NOTES The function retrieves the PowerBI access token and makes a GET request to the PowerBI API to retrieve the datasets. It then extracts the '@odata.context' property from the response, splits it on the '/' character, and selects the third element. This element is used to construct the cluster URI, which is then returned by the function. #> #This function retrieves the cluster URI for the tenant. # Define aliases for the function for flexibility. [Alias("Get-FabAPIClusterURI")] [CmdletBinding()] [OutputType([string])] Param ( ) Confirm-FabricAuthToken | Out-Null # Make a GET request to the PowerBI API to retrieve the datasets. $reply = Invoke-RestMethod -uri "$($PowerBI.BaseApiUrl)/datasets" -Headers $FabricSession.HeaderParams -Method GET # Extract the '@odata.context' property from the response. $unaltered = $reply.'@odata.context' # Split the '@odata.context' property on the '/' character and select the third element. $stripped = $unaltered.split('/')[2] # Construct the cluster URI. $clusterURI = "https://$stripped/beta/myorg/groups" # Return the cluster URI. return $clusterURI } #EndRegion './Public/Get-FabricAPIClusterURI.ps1' 44 #Region './Public/Get-FabricAuthToken.ps1' -1 <# .SYNOPSIS Retrieves the Fabric API authentication token. .DESCRIPTION The Get-FabricAuthToken function retrieves the Fabric API authentication token. If the token is not already set, it calls the Set-FabricAuthToken function to set it. It then outputs the token. .EXAMPLE Get-FabricAuthToken This command retrieves the Fabric API authentication token. .INPUTS None. You cannot pipe inputs to this function. .OUTPUTS String. This function returns the Fabric API authentication token. .NOTES This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> function Get-FabricAuthToken { [Alias("Get-FabAuthToken")] [CmdletBinding()] param ( ) # Check if the Fabric token is already set if (!$FabricSession.FabricToken) { # If not, set the Fabric token Set-FabricAuthToken } # Output the Fabric token return $FabricSession.FabricToken } #EndRegion './Public/Get-FabricAuthToken.ps1' 40 #Region './Public/Get-FabricConnection.ps1' -1 function Get-FabricConnection { <# .SYNOPSIS Retrieves Fabric connections. .DESCRIPTION The Get-FabricConnection function retrieves Fabric connections. It can retrieve all connections or the specified one only. .PARAMETER connectionId The ID of the connection to retrieve. .EXAMPLE Get-FabricConnection This example retrieves all connections from Fabric .EXAMPLE Get-FabricConnection -connectionId "12345" This example retrieves specific connection from Fabric with ID "12345". .NOTES https://learn.microsoft.com/en-us/rest/api/fabric/core/connections/get-connection?tabs=HTTP https://learn.microsoft.com/en-us/rest/api/fabric/core/connections/list-connections?tabs=HTTP #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$connectionId ) begin { Confirm-FabricAuthToken | Out-Null } process { if ($connectionId) { $result = Invoke-FabricAPIRequest -Uri "/connections/$($connectionId)" -Method GET } else { $result = Invoke-FabricAPIRequest -Uri "/connections" -Method GET } return $result.value } } #EndRegion './Public/Get-FabricConnection.ps1' 47 #Region './Public/Get-FabricDatasetRefreshes.ps1' -1 <# .SYNOPSIS Retrieves the refresh history of a specified dataset in a PowerBI workspace. .DESCRIPTION The Get-FabricDatasetRefreshes function uses the PowerBI cmdlets to retrieve the refresh history of a specified dataset in a workspace. It uses the dataset ID and workspace ID to get the dataset and checks if it is refreshable. If it is, the function retrieves the refresh history. .PARAMETER DatasetID The ID of the dataset. This is a mandatory parameter. .PARAMETER workspaceId The ID of the workspace. This is a mandatory parameter. .EXAMPLE Get-FabricDatasetRefreshes -DatasetID "12345678-90ab-cdef-1234-567890abcdef" -workspaceId "abcdef12-3456-7890-abcd-ef1234567890" This command retrieves the refresh history of the specified dataset in the specified workspace. .INPUTS String. You can pipe two strings that contain the dataset ID and workspace ID to Get-FabricDatasetRefreshes. .OUTPUTS Object. Get-FabricDatasetRefreshes returns an object that contains the refresh history. .NOTES Alias: Get-PowerBIDatasetRefreshes, Get-FabricDatasetRefreshes #> function Get-FabricDatasetRefreshes { # Define aliases for the function for flexibility. [Alias("Get-FabDatasetRefreshes")] # Define a mandatory parameter for the dataset ID. Param ( [Parameter(Mandatory = $true)] [string]$DatasetID, [Parameter(Mandatory = $true)] [string]$workspaceId ) # Get the dataset information. $di = Get-PowerBIDataset -id $DatasetID -WorkspaceId $workspaceId # Check if the dataset is refreshable. if ($di.isrefreshable -eq "True") { # Get a list of all the refreshes for the dataset. $results = (Invoke-PowerBIRestMethod -Method get -Url ("datasets/" + $di.id + "/Refreshes") | ConvertFrom-Json) # Create a PSCustomObject with the information about the refresh. $refresh = [PSCustomObject]@{ Clock = Get-Date Workspace = $w.name Dataset = $di.Name refreshtype = $results.value[0].refreshType startTime = $results.value[0].startTime endTime = $results.value[0].endTime status = $results.value[0].status ErrorMessage = $results.value[0].serviceExceptionJson } # Return the PSCustomObject. return $refresh } else { # If the dataset is not refreshable, return null. Write-Warning "Dataset is not refreshable." return $null } } #EndRegion './Public/Get-FabricDatasetRefreshes.ps1' 70 #Region './Public/Get-FabricDebugInfo.ps1' -1 function Get-FabricDebugInfo { <# .SYNOPSIS Shows internal debug information about the current session. .DESCRIPTION Shows internal debug information about the current session. It is useful for troubleshooting purposes. It will show you the current session object. This includes the bearer token. This can be useful for connecting to the REST API directly via Postman. .Example Get-FabricDebugInfo This example shows the current session object. .NOTES Revsion History: - 2024-12-22 - FGE: Added Verbose Output #> [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( ) begin { } process { Write-Verbose "Show current session object" return @{ FabricSession = $script:FabricSession AzureSession = $script:AzureSession FabricConfig = $script:FabricConfig } } end { } } #EndRegion './Public/Get-FabricDebugInfo.ps1' 47 #Region './Public/Get-FabricUsageMetricsQuery.ps1' -1 function Get-FabricUsageMetricsQuery { <# .SYNOPSIS Retrieves usage metrics for a specific dataset. .DESCRIPTION The Get-FabricUsageMetricsQuery function retrieves usage metrics for a specific dataset. It supports multiple aliases for flexibility. .PARAMETER DatasetID The ID of the dataset. This is a mandatory parameter. .PARAMETER groupId The ID of the group. This is a mandatory parameter. .PARAMETER reportname The name of the report. This is a mandatory parameter. .PARAMETER token The access token. This is a mandatory parameter. .PARAMETER ImpersonatedUser The name of the impersonated user. This is an optional parameter. .PARAMETER authToken The authentication token. This is an optional parameter. .EXAMPLE Get-FabricUsageMetricsQuery -DatasetID "your-dataset-id" -groupId "your-group-id" -reportname "your-report-name" -token "your-token" This example retrieves the usage metrics for a specific dataset given the dataset ID, group ID, report name, and token. .NOTES The function defines the headers and body for a POST request to the PowerBI API to retrieve the usage metrics for the specified dataset. It then makes the POST request and returns the response. #> # This function retrieves usage metrics for a specific dataset. # Define aliases for the function for flexibility. [Alias("Get-FabUsageMetricsQuery")] # Define parameters for the dataset ID, group ID, report name, token, and impersonated user. param ( [Parameter(Mandatory = $true)] [string]$DatasetID, [Parameter(Mandatory = $true)] [string]$groupId, [Parameter(Mandatory = $true)] $reportname, [Parameter(Mandatory = $false)] [string]$ImpersonatedUser = "" ) # Confirm the authentication token. Confirm-FabricAuthToken | Out-Null # Define the body of the POST request. if ($ImpersonatedUser -ne "") { $reportbody = '{ "queries": [ { "query": "EVALUATE VALUES(' + $reportname + ')" } ], "serializerSettings": { "includeNulls": true }, "impersonatedUserName": "' + $ImpersonatedUser + '" }' } else { $reportbody = '{ "queries": [ { "query": "EVALUATE VALUES(' + $reportname + ')" } ], "serializerSettings": { "includeNulls": true } }' } # Make a POST request to the PowerBI API to retrieve the usage metrics for the specified dataset. # The function returns the response of the POST request. return Invoke-RestMethod -uri "$($PowerBI.BaseApiUrl)/groups/$groupId/datasets/$DatasetID/executeQueries" -Headers $FabricSession.HeaderParams -Body $reportbody -Method Post } #EndRegion './Public/Get-FabricUsageMetricsQuery.ps1' 84 #Region './Public/Get-SHA256.ps1' -1 function Get-Sha256 ($string) { <# .SYNOPSIS Calculates the SHA256 hash of a string. .DESCRIPTION The Get-Sha256 function calculates the SHA256 hash of a string. .PARAMETER string The string to hash. This is a mandatory parameter. .EXAMPLE Get-Sha256 -string "your-string" This example calculates the SHA256 hash of a string. .NOTES The function creates a new SHA256CryptoServiceProvider object, converts the string to a byte array using UTF8 encoding, computes the SHA256 hash of the byte array, converts the hash to a string and removes any hyphens, and returns the resulting hash. #> # This function calculates the SHA256 hash of a string. # Create a new SHA256CryptoServiceProvider object. $sha256 = New-Object System.Security.Cryptography.SHA256CryptoServiceProvider # Convert the string to a byte array using UTF8 encoding. $bytes = [System.Text.Encoding]::UTF8.GetBytes($string) # Compute the SHA256 hash of the byte array. $hash = $sha256.ComputeHash($bytes) # Convert the hash to a string and remove any hyphens. $result = [System.BitConverter]::ToString($hash) -replace '-' # Return the resulting hash. return $result } #EndRegion './Public/Get-SHA256.ps1' 38 #Region './Public/Invoke-FabricAPIRequest.ps1' -1 Function Invoke-FabricAPIRequest { <# .SYNOPSIS Sends an HTTP request to a Fabric API endpoint and retrieves the response. Takes care of: authentication, 429 throttling, Long-Running-Operation (LRO) response .DESCRIPTION The Invoke-FabricAPIRequest function is used to send an HTTP request to a Fabric API endpoint and retrieve the response. It handles various aspects such as authentication, 429 throttling, and Long-Running-Operation (LRO) response. .PARAMETER authToken The authentication token to be used for the request. If not provided, it will be obtained using the Get-FabricAuthToken function. .PARAMETER uri The URI of the Fabric API endpoint to send the request to. .PARAMETER method The HTTP method to be used for the request. Valid values are 'Get', 'Post', 'Delete', 'Put', and 'Patch'. The default value is 'Get'. .PARAMETER body The body of the request, if applicable. .PARAMETER contentType The content type of the request. The default value is 'application/json; charset=utf-8'. .PARAMETER timeoutSec The timeout duration for the request in seconds. The default value is 240 seconds. .PARAMETER outFile The file path to save the response content to, if applicable. .PARAMETER retryCount The number of times to retry the request in case of a 429 (Too Many Requests) error. The default value is 0. .EXAMPLE Invoke-FabricAPIRequest -uri "/api/resource" -method "Get" This example sends a GET request to the "/api/resource" endpoint of the Fabric API. .EXAMPLE Invoke-FabricAPIRequest -authToken "abc123" -uri "/api/resource" -method "Post" -body $requestBody This example sends a POST request to the "/api/resource" endpoint of the Fabric API with a request body. .NOTES This function requires the Get-FabricAuthToken function to be defined in the same script or module. This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string] $authToken, [Parameter(Mandatory = $true)] [string] $uri, [Parameter(Mandatory = $false)] [ValidateSet('Get', 'Post', 'Delete', 'Put', 'Patch')] [string] $method = "Get", [Parameter(Mandatory = $false)] $body, [Parameter(Mandatory = $false)] [string] $contentType = "application/json; charset=utf-8", [Parameter(Mandatory = $false)] [int] $timeoutSec = 240, [Parameter(Mandatory = $false)] [int] $retryCount = 0 ) Confirm-FabricAuthToken | Out-Null $fabricHeaders = $FabricSession.HeaderParams try { $requestUrl = "$($FabricSession.BaseApiUrl)/$uri" Write-Verbose "Calling $requestUrl" $response = Invoke-WebRequest -Headers $fabricHeaders -ContentType $contentType -Method $method -Uri $requestUrl -Body $body -TimeoutSec $timeoutSec if ($response.StatusCode -eq 202) { if ($uri -match "jobType=Pipeline") { Write-Output "Waiting for pipeline to complete. Please check the status in the Power BI Service." } else { do { $asyncUrl = [string]$response.Headers.Location Write-Output "Waiting for request to complete. Sleeping..." Start-Sleep -Seconds 5 $response2 = Invoke-WebRequest -Headers $fabricHeaders -Method Get -Uri $asyncUrl $lroStatusContent = $response2.Content | ConvertFrom-Json } while ($lroStatusContent.status -ine "succeeded" -and $lroStatusContent.status -ine "failed") try { $response = Invoke-WebRequest -Headers $fabricHeaders -Method Get -Uri "$asyncUrl/result" } catch { Write-Output "No result URL" } } } #if ($response.StatusCode -in @(200,201) -and $response.Content) if ($response.Content) { $contentBytes = $response.RawContentStream.ToArray() if ($contentBytes[0] -eq 0xef -and $contentBytes[1] -eq 0xbb -and $contentBytes[2] -eq 0xbf) { $contentText = [System.Text.Encoding]::UTF8.GetString($contentBytes[3..$contentBytes.Length]) } else { $contentText = $response.Content } $jsonResult = $contentText | ConvertFrom-Json Write-Output $jsonResult -NoEnumerate } else { Write-Output $response -NoEnumerate } } catch { $ex = $_.Exception $message = $null if ($null -ne $ex.Response) { $responseStatusCode = [int]$ex.Response.StatusCode if ($responseStatusCode -in @(429)) { if ($ex.Response.Headers.RetryAfter) { $retryAfterSeconds = $ex.Response.Headers.RetryAfter.Delta.TotalSeconds + 5 } if (!$retryAfterSeconds) { $retryAfterSeconds = 60 } Write-Output "Exceeded the amount of calls (TooManyRequests - 429), sleeping for $retryAfterSeconds seconds." Start-Sleep -Seconds $retryAfterSeconds $maxRetries = 3 if ($retryCount -le $maxRetries) { Invoke-FabricAPIRequest -authToken $authToken -uri $uri -method $method -body $body -contentType $contentType -timeoutSec $timeoutSec -retryCount ($retryCount + 1) } else { throw "Exceeded the amount of retries ($maxRetries) after 429 error." } } else { $apiErrorObj = $ex.Response.Headers | Where-Object { $_.key -ieq "x-ms-public-api-error-code" } | Select-Object -First 1 if ($apiErrorObj) { $apiError = $apiErrorObj.Value[0] } if ($apiError -ieq "ItemHasProtectedLabel") { Write-Warning "Item has a protected label." } else { throw } # TODO: Investigate why response.Content is empty but powershell can read it on throw #$errorContent = $ex.Response.Content.ReadAsStringAsync().Result; #$message = "$($ex.Message) - StatusCode: '$($ex.Response.StatusCode)'; Content: '$errorContent'" } } else { $message = "$($ex.Message)" } if ($message) { throw $message } } } #EndRegion './Public/Invoke-FabricAPIRequest.ps1' 174 #Region './Public/Invoke-FabricDatasetRefresh.ps1' -1 <# .SYNOPSIS This function invokes a refresh of a PowerBI dataset .DESCRIPTION The Invoke-FabricDatasetRefresh function is used to refresh a PowerBI dataset. It first checks if the dataset is refreshable. If it is not, it writes an error. If it is, it invokes a PowerBI REST method to refresh the dataset. The URL for the request is constructed using the provided dataset ID. .PARAMETER DatasetID A mandatory parameter that specifies the dataset ID. .EXAMPLE Invoke-FabricDatasetRefresh -DatasetID "12345678-1234-1234-1234-123456789012" This command invokes a refresh of the dataset with the ID "12345678-1234-1234-1234-123456789012" .NOTES Alias: Invoke-FabDatasetRetresh #> function Invoke-FabricDatasetRefresh { # Define aliases for the function for flexibility. [Alias("Invoke-FabDatasetRefresh")] # Define parameters for the workspace ID and dataset ID. param( # Mandatory parameter for the dataset ID [Parameter(Mandatory = $true, ParameterSetName = "DatasetId")] [string]$DatasetID ) Confirm-FabricAuthToken | Out-Null # Check if the dataset is refreshable if ((Get-FabricDataset -DatasetId $DatasetID).isrefreshable -eq $false) { # If the dataset is not refreshable, write an error Write-Error "Dataset is not refreshable" } else { # If the dataset is refreshable, invoke a PowerBI REST method to refresh the dataset # The URL for the request is constructed using the provided workspace ID and dataset ID. # Check if the dataset is refreshable # If the dataset is refreshable, invoke a PowerBI REST method to refresh the dataset # The URL for the request is constructed using the provided workspace ID and dataset ID. return Invoke-RestMethod -Method POST -uri ("$($PowerBI.BaseApiUrl)/datasets/$datasetid/refreshes") -Headers $FabricSession.HeaderParams } } #EndRegion './Public/Invoke-FabricDatasetRefresh.ps1' 47 #Region './Public/Item/Export-FabricItem.ps1' -1 <# .SYNOPSIS Exports items from a Fabric workspace. Either all items in a workspace or a specific item. .DESCRIPTION The Export-FabricItem function exports items from a Fabric workspace to a specified directory. It can export items of type "Report", "SemanticModel", "SparkJobDefinitionV1" or "Notebook". If a specific item ID is provided, only that item will be exported. Otherwise, all items in the workspace will be exported. .PARAMETER path The path to the directory where the items will be exported. The default value is '.\pbipOutput'. .PARAMETER workspaceId The ID of the Fabric workspace. .PARAMETER filter A script block used to filter the items to be exported. Only items that match the filter will be exported. The default filter includes items of type "Report", "SemanticModel", "SparkJobDefinitionV1" or "Notebook". .PARAMETER itemID The ID of the specific item to export. If provided, only that item will be exported. .EXAMPLE Export-FabricItem -workspaceId "12345678-1234-1234-1234-1234567890AB" -path "C:\ExportedItems" This example exports all items from the Fabric workspace with the specified ID to the "C:\ExportedItems" directory. .EXAMPLE Export-FabricItem -workspaceId "12345678-1234-1234-1234-1234567890AB" -itemID "98765432-4321-4321-4321-9876543210BA" -path "C:\ExportedItems" This example exports the item with the specified ID from the Fabric workspace with the specified ID to the "C:\ExportedItems" directory. .NOTES This function is based on the Export-FabricItems function written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> Function Export-FabricItem { [Alias("Export-FabItem")] [CmdletBinding()] param ( [string]$path = '.\pbipOutput', [string]$workspaceId = '', [scriptblock]$filter = { $_.type -in @("Report", "SemanticModel", "Notebook", "SparkJobDefinitionV1") }, [string]$itemID = '' ) if (![string]::IsNullOrEmpty($itemID)) { # Invoke the Fabric API to get the specific item in the workspace $item = Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items/$itemID/getDefinition" -Method POST # If a filter is provided $parts = $item.definition.parts if (!(Test-Path $path)) { New-Item -ItemType Directory -Force -Path $path } foreach ($part in $parts) { $filename = $part.path $payload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($part.payload)) $payload | Out-File -FilePath "$path\$filename" } # Display a message indicating the items were exported Write-Output "Items exported to $path" } else { $items = Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items" -Method Get if ($filter) { $items = $items.value | Where-Object $filter } else { $items = $items.value } Write-Output "Existing items: $($items.Count)" foreach ($item in $items) { $itemId = $item.id $itemName = $item.displayName $itemType = $item.type $itemOutputPath = "$path\$workspaceId\$($itemName).$($itemType)" if ($itemType -in @("report", "semanticmodel", "notebook", "SparkJobDefinitionV1", "DataPipeline")) { Write-Output "Getting definition of: $itemId / $itemName / $itemType" $response = Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items/$itemId/getDefinition" -Method Post $partCount = $response.definition.parts.Count Write-Output "Parts: $partCount" if ($partCount -gt 0) { foreach ($part in $response.definition.parts) { Write-Output "Saving part: $($part.path)" $outputFilePath = "$itemOutputPath\$($part.path.Replace("/", "\"))" New-Item -ItemType Directory -Path (Split-Path $outputFilePath -Parent) -ErrorAction SilentlyContinue | Out-Null $payload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($part.payload)) $payload | Out-File -FilePath "$outputFilePath" } @{ "type" = $itemType "displayName" = $itemName } | ConvertTo-Json | Out-File "$itemOutputPath\item.metadata.json" } } else { Write-Output "Type '$itemType' not available for export." } } } } #EndRegion './Public/Item/Export-FabricItem.ps1' 115 #Region './Public/Item/Get-FabricItem.ps1' -1 function Get-FabricItem { <# .SYNOPSIS Retrieves fabric items from a workspace. .DESCRIPTION The Get-FabricItem function retrieves fabric items from a specified workspace. It can retrieve all items or filter them by item type. .PARAMETER workspaceId The ID of the workspace from which to retrieve the fabric items. .PARAMETER Workspace The workspace object from which to retrieve the fabric items. This parameter can be piped into the function. .PARAMETER itemID The ID of the specific item to retrieve. If not specified, all items will be retrieved. .PARAMETER type (Optional) The type of the fabric items to retrieve. If not specified, all items will be retrieved. .EXAMPLE Get-FabricItem -workspaceId "12345" -type "file" This example retrieves all fabric items of type "file" from the workspace with ID "12345". .NOTES This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceId')] [string]$workspaceId, [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceObject', ValueFromPipeline = $true )] $Workspace, [Parameter(Mandatory = $false)] [Alias("itemType")] [string]$type, [Parameter(Mandatory = $false)] [string]$itemID ) begin { Confirm-FabricAuthToken | Out-Null } process { if ($PSCmdlet.ParameterSetName -eq 'WorkspaceObject') { $workspaceID = $Workspace.id } if ($itemID) { $result = Invoke-FabricAPIRequest -Uri "workspaces/$($workspaceID)/items/$($itemID)" -Method Get } else { if ($type) { $result = Invoke-FabricAPIRequest -Uri "workspaces/$($workspaceID)/items?type=$type" -Method Get } else { # Invoke the Fabric API to get the workspaces $result = Invoke-FabricAPIRequest -Uri "workspaces/$($workspaceID)/items" -Method Get } # Output the result return $result.value } } } #EndRegion './Public/Item/Get-FabricItem.ps1' 70 #Region './Public/Item/Import-FabricItem.ps1' -1 <# .SYNOPSIS Imports items using the Power BI Project format (PBIP) into a Fabric workspace from a specified file system source. .DESCRIPTION The Import-FabricItem function imports items using the Power BI Project format (PBIP) into a Fabric workspace from a specified file system source. It supports multiple aliases for flexibility. The function handles the import of datasets and reports, ensuring that the correct item type is used and that the items are created or updated as necessary. .PARAMETER fileOverrides This parameter let's you override a PBIP file without altering the local file. .PARAMETER path The path to the PBIP files. Default value is '.\pbipOutput'. .PARAMETER workspaceId The ID of the Fabric workspace. .PARAMETER filter A filter to limit the search for PBIP files to specific folders. .EXAMPLE Import-FabricItems -path 'C:\PBIPFiles' -workspaceId '12345' -filter 'C:\PBIPFiles\Reports' This example imports PBIP files from the 'C:\PBIPFiles' folder into the Fabric workspace with ID '12345'. It only searches for PBIP files in the 'C:\PBIPFiles\Reports' folder. .NOTES This function requires the Invoke-FabricAPIRequest function to be available in the current session. This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> Function Import-FabricItem { <# .SYNOPSIS Imports items using the Power BI Project format (PBIP) into a Fabric workspace from a specified file system source. .PARAMETER fileOverrides This parameter let's you override a PBIP file without altering the local file. #> [CmdletBinding(SupportsShouldProcess)] param ( [string] $path = '.\pbipOutput' , [string] $workspaceId , [string] $filter = $null , [hashtable] $fileOverrides ) # Search for folders with .pbir and .pbidataset in it Confirm-FabricAuthToken | Out-Null $itemsFolders = Get-ChildItem -Path $path -recurse -include *.pbir, *.pbidataset if ($filter) { $itemsFolders = $itemsFolders | Where-Object { $_.Directory.FullName -like $filter } } # Get existing items of the workspace $items = Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items" -Method Get Write-Output "Existing items: $($items.Count)" # Datasets first $itemsFolders = $itemsFolders | Select-Object @{n = "Order"; e = { if ($_.Name -like "*.pbidataset") { 1 } else { 2 } } }, * | Sort-Object Order $datasetReferences = @{ } foreach ($itemFolder in $itemsFolders) { # Get the parent folder $itemPath = $itemFolder.Directory.FullName Write-Output "Processing item: '$itemPath'" $files = Get-ChildItem -Path $itemPath -Recurse -Attributes !Directory # Remove files not required for the API: item.*.json; cache.abf; .pbi folder $files = $files | Where-Object { $_.Name -notlike "item.*.json" -and $_.Name -notlike "*.abf" -and $_.Directory.Name -notlike ".pbi" } # There must be a item.metadata.json in the item folder containing the item type and displayname, necessary for the item creation $itemMetadataStr = Get-Content "$itemPath\item.metadata.json" if ($fileOverrides) { $fileOverrideMatch = $fileOverrides.GetEnumerator() | Where-Object { "$itemPath\item.metadata.json" -ilike $_.Name } | Select-Object -First 1 if ($fileOverrideMatch) { $itemMetadataStr = $fileOverrideMatch.Value } } $itemMetadata = $itemMetadataStr | ConvertFrom-Json $itemType = $itemMetadata.type if ($itemType -ieq "dataset") { $itemType = "SemanticModel" } $displayName = $itemMetadata.displayName $itemPathAbs = Resolve-Path $itemPath $parts = $files | ForEach-Object { #$fileName = $_.Name $filePath = $_.FullName if ($fileOverrides) { $fileOverrideMatch = $fileOverrides.GetEnumerator() | Where-Object { $filePath -ilike $_.Name } | Select-Object -First 1 } if ($fileOverrideMatch) { $fileContent = $fileOverrideMatch.Value # convert to byte array if ($fileContent -is [string]) { $fileContent = [system.Text.Encoding]::UTF8.GetBytes($fileContent) } elseif (!($fileContent -is [byte[]])) { throw "FileOverrides value type must be string or byte[]" } } else { if ($filePath -like "*.pbir") { $pbirJson = Get-Content -Path $filePath | ConvertFrom-Json if ($pbirJson.datasetReference.byPath -and $pbirJson.datasetReference.byPath.path) { # try to swap byPath to byConnection $reportDatasetPath = (Resolve-Path (Join-Path $itemPath $pbirJson.datasetReference.byPath.path.Replace("/", "\"))).Path $datasetReference = $datasetReferences[$reportDatasetPath] if ($datasetReference) { # $datasetName = $datasetReference.name $datasetId = $datasetReference.id $newPBIR = @{ "version" = "1.0" "datasetReference" = @{ "byConnection" = @{ "connectionString" = $null "pbiServiceModelId" = $null "pbiModelVirtualServerName" = "sobe_wowvirtualserver" "pbiModelDatabaseName" = "$datasetId" "name" = "EntityDataSource" "connectionType" = "pbiServiceXmlaStyleLive" } } } | ConvertTo-Json $fileContent = [system.Text.Encoding]::UTF8.GetBytes($newPBIR) } else { throw "Item API dont support byPath connection, switch the connection in the *.pbir file to 'byConnection'." } } else { $fileContent = Get-Content -Path $filePath -AsByteStream -Raw } } else { $fileContent = Get-Content -Path $filePath -AsByteStream -Raw } } $partPath = $filePath.Replace($itemPathAbs, "").TrimStart("\").Replace("\", "/") Write-Output "Processing part: '$partPath'" $fileEncodedContent = [Convert]::ToBase64String($fileContent) Write-Output @{ Path = $partPath Payload = $fileEncodedContent PayloadType = "InlineBase64" } } $itemId = $null # Check if there is already an item with same displayName and type $foundItem = $items | Where-Object { $_.type -ieq $itemType -and $_.displayName -ieq $displayName } if ($foundItem) { if ($foundItem.Count -gt 1) { throw "Found more than one item for displayName '$displayName'" } Write-Output "Item '$displayName' of type '$itemType' already exists." -ForegroundColor Yellow $itemId = $foundItem.id } if ($null -eq $itemId) { Write-Output "Creating a new item" # Prepare the request $itemRequest = @{ displayName = $displayName type = $itemType definition = @{ Parts = $parts } } | ConvertTo-Json -Depth 3 if($PSCmdlet.ShouldProcess($itemPath, "Create Item")) { $createItemResult = Invoke-FabricAPIRequest -uri "workspaces/$workspaceId/items" -method Post -body $itemRequest } $itemId = $createItemResult.id Write-Output "Created a new item with ID '$itemId' $([datetime]::Now.ToString("s"))" -ForegroundColor Green Write-Output $itemId } else { Write-Output "Updating item definition" $itemRequest = @{ definition = @{ Parts = $parts } } | ConvertTo-Json -Depth 3 if($PSCmdlet.ShouldProcess($itemPath, "Update Item")) { Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items/$itemId/updateDefinition" -Method Post -Body $itemRequest } Write-Output "Updated new item with ID '$itemId' $([datetime]::Now.ToString("s"))" -ForegroundColor Green Write-Output $itemId } # Save dataset references to swap byPath to byConnection if ($itemType -ieq "semanticmodel") { $datasetReferences[$itemPath] = @{"id" = $itemId; "name" = $displayName } } } } #EndRegion './Public/Item/Import-FabricItem.ps1' 243 #Region './Public/Item/Remove-FabricItem.ps1' -1 <# .SYNOPSIS Removes selected items from a Fabric workspace. .DESCRIPTION The Remove-FabricItems function removes selected items from a specified Fabric workspace. It uses the workspace ID and an optional filter to select the items to remove. If a filter is provided, only items whose DisplayName matches the filter are removed. .PARAMETER WorkspaceID The ID of the Fabric workspace. This is a mandatory parameter. .PARAMETER Filter An optional filter to select items to remove. If provided, only items whose DisplayName matches the filter are removed. .PARAMETER ItemID The ID of a specific item to remove. If provided, this item is removed regardless of the filter .EXAMPLE Remove-FabricItems -WorkspaceID "12345678-90ab-cdef-1234-567890abcdef" -Filter "*test*" This command removes all items from the workspace with the specified ID whose DisplayName includes "test". .INPUTS String. You can pipe two strings that contain the workspace ID and filter to Remove-FabricItems. .OUTPUTS None. This function does not return any output. .NOTES This function was written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> Function Remove-FabricItem { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$workspaceId, [Parameter(Mandatory = $false)] [string]$filter, [Parameter(Mandatory = $false)] [string]$itemID ) Confirm-FabricAuthToken | Out-Null # Invoke the Fabric API to get the items in the workspace if ($PSCmdlet.ShouldProcess("Remove items from workspace $workspaceId")) { if ($itemID) { Invoke-FabricAPIRequest -Uri "workspaces/$($workspaceID)/items/$($itemID)" -Method Delete } else { $items = Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items" -Method Get # Display the count of existing items Write-Output "Existing items: $($items.Count)" # If a filter is provided if ($filter) { # Filter the items whose DisplayName matches the filter $items = $items | Where-Object { $_.DisplayName -like $filter } } # For each item foreach ($item in $items) { # Remove the item Invoke-FabricAPIRequest -Uri "workspaces/$workspaceId/items/$($item.ID)" -Method Delete } } } } #EndRegion './Public/Item/Remove-FabricItem.ps1' 71 #Region './Public/KQL Dashboard/Get-FabricKQLDashboard.ps1' -1 <# .SYNOPSIS Retrieves an KQLDashboard or a list of KQLDashboards from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricKQLDashboard` function sends a GET request to the Fabric API to retrieve KQLDashboard details for a given workspace. It can filter the results by `KQLDashboardName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query KQLDashboards. .PARAMETER KQLDashboardName (Optional) The name of the specific KQLDashboard to retrieve. .EXAMPLE Get-FabricKQLDashboard -WorkspaceId "12345" -KQLDashboardName "Development" Retrieves the "Development" KQLDashboard from workspace "12345". .PARAMETER KQLDashboardID The Id of the KQLDashboard to retrieve. This parameter cannot be used together with KQLDashboardName. The value for KQLDashboardID is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .EXAMPLE Get-FabricKQLDashboard -WorkspaceId "12345" Retrieves all KQLDashboards in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricKQLDashboard { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDashboardName ) try { # Step 1: Handle ambiguous input if ($KQLDashboardId -and $KQLDashboardName) { Write-Message -Message "Both 'KQLDashboardId' and 'KQLDashboardName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $KQLDashboards = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/kqlDashboards" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $KQLDashboards += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $KQLDashboard = if ($KQLDashboardId) { $KQLDashboards | Where-Object { $_.Id -eq $KQLDashboardId } } elseif ($KQLDashboardName) { $KQLDashboards | Where-Object { $_.DisplayName -eq $KQLDashboardName } } else { # Return all KQLDashboards if no filter is provided Write-Message -Message "No filter provided. Returning all KQLDashboards." -Level Debug $KQLDashboards } # Step 9: Handle results if ($KQLDashboard) { Write-Message -Message "KQLDashboard found matching the specified criteria." -Level Debug return $KQLDashboard } else { Write-Message -Message "No KQLDashboard found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLDashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/Get-FabricKQLDashboard.ps1' 154 #Region './Public/KQL Dashboard/Get-FabricKQLDashboardDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a KQLDashboard from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the KQLDashboard's content or metadata from a workspace. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the KQLDashboard definition is to be retrieved. .PARAMETER KQLDashboardId (Optional)The unique identifier of the KQLDashboard whose definition needs to be retrieved. .PARAMETER KQLDashboardFormat Specifies the format of the KQLDashboard definition. .EXAMPLE Get-FabricKQLDashboardDefinition -WorkspaceId "12345" -KQLDashboardId "67890" Retrieves the definition of the KQLDashboard with ID `67890` from the workspace with ID `12345` in the `ipynb` format. .EXAMPLE Get-FabricKQLDashboardDefinition -WorkspaceId "12345" Retrieves the definitions of all KQLDashboards in the workspace with ID `12345` in the `ipynb` format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricKQLDashboardDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDashboards/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDashboardId if ($KQLDashboardFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $KQLDashboardFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "KQLDashboard '$KQLDashboardId' definition retrieved successfully!" -Level Debug return $response.definition.parts } 202 { Write-Message -Message "Getting KQLDashboard '$KQLDashboardId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLDashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/Get-FabricKQLDashboardDefinition.ps1' 119 #Region './Public/KQL Dashboard/New-FabricKQLDashboard.ps1' -1 <# .SYNOPSIS Creates a new KQLDashboard in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new KQLDashboard in the specified workspace. It supports optional parameters for KQLDashboard description and path definitions for the KQLDashboard content. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLDashboard will be created. .PARAMETER KQLDashboardName The name of the KQLDashboard to be created. .PARAMETER KQLDashboardDescription An optional description for the KQLDashboard. .PARAMETER KQLDashboardPathDefinition An optional path to the KQLDashboard definition file (e.g., .ipynb file) to upload. .PARAMETER KQLDashboardPathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricKQLDashboard -WorkspaceId "workspace-12345" -KQLDashboardName "New KQLDashboard" -KQLDashboardPathDefinition "C:\KQLDashboards\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricKQLDashboard { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDashboardName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDashboards" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $KQLDashboardName } if ($KQLDashboardDescription) { $body.description = $KQLDashboardDescription } if ($KQLDashboardPathDefinition) { $KQLDashboardEncodedContent = Convert-ToBase64 -filePath $KQLDashboardPathDefinition if (-not [string]::IsNullOrEmpty($KQLDashboardEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "KQLDashboard" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "RealTimeDashboard.json" payload = $KQLDashboardEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLDashboard definition." -Level Error return $null } } if ($KQLDashboardPathPlatformDefinition) { $KQLDashboardEncodedPlatformContent = Convert-ToBase64 -filePath $KQLDashboardPathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLDashboardEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = $null parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLDashboardEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDashboardName, "Create KQLDashboard")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "KQLDashboard '$KQLDashboardName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "KQLDashboard '$KQLDashboardName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create KQLDashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/New-FabricKQLDashboard.ps1' 209 #Region './Public/KQL Dashboard/Remove-FabricKQLDashboard.ps1' -1 <# .SYNOPSIS Deletes an KQLDashboard from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricKQLDashboard` function sends a DELETE request to the Fabric API to remove a specified KQLDashboard from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the KQLDashboard to delete. .PARAMETER KQLDashboardId (Mandatory) The ID of the KQLDashboard to be deleted. .EXAMPLE Remove-FabricKQLDashboard -WorkspaceId "12345" -KQLDashboardId "67890" Deletes the KQLDashboard with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricKQLDashboard { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDashboards/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDashboardId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove KQLDashboard")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "KQLDashboard '$KQLDashboardId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete KQLDashboard '$KQLDashboardId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/Remove-FabricKQLDashboard.ps1' 81 #Region './Public/KQL Dashboard/Update-FabricKQLDashboard.ps1' -1 function Update-FabricKQLDashboard { <# .SYNOPSIS Updates the properties of a Fabric KQLDashboard. .DESCRIPTION The `Update-FabricKQLDashboard` function updates the name and/or description of a specified Fabric KQLDashboard by making a PATCH request to the API. .PARAMETER KQLDashboardId The unique identifier of the KQLDashboard to be updated. .PARAMETER KQLDashboardName The new name for the KQLDashboard. .PARAMETER KQLDashboardDescription (Optional) The new description for the KQLDashboard. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLDashboard exists. .EXAMPLE Update-FabricKQLDashboard -KQLDashboardId "KQLDashboard123" -KQLDashboardName "NewKQLDashboardName" Updates the name of the KQLDashboard with the ID "KQLDashboard123" to "NewKQLDashboardName". .EXAMPLE Update-FabricKQLDashboard -KQLDashboardId "KQLDashboard123" -KQLDashboardName "NewName" -KQLDashboardDescription "Updated description" Updates both the name and description of the KQLDashboard "KQLDashboard123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDashboardName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDashboards/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDashboardId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $KQLDashboardName } if ($KQLDashboardDescription) { $body.description = $KQLDashboardDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDashboardId, "Update KQLDashboard")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "KQLDashboard '$KQLDashboardName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLDashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/Update-FabricKQLDashboard.ps1' 118 #Region './Public/KQL Dashboard/Update-FabricKQLDashboardDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a KQLDashboard in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a KQLDashboard in a Microsoft Fabric workspace. The KQLDashboard content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the KQLDashboard resides. .PARAMETER KQLDashboardId (Mandatory) The unique identifier of the KQLDashboard to be updated. .PARAMETER KQLDashboardPathDefinition (Mandatory) The file path to the KQLDashboard content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER KQLDashboardPathPlatformDefinition (Optional) The file path to the KQLDashboard's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .EXAMPLE Update-FabricKQLDashboardDefinition -WorkspaceId "12345" -KQLDashboardId "67890" -KQLDashboardPathDefinition "C:\KQLDashboards\KQLDashboard.ipynb" Updates the content of the KQLDashboard with ID `67890` in the workspace `12345` using the specified KQLDashboard file. .EXAMPLE Update-FabricKQLDashboardDefinition -WorkspaceId "12345" -KQLDashboardId "67890" -KQLDashboardPathDefinition "C:\KQLDashboards\KQLDashboard.ipynb" Updates both the content and metadata of the KQLDashboard with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The KQLDashboard content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricKQLDashboardDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDashboardPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/KQLDashboards/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDashboardId if ($KQLDashboardPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ format = $null parts = @() } } if ($KQLDashboardPathDefinition) { $KQLDashboardEncodedContent = Convert-ToBase64 -filePath $KQLDashboardPathDefinition if (-not [string]::IsNullOrEmpty($KQLDashboardEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "RealTimeDashboard.json" payload = $KQLDashboardEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLDashboard definition." -Level Error return $null } } if ($KQLDashboardPathPlatformDefinition) { $KQLDashboardEncodedPlatformContent = Convert-ToBase64 -filePath $KQLDashboardPathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLDashboardEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLDashboardEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDashboardId, "Update KQLDashboard")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for KQLDashboard '$KQLDashboardId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for KQLDashboard '$KQLDashboardId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] $operationResult = Get-FabricLongRunningOperation -operationId $operationId # Handle operation result if ($operationResult.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug $result = Get-FabricLongRunningOperationResult -operationId $operationId return $result.definition.parts } else { Write-Message -Message "Operation Failed" -Level Debug return $operationResult.definition.parts } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLDashboard. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Dashboard/Update-FabricKQLDashboardDefinition.ps1' 186 #Region './Public/KQL Database/Get-FabricKQLDatabase.ps1' -1 function Get-FabricKQLDatabase { <# .SYNOPSIS Retrieves an KQLDatabase or a list of KQLDatabases from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricKQLDatabase` function sends a GET request to the Fabric API to retrieve KQLDatabase details for a given workspace. It can filter the results by `KQLDatabaseName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query KQLDatabases. .PARAMETER KQLDatabaseId (Optional) The ID of a specific KQLDatabase to retrieve. .PARAMETER KQLDatabaseName (Optional) The name of the specific KQLDatabase to retrieve. .EXAMPLE Get-FabricKQLDatabase -WorkspaceId "12345" -KQLDatabaseName "Development" Retrieves the "Development" KQLDatabase from workspace "12345". .EXAMPLE Get-FabricKQLDatabase -WorkspaceId "12345" Retrieves all KQLDatabases in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDatabaseName ) try { # Step 1: Handle ambiguous input if ($KQLDatabaseId -and $KQLDatabaseName) { Write-Message -Message "Both 'KQLDatabaseId' and 'KQLDatabaseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $KQLDatabases = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/kqlDatabases" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $KQLDatabases += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $KQLDatabase = if ($KQLDatabaseId) { $KQLDatabases | Where-Object { $_.Id -eq $KQLDatabaseId } } elseif ($KQLDatabaseName) { $KQLDatabases | Where-Object { $_.DisplayName -eq $KQLDatabaseName } } else { # Return all KQLDatabases if no filter is provided Write-Message -Message "No filter provided. Returning all KQLDatabases." -Level Debug $KQLDatabases } # Step 9: Handle results if ($KQLDatabase) { Write-Message -Message "KQLDatabase found matching the specified criteria." -Level Debug return $KQLDatabase } else { Write-Message -Message "No KQLDatabase found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/Get-FabricKQLDatabase.ps1' 151 #Region './Public/KQL Database/Get-FabricKQLDatabaseDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a KQLDatabase from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the KQLDatabase's content or metadata from a workspace. It supports retrieving KQLDatabase definitions in the Jupyter KQLDatabase (`ipynb`) format. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the KQLDatabase definition is to be retrieved. .PARAMETER KQLDatabaseId (Optional)The unique identifier of the KQLDatabase whose definition needs to be retrieved. .PARAMETER KQLDatabaseFormat Specifies the format of the KQLDatabase definition. Currently, only 'ipynb' is supported. .EXAMPLE Get-FabricKQLDatabaseDefinition -WorkspaceId "12345" -KQLDatabaseId "67890" Retrieves the definition of the KQLDatabase with ID `67890` from the workspace with ID `12345` in the `ipynb` format. .EXAMPLE Get-FabricKQLDatabaseDefinition -WorkspaceId "12345" Retrieves the definitions of all KQLDatabases in the workspace with ID `12345` in the `ipynb` format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricKQLDatabaseDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/KQLDatabases/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDatabaseId if ($KQLDatabaseFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $KQLDatabaseFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "KQLDatabase '$KQLDatabaseId' definition retrieved successfully!" -Level Debug return $response } 202 { Write-Message -Message "Getting KQLDatabase '$KQLDatabaseId' definition request accepted. Retrieving in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/Get-FabricKQLDatabaseDefinition.ps1' 128 #Region './Public/KQL Database/New-FabricKQLDatabase.ps1' -1 function New-FabricKQLDatabase { <# .SYNOPSIS Creates a new KQLDatabase in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new KQLDatabase in the specified workspace. It supports optional parameters for KQLDatabase description and path definitions for the KQLDatabase content. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLDatabase will be created. .PARAMETER KQLInvitationToken An optional invitation token for the KQLDatabase. .PARAMETER KQLSourceClusterUri An optional source cluster URI for the KQLDatabase. .PARAMETER KQLDatabasePathSchemaDefinition the path to the KQLDatabase schema definition file (e.g., .kql file) to upload. .PARAMETER KQLSourceDatabaseName An optional source database name for the KQLDatabase. .PARAMETER parentEventhouseId The ID of the parent Eventhouse item for the KQLDatabase. This is mandatory for ReadWrite type databases. .PARAMETER KQLDatabaseType The type of KQLDatabase to create. Valid values are "ReadWrite" and "Shortcut". .PARAMETER KQLDatabaseName The name of the KQLDatabase to be created. .PARAMETER KQLDatabaseDescription An optional description for the KQLDatabase. .PARAMETER KQLDatabasePathDefinition An optional path to the KQLDatabase definition file (e.g., .ipynb file) to upload. .PARAMETER KQLDatabasePathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricKQLDatabase -WorkspaceId "workspace-12345" -KQLDatabaseName "New KQLDatabase" -KQLDatabasePathDefinition "C:\KQLDatabases\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Precedent Request Body - Definition file high priority. - CreationPayload is evaluate only if Definition file is not provided. - invitationToken has priority over all other payload fields. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDatabaseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$parentEventhouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet("ReadWrite", "Shortcut")] [string]$KQLDatabaseType, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLInvitationToken, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLSourceClusterUri, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLSourceDatabaseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathPlatformDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathSchemaDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDatabases" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body ### This is working $body = @{ displayName = $KQLDatabaseName } if ($KQLDatabaseDescription) { $body.description = $KQLDatabaseDescription } if ($KQLDatabasePathDefinition) { $KQLDatabaseEncodedContent = Convert-ToBase64 -filePath $KQLDatabasePathDefinition $body.definition = @{ parts = @() } if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "DatabaseProperties.json" payload = $KQLDatabaseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLDatabase definition." -Level Error return $null } if ($KQLDatabasePathPlatformDefinition) { $KQLDatabaseEncodedPlatformContent = Convert-ToBase64 -filePath $KQLDatabasePathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLDatabaseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } if ($KQLDatabasePathSchemaDefinition) { $KQLDatabaseEncodedSchemaContent = Convert-ToBase64 -filePath $KQLDatabasePathSchemaDefinition if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedSchemaContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "DatabaseSchema.kql" payload = $KQLDatabaseEncodedSchemaContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in schema definition." -Level Error return $null } } } else { if ($KQLDatabaseType -eq "Shortcut") { if (-not $parentEventhouseId) { Write-Message -Message "Error: 'parentEventhouseId' is required for Shortcut type." -Level Error return $null } if (-not ($KQLInvitationToken -or $KQLSourceClusterUri -or $KQLSourceDatabaseName)) { Write-Message -Message "Error: Provide either 'KQLInvitationToken', 'KQLSourceClusterUri', or 'KQLSourceDatabaseName'." -Level Error return $null } if ($KQLInvitationToken) { Write-Message -Message "Info: 'KQLInvitationToken' is provided." -Level Warning if ($KQLSourceClusterUri) { Write-Message -Message "Warning: 'KQLSourceClusterUri' is ignored when 'KQLInvitationToken' is provided." -Level Warning #$KQLSourceClusterUri = $null } if ($KQLSourceDatabaseName) { Write-Message -Message "Warning: 'KQLSourceDatabaseName' is ignored when 'KQLInvitationToken' is provided." -Level Warning #$KQLSourceDatabaseName = $null } } if ($KQLSourceClusterUri -and -not $KQLSourceDatabaseName) { Write-Message -Message "Error: 'KQLSourceDatabaseName' is required when 'KQLSourceClusterUri' is provided." -Level Error return $null } } # Validate ReadWrite type database if ($KQLDatabaseType -eq "ReadWrite" -and -not $parentEventhouseId) { Write-Message -Message "Error: 'parentEventhouseId' is required for ReadWrite type." -Level Error return $null } $body.creationPayload = @{ databaseType = $KQLDatabaseType parentEventhouseItemId = $parentEventhouseId } if ($KQLDatabaseType -eq "Shortcut") { if ($KQLInvitationToken) { $body.creationPayload.invitationToken = $KQLInvitationToken } if ($KQLSourceClusterUri -and -not $KQLInvitationToken) { $body.creationPayload.sourceClusterUri = $KQLSourceClusterUri } if ($KQLSourceDatabaseName -and -not $KQLInvitationToken) { $body.creationPayload.sourceDatabaseName = $KQLSourceDatabaseName } } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDatabaseName, "Create KQLDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "KQLDatabase '$KQLDatabaseName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "KQLDatabase '$KQLDatabaseName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation result: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create KQLDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/New-FabricKQLDatabase.ps1' 340 #Region './Public/KQL Database/Remove-FabricKQLDatabase.ps1' -1 <# .SYNOPSIS Deletes an KQLDatabase from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricKQLDatabase` function sends a DELETE request to the Fabric API to remove a specified KQLDatabase from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the KQLDatabase to delete. .PARAMETER KQLDatabaseId (Mandatory) The ID of the KQLDatabase to be deleted. .EXAMPLE Remove-FabricKQLDatabase -WorkspaceId "12345" -KQLDatabaseId "67890" Deletes the KQLDatabase with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricKQLDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDatabases/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove KQLDatabase")) { # Step 3: Check if the API endpoint is valid # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "KQLDatabase '$KQLDatabaseId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete KQLDatabase '$KQLDatabaseId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/Remove-FabricKQLDatabase.ps1' 82 #Region './Public/KQL Database/Update-FabricKQLDatabase.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric KQLDatabase. .DESCRIPTION The `Update-FabricKQLDatabase` function updates the name and/or description of a specified Fabric KQLDatabase by making a PATCH request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLDatabase resides. .PARAMETER KQLDatabaseId The unique identifier of the KQLDatabase to be updated. .PARAMETER KQLDatabaseName The new name for the KQLDatabase. .PARAMETER KQLDatabaseDescription (Optional) The new description for the KQLDatabase. .EXAMPLE Update-FabricKQLDatabase -KQLDatabaseId "KQLDatabase123" -KQLDatabaseName "NewKQLDatabaseName" Updates the name of the KQLDatabase with the ID "KQLDatabase123" to "NewKQLDatabaseName". .EXAMPLE Update-FabricKQLDatabase -KQLDatabaseId "KQLDatabase123" -KQLDatabaseName "NewName" -KQLDatabaseDescription "Updated description" Updates both the name and description of the KQLDatabase "KQLDatabase123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricKQLDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLDatabaseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDatabases/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $KQLDatabaseName } if ($KQLDatabaseDescription) { $body.description = $KQLDatabaseDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDatabaseId, "Update KQLDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "KQLDatabase '$KQLDatabaseName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/Update-FabricKQLDatabase.ps1' 119 #Region './Public/KQL Database/Update-FabricKQLDatabaseDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a KQLDatabase in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a KQLDatabase in a Microsoft Fabric workspace. The KQLDatabase content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the KQLDatabase resides. .PARAMETER KQLDatabaseId (Mandatory) The unique identifier of the KQLDatabase to be updated. .PARAMETER KQLDatabasePathDefinition (Mandatory) The file path to the KQLDatabase content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER KQLDatabasePathPlatformDefinition (Optional) The file path to the KQLDatabase's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER UpdateMetadata (Optional)A boolean flag indicating whether to update the KQLDatabase's metadata. Default: `$false`. .PARAMETER KQLDatabasePathSchemaDefinition (Optional) The file path to the KQLDatabase's schema definition file. The content will be encoded as Base64 and sent in the request. .EXAMPLE Update-FabricKQLDatabaseDefinition -WorkspaceId "12345" -KQLDatabaseId "67890" -KQLDatabasePathDefinition "C:\KQLDatabases\KQLDatabase.ipynb" Updates the content of the KQLDatabase with ID `67890` in the workspace `12345` using the specified KQLDatabase file. .EXAMPLE Update-FabricKQLDatabaseDefinition -WorkspaceId "12345" -KQLDatabaseId "67890" -KQLDatabasePathDefinition "C:\KQLDatabases\KQLDatabase.ipynb" -UpdateMetadata $true Updates both the content and metadata of the KQLDatabase with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The KQLDatabase content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricKQLDatabaseDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDatabaseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathPlatformDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLDatabasePathSchemaDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlDatabases/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLDatabaseId if ($KQLDatabasePathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($KQLDatabasePathDefinition) { $KQLDatabaseEncodedContent = Convert-ToBase64 -filePath $KQLDatabasePathDefinition if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "DatabaseProperties.json" payload = $KQLDatabaseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLDatabase definition." -Level Error return $null } } if ($KQLDatabasePathPlatformDefinition) { $KQLDatabaseEncodedPlatformContent = Convert-ToBase64 -filePath $KQLDatabasePathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLDatabaseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } if ($KQLDatabasePathSchemaDefinition) { $KQLDatabaseEncodedSchemaContent = Convert-ToBase64 -filePath $KQLDatabasePathSchemaDefinition if (-not [string]::IsNullOrEmpty($KQLDatabaseEncodedSchemaContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "DatabaseSchema.kql" payload = $KQLDatabaseEncodedSchemaContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in schema definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLDatabaseId, "Update KQLDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for KQLDatabase '$KQLDatabaseId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for KQLDatabase '$KQLDatabaseId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug Write-Message -Message "Operation completed successfully." -Level Info $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Database/Update-FabricKQLDatabaseDefinition.ps1' 228 #Region './Public/KQL Queryset/Get-FabricKQLQueryset.ps1' -1 function Get-FabricKQLQueryset { <# .SYNOPSIS Retrieves an KQLQueryset or a list of KQLQuerysets from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricKQLQueryset` function sends a GET request to the Fabric API to retrieve KQLQueryset details for a given workspace. It can filter the results by `KQLQuerysetName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query KQLQuerysets. .PARAMETER KQLQuerysetId (Optional) The ID of a specific KQLQueryset to retrieve. .PARAMETER KQLQuerysetName (Optional) The name of the specific KQLQueryset to retrieve. .EXAMPLE Get-FabricKQLQueryset -WorkspaceId "12345" -KQLQuerysetName "Development" Retrieves the "Development" KQLQueryset from workspace "12345". .EXAMPLE Get-FabricKQLQueryset -WorkspaceId "12345" Retrieves all KQLQuerysets in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLQuerysetName ) try { # Step 1: Handle ambiguous input if ($KQLQuerysetId -and $KQLQuerysetName) { Write-Message -Message "Both 'KQLQuerysetId' and 'KQLQuerysetName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $KQLQuerysets = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $KQLQuerysets += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $KQLQueryset = if ($KQLQuerysetId) { $KQLQuerysets | Where-Object { $_.Id -eq $KQLQuerysetId } } elseif ($KQLQuerysetName) { $KQLQuerysets | Where-Object { $_.DisplayName -eq $KQLQuerysetName } } else { # Return all KQLQuerysets if no filter is provided Write-Message -Message "No filter provided. Returning all KQLQuerysets." -Level Debug $KQLQuerysets } # Step 9: Handle results if ($KQLQueryset) { Write-Message -Message "KQLQueryset found matching the specified criteria." -Level Debug return $KQLQueryset } else { Write-Message -Message "No KQLQueryset found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLQueryset. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/Get-FabricKQLQueryset.ps1' 151 #Region './Public/KQL Queryset/Get-FabricKQLQuerysetDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a KQLQueryset from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the KQLQueryset's content or metadata from a workspace. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the KQLQueryset definition is to be retrieved. .PARAMETER KQLQuerysetId (Optional)The unique identifier of the KQLQueryset whose definition needs to be retrieved. .PARAMETER KQLQuerysetFormat Specifies the format of the KQLQueryset definition. .EXAMPLE Get-FabricKQLQuerysetDefinition -WorkspaceId "12345" -KQLQuerysetId "67890" Retrieves the definition of the KQLQueryset with ID `67890` from the workspace with ID `12345` in the `ipynb` format. .EXAMPLE Get-FabricKQLQuerysetDefinition -WorkspaceId "12345" Retrieves the definitions of all KQLQuerysets in the workspace with ID `12345` in the `ipynb` format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricKQLQuerysetDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLQuerysetId if ($KQLQuerysetFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $KQLQuerysetFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "KQLQueryset '$KQLQuerysetId' definition retrieved successfully!" -Level Debug return $response.definition.parts } 202 { Write-Message -Message "Getting KQLQueryset '$KQLQuerysetId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve KQLQueryset. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/Get-FabricKQLQuerysetDefinition.ps1' 119 #Region './Public/KQL Queryset/Invoke-FabricKQLCommand.ps1' -1 function Invoke-FabricKQLCommand { <# .SYNOPSIS Executes a KQL command in a Kusto Database. .DESCRIPTION Executes a KQL command in a Kusto Database. The KQL command is executed in the Kusto Database that is specified by the KQLDatabaseName or KQLDatabaseId parameter. The KQL command is executed in the context of the Fabric Real-Time Intelligence session that is established by the Connect-RTISession cmdlet. The cmdlet distinguishes between management commands and query commands. Management commands are executed in the management API, while query commands are executed in the query API. The distinction is made by checking if the KQL command starts with a dot. If it does, it is a management command else it is a query command. If the KQL command is a management command, it is crucial to have the execute database script <| in the beginning, otherwise the Kusto API will not execute the script. This cmdlet will automatically add the .execute database script <| in the beginning of the KQL command if it is a management command and if it is not already present. If the KQL Command is a query command, the result is returned as an array of PowerShell objects by default. If the parameter -ReturnRawResult is used, the raw result of the KQL query is returned which is a JSON object. .PARAMETER WorkspaceId Id of the Fabric Workspace for which the KQL command should be executed. The value for WorkspaceId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .PARAMETER KQLDatabaseName The name of the KQLDatabase in which the KQL command should be executed. This parameter cannot be used together with KQLDatabaseId. .PARAMETER KQLDatabaseId The Id of the KQLDatabase in which the KQL command should be executed. This parameter cannot be used together with KQLDatabaseName. The value for KQLDatabaseId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .PARAMETER KQLCommand The KQL command that should be executed in the Kusto Database. The KQL command is a string. An example of a string is '.create table MyTable (MyColumn: string)'. .PARAMETER ReturnRawResult When this switch is used, the raw result of the KQL command is returned. By default, the result is returned as a PowerShell object. .EXAMPLE Invoke-FabricKQLCommand -WorkspaceId '12345678-1234-1234-1234-123456789012' -KQLDatabaseName 'MyKQLDatabase'-KQLCommand '.create table MyTable (MyColumn: string) This example will create a table named 'MyTable' with a column named 'MyColumn' in the KQLDatabase 'MyKQLDatabase'. .EXAMPLE Invoke-FabricKQLCommand ` -WorkspaceId '2c4ccbb5-9b13-4495-9ab3-ba41152733d9' ` -KQLDatabaseName 'MyEventhouse2' ` -KQLCommand 'productcategory | take 100' This example will Execute the Query 'productcategory | take 100' in the KQLDatabase 'MyEventhouse2' and it will return the result as an array of PowerShell objects. .EXAMPLE Invoke-FabricKQLCommand ` -WorkspaceId '2c4ccbb5-9b13-4495-9ab3-ba41152733d9' ` -KQLDatabaseName 'MyEventhouse2' ` -ReturnRawResult ` -KQLCommand 'productcategory | take 100' This example will Execute the Query 'productcategory | take 100' in the KQLDatabase 'MyEventhouse2' and it will return the result as the raw result of the KQL command, which is a JSON object. .NOTES Revision History: 2024-12-22 - FGE: Added Verbose Output 2024-12-27 - FGE: Major Update to support KQL Queries and Management Commands #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$WorkspaceId, [string]$KQLDatabaseName, [string]$KQLDatabaseId, [Parameter(Mandatory = $true)] [string]$KQLCommand, [switch]$ReturnRawResult ) begin { Confirm-FabricAuthToken | Out-Null Write-Verbose "Check if KQLDatabaseName and KQLDatabaseId are used together" if ($PSBoundParameters.ContainsKey("KQLDatabaseName") -and $PSBoundParameters.ContainsKey("KQLDatabaseId")) { throw "Parameters KQLDatabaseName and KQLDatabaseId cannot be used together" } Write-Verbose "Get Kusto Database" if ($PSBoundParameters.ContainsKey("KQLDatabaseName")) { Write-Verbose "Getting Kusto Database by Name: $KQLDatabaseName" $kustDB = Get-FabricKQLDatabase ` -WorkspaceId $WorkspaceId ` -KQLDatabaseName $KQLDatabaseName } if ($PSBoundParameters.ContainsKey("KQLDatabaseId")) { Write-Verbose "Getting Kusto Database by Id: $KQLDatabaseId" $kustDB = Get-FabricKQLDatabase ` -WorkspaceId $WorkspaceId ` -KQLDatabaseId $KQLDatabaseId } Write-Verbose "Check if Kusto Database was found" if ($null -eq $kustDB) { throw "Kusto Database not found" } Write-Verbose "Generate the Management API URL" $mgmtAPI = "$($kustDB.queryServiceUri)/v1/rest/mgmt" Write-Verbose "Generate the query API URL" $queryAPI = "$($kustDB.queryServiceUri)/v1/rest/query" $KQLCommand = $KQLCommand | Out-String Write-Verbose "Check if the KQL command starts with a dot so it is a management command. Otherwise it is a query command" if (-not ($KQLCommand -match "^\.")) { $isManamgentCommand = $false Write-Verbose "The command is a query command." } else { $isManamgentCommand = $true Write-Verbose "The command is a management command. It is crucial to have the .execute database script <| in the beginning, otherwise the Kusto API will not execute the script." if (-not ($KQLCommand -match "\.execute database script <\|")) { $KQLCommand = ".execute database script <| $KQLCommand" } } } process { Write-Verbose "The KQL-Command is: $KQLCommand" Write-Verbose "Create body of the request" $body = @{ 'csl' = $KQLCommand; 'db' = $kustDB.displayName } | ConvertTo-Json -Depth 1 if ($isManamgentCommand) { Write-Verbose "Calling Management API" Write-Verbose "----------------------" Write-Verbose "Sending the following values to the Query API:" Write-Verbose "Headers: $($FabricSession.headerParams | Format-List | Out-String)" Write-Verbose "Method: POST" Write-Verbose "URI: $mgmtAPI" Write-Verbose "Body of request: $body" Write-Verbose "ContentType: application/json" $result = Invoke-RestMethod ` -Headers $headerParams ` -Method POST ` -Uri $mgmtAPI ` -Body ($body) ` -ContentType "application/json; charset=utf-8" Write-Verbose "Result of the Management API: $($result | ` ConvertTo-Json ` -Depth 10)" $result } else { Write-Verbose "Calling Query API" Write-Verbose "-----------------" Write-Verbose "Sending the following values to the Query API:" Write-Verbose "Headers: $($FabricSession.headerParams | Format-List | Out-String)" Write-Verbose "Method: POST" Write-Verbose "URI: $queryAPI" Write-Verbose "Body of request: $body" Write-Verbose "ContentType: application/json" $result = Invoke-RestMethod ` -Headers $headerParams ` -Method POST ` -Uri $queryAPI ` -Body ($body) ` -ContentType "application/json; charset=utf-8" Write-Verbose "Result of the Query API: $($result | ` ConvertTo-Json ` -Depth 10)" if ($ReturnRawResult) { $result } else { $myRecords = @() for ($j = 0; $j -lt $Result.tables[0].rows.Count; $j++) { $myTableRow = [PSCustomObject]@{ } for ($i = 0; $i -lt $Result.tables[0].rows[0].Count; $i++) { $myTableRow | ` Add-Member ` -MemberType NoteProperty ` -Name $Result.Tables[0].Columns[$i].ColumnName ` -Value $Result.Tables[0].rows[$j][$i] } $myRecords += $myTableRow } $myRecords } } } end { } } #EndRegion './Public/KQL Queryset/Invoke-FabricKQLCommand.ps1' 212 #Region './Public/KQL Queryset/New-FabricKQLQueryset.ps1' -1 <# .SYNOPSIS Creates a new KQLQueryset in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new KQLQueryset in the specified workspace. It supports optional parameters for KQLQueryset description and path definitions for the KQLQueryset content. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLQueryset will be created. .PARAMETER KQLQuerysetName The name of the KQLQueryset to be created. .PARAMETER KQLQuerysetDescription An optional description for the KQLQueryset. .PARAMETER KQLQuerysetPathDefinition An optional path to the KQLQueryset definition file (e.g., .ipynb file) to upload. .PARAMETER KQLQuerysetPathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricKQLQueryset -WorkspaceId "workspace-12345" -KQLQuerysetName "New KQLQueryset" -KQLQuerysetPathDefinition "C:\KQLQuerysets\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricKQLQueryset { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLQuerysetName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $KQLQuerysetName } if ($KQLQuerysetDescription) { $body.description = $KQLQuerysetDescription } if ($KQLQuerysetPathDefinition) { $KQLQuerysetEncodedContent = Convert-ToBase64 -filePath $KQLQuerysetPathDefinition if (-not [string]::IsNullOrEmpty($KQLQuerysetEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = $null parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "RealTimeQueryset.json" payload = $KQLQuerysetEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLQueryset definition." -Level Error return $null } } if ($KQLQuerysetPathPlatformDefinition) { $KQLQuerysetEncodedPlatformContent = Convert-ToBase64 -filePath $KQLQuerysetPathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLQuerysetEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = $null parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLQuerysetEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLQuerysetName, "Create KQLQueryset")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "KQLQueryset '$KQLQuerysetName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "KQLQueryset '$KQLQuerysetName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create KQLQueryset. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/New-FabricKQLQueryset.ps1' 187 #Region './Public/KQL Queryset/Remove-FabricKQLQueryset.ps1' -1 <# .SYNOPSIS Deletes an KQLQueryset from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricKQLQueryset` function sends a DELETE request to the Fabric API to remove a specified KQLQueryset from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the KQLQueryset to delete. .PARAMETER KQLQuerysetId (Mandatory) The ID of the KQLQueryset to be deleted. .EXAMPLE Remove-FabricKQLQueryset -WorkspaceId "12345" -KQLQuerysetId "67890" Deletes the KQLQueryset with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricKQLQueryset { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLQuerysetId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove KQLQueryset")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "KQLQueryset '$KQLQuerysetId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete KQLQueryset '$KQLQuerysetId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/Remove-FabricKQLQueryset.ps1' 79 #Region './Public/KQL Queryset/Update-FabricKQLQueryset.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric KQLQueryset. .DESCRIPTION The `Update-FabricKQLQueryset` function updates the name and/or description of a specified Fabric KQLQueryset by making a PATCH request to the API. .PARAMETER KQLQuerysetId The unique identifier of the KQLQueryset to be updated. .PARAMETER KQLQuerysetName The new name for the KQLQueryset. .PARAMETER KQLQuerysetDescription (Optional) The new description for the KQLQueryset. .PARAMETER WorkspaceId The unique identifier of the workspace where the KQLQueryset exists. .EXAMPLE Update-FabricKQLQueryset -KQLQuerysetId "KQLQueryset123" -KQLQuerysetName "NewKQLQuerysetName" Updates the name of the KQLQueryset with the ID "KQLQueryset123" to "NewKQLQuerysetName". .EXAMPLE Update-FabricKQLQueryset -KQLQuerysetId "KQLQueryset123" -KQLQuerysetName "NewName" -KQLQuerysetDescription "Updated description" Updates both the name and description of the KQLQueryset "KQLQueryset123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricKQLQueryset { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$KQLQuerysetName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLQuerysetId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $KQLQuerysetName } if ($KQLQuerysetDescription) { $body.description = $KQLQuerysetDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLQuerysetId, "Update KQLQueryset")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "KQLQueryset '$KQLQuerysetName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLQueryset. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/Update-FabricKQLQueryset.ps1' 118 #Region './Public/KQL Queryset/Update-FabricKQLQuerysetDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a KQLQueryset in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a KQLQueryset in a Microsoft Fabric workspace. The KQLQueryset content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the KQLQueryset resides. .PARAMETER KQLQuerysetId (Mandatory) The unique identifier of the KQLQueryset to be updated. .PARAMETER KQLQuerysetPathDefinition (Mandatory) The file path to the KQLQueryset content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER KQLQuerysetPathPlatformDefinition (Optional) The file path to the KQLQueryset's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .EXAMPLE Update-FabricKQLQuerysetDefinition -WorkspaceId "12345" -KQLQuerysetId "67890" -KQLQuerysetPathDefinition "C:\KQLQuerysets\KQLQueryset.ipynb" Updates the content of the KQLQueryset with ID `67890` in the workspace `12345` using the specified KQLQueryset file. .EXAMPLE Update-FabricKQLQuerysetDefinition -WorkspaceId "12345" -KQLQuerysetId "67890" -KQLQuerysetPathDefinition "C:\KQLQuerysets\KQLQueryset.ipynb" Updates both the content and metadata of the KQLQueryset with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The KQLQueryset content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricKQLQuerysetDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$KQLQuerysetPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/kqlQuerysets/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $KQLQuerysetId if ($KQLQuerysetPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ format = $null parts = @() } } if ($KQLQuerysetPathDefinition) { $KQLQuerysetEncodedContent = Convert-ToBase64 -filePath $KQLQuerysetPathDefinition if (-not [string]::IsNullOrEmpty($KQLQuerysetEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "RealTimeQueryset.json" payload = $KQLQuerysetEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in KQLQueryset definition." -Level Error return $null } } if ($KQLQuerysetPathPlatformDefinition) { $KQLQuerysetEncodedPlatformContent = Convert-ToBase64 -filePath $KQLQuerysetPathPlatformDefinition if (-not [string]::IsNullOrEmpty($KQLQuerysetEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $KQLQuerysetEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($KQLQuerysetId, "Update KQLQueryset")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for KQLQueryset '$KQLQuerysetId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for KQLQueryset '$KQLQuerysetId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] $operationResult = Get-FabricLongRunningOperation -operationId $operationId # Handle operation result if ($operationResult.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug $result = Get-FabricLongRunningOperationResult -operationId $operationId return $result.definition.parts } else { Write-Message -Message "Operation Failed" -Level Debug return $operationResult.definition.parts } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update KQLQueryset. Error: $errorDetails" -Level Error } } #EndRegion './Public/KQL Queryset/Update-FabricKQLQuerysetDefinition.ps1' 165 #Region './Public/Lakehouse/Get-FabricLakehouse.ps1' -1 function Get-FabricLakehouse { <# .SYNOPSIS Retrieves an Lakehouse or a list of Lakehouses from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricLakehouse` function sends a GET request to the Fabric API to retrieve Lakehouse details for a given workspace. It can filter the results by `LakehouseName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query Lakehouses. .PARAMETER LakehouseId (Optional) The ID of a specific Lakehouse to retrieve. .PARAMETER LakehouseName (Optional) The name of the specific Lakehouse to retrieve. .EXAMPLE Get-FabricLakehouse -WorkspaceId "12345" -LakehouseName "Development" Retrieves the "Development" Lakehouse from workspace "12345". .EXAMPLE Get-FabricLakehouse -WorkspaceId "12345" Retrieves all Lakehouses in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$LakehouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$LakehouseName ) try { # Step 1: Handle ambiguous input if ($LakehouseId -and $LakehouseName) { Write-Message -Message "Both 'LakehouseId' and 'LakehouseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $lakehouses = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/lakehouses" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $lakehouses += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $lakehouse = if ($LakehouseId) { $lakehouses | Where-Object { $_.Id -eq $LakehouseId } } elseif ($LakehouseName) { $lakehouses | Where-Object { $_.DisplayName -eq $LakehouseName } } else { # Return all lakehouses if no filter is provided Write-Message -Message "No filter provided. Returning all Lakehouses." -Level Debug $lakehouses } # Step 9: Handle results if ($Lakehouse) { Write-Message -Message "Lakehouse found matching the specified criteria." -Level Debug return $Lakehouse } else { Write-Message -Message "No Lakehouse found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Lakehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Get-FabricLakehouse.ps1' 151 #Region './Public/Lakehouse/Get-FabricLakehouseTable.ps1' -1 function Get-FabricLakehouseTable { <# .SYNOPSIS Retrieves tables from a specified Lakehouse in a Fabric workspace. .DESCRIPTION This function retrieves tables from a specified Lakehouse in a Fabric workspace. It handles pagination using a continuation token to ensure all data is retrieved. .PARAMETER WorkspaceId The ID of the workspace containing the Lakehouse. .PARAMETER LakehouseId The ID of the Lakehouse from which to retrieve tables. .EXAMPLE Get-FabricLakehouseTable -WorkspaceId "your-workspace-id" -LakehouseId "your-lakehouse-id" This example retrieves all tables from the specified Lakehouse in the specified workspace. #> [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$LakehouseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Initialize variables $continuationToken = $null $tables = @() $maxResults = 100 if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } $baseApiEndpointUrl = "{0}/workspaces/{1}/lakehouses/{2}/tables?maxResults={3}" -f $FabricConfig.BaseUrl, $WorkspaceId, $LakehouseId, $maxResults # Step 3: Loop to retrieve data with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug do { # Step 4: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}&continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 5: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" Write-Message -Message "API response code: $statusCode" -Level Debug # Step 6: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 7: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $tables += $response.data # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 9: Handle results if ($tables) { Write-Message -Message "Tables found in the Lakehouse '$LakehouseId'." -Level Debug return $tables } else { Write-Message -Message "No tables found matching in the Lakehouse '$LakehouseId'." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Lakehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Get-FabricLakehouseTable.ps1' 115 #Region './Public/Lakehouse/New-FabricLakehouse.ps1' -1 <# .SYNOPSIS Creates a new Lakehouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Lakehouse in the specified workspace. It supports optional parameters for Lakehouse description and path definitions for the Lakehouse content. .PARAMETER WorkspaceId The unique identifier of the workspace where the Lakehouse will be created. .PARAMETER LakehouseName The name of the Lakehouse to be created. .PARAMETER LakehouseDescription An optional description for the Lakehouse. .PARAMETER LakehouseEnableSchemas An optional path to enable schemas in the Lakehouse .EXAMPLE Add-FabricLakehouse -WorkspaceId "workspace-12345" -LakehouseName "New Lakehouse" -LakehouseEnableSchemas $true .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricLakehouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$LakehouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$LakehouseDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$LakehouseEnableSchemas = $false ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/lakehouses" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $LakehouseName } if ($LakehouseDescription) { $body.description = $LakehouseDescription } if ($true -eq $LakehouseEnableSchemas) { $body.creationPayload = @{ enableSchemas = $LakehouseEnableSchemas } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($LakehouseName, "Create Lakehouse")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Lakehouse '$LakehouseName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Lakehouse '$LakehouseName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Lakehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/New-FabricLakehouse.ps1' 149 #Region './Public/Lakehouse/Remove-FabricLakehouse.ps1' -1 <# .SYNOPSIS Deletes an Lakehouse from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricLakehouse` function sends a DELETE request to the Fabric API to remove a specified Lakehouse from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the Lakehouse to delete. .PARAMETER LakehouseId (Mandatory) The ID of the Lakehouse to be deleted. .EXAMPLE Remove-FabricLakehouse -WorkspaceId "12345" -LakehouseId "67890" Deletes the Lakehouse with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricLakehouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LakehouseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/lakehouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $LakehouseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Lakehouse")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Lakehouse '$LakehouseId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Lakehouse '$LakehouseId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Remove-FabricLakehouse.ps1' 80 #Region './Public/Lakehouse/Start-FabricLakehouseTableMaintenance.ps1' -1 function Start-FabricLakehouseTableMaintenance { <# .SYNOPSIS Initiates a table maintenance job for a specified Lakehouse in a Fabric workspace. .DESCRIPTION This function sends a POST request to the Fabric API to start a table maintenance job for a specified Lakehouse. It allows for optional parameters such as schema name, table name, and Z-ordering columns. The function also handles asynchronous operations and can wait for completion if specified. .PARAMETER WorkspaceId The unique identifier of the workspace where the Lakehouse resides. This parameter is mandatory. .PARAMETER LakehouseId The unique identifier of the Lakehouse for which the table maintenance job is to be initiated. This parameter is mandatory. .PARAMETER JobType The type of job to be initiated. Default is "TableMaintenance". This parameter is optional. .PARAMETER SchemaName The name of the schema in the Lakehouse. This parameter is optional. .PARAMETER TableName The name of the table in the Lakehouse. This parameter is optional. .PARAMETER IsVOrder A boolean flag indicating whether to apply V-ordering. This parameter is optional. .PARAMETER ColumnsZOrderBy An array of columns to be used for Z-ordering. This parameter is optional. .PARAMETER retentionPeriod The retention period for the table maintenance job. This parameter is optional. .PARAMETER waitForCompletion A boolean flag indicating whether to wait for the job to complete. Default is false. This parameter is optional. .EXAMPLE Start-FabricLakehouseTableMaintenance -WorkspaceId "12345" -LakehouseId "67890" -JobType "TableMaintenance" -SchemaName "dbo" -TableName "MyTable" -IsVOrder $true -ColumnsZOrderBy @("Column1", "Column2") -retentionPeriod "7:00:00" -waitForCompletion $true Initiates a table maintenance job for the specified Lakehouse and waits for its completion. .EXAMPLE Start-FabricLakehouseTableMaintenance -WorkspaceId "12345" -LakehouseId "67890" -JobType "TableMaintenance" -SchemaName "dbo" -TableName "MyTable" -IsVOrder $false -ColumnsZOrderBy @("Column1", "Column2") -retentionPeriod "7:00:00" Initiates a table maintenance job for the specified Lakehouse without waiting for its completion. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - This function handles asynchronous operations and retrieves operation results if required. - The function uses the `Write-Message` function for logging and debugging purposes. - The function uses the `Get-FabricLakehouse` function to retrieve Lakehouse details. - The function uses the `Get-FabricLongRunningOperation` function to check the status of long-running operations. - The function uses the `Invoke-RestMethod` cmdlet to make API requests. .NOTES #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LakehouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('TableMaintenance')] [string]$JobType = "TableMaintenance", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SchemaName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$TableName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$IsVOrder, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [array]$ColumnsZOrderBy, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern("^\d+:[0-1][0-9]|2[0-3]:[0-5][0-9]:[0-5][0-9]$")] [string]$retentionPeriod, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$waitForCompletion = $false ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $lakehouse = Get-FabricLakehouse -WorkspaceId $WorkspaceId -LakehouseId $LakehouseId if ($lakehouse.properties.PSObject.Properties['defaultSchema'] -and -not $SchemaName) { Write-Error "The Lakehouse '$lakehouse.displayName' has schema enabled, but no schema name was provided. Please specify the 'SchemaName' parameter to proceed." return } # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/lakehouses/{2}/jobs/instances?jobType={3}" -f $FabricConfig.BaseUrl, $WorkspaceId , $LakehouseId, $JobType Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ executionData = @{ tableName = $TableName optimizeSettings = @{ } } } if ($lakehouse.properties.PSObject.Properties['defaultSchema'] -and $SchemaName) { $body.executionData.schemaName = $SchemaName } if ($IsVOrder) { $body.executionData.optimizeSettings.vOrder = $IsVOrder } if ($ColumnsZOrderBy) { # Ensure $ColumnsZOrderBy is an array if (-not ($ColumnsZOrderBy -is [array])) { $ColumnsZOrderBy = $ColumnsZOrderBy -split "," } # Add it to the optimizeSettings in the request body $body.executionData.optimizeSettings.zOrderBy = $ColumnsZOrderBy } if ($retentionPeriod) { if (-not $body.executionData.PSObject.Properties['vacuumSettings']) { $body.executionData.vacuumSettings = @{ retentionPeriod = @() } } $body.executionData.vacuumSettings.retentionPeriod = $retentionPeriod } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Start Table Maintenance Job")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Table maintenance job successfully initiated for Lakehouse '$lakehouse.displayName'." -Level Info return $response } 202 { Write-Message -Message "Table maintenance job accepted and is now running in the background. Job execution is in progress." -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug if ($waitForCompletion -eq $true) { Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location -retryAfter $retryAfter Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug return $operationStatus } else { Write-Message -Message "The operation is running asynchronously." -Level Info Write-Message -Message "Use the returned details to check the operation status." -Level Info Write-Message -Message "To wait for the operation to complete, set the 'waitForCompletion' parameter to true." -Level Info $operationDetails = [PSCustomObject]@{ OperationId = $operationId Location = $location RetryAfter = $retryAfter } return $operationDetails } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to start table maintenance job. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Start-FabricLakehouseTableMaintenance.ps1' 223 #Region './Public/Lakehouse/Update-FabricLakehouse.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric Lakehouse. .DESCRIPTION The `Update-FabricLakehouse` function updates the name and/or description of a specified Fabric Lakehouse by making a PATCH request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace where the Lakehouse exists. .PARAMETER LakehouseId The unique identifier of the Lakehouse to be updated. .PARAMETER LakehouseName The new name for the Lakehouse. .PARAMETER LakehouseDescription (Optional) The new description for the Lakehouse. .EXAMPLE Update-FabricLakehouse -LakehouseId "Lakehouse123" -LakehouseName "NewLakehouseName" Updates the name of the Lakehouse with the ID "Lakehouse123" to "NewLakehouseName". .EXAMPLE Update-FabricLakehouse -LakehouseId "Lakehouse123" -LakehouseName "NewName" -LakehouseDescription "Updated description" Updates both the name and description of the Lakehouse "Lakehouse123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricLakehouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LakehouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$LakehouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$LakehouseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/lakehouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $LakehouseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $LakehouseName } if ($LakehouseDescription) { $body.description = $LakehouseDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($LakehouseId, "Update Lakehouse")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Lakehouse '$LakehouseName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Lakehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Update-FabricLakehouse.ps1' 119 #Region './Public/Lakehouse/Write-FabricLakehouseTableData.ps1' -1 function Write-FabricLakehouseTableData { <# .SYNOPSIS Loads data into a specified table in a Lakehouse within a Fabric workspace. .DESCRIPTION Loads data into a specified table in a Lakehouse within a Fabric workspace. The function supports loading data from files or folders, with options for file format and CSV settings. .PARAMETER WorkspaceId The ID of the workspace containing the Lakehouse. .PARAMETER LakehouseId The ID of the Lakehouse where the table resides. .PARAMETER TableName The name of the table to load data into. .PARAMETER PathType The type of path to load data from (File or Folder). .PARAMETER RelativePath The relative path to the file or folder to load data from. .PARAMETER FileFormat The format of the file to load data from (CSV or Parquet). .PARAMETER CsvDelimiter The delimiter used in the CSV file (default is comma). .PARAMETER CsvHeader Indicates whether the CSV file has a header row (default is false). .PARAMETER Mode The mode for loading data (append or overwrite). .PARAMETER Recursive Indicates whether to load data recursively from subfolders (default is false). .EXAMPLE Import-FabricLakehouseTableData -WorkspaceId "your-workspace-id" -LakehouseId "your-lakehouse-id" -TableName "your-table-name" -PathType "File" -RelativePath "path/to/your/file.csv" -FileFormat "CSV" -CsvDelimiter "," -CsvHeader $true -Mode "append" -Recursive $false This example loads data from a CSV file into the specified table in the Lakehouse. .EXAMPLE Import-FabricLakehouseTableData -WorkspaceId "your-workspace-id" -LakehouseId "your-lakehouse-id" -TableName "your-table-name" -PathType "Folder" -RelativePath "path/to/your/folder" -FileFormat "Parquet" -Mode "overwrite" -Recursive $true This example loads data from a folder into the specified table in the Lakehouse, overwriting any existing data. #> [CmdletBinding(SupportsShouldProcess)] [Alias("Import-FabricLakehouseTableData")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$LakehouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$TableName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('File', 'Folder')] [string]$PathType, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$RelativePath, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('CSV', 'Parquet')] [string]$FileFormat, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CsvDelimiter = ",", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$CsvHeader = $false, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('append', 'overwrite')] [string]$Mode = "append", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$Recursive = $false ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/lakehouses/{2}/tables/{3}/load" -f $FabricConfig.BaseUrl, $WorkspaceId, $LakehouseId, $TableName Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ relativePath = $RelativePath pathType = $PathType mode = $Mode recursive = $Recursive formatOptions = @{ format = $FileFormat } } if ($FileFormat -eq "CSV") { $body.formatOptions.delimiter = $CsvDelimiter $body.formatOptions.hasHeader = $CsvHeader } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Load Lakehouse Table Data")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 202) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 5: Handle and log the response switch ($statusCode) { 202 { Write-Message -Message "Load table '$TableName' request accepted. Load table operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Load table '$TableName' operation complete successfully!" -Level Info return $operationStatus } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error throw "API request failed with status code $statusCode." } } # Step 6: Handle results } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Lakehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Lakehouse/Write-FabricLakehouseTableData.ps1' 186 #Region './Public/Mirrored Database/Get-FabricMirroredDatabase.ps1' -1 function Get-FabricMirroredDatabase { <# .SYNOPSIS Retrieves an MirroredDatabase or a list of MirroredDatabases from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricMirroredDatabase` function sends a GET request to the Fabric API to retrieve MirroredDatabase details for a given workspace. It can filter the results by `MirroredDatabaseName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query MirroredDatabases. .PARAMETER MirroredDatabaseId (Optional) The ID of a specific MirroredDatabase to retrieve. .PARAMETER MirroredDatabaseName (Optional) The name of the specific MirroredDatabase to retrieve. .EXAMPLE Get-FabricMirroredDatabase -WorkspaceId "12345" -MirroredDatabaseName "Development" Retrieves the "Development" MirroredDatabase from workspace "12345". .EXAMPLE Get-FabricMirroredDatabase -WorkspaceId "12345" Retrieves all MirroredDatabases in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MirroredDatabaseName ) try { # Step 1: Handle ambiguous input if ($MirroredDatabaseId -and $MirroredDatabaseName) { Write-Message -Message "Both 'MirroredDatabaseId' and 'MirroredDatabaseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $continuationToken = $null $MirroredDatabases = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $MirroredDatabases += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $MirroredDatabase = if ($MirroredDatabaseId) { $MirroredDatabases | Where-Object { $_.Id -eq $MirroredDatabaseId } } elseif ($MirroredDatabaseName) { $MirroredDatabases | Where-Object { $_.DisplayName -eq $MirroredDatabaseName } } else { # Return all MirroredDatabases if no filter is provided Write-Message -Message "No filter provided. Returning all MirroredDatabases." -Level Debug $MirroredDatabases } # Step 9: Handle results if ($MirroredDatabase) { Write-Message -Message "MirroredDatabase found matching the specified criteria." -Level Debug return $MirroredDatabase } else { Write-Message -Message "No MirroredDatabase found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Get-FabricMirroredDatabase.ps1' 154 #Region './Public/Mirrored Database/Get-FabricMirroredDatabaseDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a MirroredDatabase from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the MirroredDatabase's content or metadata from a workspace. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the MirroredDatabase definition is to be retrieved. .PARAMETER MirroredDatabaseId (Optional)The unique identifier of the MirroredDatabase whose definition needs to be retrieved. .EXAMPLE Get-FabricMirroredDatabaseDefinition -WorkspaceId "12345" -MirroredDatabaseId "67890" Retrieves the definition of the MirroredDatabase with ID `67890` from the workspace with ID `12345`. .EXAMPLE Get-FabricMirroredDatabaseDefinition -WorkspaceId "12345" Retrieves the definitions of all MirroredDatabases in the workspace with ID `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricMirroredDatabaseDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "MirroredDatabase '$MirroredDatabaseId' definition retrieved successfully!" -Level Debug return $response.definition.parts } 202 { Write-Message -Message "Getting MirroredDatabase '$MirroredDatabaseId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Get-FabricMirroredDatabaseDefinition.ps1' 108 #Region './Public/Mirrored Database/Get-FabricMirroredDatabaseStatus.ps1' -1 function Get-FabricMirroredDatabaseStatus { <# .SYNOPSIS Retrieves the status of a mirrored database in a specified workspace. .DESCRIPTION Retrieves the status of a mirrored database in a specified workspace. The function validates the authentication token, constructs the API endpoint URL, and makes a POST request to retrieve the mirroring status. It handles errors and logs messages at various levels (Debug, Error). .PARAMETER WorkspaceId The ID of the workspace containing the mirrored database. .PARAMETER MirroredDatabaseId the ID of the mirrored database whose status is to be retrieved. .EXAMPLE Get-FabricMirroredDatabaseStatus -WorkspaceId "your-workspace-id" -MirroredDatabaseId "your-mirrored-database-id" This example retrieves the status of a mirrored database with the specified ID in the specified workspace. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/getMirroringStatus" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 9: Handle results Write-Message -Message "Returning status of MirroredDatabases." -Level Debug return $response } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Get-FabricMirroredDatabaseStatus.ps1' 66 #Region './Public/Mirrored Database/Get-FabricMirroredDatabaseTableStatus.ps1' -1 function Get-FabricMirroredDatabaseTableStatus { <# .SYNOPSIS Retrieves the status of tables in a mirrored database. .DESCRIPTION Retrieves the status of tables in a mirrored database. The function validates the authentication token, constructs the API endpoint URL, and makes a POST request to retrieve the mirroring status of tables. It handles errors and logs messages at various levels (Debug, Error). .PARAMETER WorkspaceId The ID of the workspace containing the mirrored database. .PARAMETER MirroredDatabaseId The ID of the mirrored database whose table status is to be retrieved. .EXAMPLE Get-FabricMirroredDatabaseTableStatus -WorkspaceId "your-workspace-id" -MirroredDatabaseId "your-mirrored-database-id" This example retrieves the status of tables in a mirrored database with the specified ID in the specified workspace. .NOTES The function retrieves the PowerBI access token and makes a POST request to the PowerBI API to retrieve the status of tables in the specified mirrored database. It then returns the 'value' property of the response, which contains the table statuses. #> [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $continuationToken = $null $MirroredDatabaseTableStatus = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/getTablesMirroringStatus" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $MirroredDatabaseTableStatus += $response.data # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 9: Handle results # Return all Mirrored Database Table Status Write-Message -Message "No filter provided. Returning all MirroredDatabases." -Level Debug $MirroredDatabaseTableStatus } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Get-FabricMirroredDatabaseTableStatus.ps1' 112 #Region './Public/Mirrored Database/New-FabricMirroredDatabase.ps1' -1 <# .SYNOPSIS Creates a new MirroredDatabase in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new MirroredDatabase in the specified workspace. It supports optional parameters for MirroredDatabase description and path definitions for the MirroredDatabase content. .PARAMETER WorkspaceId The unique identifier of the workspace where the MirroredDatabase will be created. .PARAMETER MirroredDatabaseName The name of the MirroredDatabase to be created. .PARAMETER MirroredDatabaseDescription An optional description for the MirroredDatabase. .PARAMETER MirroredDatabasePathDefinition An optional path to the MirroredDatabase definition file to upload. .PARAMETER MirroredDatabasePathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricMirroredDatabase -WorkspaceId "workspace-12345" -MirroredDatabaseName "New MirroredDatabase" -MirroredDatabasePathDefinition "C:\MirroredDatabases\example.json" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricMirroredDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MirroredDatabaseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabasePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabasePathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $MirroredDatabaseName } if ($MirroredDatabaseDescription) { $body.description = $MirroredDatabaseDescription } if ($MirroredDatabasePathDefinition) { $MirroredDatabaseEncodedContent = Convert-ToBase64 -filePath $MirroredDatabasePathDefinition if (-not [string]::IsNullOrEmpty($MirroredDatabaseEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "mirroredDatabase.json" payload = $MirroredDatabaseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in MirroredDatabase definition." -Level Error return $null } } if ($MirroredDatabasePathPlatformDefinition) { $MirroredDatabaseEncodedPlatformContent = Convert-ToBase64 -filePath $MirroredDatabasePathPlatformDefinition if (-not [string]::IsNullOrEmpty($MirroredDatabaseEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "MirroredDatabase" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $MirroredDatabaseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MirroredDatabaseName, "Create MirroredDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "MirroredDatabase '$MirroredDatabaseName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "MirroredDatabase '$MirroredDatabaseName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation Failed" -Level Debug return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/New-FabricMirroredDatabase.ps1' 207 #Region './Public/Mirrored Database/Remove-FabricMirroredDatabase.ps1' -1 <# .SYNOPSIS Deletes an MirroredDatabase from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricMirroredDatabase` function sends a DELETE request to the Fabric API to remove a specified MirroredDatabase from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the MirroredDatabase to delete. .PARAMETER MirroredDatabaseId (Mandatory) The ID of the MirroredDatabase to be deleted. .EXAMPLE Remove-FabricMirroredDatabase -WorkspaceId "12345" -MirroredDatabaseId "67890" Deletes the MirroredDatabase with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricMirroredDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove MirroredDatabase")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "MirroredDatabase '$MirroredDatabaseId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete MirroredDatabase '$MirroredDatabaseId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Remove-FabricMirroredDatabase.ps1' 79 #Region './Public/Mirrored Database/Start-FabricMirroredDatabaseMirroring.ps1' -1 function Start-FabricMirroredDatabaseMirroring { <# .SYNOPSIS Starts the mirroring of a specified mirrored database in a given workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to start the mirroring of a specified mirrored database. It requires the workspace ID and the mirrored database ID as parameters. .PARAMETER WorkspaceId The unique identifier of the workspace where the mirrored database resides. This parameter is mandatory. .PARAMETER MirroredDatabaseId The unique identifier of the mirrored database to be started. This parameter is mandatory. .EXAMPLE Start-FabricMirroredDatabaseMirroring -WorkspaceId "12345" -MirroredDatabaseId "67890" Starts the mirroring of the mirrored database with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - This function handles asynchronous operations and retrieves operation results if required. #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/startMirroring" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Start MirroredDatabase Mirroring")) { # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 9: Handle results Write-Message -Message "Database mirroring started successfully for MirroredDatabaseId: $MirroredDatabaseId" -Level Info return } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to start MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Start-FabricMirroredDatabaseMirroring.ps1' 77 #Region './Public/Mirrored Database/Stop-FabricMirroredDatabaseMirroring.ps1' -1 function Stop-FabricMirroredDatabaseMirroring { <# .SYNOPSIS Stops the mirroring of a specified mirrored database in a given workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to stop the mirroring of a specified mirrored database. It requires the workspace ID and the mirrored database ID as parameters. .PARAMETER WorkspaceId The unique identifier of the workspace where the mirrored database resides. This parameter is mandatory. .PARAMETER MirroredDatabaseId The unique identifier of the mirrored database to be stopped. This parameter is mandatory. .EXAMPLE Stop-FabricMirroredDatabaseMirroring -WorkspaceId "12345" -MirroredDatabaseId "67890" Stops the mirroring of the mirrored database with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - This function handles asynchronous operations and retrieves operation results if required. #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/stopMirroring" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Stop MirroredDatabase Mirroring")) { # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 9: Handle results Write-Message -Message "Database mirroring stopped successfully for MirroredDatabaseId: $MirroredDatabaseId" -Level Info return } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to stop MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Stop-FabricMirroredDatabaseMirroring.ps1' 81 #Region './Public/Mirrored Database/Update-FabricMirroredDatabase.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric MirroredDatabase. .DESCRIPTION The `Update-FabricMirroredDatabase` function updates the name and/or description of a specified Fabric MirroredDatabase by making a PATCH request to the API. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the MirroredDatabase resides. .PARAMETER MirroredDatabaseId The unique identifier of the MirroredDatabase to be updated. .PARAMETER MirroredDatabaseName The new name for the MirroredDatabase. .PARAMETER MirroredDatabaseDescription (Optional) The new description for the MirroredDatabase. .EXAMPLE Update-FabricMirroredDatabase -MirroredDatabaseId "MirroredDatabase123" -MirroredDatabaseName "NewMirroredDatabaseName" Updates the name of the MirroredDatabase with the ID "MirroredDatabase123" to "NewMirroredDatabaseName". .EXAMPLE Update-FabricMirroredDatabase -MirroredDatabaseId "MirroredDatabase123" -MirroredDatabaseName "NewName" -MirroredDatabaseDescription "Updated description" Updates both the name and description of the MirroredDatabase "MirroredDatabase123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricMirroredDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MirroredDatabaseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $MirroredDatabaseName } if ($MirroredDatabaseDescription) { $body.description = $MirroredDatabaseDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MirroredDatabaseId, "Update MirroredDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "MirroredDatabase '$MirroredDatabaseName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Update-FabricMirroredDatabase.ps1' 118 #Region './Public/Mirrored Database/Update-FabricMirroredDatabaseDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a MirroredDatabase in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a MirroredDatabase in a Microsoft Fabric workspace. The MirroredDatabase content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the MirroredDatabase resides. .PARAMETER MirroredDatabaseId (Mandatory) The unique identifier of the MirroredDatabase to be updated. .PARAMETER MirroredDatabasePathDefinition (Mandatory) The file path to the MirroredDatabase content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER MirroredDatabasePathPlatformDefinition (Optional) The file path to the MirroredDatabase's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER UpdateMetadata (Optional)A boolean flag indicating whether to update the MirroredDatabase's metadata. Default: `$false`. .EXAMPLE Update-FabricMirroredDatabaseDefinition -WorkspaceId "12345" -MirroredDatabaseId "67890" -MirroredDatabasePathDefinition "C:\MirroredDatabases\MirroredDatabase.json" Updates the content of the MirroredDatabase with ID `67890` in the workspace `12345` using the specified MirroredDatabase file. .EXAMPLE Update-FabricMirroredDatabaseDefinition -WorkspaceId "12345" -MirroredDatabaseId "67890" -MirroredDatabasePathDefinition "C:\MirroredDatabases\MirroredDatabase.json" -UpdateMetadata $true Updates both the content and metadata of the MirroredDatabase with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The MirroredDatabase content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricMirroredDatabaseDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabaseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabasePathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredDatabasePathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mirroredDatabases/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $MirroredDatabaseId if ($MirroredDatabasePathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($MirroredDatabasePathDefinition) { $MirroredDatabaseEncodedContent = Convert-ToBase64 -filePath $MirroredDatabasePathDefinition if (-not [string]::IsNullOrEmpty($MirroredDatabaseEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "MirroredDatabase.json" payload = $MirroredDatabaseEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in MirroredDatabase definition." -Level Error return $null } } if ($MirroredDatabasePathPlatformDefinition) { $MirroredDatabaseEncodedPlatformContent = Convert-ToBase64 -filePath $MirroredDatabasePathPlatformDefinition if (-not [string]::IsNullOrEmpty($MirroredDatabaseEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $MirroredDatabaseEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MirroredDatabaseId, "Update MirroredDatabase")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for MirroredDatabase '$MirroredDatabaseId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for MirroredDatabase '$MirroredDatabaseId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] $operationResult = Get-FabricLongRunningOperation -operationId $operationId # Handle operation result if ($operationResult.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug $result = Get-FabricLongRunningOperationResult -operationId $operationId return $result.definition.parts } else { Write-Message -Message "Operation Failed" -Level Debug return $operationResult.definition.parts } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update MirroredDatabase. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Database/Update-FabricMirroredDatabaseDefinition.ps1' 187 #Region './Public/Mirrored Warehouse/Get-FabricMirroredWarehouse.ps1' -1 function Get-FabricMirroredWarehouse { <# .SYNOPSIS Retrieves an MirroredWarehouse or a list of MirroredWarehouses from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricMirroredWarehouse` function sends a GET request to the Fabric API to retrieve MirroredWarehouse details for a given workspace. It can filter the results by `MirroredWarehouseName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query MirroredWarehouses. .PARAMETER MirroredWarehouseId (Optional) The ID of a specific MirroredWarehouse to retrieve. .PARAMETER MirroredWarehouseName (Optional) The name of the specific MirroredWarehouse to retrieve. .EXAMPLE Get-FabricMirroredWarehouse -WorkspaceId "12345" -MirroredWarehouseName "Development" Retrieves the "Development" MirroredWarehouse from workspace "12345". .EXAMPLE Get-FabricMirroredWarehouse -WorkspaceId "12345" Retrieves all MirroredWarehouses in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MirroredWarehouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MirroredWarehouseName ) try { # Step 1: Handle ambiguous input if ($MirroredWarehouseId -and $MirroredWarehouseName) { Write-Message -Message "Both 'MirroredWarehouseId' and 'MirroredWarehouseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug $continuationToken = $null $MirroredWarehouses = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/MirroredWarehouses" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $MirroredWarehouses += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $MirroredWarehouse = if ($MirroredWarehouseId) { $MirroredWarehouses | Where-Object { $_.Id -eq $MirroredWarehouseId } } elseif ($MirroredWarehouseName) { $MirroredWarehouses | Where-Object { $_.DisplayName -eq $MirroredWarehouseName } } else { # Return all MirroredWarehouses if no filter is provided Write-Message -Message "No filter provided. Returning all MirroredWarehouses." -Level Debug $MirroredWarehouses } # Step 9: Handle results if ($MirroredWarehouse) { Write-Message -Message "MirroredWarehouse found matching the specified criteria." -Level Debug return $MirroredWarehouse } else { Write-Message -Message "No MirroredWarehouse found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve MirroredWarehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Mirrored Warehouse/Get-FabricMirroredWarehouse.ps1' 154 #Region './Public/ML Experiment/Get-FabricMLExperiment.ps1' -1 <# .SYNOPSIS Retrieves ML Experiment details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves ML Experiment details from a specified workspace using either the provided MLExperimentId or MLExperimentName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Experiment exists. This parameter is mandatory. .PARAMETER MLExperimentId The unique identifier of the ML Experiment to retrieve. This parameter is optional. .PARAMETER MLExperimentName The name of the ML Experiment to retrieve. This parameter is optional. .EXAMPLE Get-FabricMLExperiment -WorkspaceId "workspace-12345" -MLExperimentId "experiment-67890" This example retrieves the ML Experiment details for the experiment with ID "experiment-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricMLExperiment -WorkspaceId "workspace-12345" -MLExperimentName "My ML Experiment" This example retrieves the ML Experiment details for the experiment named "My ML Experiment" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricMLExperiment { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLExperimentId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MLExperimentName ) try { # Step 1: Handle ambiguous input if ($MLExperimentId -and $MLExperimentName) { Write-Message -Message "Both 'MLExperimentId' and 'MLExperimentName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $MLExperiments = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/mlExperiments" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $MLExperiments += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $MLExperiment = if ($MLExperimentId) { $MLExperiments | Where-Object { $_.Id -eq $MLExperimentId } } elseif ($MLExperimentName) { $MLExperiments | Where-Object { $_.DisplayName -eq $MLExperimentName } } else { # Return all MLExperiments if no filter is provided Write-Message -Message "No filter provided. Returning all MLExperiments." -Level Debug $MLExperiments } # Step 9: Handle results if ($MLExperiment) { Write-Message -Message "ML Experiment found matching the specified criteria." -Level Debug return $MLExperiment } else { Write-Message -Message "No ML Experiment found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve ML Experiment. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Experiment/Get-FabricMLExperiment.ps1' 151 #Region './Public/ML Experiment/New-FabricMLExperiment.ps1' -1 <# .SYNOPSIS Creates a new ML Experiment in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new ML Experiment in the specified workspace. It supports optional parameters for ML Experiment description. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Experiment will be created. This parameter is mandatory. .PARAMETER MLExperimentName The name of the ML Experiment to be created. This parameter is mandatory. .PARAMETER MLExperimentDescription An optional description for the ML Experiment. .EXAMPLE New-FabricMLExperiment -WorkspaceId "workspace-12345" -MLExperimentName "New ML Experiment" -MLExperimentDescription "Description of the new ML Experiment" This example creates a new ML Experiment named "New ML Experiment" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricMLExperiment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$MLExperimentName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLExperimentDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlExperiments" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $MLExperimentName } if ($MLExperimentDescription) { $body.description = $MLExperimentDescription } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MLExperimentName, "Create ML Experiment")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "ML Experiment '$MLExperimentName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "ML Experiment '$MLExperimentName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create ML Experiment. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Experiment/New-FabricMLExperiment.ps1' 143 #Region './Public/ML Experiment/Remove-FabricMLExperiment.ps1' -1 <# .SYNOPSIS Removes an ML Experiment from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an ML Experiment from the specified workspace using the provided WorkspaceId and MLExperimentId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the MLExperiment will be removed. .PARAMETER MLExperimentId The unique identifier of the MLExperiment to be removed. .EXAMPLE Remove-FabricMLExperiment -WorkspaceId "workspace-12345" -MLExperimentId "experiment-67890" This example removes the MLExperiment with ID "experiment-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricMLExperiment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MLExperimentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlExperiments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MLExperimentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove ML Experiment")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "ML Experiment '$MLExperimentId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete ML Experiment '$MLExperimentId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Experiment/Remove-FabricMLExperiment.ps1' 79 #Region './Public/ML Experiment/Update-FabricMLExperiment.ps1' -1 <# .SYNOPSIS Updates an existing ML Experiment in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing ML Experiment in the specified workspace. It supports optional parameters for ML Experiment description. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Experiment exists. This parameter is optional. .PARAMETER MLExperimentId The unique identifier of the ML Experiment to be updated. This parameter is mandatory. .PARAMETER MLExperimentName The new name of the ML Experiment. This parameter is mandatory. .PARAMETER MLExperimentDescription An optional new description for the ML Experiment. .EXAMPLE Update-FabricMLExperiment -WorkspaceId "workspace-12345" -MLExperimentId "experiment-67890" -MLExperimentName "Updated ML Experiment" -MLExperimentDescription "Updated description" This example updates the ML Experiment with ID "experiment-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricMLExperiment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MLExperimentId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$MLExperimentName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLExperimentDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlExperiments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MLExperimentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $MLExperimentName } if ($MLExperimentDescription) { $body.description = $MLExperimentDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MLExperimentName, "Update ML Experiment")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "ML Experiment '$MLExperimentName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update ML Experiment. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Experiment/Update-FabricMLExperiment.ps1' 112 #Region './Public/ML Model/Get-FabricMLModel.ps1' -1 <# .SYNOPSIS Retrieves ML Model details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves ML Model details from a specified workspace using either the provided MLModelId or MLModelName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Model exists. This parameter is mandatory. .PARAMETER MLModelId The unique identifier of the ML Model to retrieve. This parameter is optional. .PARAMETER MLModelName The name of the ML Model to retrieve. This parameter is optional. .EXAMPLE Get-FabricMLModel -WorkspaceId "workspace-12345" -MLModelId "model-67890" This example retrieves the ML Model details for the model with ID "model-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricMLModel -WorkspaceId "workspace-12345" -MLModelName "My ML Model" This example retrieves the ML Model details for the model named "My ML Model" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricMLModel { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLModelId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$MLModelName ) try { # Step 1: Handle ambiguous input if ($MLModelId -and $MLModelName) { Write-Message -Message "Both 'MLModelId' and 'MLModelName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $MLModels = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/mlModels" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $MLModels += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $MLModel = if ($MLModelId) { $MLModels | Where-Object { $_.Id -eq $MLModelId } } elseif ($MLModelName) { $MLModels | Where-Object { $_.DisplayName -eq $MLModelName } } else { # Return all MLModels if no filter is provided Write-Message -Message "No filter provided. Returning all MLModels." -Level Debug $MLModels } # Step 9: Handle results if ($MLModel) { Write-Message -Message "ML Model found matching the specified criteria." -Level Debug return $MLModel } else { Write-Message -Message "No ML Model found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve ML Model. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Model/Get-FabricMLModel.ps1' 151 #Region './Public/ML Model/New-FabricMLModel.ps1' -1 <# .SYNOPSIS Creates a new ML Model in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new ML Model in the specified workspace. It supports optional parameters for ML Model description. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Model will be created. This parameter is mandatory. .PARAMETER MLModelName The name of the ML Model to be created. This parameter is mandatory. .PARAMETER MLModelDescription An optional description for the ML Model. .EXAMPLE New-FabricMLModel -WorkspaceId "workspace-12345" -MLModelName "New ML Model" -MLModelDescription "Description of the new ML Model" This example creates a new ML Model named "New ML Model" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricMLModel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$MLModelName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLModelDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlModels" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $MLModelName } if ($MLModelDescription) { $body.description = $MLModelDescription } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($MLModelName, "Create ML Model")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "ML Model '$MLModelName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "ML Model '$MLModelName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create ML Model. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Model/New-FabricMLModel.ps1' 143 #Region './Public/ML Model/Remove-FabricMLModel.ps1' -1 <# .SYNOPSIS Removes an ML Model from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an ML Model from the specified workspace using the provided WorkspaceId and MLModelId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the ML Model will be removed. .PARAMETER MLModelId The unique identifier of the ML Model to be removed. .EXAMPLE Remove-FabricMLModel -WorkspaceId "workspace-12345" -MLModelId "model-67890" This example removes the ML Model with ID "model-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricMLModel { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MLModelId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlModels/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MLModelId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove ML Model")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "ML Model '$MLModelId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete ML Model '$MLModelId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Model/Remove-FabricMLModel.ps1' 78 #Region './Public/ML Model/Update-FabricMLModel.ps1' -1 <# .SYNOPSIS Updates an existing ML Model in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing ML Model in the specified workspace. It supports optional parameters for ML Model description. .PARAMETER WorkspaceId The unique identifier of the workspace where the ML Model exists. This parameter is optional. .PARAMETER MLModelId The unique identifier of the ML Model to be updated. This parameter is mandatory. .PARAMETER MLModelDescription New description for the ML Model. .EXAMPLE Update-FabricMLModel -WorkspaceId "workspace-12345" -MLModelId "model-67890" -MLModelName "Updated ML Model" -MLModelDescription "Updated description" This example updates the ML Model with ID "model-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricMLModel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$MLModelId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$MLModelDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/mlModels/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $MLModelId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ description = $MLModelDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update ML Model")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "ML Model '$MLModelId' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update ML Model. Error: $errorDetails" -Level Error } } #EndRegion './Public/ML Model/Update-FabricMLModel.ps1' 99 #Region './Public/Notebook/Get-FabricNotebook.ps1' -1 function Get-FabricNotebook { <# .SYNOPSIS Retrieves an Notebook or a list of Notebooks from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Get-FabricNotebook` function sends a GET request to the Fabric API to retrieve Notebook details for a given workspace. It can filter the results by `NotebookName`. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace to query Notebooks. .PARAMETER NotebookId (Optional) The ID of a specific Notebook to retrieve. .PARAMETER NotebookName (Optional) The name of the specific Notebook to retrieve. .EXAMPLE Get-FabricNotebook -WorkspaceId "12345" -NotebookName "Development" Retrieves the "Development" Notebook from workspace "12345". .EXAMPLE Get-FabricNotebook -WorkspaceId "12345" Retrieves all Notebooks in workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$NotebookName ) try { # Step 1: Handle ambiguous input if ($NotebookId -and $NotebookName) { Write-Message -Message "Both 'NotebookId' and 'NotebookName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $notebooks = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/notebooks" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $notebooks += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $notebook = if ($NotebookId) { $notebooks | Where-Object { $_.Id -eq $NotebookId } } elseif ($NotebookName) { $notebooks | Where-Object { $_.DisplayName -eq $NotebookName } } else { # Return all notebooks if no filter is provided Write-Message -Message "No filter provided. Returning all Notebooks." -Level Debug $notebooks } # Step 9: Handle results if ($notebook) { Write-Message -Message "Notebook found matching the specified criteria." -Level Debug return $notebook } else { Write-Message -Message "No notebook found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/Get-FabricNotebook.ps1' 152 #Region './Public/Notebook/Get-FabricNotebookDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of a notebook from a specific workspace in Microsoft Fabric. .DESCRIPTION This function fetches the notebook's content or metadata from a workspace. It supports retrieving notebook definitions in the Jupyter Notebook (`ipynb`) format. Handles both synchronous and asynchronous operations, with detailed logging and error handling. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace from which the notebook definition is to be retrieved. .PARAMETER NotebookId (Optional)The unique identifier of the notebook whose definition needs to be retrieved. .PARAMETER NotebookFormat Specifies the format of the notebook definition. Currently, only 'ipynb' is supported. Default: 'ipynb'. .EXAMPLE Get-FabricNotebookDefinition -WorkspaceId "12345" -NotebookId "67890" Retrieves the definition of the notebook with ID `67890` from the workspace with ID `12345` in the `ipynb` format. .EXAMPLE Get-FabricNotebookDefinition -WorkspaceId "12345" Retrieves the definitions of all notebooks in the workspace with ID `12345` in the `ipynb` format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles long-running operations asynchronously. #> function Get-FabricNotebookDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('ipynb')] [string]$NotebookFormat = 'ipynb' ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $NotebookId if ($NotebookFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $NotebookFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Notebook '$NotebookId' definition retrieved successfully!" -Level Debug return $response } 202 { Write-Message -Message "Getting notebook '$NotebookId' definition request accepted. Retrieving in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] #[string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/Get-FabricNotebookDefinition.ps1' 130 #Region './Public/Notebook/New-FabricNotebook.ps1' -1 <# .SYNOPSIS Creates a new notebook in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new notebook in the specified workspace. It supports optional parameters for notebook description and path definitions for the notebook content. .PARAMETER WorkspaceId The unique identifier of the workspace where the notebook will be created. .PARAMETER NotebookName The name of the notebook to be created. .PARAMETER NotebookDescription An optional description for the notebook. .PARAMETER NotebookPathDefinition An optional path to the notebook definition file (e.g., .ipynb file) to upload. .PARAMETER NotebookPathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricNotebook -WorkspaceId "workspace-12345" -NotebookName "New Notebook" -NotebookPathDefinition "C:\notebooks\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricNotebook { [CmdletBinding(supportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$NotebookName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $NotebookName } if ($NotebookDescription) { $body.description = $NotebookDescription } if ($NotebookPathDefinition) { $notebookEncodedContent = Convert-ToBase64 -filePath $NotebookPathDefinition if (-not [string]::IsNullOrEmpty($notebookEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "ipynb" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "notebook-content.py" payload = $notebookEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in notebook definition." -Level Error return $null } } if ($NotebookPathPlatformDefinition) { $notebookEncodedPlatformContent = Convert-ToBase64 -filePath $NotebookPathPlatformDefinition if (-not [string]::IsNullOrEmpty($notebookEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "ipynb" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $notebookEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($NotebookName, "Create Notebook")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Notebook '$NotebookName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Notebook '$NotebookName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/New-FabricNotebook.ps1' 213 #Region './Public/Notebook/New-FabricNotebookNEW.ps1' -1 <# .SYNOPSIS Creates a new notebook in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new notebook in the specified workspace. It supports optional parameters for notebook description and path definitions for the notebook content. .PARAMETER WorkspaceId The unique identifier of the workspace where the notebook will be created. .PARAMETER NotebookName The name of the notebook to be created. .PARAMETER NotebookDescription An optional description for the notebook. .PARAMETER NotebookPathDefinition An optional path to the notebook definition file (e.g., .ipynb file) to upload. .PARAMETER NotebookPathPlatformDefinition An optional path to the platform-specific definition (e.g., .platform file) to upload. .EXAMPLE Add-FabricNotebook -WorkspaceId "workspace-12345" -NotebookName "New Notebook" -NotebookPathDefinition "C:\notebooks\example.ipynb" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricNotebookNEW { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$NotebookName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookPathDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $NotebookName } if ($NotebookDescription) { $body.description = $NotebookDescription } if ($NotebookPathDefinition) { if (-not $body.definition) { $body.definition = @{ format = "ipynb" parts = @() } } $jsonObjectParts = Get-FileDefinitionParts -sourceDirectory $NotebookPathDefinition # Add new part to the parts array $body.definition.parts = $jsonObjectParts.parts } # Check if any path is .platform foreach ($part in $jsonObjectParts.parts) { if ($part.path -eq ".platform") { $hasPlatformFile = $true Write-Message -Message "Platform File: $hasPlatformFile" -Level Debug } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($NotebookName, "Create Notebook")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Notebook '$NotebookName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Notebook '$NotebookName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/New-FabricNotebookNEW.ps1' 175 #Region './Public/Notebook/Remove-FabricNotebook.ps1' -1 <# .SYNOPSIS Deletes an Notebook from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricNotebook` function sends a DELETE request to the Fabric API to remove a specified Notebook from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the Notebook to delete. .PARAMETER NotebookId (Mandatory) The ID of the Notebook to be deleted. .EXAMPLE Remove-FabricNotebook -WorkspaceId "12345" -NotebookId "67890" Deletes the Notebook with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Tiago Balabuch #> function Remove-FabricNotebook { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NotebookId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $NotebookId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Notebook")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Notebook '$NotebookId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete notebook '$NotebookId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/Remove-FabricNotebook.ps1' 80 #Region './Public/Notebook/Update-FabricNotebook.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric Notebook. .DESCRIPTION The `Update-FabricNotebook` function updates the name and/or description of a specified Fabric Notebook by making a PATCH request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace where the Notebook exists. .PARAMETER NotebookId The unique identifier of the Notebook to be updated. .PARAMETER NotebookName The new name for the Notebook. .PARAMETER NotebookDescription (Optional) The new description for the Notebook. .EXAMPLE Update-FabricNotebook -NotebookId "Notebook123" -NotebookName "NewNotebookName" Updates the name of the Notebook with the ID "Notebook123" to "NewNotebookName". .EXAMPLE Update-FabricNotebook -NotebookId "Notebook123" -NotebookName "NewName" -NotebookDescription "Updated description" Updates both the name and description of the Notebook "Notebook123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricNotebook { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NotebookId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$NotebookName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $NotebookId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $NotebookName } if ($NotebookDescription) { $body.description = $NotebookDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Notebook")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Notebook '$NotebookName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/Update-FabricNotebook.ps1' 117 #Region './Public/Notebook/Update-FabricNotebookDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of a notebook in a Microsoft Fabric workspace. .DESCRIPTION This function allows updating the content or metadata of a notebook in a Microsoft Fabric workspace. The notebook content can be provided as file paths, and metadata updates can optionally be enabled. .PARAMETER WorkspaceId (Mandatory) The unique identifier of the workspace where the notebook resides. .PARAMETER NotebookId (Mandatory) The unique identifier of the notebook to be updated. .PARAMETER NotebookPathDefinition (Mandatory) The file path to the notebook content definition file. The content will be encoded as Base64 and sent in the request. .PARAMETER NotebookPathPlatformDefinition (Optional) The file path to the notebook's platform-specific definition file. The content will be encoded as Base64 and sent in the request. .EXAMPLE Update-FabricNotebookDefinition -WorkspaceId "12345" -NotebookId "67890" -NotebookPathDefinition "C:\Notebooks\Notebook.ipynb" Updates the content of the notebook with ID `67890` in the workspace `12345` using the specified notebook file. .EXAMPLE Update-FabricNotebookDefinition -WorkspaceId "12345" -NotebookId "67890" -NotebookPathDefinition "C:\Notebooks\Notebook.ipynb" -NotebookPathPlatformDefinition "C:\Notebooks\.platform" Updates both the content and metadata of the notebook with ID `67890` in the workspace `12345`. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - The notebook content is encoded as Base64 before being sent to the Fabric API. - This function handles asynchronous operations and retrieves operation results if required. Author: Tiago Balabuch #> function Update-FabricNotebookDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NotebookId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NotebookPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$NotebookPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/notebooks/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $NotebookId if ($NotebookPathPlatformDefinition) { $apiEndpointUrl += "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ format = "ipynb" parts = @() } } if ($NotebookPathDefinition) { $notebookEncodedContent = Convert-ToBase64 -filePath $NotebookPathDefinition if (-not [string]::IsNullOrEmpty($notebookEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "notebook-content.py" payload = $notebookEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in notebook definition." -Level Error return $null } } if ($NotebookPathPlatformDefinition) { $notebookEncodedPlatformContent = Convert-ToBase64 -filePath $NotebookPathPlatformDefinition if (-not [string]::IsNullOrEmpty($notebookEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $notebookEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($NotebookId, "Update Notebook Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for notebook '$NotebookId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for notebook '$NotebookId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update notebook. Error: $errorDetails" -Level Error } } #EndRegion './Public/Notebook/Update-FabricNotebookDefinition.ps1' 198 #Region './Public/Paginated Reports/Get-FabricPaginatedReport.ps1' -1 <# .SYNOPSIS Retrieves paginated report details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves paginated report details from a specified workspace using either the provided PaginatedReportId or PaginatedReportName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the paginated reports exist. This parameter is mandatory. .PARAMETER PaginatedReportId The unique identifier of the paginated report to retrieve. This parameter is optional. .PARAMETER PaginatedReportName The name of the paginated report to retrieve. This parameter is optional. .EXAMPLE Get-FabricPaginatedReports -WorkspaceId "workspace-12345" -PaginatedReportId "report-67890" This example retrieves the paginated report details for the report with ID "report-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricPaginatedReports -WorkspaceId "workspace-12345" -PaginatedReportName "My Paginated Report" This example retrieves the paginated report details for the report named "My Paginated Report" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricPaginatedReport { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$PaginatedReportId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$PaginatedReportName ) try { # Step 1: Handle ambiguous input if ($PaginatedReportId -and $PaginatedReportName) { Write-Message -Message "Both 'PaginatedReportId' and 'PaginatedReportName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $PaginatedReports = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/paginatedReports" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $PaginatedReports += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $PaginatedReport = if ($PaginatedReportId) { $PaginatedReports | Where-Object { $_.Id -eq $PaginatedReportId } } elseif ($PaginatedReportName) { $PaginatedReports | Where-Object { $_.DisplayName -eq $PaginatedReportName } } else { # Return all PaginatedReports if no filter is provided Write-Message -Message "No filter provided. Returning all Paginated Reports." -Level Debug $PaginatedReports } # Step 9: Handle results if ($PaginatedReport) { Write-Message -Message "Paginated Report found matching the specified criteria." -Level Debug return $PaginatedReport } else { Write-Message -Message "No Paginated Report found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Paginated Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Paginated Reports/Get-FabricPaginatedReport.ps1' 150 #Region './Public/Paginated Reports/Update-FabricPaginatedReport.ps1' -1 <# .SYNOPSIS Updates an existing paginated report in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing paginated report in the specified workspace. It supports optional parameters for paginated report description. .PARAMETER WorkspaceId The unique identifier of the workspace where the paginated report exists. This parameter is optional. .PARAMETER PaginatedReportId The unique identifier of the paginated report to be updated. This parameter is mandatory. .PARAMETER PaginatedReportName The new name of the paginated report. This parameter is mandatory. .PARAMETER PaginatedReportDescription An optional new description for the paginated report. .EXAMPLE Update-FabricPaginatedReport -WorkspaceId "workspace-12345" -PaginatedReportId "report-67890" -PaginatedReportName "Updated Paginated Report" -PaginatedReportDescription "Updated description" This example updates the paginated report with ID "report-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricPaginatedReport { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$PaginatedReportId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$PaginatedReportName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$PaginatedReportDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/paginatedReports/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $PaginatedReportId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $PaginatedReportName } if ($PaginatedReportDescription) { $body.description = $PaginatedReportDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($PaginatedReportName, "Update Paginated Report")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Paginated Report '$PaginatedReportName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Paginated Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Paginated Reports/Update-FabricPaginatedReport.ps1' 114 #Region './Public/Reflex/Get-FabricReflex.ps1' -1 <# .SYNOPSIS Retrieves Reflex details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves Reflex details from a specified workspace using either the provided ReflexId or ReflexName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Reflex exists. This parameter is mandatory. .PARAMETER ReflexId The unique identifier of the Reflex to retrieve. This parameter is optional. .PARAMETER ReflexName The name of the Reflex to retrieve. This parameter is optional. .EXAMPLE Get-FabricReflex -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" This example retrieves the Reflex details for the Reflex with ID "Reflex-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricReflex -WorkspaceId "workspace-12345" -ReflexName "My Reflex" This example retrieves the Reflex details for the Reflex named "My Reflex" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricReflex { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReflexName ) try { # Step 1: Handle ambiguous input if ($ReflexId -and $ReflexName) { Write-Message -Message "Both 'ReflexId' and 'ReflexName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $Reflexes = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/reflexes" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $Reflexes += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $Reflex = if ($ReflexId) { $Reflexes | Where-Object { $_.Id -eq $ReflexId } } elseif ($ReflexName) { $Reflexes | Where-Object { $_.DisplayName -eq $ReflexName } } else { # Return all Reflexes if no filter is provided Write-Message -Message "No filter provided. Returning all Reflexes." -Level Debug $Reflexes } # Step 9: Handle results if ($Reflex) { Write-Message -Message "Reflex found in the Workspace '$WorkspaceId'." -Level Debug return $Reflex } else { Write-Message -Message "No Reflex found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Reflex. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/Get-FabricReflex.ps1' 151 #Region './Public/Reflex/Get-FabricReflexDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of an Reflex from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves the definition of an Reflex from a specified workspace using the provided ReflexId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Reflex exists. This parameter is mandatory. .PARAMETER ReflexId The unique identifier of the Reflex to retrieve the definition for. This parameter is optional. .PARAMETER ReflexFormat The format in which to retrieve the Reflex definition. This parameter is optional. .EXAMPLE Get-FabricReflexDefinition -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" This example retrieves the definition of the Reflex with ID "Reflex-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricReflexDefinition -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" -ReflexFormat "json" This example retrieves the definition of the Reflex with ID "Reflex-67890" in the workspace with ID "workspace-12345" in JSON format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricReflexDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reflexes/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReflexId if ($ReflexFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $ReflexFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Reflex '$ReflexId' definition retrieved successfully!" -Level Debug return $response.definition.parts } 202 { Write-Message -Message "Getting Reflex '$ReflexId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId, -location $location Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Reflex. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/Get-FabricReflexDefinition.ps1' 123 #Region './Public/Reflex/New-FabricReflex.ps1' -1 <# .SYNOPSIS Creates a new Reflex in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Reflex in the specified workspace. It supports optional parameters for Reflex description and path definitions. .PARAMETER WorkspaceId The unique identifier of the workspace where the Reflex will be created. This parameter is mandatory. .PARAMETER ReflexName The name of the Reflex to be created. This parameter is mandatory. .PARAMETER ReflexDescription An optional description for the Reflex. .PARAMETER ReflexPathDefinition An optional path to the Reflex definition file to upload. .PARAMETER ReflexPathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE New-FabricReflex -WorkspaceId "workspace-12345" -ReflexName "New Reflex" -ReflexDescription "Description of the new Reflex" This example creates a new Reflex named "New Reflex" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricReflex { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReflexName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reflexes" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $ReflexName } if ($ReflexDescription) { $body.description = $ReflexDescription } if ($ReflexPathDefinition) { $ReflexEncodedContent = Convert-ToBase64 -filePath $ReflexPathDefinition if (-not [string]::IsNullOrEmpty($ReflexEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "ReflexEntities.json" payload = $ReflexEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Reflex definition." -Level Error return $null } } if ($ReflexPathPlatformDefinition) { $ReflexEncodedPlatformContent = Convert-ToBase64 -filePath $ReflexPathPlatformDefinition if (-not [string]::IsNullOrEmpty($ReflexEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $ReflexEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($ReflexName, "Create Reflex")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Reflex '$ReflexName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Reflex '$ReflexName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Reflex. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/New-FabricReflex.ps1' 215 #Region './Public/Reflex/Remove-FabricReflex.ps1' -1 <# .SYNOPSIS Removes an Reflex from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an Reflex from the specified workspace using the provided WorkspaceId and ReflexId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the Reflex will be removed. .PARAMETER ReflexId The unique identifier of the Reflex to be removed. .EXAMPLE Remove-FabricReflex -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" This example removes the Reflex with ID "Reflex-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricReflex { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReflexId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reflexes/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReflexId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Reflex")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle response if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Reflex '$ReflexId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Reflex '$ReflexId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/Remove-FabricReflex.ps1' 81 #Region './Public/Reflex/Update-FabricReflex.ps1' -1 <# .SYNOPSIS Updates an existing Reflex in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing Reflex in the specified workspace. It supports optional parameters for Reflex description. .PARAMETER WorkspaceId The unique identifier of the workspace where the Reflex exists. This parameter is optional. .PARAMETER ReflexId The unique identifier of the Reflex to be updated. This parameter is mandatory. .PARAMETER ReflexName The new name of the Reflex. This parameter is mandatory. .PARAMETER ReflexDescription An optional new description for the Reflex. .EXAMPLE Update-FabricReflex -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" -ReflexName "Updated Reflex" -ReflexDescription "Updated description" This example updates the Reflex with ID "Reflex-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricReflex { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReflexId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReflexName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reflexes/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReflexId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $ReflexName } if ($ReflexDescription) { $body.description = $ReflexDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess("Reflex", "Update")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Reflex '$ReflexName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Reflex. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/Update-FabricReflex.ps1' 114 #Region './Public/Reflex/Update-FabricReflexDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of an existing Reflex in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the definition of an existing Reflex in the specified workspace. It supports optional parameters for Reflex definition and platform-specific definition. .PARAMETER WorkspaceId The unique identifier of the workspace where the Reflex exists. This parameter is mandatory. .PARAMETER ReflexId The unique identifier of the Reflex to be updated. This parameter is mandatory. .PARAMETER ReflexPathDefinition An optional path to the Reflex definition file to upload. .PARAMETER ReflexPathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE Update-FabricReflexDefinition -WorkspaceId "workspace-12345" -ReflexId "Reflex-67890" -ReflexPathDefinition "C:\Path\To\ReflexDefinition.json" This example updates the definition of the Reflex with ID "Reflex-67890" in the workspace with ID "workspace-12345" using the provided definition file. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricReflexDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReflexId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReflexPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReflexPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reflexes/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReflexId #if ($UpdateMetadata -eq $true) { if ($ReflexPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($ReflexPathDefinition) { $ReflexEncodedContent = Convert-ToBase64 -filePath $ReflexPathDefinition if (-not [string]::IsNullOrEmpty($ReflexEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "ReflexEntities.json" payload = $ReflexEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in Reflex definition." -Level Error return $null } } if ($ReflexPathPlatformDefinition) { $ReflexEncodedPlatformContent = Convert-ToBase64 -filePath $ReflexPathPlatformDefinition if (-not [string]::IsNullOrEmpty($ReflexEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $ReflexEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Reflex Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for Reflex '$ReflexId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for Reflex '$ReflexId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Reflex. Error: $errorDetails" -Level Error } } #EndRegion './Public/Reflex/Update-FabricReflexDefinition.ps1' 188 #Region './Public/Report/Get-FabricReport.ps1' -1 <# .SYNOPSIS Retrieves Report details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves Report details from a specified workspace using either the provided ReportId or ReportName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Report exists. This parameter is mandatory. .PARAMETER ReportId The unique identifier of the Report to retrieve. This parameter is optional. .PARAMETER ReportName The name of the Report to retrieve. This parameter is optional. .EXAMPLE Get-FabricReport -WorkspaceId "workspace-12345" -ReportId "Report-67890" This example retrieves the Report details for the Report with ID "Report-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricReport -WorkspaceId "workspace-12345" -ReportName "My Report" This example retrieves the Report details for the Report named "My Report" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricReport { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReportId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReportName ) try { # Step 1: Handle ambiguous input if ($ReportId -and $ReportName) { Write-Message -Message "Both 'ReportId' and 'ReportName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $Reports = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/reports" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $Reports += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $Report = if ($ReportId) { $Reports | Where-Object { $_.Id -eq $ReportId } } elseif ($ReportName) { $Reports | Where-Object { $_.DisplayName -eq $ReportName } } else { # Return all Reports if no filter is provided Write-Message -Message "No filter provided. Returning all Reports." -Level Debug $Reports } # Step 9: Handle results if ($Report) { Write-Message -Message "Report found in the Workspace '$WorkspaceId'." -Level Debug return $Report } else { Write-Message -Message "No Report found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/Get-FabricReport.ps1' 151 #Region './Public/Report/Get-FabricReportDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of an Report from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves the definition of an Report from a specified workspace using the provided ReportId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the Report exists. This parameter is mandatory. .PARAMETER ReportId The unique identifier of the Report to retrieve the definition for. This parameter is optional. .PARAMETER ReportFormat The format in which to retrieve the Report definition. This parameter is optional. .EXAMPLE Get-FabricReportDefinition -WorkspaceId "workspace-12345" -ReportId "Report-67890" This example retrieves the definition of the Report with ID "Report-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricReportDefinition -WorkspaceId "workspace-12345" -ReportId "Report-67890" -ReportFormat "json" This example retrieves the definition of the Report with ID "Report-67890" in the workspace with ID "workspace-12345" in JSON format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricReportDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReportId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReportFormat ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reports/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReportId if ($ReportFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $ReportFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Report '$ReportId' definition retrieved successfully!" -Level Debug return $response } 202 { Write-Message -Message "Getting Report '$ReportId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/Get-FabricReportDefinition.ps1' 123 #Region './Public/Report/New-FabricReport.ps1' -1 <# .SYNOPSIS Creates a new Report in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Report in the specified workspace. It supports optional parameters for Report description and path definitions. .PARAMETER WorkspaceId The unique identifier of the workspace where the Report will be created. This parameter is mandatory. .PARAMETER ReportName The name of the Report to be created. This parameter is mandatory. .PARAMETER ReportDescription An optional description for the Report. .PARAMETER ReportPathDefinition A mandatory path to the folder that contains Report definition files to upload. .EXAMPLE New-FabricReport -WorkspaceId "workspace-12345" -ReportName "New Report" -ReportDescription "Description of the new Report" This example creates a new Report named "New Report" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricReport { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReportName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReportDescription, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReportPathDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reports" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $ReportName } if ($ReportDescription) { $body.description = $ReportDescription } if ($ReportPathDefinition) { if (-not $body.definition) { $body.definition = @{ parts = @() } } $jsonObjectParts = Get-FileDefinitionParts -sourceDirectory $ReportPathDefinition # Add new part to the parts array $body.definition.parts = $jsonObjectParts.parts } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($ReportName, "Create Report")){ # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Report '$ReportName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Report '$ReportName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/New-FabricReport.ps1' 165 #Region './Public/Report/Remove-FabricReport.ps1' -1 <# .SYNOPSIS Removes an Report from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an Report from the specified workspace using the provided WorkspaceId and ReportId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the Report will be removed. .PARAMETER ReportId The unique identifier of the Report to be removed. .EXAMPLE Remove-FabricReport -WorkspaceId "workspace-12345" -ReportId "Report-67890" This example removes the Report with ID "Report-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricReport { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReportId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reports/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReportId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Report")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle response if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Report '$ReportId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Report '$ReportId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/Remove-FabricReport.ps1' 81 #Region './Public/Report/Update-FabricReport.ps1' -1 <# .SYNOPSIS Updates an existing Report in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing Report in the specified workspace. It supports optional parameters for Report description. .PARAMETER WorkspaceId The unique identifier of the workspace where the Report exists. This parameter is optional. .PARAMETER ReportId The unique identifier of the Report to be updated. This parameter is mandatory. .PARAMETER ReportName The new name of the Report. This parameter is mandatory. .PARAMETER ReportDescription An optional new description for the Report. .EXAMPLE Update-FabricReport -WorkspaceId "workspace-12345" -ReportId "Report-67890" -ReportName "Updated Report" -ReportDescription "Updated description" This example updates the Report with ID "Report-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricReport { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReportId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$ReportName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$ReportDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/reports/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReportId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $ReportName } if ($ReportDescription) { $body.description = $ReportDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($ReportName, "Update Report")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Report '$ReportName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/Update-FabricReport.ps1' 114 #Region './Public/Report/Update-FabricReportDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of an existing Report in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the definition of an existing Report in the specified workspace. It supports optional parameters for Report definition and platform-specific definition. .PARAMETER WorkspaceId The unique identifier of the workspace where the Report exists. This parameter is mandatory. .PARAMETER ReportId The unique identifier of the Report to be updated. This parameter is mandatory. .PARAMETER ReportPathDefinition A mandatory path to the Report definition file to upload. .EXAMPLE Update-FabricReportDefinition -WorkspaceId "workspace-12345" -ReportId "Report-67890" -ReportPathDefinition "C:\Path\To\ReportDefinition.json" This example updates the definition of the Report with ID "Report-67890" in the workspace with ID "workspace-12345" using the provided definition file. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricReportDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReportId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ReportPathDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/Reports/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $ReportId #if ($UpdateMetadata -eq $true) { # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } if ($ReportPathDefinition) { if (-not $body.definition) { $body.definition = @{ parts = @() } } $jsonObjectParts = Get-FileDefinitionParts -sourceDirectory $ReportPathDefinition # Add new part to the parts array $body.definition.parts = $jsonObjectParts.parts } # Check if any path is .platform foreach ($part in $jsonObjectParts.parts) { if ($part.path -eq ".platform") { $hasPlatformFile = $true Write-Message -Message "Platform File: $hasPlatformFile" -Level Debug } } if ($hasPlatformFile -eq $true) { $apiEndpointUrl += "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Report Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for Report '$ReportId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for Report '$ReportId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Update definition operation for Report '$ReportId' succeeded!" -Level Info return $operationStatus } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/Report/Update-FabricReportDefinition.ps1' 163 #Region './Public/Restore Points/Get-FabricRecoveryPoint.ps1' -1 <# .SYNOPSIS Get a list of Fabric recovery points. .DESCRIPTION Get a list of Fabric recovery points. Results can be filter by date or type. .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER WorkspaceGUID This is the workspace GUID in which the data warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the data warehouse which we want to retrieve restore points for. .PARAMETER Since Filter the results to only include restore points created after this date. .PARAMETER Type Filter the results to only include restore points of this type. .PARAMETER CreateTime The specific unique time of the restore point to remove. Get this from Get-FabricRecoveryPoint. .EXAMPLE PS> Get-FabricRecoveryPoint -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Gets all the available recovery points for the specified data warehouse, in the specified workspace. .NOTES Based on API calls from this blog post: https://blog.fabric.microsoft.com/en-US/blog/the-art-of-data-warehouse-recovery-within-microsoft-fabric/ #> function Get-FabricRecoveryPoint { param ( [String]$WorkspaceGUID, [String]$DataWarehouseGUID, [String]$BaseUrl = 'api.powerbi.com', [DateTime]$Since, [ValidateSet("automatic", "userDefined")] [string]$Type, #TODO: accept a list of times [string]$CreateTime ) #region handle the config parameters if(-not $WorkspaceGUID) { $WorkspaceGUID = Get-PSFConfigValue -FullName PSFabricTools.WorkspaceGUID } if(-not $DataWarehouseGUID) { $DataWarehouseGUID = Get-PSFConfigValue -FullName PSFabricTools.DataWarehouseGUID } if(-not $BaseUrl) { $BaseUrl = Get-PSFConfigValue -FullName PSFabricTools.BaseUrl } if (-not $WorkspaceGUID -or -not $DataWarehouseGUID -or -not $BaseUrl) { Stop-PSFFunction -Message 'WorkspaceGUID, DataWarehouseGUID, and BaseUrl are required parameters. Either set them with Set-FabricConfig or pass them in as parameter values' -EnableException $true } else { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl) } #endregion #region setting up the API call try { # Get token and setup the uri $getUriParam = @{ BaseUrl = $BaseUrl WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID } $iwr = Get-FabricUri @getUriParam } catch { Stop-PSFFunction -Message 'Failed to get Fabric URI - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } #endregion #region call the API if (-not $iwr) { Stop-PSFFunction -Message 'No URI received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } else { # set the body to list restore points $command = [PSCustomObject]@{ Commands = @(@{ '$type' = 'WarehouseListRestorePointsCommand' }) } try { # add the body and invoke $iwr.Add('Body', ($command | ConvertTo-Json -Compress)) $content = Invoke-WebRequest @iwr if($content) { # change output to be a PowerShell object and view restore points $restorePoints = ($content.Content | ConvertFrom-Json).operationInformation.progressDetail.restorePoints if($CreateTime) { $restorePoints = $restorePoints | Select-Object @{l='createTimeWhere';e={get-date($_.createTime) -Format 'yyyy-MM-ddTHH:mm:ssZ'}}, * | Where-Object createTimeWhere -eq $createTime } if($Since) { $restorePoints = $restorePoints | Where-Object { $_.createTime -gt $Since } } if($Type) { $restorePoints = $restorePoints | Where-Object { $_.createMode -eq $Type } } $restorePoints | Select-Object @{l='createTime';e={get-date($_.createTime) -Format 'yyyy-MM-ddTHH:mm:ssZ'}}, @{l='friendlyCreateTime';e={$_.createTime}}, label, createMode, type, createdByUserObjectId | Sort-Object createTime #TODO: default view rather than select\sort? } else { Stop-PSFFunction -Message 'No Content received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Invoke-WebRequest' -ErrorRecord $_ -EnableException $true } } #endregion } #EndRegion './Public/Restore Points/Get-FabricRecoveryPoint.ps1' 131 #Region './Public/Restore Points/New-FabricRecoveryPoint.ps1' -1 <# .SYNOPSIS Create a recovery point for a Fabric data warehouse .DESCRIPTION Create a recovery point for a Fabric data warehouse .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER WorkspaceGUID This is the workspace GUID in which the data warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the data warehouse which we want to retrieve restore points for. .EXAMPLE PS> New-FabricRecoveryPoint Create a new recovery point for the data warehouse specified in the configuration. .EXAMPLE PS> New-FabricRecoveryPoint -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Create a new recovery point for the specified data warehouse, in the specified workspace. #> function New-FabricRecoveryPoint { [CmdletBinding(SupportsShouldProcess)] param ( [String]$WorkspaceGUID, [String]$DataWarehouseGUID, [String]$BaseUrl = 'api.powerbi.com' ) #region handle the config parameters if(-not $WorkspaceGUID) { $WorkspaceGUID = Get-PSFConfigValue -FullName PSFabricTools.WorkspaceGUID } if(-not $DataWarehouseGUID) { $DataWarehouseGUID = Get-PSFConfigValue -FullName PSFabricTools.DataWarehouseGUID } if(-not $BaseUrl) { $BaseUrl = Get-PSFConfigValue -FullName PSFabricTools.BaseUrl } if (-not $WorkspaceGUID -or -not $DataWarehouseGUID -or -not $BaseUrl) { Stop-PSFFunction -Message 'WorkspaceGUID, DataWarehouseGUID, and BaseUrl are required parameters. Either set them with Set-FabricConfig or pass them in as parameter values' -EnableException $true } else { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl) } #endregion if ($PSCmdlet.ShouldProcess("Create a recovery point for a Fabric Data Warehouse")) { #region setting up the API call try { # Get token and setup the uri $getUriParam = @{ BaseUrl = $BaseUrl WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID } $iwr = Get-FabricUri @getUriParam } catch { Stop-PSFFunction -Message 'Failed to get Fabric URI - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } #endregion #region call the API if (-not $iwr) { Stop-PSFFunction -Message 'No URI received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } else { $command = [PSCustomObject]@{ Commands = @(@{ '$type' = 'WarehouseCreateRestorePointCommand' }) } try { # add the body and invoke $iwr.Add('Body', ($command | ConvertTo-Json -Compress)) $content = Invoke-WebRequest @iwr if($content) { # change output to be a PowerShell object and view new restore point #TODO: output - select default view but return more? ($content.Content | ConvertFrom-Json) | Select-Object progressState,@{l='type';e={$_.operationInformation.progressDetail.restorePoint.type}},@{l='createTime';e={get-date($_.operationInformation.progressDetail.restorePoint.createTime) -format 'yyyy-MM-ddTHH:mm:ssZ'}},@{l='friendlyCreateTime';e={$_.operationInformation.progressDetail.restorePoint.createTime}}, @{l='label';e={$_.operationInformation.progressDetail.restorePoint.label}}, @{l='createMode';e={$_.operationInformation.progressDetail.restorePoint.createMode}}, @{l='description';e={$_.operationInformation.progressDetail.restorePoint.description}}, @{l='createdByUserObjectId';e={$_.operationInformation.progressDetail.restorePoint.createdByUserObjectId}}, @{l='lastModifiedByUserObjectId';e={$_.operationInformation.progressDetail.restorePoint.lastModifiedByUserObjectId}}, @{l='lastModifiedTime';e={$_.operationInformation.progressDetail.restorePoint.lastModifiedTime}} } else { Stop-PSFFunction -Message 'No Content received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Invoke-WebRequest' -ErrorRecord $_ -EnableException $true } } #endregion } } #EndRegion './Public/Restore Points/New-FabricRecoveryPoint.ps1' 102 #Region './Public/Restore Points/Remove-FabricRecoveryPoint.ps1' -1 <# .SYNOPSIS Remove a selected Fabric Recovery Point. .DESCRIPTION Remove a selected Fabric Recovery Point. .PARAMETER CreateTime The specific unique time of the restore point to remove. Get this from Get-FabricRecoveryPoint. .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER WorkspaceGUID This is the workspace GUID in which the data warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the data warehouse which we want to retrieve restore points for. .EXAMPLE PS> Remove-FabricRecoveryPoint -CreateTime '2024-07-23T11:20:26Z' Remove a specific restore point from a Fabric Data Warehouse that has been set using Set-FabricConfig. .EXAMPLE PS> Remove-FabricRecoveryPoint -CreateTime '2024-07-23T11:20:26Z' -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Remove a specific restore point from a Fabric Data Warehouse, specifying the workspace and data warehouse GUIDs. .NOTES General notes #> function Remove-FabricRecoveryPoint { [CmdletBinding(SupportsShouldProcess)] param ( [string]$CreateTime, [String]$WorkspaceGUID, [String]$DataWarehouseGUID, [String]$BaseUrl = 'api.powerbi.com' #TODO - implement piping from get? or a way of interactively choosing points to remove ) #region handle the config parameters if(-not $WorkspaceGUID) { $WorkspaceGUID = Get-PSFConfigValue -FullName PSFabricTools.WorkspaceGUID } if(-not $DataWarehouseGUID) { $DataWarehouseGUID = Get-PSFConfigValue -FullName PSFabricTools.DataWarehouseGUID } if(-not $BaseUrl) { $BaseUrl = Get-PSFConfigValue -FullName PSFabricTools.BaseUrl } if (-not $WorkspaceGUID -or -not $DataWarehouseGUID -or -not $BaseUrl) { Stop-PSFFunction -Message 'WorkspaceGUID, DataWarehouseGUID, and BaseUrl are required parameters. Either set them with Set-FabricConfig or pass them in as parameter values' -EnableException $true } else { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl) } #endregion if ($PSCmdlet.ShouldProcess("Remove recovery point for a Fabric Data Warehouse")) { #region setting up the API call try { # Get token and setup the uri $getUriParam = @{ BaseUrl = $BaseUrl WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID } $iwr = Get-FabricUri @getUriParam } catch { Stop-PSFFunction -Message 'Failed to get Fabric URI - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } #endregion #region call the API if (-not $iwr) { Stop-PSFFunction -Message 'No URI received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } else { # for the API this needs to be an array, even if it's just one item [string[]]$CreateTimeObj = $CreateTime #region check restore point exists #Get the restore point to make sure it exists - the fabric API doesn't really confirm we deleted anything so we will manually check $getSplat = @{ WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID BaseUrl = $BaseUrl CreateTime = $CreateTimeObj } try { if(Get-FabricRecoveryPoint @getSplat) { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point exists' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) } else { Stop-PSFFunction -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point not found!' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Get-FabricRecoveryPoint to check restore point exists before removal' -ErrorRecord $_ -EnableException $true } #endregion #region remove the restore point $command = [PSCustomObject]@{ commands = @([ordered]@{ '$type' = 'WarehouseDeleteRestorePointsCommand' 'RestorePointsToDelete' = $CreateTimeObj }) } try { # add the body and invoke $iwr.Add('Body', ($command | ConvertTo-Json -Compress -Depth 3)) $content = Invoke-WebRequest @iwr if($content) { # change output to be a PowerShell object and view new restore point #TODO: output - select default view but return more? $results = ($content.Content | ConvertFrom-Json) } else { Stop-PSFFunction -Message 'No Content received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Invoke-WebRequest' -ErrorRecord $_ -EnableException $true } #endregion #region check restore point exists try { #Get the restore point to make sure it exists - the fabric API doesn't really confirm we deleted anything so we will manually check if(Get-FabricRecoveryPoint @getSplat) { Stop-PSFFunction -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point not was not successfully removed!' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) -ErrorRecord $_ -EnableException $true } else { Write-PSFMessage -Level Output -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point successfully removed' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) $results } } catch { Stop-PSFFunction -Message 'Issue calling Get-FabricRecoveryPoint to check restore point exists before removal' -ErrorRecord $_ -EnableException $true } #endregion } #endregion } } #EndRegion './Public/Restore Points/Remove-FabricRecoveryPoint.ps1' 152 #Region './Public/Restore Points/Restore-FabricRecoveryPoint.ps1' -1 <# .SYNOPSIS Restore a Fabric data warehouse to a specified restore pont. .DESCRIPTION Restore a Fabric data warehouse to a specified restore pont. .PARAMETER CreateTime The specific unique time of the restore point to remove. Get this from Get-FabricRecoveryPoint. .PARAMETER BaseUrl Defaults to api.powerbi.com .PARAMETER WorkspaceGUID This is the workspace GUID in which the data warehouse resides. .PARAMETER DataWarehouseGUID The GUID for the data warehouse which we want to retrieve restore points for. .PARAMETER Wait Wait for the restore to complete before returning. .EXAMPLE PS> Restore-FabricRecoveryPoint -CreateTime '2024-07-23T11:20:26Z' Restore a Fabric Data Warehouse to a specific restore point that has been set using Set-FabricConfig. .EXAMPLE PS> Restore-FabricRecoveryPoint -CreateTime '2024-07-23T11:20:26Z' -WorkspaceGUID 'GUID-GUID-GUID-GUID' -DataWarehouseGUID 'GUID-GUID-GUID-GUID' Restore a Fabric Data Warehouse to a specific restore point, specifying the workspace and data warehouse GUIDs. #> function Restore-FabricRecoveryPoint { [CmdletBinding(SupportsShouldProcess)] param ( [string]$CreateTime, [String]$WorkspaceGUID, [String]$DataWarehouseGUID, [String]$BaseUrl = 'api.powerbi.com', [switch]$Wait ) #region handle the config parameters if(-not $WorkspaceGUID) { $WorkspaceGUID = Get-PSFConfigValue -FullName PSFabricTools.WorkspaceGUID } if(-not $DataWarehouseGUID) { $DataWarehouseGUID = Get-PSFConfigValue -FullName PSFabricTools.DataWarehouseGUID } if(-not $BaseUrl) { $BaseUrl = Get-PSFConfigValue -FullName PSFabricTools.BaseUrl } if (-not $WorkspaceGUID -or -not $DataWarehouseGUID -or -not $BaseUrl) { Stop-PSFFunction -Message 'WorkspaceGUID, DataWarehouseGUID, and BaseUrl are required parameters. Either set them with Set-FabricConfig or pass them in as parameter values' -EnableException $true } else { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl) } #endregion if ($PSCmdlet.ShouldProcess("Recover a Fabric Data Warehouse to a restore point")) { #region setting up the API call try { # Get token and setup the uri $getUriParam = @{ BaseUrl = $BaseUrl WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID } $iwr = Get-FabricUri @getUriParam } catch { Stop-PSFFunction -Message 'Failed to get Fabric URI - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } #endregion #region call the API if (-not $iwr) { Stop-PSFFunction -Message 'No URI received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } else { #region check restore point exists #Get the restore point to make sure it exists before we try and restore to it $getSplat = @{ WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID BaseUrl = $BaseUrl CreateTime = $CreateTime } try { if(Get-FabricRecoveryPoint @getSplat) { Write-PSFMessage -Level Verbose -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point exists' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) } else { Stop-PSFFunction -Message ('WorkspaceGUID: {0}; DataWarehouseGUID: {1}; BaseUrl: {2}; CreateTime: {3} - restore point not found!' -f $WorkspaceGUID, $DataWarehouseGUID, $BaseUrl, $CreateTime) -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Get-FabricRecoveryPoint to check restore point exists before attempting recovery' -ErrorRecord $_ -EnableException $true } #endregion #region recover to the restore point # command is now WarehouseRestoreInPlaceCommand and the RestorePoint is the create time of the specific restore point to use $command = [PSCustomObject]@{ commands = @([ordered]@{ '$type' = 'WarehouseRestoreInPlaceCommand' 'RestorePoint' = $CreateTime }) } try { # add the body and invoke $iwr.Add('Body', ($command | ConvertTo-Json -Compress)) $content = Invoke-WebRequest @iwr if($content) { #TODO: output - select default view but return more? $content = ($content.Content | ConvertFrom-Json) } else { Stop-PSFFunction -Message 'No Content received from API - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } } catch { Stop-PSFFunction -Message 'Issue calling Invoke-WebRequest' -ErrorRecord $_ -EnableException $true } #endregion #region check the progress of the restore if ($Wait) { # we need to append batches to the uri try { while($Wait) { # Get token and setup the uri $getUriParam = @{ BaseUrl = $BaseUrl WorkspaceGUID = $WorkspaceGUID DataWarehouseGUID = $DataWarehouseGUID BatchId = $content.batchId } $iwr = Get-FabricUri @getUriParam $restoreProgress = ((Invoke-WebRequest @iwr).Content | ConvertFrom-Json) if($restoreProgress.progressState -eq 'inProgress') { Write-PSFMessage -Level Output -Message 'Restore in progress' } elseif ($restoreProgress.progressState -eq 'success') { Write-PSFMessage -Level Output -Message 'Restore completed successfully' $restoreProgress | Select-Object progressState, @{l='startDateTimeUtc';e={$_.startTimeStamp }}, @{l='RestorePointCreateTime';e={$CreateTime }} $wait = $false break } else { Write-PSFMessage -Level Output -Message 'Restore failed' $restoreProgress | Select-Object progressState, @{l='startDateTimeUtc';e={$_.startTimeStamp }} $wait = $false break } # wait a few seconds Start-Sleep -Seconds 3 } } catch { Stop-PSFFunction -Message 'Failed to get Fabric URI for the batchId - check authentication and parameters.' -ErrorRecord $_ -EnableException $true } } else { Write-PSFMessage -Level Output -Message 'Restore in progress - use the -Wait parameter to wait for restore to complete' $content } } #endregion } } #EndRegion './Public/Restore Points/Restore-FabricRecoveryPoint.ps1' 180 #Region './Public/Semantic Model/Get-FabricSemanticModel.ps1' -1 <# .SYNOPSIS Retrieves SemanticModel details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves SemanticModel details from a specified workspace using either the provided SemanticModelId or SemanticModelName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the SemanticModel exists. This parameter is mandatory. .PARAMETER SemanticModelId The unique identifier of the SemanticModel to retrieve. This parameter is optional. .PARAMETER SemanticModelName The name of the SemanticModel to retrieve. This parameter is optional. .EXAMPLE Get-FabricSemanticModel -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" This example retrieves the SemanticModel details for the SemanticModel with ID "SemanticModel-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricSemanticModel -WorkspaceId "workspace-12345" -SemanticModelName "My SemanticModel" This example retrieves the SemanticModel details for the SemanticModel named "My SemanticModel" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricSemanticModel { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SemanticModelId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SemanticModelName ) try { # Step 1: Handle ambiguous input if ($SemanticModelId -and $SemanticModelName) { Write-Message -Message "Both 'SemanticModelId' and 'SemanticModelName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $SemanticModels = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/semanticModels" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $SemanticModels += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $SemanticModel = if ($SemanticModelId) { $SemanticModels | Where-Object { $_.Id -eq $SemanticModelId } } elseif ($SemanticModelName) { $SemanticModels | Where-Object { $_.DisplayName -eq $SemanticModelName } } else { # Return all SemanticModels if no filter is provided Write-Message -Message "No filter provided. Returning all SemanticModels." -Level Debug $SemanticModels } # Step 9: Handle results if ($SemanticModel) { Write-Message -Message "SemanticModel found in the Workspace '$WorkspaceId'." -Level Debug return $SemanticModel } else { Write-Message -Message "No SemanticModel found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve SemanticModel. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/Get-FabricSemanticModel.ps1' 151 #Region './Public/Semantic Model/Get-FabricSemanticModelDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of an SemanticModel from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves the definition of an SemanticModel from a specified workspace using the provided SemanticModelId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the SemanticModel exists. This parameter is mandatory. .PARAMETER SemanticModelId The unique identifier of the SemanticModel to retrieve the definition for. This parameter is optional. .PARAMETER SemanticModelFormat The format in which to retrieve the SemanticModel definition. This parameter is optional. .EXAMPLE Get-FabricSemanticModelDefinition -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" This example retrieves the definition of the SemanticModel with ID "SemanticModel-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricSemanticModelDefinition -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" -SemanticModelFormat "json" This example retrieves the definition of the SemanticModel with ID "SemanticModel-67890" in the workspace with ID "workspace-12345" in JSON format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricSemanticModelDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SemanticModelId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('TMDL', 'TMSL')] [string]$SemanticModelFormat = "TMDL" ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/semanticModels/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $SemanticModelId if ($SemanticModelFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $SemanticModelFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "SemanticModel '$SemanticModelId' definition retrieved successfully!" -Level Debug return $response } 202 { Write-Message -Message "Getting SemanticModel '$SemanticModelId' definition request accepted. Retrieving in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve SemanticModel. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/Get-FabricSemanticModelDefinition.ps1' 124 #Region './Public/Semantic Model/New-FabricSemanticModel.ps1' -1 <# .SYNOPSIS Creates a new SemanticModel in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new SemanticModel in the specified workspace. It supports optional parameters for SemanticModel description and path definitions. .PARAMETER WorkspaceId The unique identifier of the workspace where the SemanticModel will be created. This parameter is mandatory. .PARAMETER SemanticModelName The name of the SemanticModel to be created. This parameter is mandatory. .PARAMETER SemanticModelDescription An optional description for the SemanticModel. .PARAMETER SemanticModelPathDefinition An optional path to the SemanticModel definition file to upload. .EXAMPLE New-FabricSemanticModel -WorkspaceId "workspace-12345" -SemanticModelName "New SemanticModel" -SemanticModelDescription "Description of the new SemanticModel" This example creates a new SemanticModel named "New SemanticModel" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricSemanticModel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SemanticModelName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SemanticModelDescription, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SemanticModelPathDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/semanticModels" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $SemanticModelName definition = @{ parts = @() } } $jsonObjectParts = Get-FileDefinitionParts -sourceDirectory $SemanticModelPathDefinition # Add new part to the parts array $body.definition.parts = $jsonObjectParts.parts if ($SemanticModelDescription) { $body.description = $SemanticModelDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess("Create SemanticModel", "Creating the SemanticModel '$SemanticModelName' in workspace '$WorkspaceId'.")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "SemanticModel '$SemanticModelName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "SemanticModel '$SemanticModelName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create SemanticModel. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/New-FabricSemanticModel.ps1' 160 #Region './Public/Semantic Model/Remove-FabricSemanticModel.ps1' -1 <# .SYNOPSIS Removes an SemanticModel from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an SemanticModel from the specified workspace using the provided WorkspaceId and SemanticModelId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the SemanticModel will be removed. .PARAMETER SemanticModelId The unique identifier of the SemanticModel to be removed. .EXAMPLE Remove-FabricSemanticModel -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" This example removes the SemanticModel with ID "SemanticModel-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricSemanticModel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SemanticModelId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/semanticModels/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SemanticModelId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove SemanticModel")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle response if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "SemanticModel '$SemanticModelId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete SemanticModel '$SemanticModelId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/Remove-FabricSemanticModel.ps1' 81 #Region './Public/Semantic Model/Update-FabricSemanticModel.ps1' -1 <# .SYNOPSIS Updates an existing SemanticModel in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing SemanticModel in the specified workspace. It supports optional parameters for SemanticModel description. .PARAMETER WorkspaceId The unique identifier of the workspace where the SemanticModel exists. This parameter is optional. .PARAMETER SemanticModelId The unique identifier of the SemanticModel to be updated. This parameter is mandatory. .PARAMETER SemanticModelName The new name of the SemanticModel. This parameter is mandatory. .PARAMETER SemanticModelDescription An optional new description for the SemanticModel. .EXAMPLE Update-FabricSemanticModel -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" -SemanticModelName "Updated SemanticModel" -SemanticModelDescription "Updated description" This example updates the SemanticModel with ID "SemanticModel-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSemanticModel { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SemanticModelId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SemanticModelName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SemanticModelDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/semanticModels/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SemanticModelId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $SemanticModelName } if ($SemanticModelDescription) { $body.description = $SemanticModelDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess("Update SemanticModel", "Updating the SemanticModel with ID '$SemanticModelId' in workspace '$WorkspaceId'.")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "SemanticModel '$SemanticModelName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update SemanticModel. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/Update-FabricSemanticModel.ps1' 114 #Region './Public/Semantic Model/Update-FabricSemanticModelDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of an existing SemanticModel in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the definition of an existing SemanticModel in the specified workspace. It supports optional parameters for SemanticModel definition and platform-specific definition. .PARAMETER WorkspaceId The unique identifier of the workspace where the SemanticModel exists. This parameter is mandatory. .PARAMETER SemanticModelId The unique identifier of the SemanticModel to be updated. This parameter is mandatory. .PARAMETER SemanticModelPathDefinition An optional path to the SemanticModel definition file to upload. .EXAMPLE Update-FabricSemanticModelDefinition -WorkspaceId "workspace-12345" -SemanticModelId "SemanticModel-67890" -SemanticModelPathDefinition "C:\Path\To\SemanticModelDefinition.json" This example updates the definition of the SemanticModel with ID "SemanticModel-67890" in the workspace with ID "workspace-12345" using the provided definition file. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSemanticModelDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SemanticModelId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SemanticModelPathDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/SemanticModels/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $SemanticModelId # Step 3: Construct the request body $body = @{ definition = @{ parts = @() } } $jsonObjectParts = Get-FileDefinitionParts -sourceDirectory $SemanticModelPathDefinition # Add new part to the parts array $body.definition.parts = $jsonObjectParts.parts # Check if any path is .platform foreach ($part in $jsonObjectParts.parts) { if ($part.path -eq ".platform") { $hasPlatformFile = $true Write-Message -Message "Platform File: $hasPlatformFile" -Level Debug } } if ($hasPlatformFile -eq $true) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update SemanticModel Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for SemanticModel '$SemanticModelId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for SemanticModel '$SemanticModelId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Update definition operation for Semantic Model '$SemanticModelId' succeeded!" -Level Info return $operationStatus } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update SemanticModel. Error: $errorDetails" -Level Error } } #EndRegion './Public/Semantic Model/Update-FabricSemanticModelDefinition.ps1' 151 #Region './Public/Set-FabricAuthToken.ps1' -1 <# .SYNOPSIS Sets the Fabric authentication token. .DESCRIPTION The Set-FabricAuthToken function sets the Fabric authentication token. It checks if an Azure context is already available. If not, it connects to the Azure account using either a service principal ID and secret, a provided credential, or interactive login. It then gets the Azure context and sets the Fabric authentication token. .PARAMETER azContext The Azure context. If not provided, the function connects to the Azure account and gets the context. .PARAMETER servicePrincipalId The service principal ID. If provided, the function uses this ID and the service principal secret to connect to the Azure account. .PARAMETER servicePrincipalSecret The service principal secret. Used with the service principal ID to connect to the Azure account. .PARAMETER tenantId The tenant ID. Used with the service principal ID and secret or the credential to connect to the Azure account. .PARAMETER credential The credential. If provided, the function uses this credential to connect to the Azure account. .PARAMETER reset A switch parameter. If provided, the function resets the Fabric authentication token. .PARAMETER apiUrl The API URL. If provided, the function sets the Fabric API URL to this value. .EXAMPLE Set-FabricAuthToken -servicePrincipalId "12345678-90ab-cdef-1234-567890abcdef" -servicePrincipalSecret "secret" -tenantId "12345678-90ab-cdef-1234-567890abcdef" This command sets the Fabric authentication token using the provided service principal ID, secret, and tenant ID. .INPUTS String, SecureString, PSCredential. You can pipe a string that contains the service principal ID, a secure string that contains the service principal secret, and a PSCredential object that contains the credential to Set-FabricAuthToken. .OUTPUTS None. This function does not return any output. .NOTES This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> function Set-FabricAuthToken { [OutputType([System.Collections.Hashtable])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification = "To pass current unit tests")] [CmdletBinding(SupportsShouldProcess)] param ( [string] $servicePrincipalId , [string] $servicePrincipalSecret , [PSCredential] $credential , [string] $tenantId , [switch] $reset , [string] $apiUrl ) if (!$reset) { $azContext = Get-AzContext } if ($apiUrl) { $FabricSession.BaseApiUrl = $apiUrl } if (!$azContext) { Write-Output "Getting authentication token" if ($servicePrincipalId) { $credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $servicePrincipalId, ($servicePrincipalSecret | ConvertTo-SecureString -AsPlainText -Force) Connect-AzAccount -ServicePrincipal -TenantId $tenantId -Credential $credential | Out-Null Set-AzContext -Tenant $tenantId | Out-Null } elseif ($null -ne $credential) { Connect-AzAccount -Credential $credential -Tenant $tenantId | Out-Null } else { Connect-AzAccount | Out-Null } $azContext = Get-AzContext } if ($PSCmdlet.ShouldProcess("Setting Fabric authentication token for $($azContext.Account)")) { Write-Output "Connected: $($azContext.Account)" Write-Output "Fabric ResourceUrl: $($FabricSession.ResourceUrl)" $FabricSession.AccessToken = (Get-AzAccessToken -AsSecureString -ResourceUrl $FabricSession.ResourceUrl) $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($FabricSession.AccessToken.Token) $FabricSession.FabricToken = ([System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)) Write-Verbose "Setup headers for API calls" $FabricSession.HeaderParams = @{ Authorization = $FabricSession.AccessToken.Type + ' ' + $FabricSession.FabricToken } Write-Output "Azure BaseApiUrl: $($FabricSession.ResourceUrl)" $script:AzureSession.AccessToken = (Get-AzAccessToken -AsSecureString -ResourceUrl $AzureSession.BaseApiUrl) $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($AzureSession.AccessToken.Token) $script:AzureSession.Token = ([System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr)) $AzureSession.HeaderParams = @{ Authorization = $AzureSession.AccessToken.Type + ' ' + $AzureSession.Token } # Copy session values to exposed $FabricConfig $FabricConfig.TenantIdGlobal = $FabricSession.AccessToken.TenantId $FabricConfig.TokenExpiresOn = $FabricSession.AccessToken.ExpiresOn $FabricConfig.FabricHeaders = $FabricSession.HeaderParams return $($FabricSession.FabricToken) } } #EndRegion './Public/Set-FabricAuthToken.ps1' 111 #Region './Public/Spark Job Definition/Get-FabricSparkJobDefinition.ps1' -1 <# .SYNOPSIS Retrieves Spark Job Definition details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves SparkJobDefinition details from a specified workspace using either the provided SparkJobDefinitionId or SparkJobDefinitionName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the SparkJobDefinition exists. This parameter is mandatory. .PARAMETER SparkJobDefinitionId The unique identifier of the SparkJobDefinition to retrieve. This parameter is optional. .PARAMETER SparkJobDefinitionName The name of the SparkJobDefinition to retrieve. This parameter is optional. .EXAMPLE Get-FabricSparkJobDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" This example retrieves the SparkJobDefinition details for the SparkJobDefinition with ID "SparkJobDefinition-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricSparkJobDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionName "My SparkJobDefinition" This example retrieves the SparkJobDefinition details for the SparkJobDefinition named "My SparkJobDefinition" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricSparkJobDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SparkJobDefinitionName ) try { # Step 1: Handle ambiguous input if ($SparkJobDefinitionId -and $SparkJobDefinitionName) { Write-Message -Message "Both 'SparkJobDefinitionId' and 'SparkJobDefinitionName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $SparkJobDefinitions = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/sparkJobDefinitions" -f $FabricConfig.BaseUrl, $WorkspaceId # Step 3: Loop to retrieve data with continuation token do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $SparkJobDefinitions += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $SparkJobDefinition = if ($SparkJobDefinitionId) { $SparkJobDefinitions | Where-Object { $_.Id -eq $SparkJobDefinitionId } } elseif ($SparkJobDefinitionName) { $SparkJobDefinitions | Where-Object { $_.DisplayName -eq $SparkJobDefinitionName } } else { # Return all SparkJobDefinitions if no filter is provided Write-Message -Message "No filter provided. Returning all SparkJobDefinitions." -Level Debug $SparkJobDefinitions } # Step 9: Handle results if ($SparkJobDefinition) { Write-Message -Message "Spark Job Definition found in the Workspace '$WorkspaceId'." -Level Debug return $SparkJobDefinition } else { Write-Message -Message "No Spark Job Definition found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve SparkJobDefinition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Get-FabricSparkJobDefinition.ps1' 151 #Region './Public/Spark Job Definition/Get-FabricSparkJobDefinitionDefinition.ps1' -1 <# .SYNOPSIS Retrieves the definition of an SparkJobDefinition from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves the definition of an SparkJobDefinition from a specified workspace using the provided SparkJobDefinitionId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the SparkJobDefinition exists. This parameter is mandatory. .PARAMETER SparkJobDefinitionId The unique identifier of the SparkJobDefinition to retrieve the definition for. This parameter is optional. .PARAMETER SparkJobDefinitionFormat The format in which to retrieve the SparkJobDefinition definition. This parameter is optional. .EXAMPLE Get-FabricSparkJobDefinitionDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" This example retrieves the definition of the SparkJobDefinition with ID "SparkJobDefinition-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricSparkJobDefinitionDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" -SparkJobDefinitionFormat "json" This example retrieves the definition of the SparkJobDefinition with ID "SparkJobDefinition-67890" in the workspace with ID "workspace-12345" in JSON format. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricSparkJobDefinitionDefinition { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('SparkJobDefinitionV1')] [string]$SparkJobDefinitionFormat = "SparkJobDefinitionV1" ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sparkJobDefinitions/{2}/getDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkJobDefinitionId if ($SparkJobDefinitionFormat) { $apiEndpointUrl = "{0}?format={1}" -f $apiEndpointUrl, $SparkJobDefinitionFormat } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code and handle the response switch ($statusCode) { 200 { Write-Message -Message "Spark Job Definition '$SparkJobDefinitionId' definition retrieved successfully!" -Level Debug return $response.definition.parts } 202 { Write-Message -Message "Getting Spark Job Definition '$SparkJobDefinitionId' definition request accepted. Retrieving in progress!" -Level Debug [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId, -location $location Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult.definition.parts } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 9: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Spark Job Definition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Get-FabricSparkJobDefinitionDefinition.ps1' 123 #Region './Public/Spark Job Definition/New-FabricSparkJobDefinition.ps1' -1 <# .SYNOPSIS Creates a new SparkJobDefinition in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new SparkJobDefinition in the specified workspace. It supports optional parameters for SparkJobDefinition description and path definitions. .PARAMETER WorkspaceId The unique identifier of the workspace where the SparkJobDefinition will be created. This parameter is mandatory. .PARAMETER SparkJobDefinitionName The name of the SparkJobDefinition to be created. This parameter is mandatory. .PARAMETER SparkJobDefinitionDescription An optional description for the SparkJobDefinition. .PARAMETER SparkJobDefinitionPathDefinition An optional path to the SparkJobDefinition definition file to upload. .PARAMETER SparkJobDefinitionPathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE New-FabricSparkJobDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionName "New SparkJobDefinition" -SparkJobDefinitionDescription "Description of the new SparkJobDefinition" This example creates a new SparkJobDefinition named "New SparkJobDefinition" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricSparkJobDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SparkJobDefinitionName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sparkJobDefinitions" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $SparkJobDefinitionName } if ($SparkJobDefinitionDescription) { $body.description = $SparkJobDefinitionDescription } if ($SparkJobDefinitionPathDefinition) { $SparkJobDefinitionEncodedContent = Convert-ToBase64 -filePath $SparkJobDefinitionPathDefinition if (-not [string]::IsNullOrEmpty($SparkJobDefinitionEncodedContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "SparkJobDefinitionV1" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = "SparkJobDefinitionProperties.json" payload = $SparkJobDefinitionEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in SparkJobDefinition definition." -Level Error return $null } } if ($SparkJobDefinitionPathPlatformDefinition) { $SparkJobDefinitionEncodedPlatformContent = Convert-ToBase64 -filePath $SparkJobDefinitionPathPlatformDefinition if (-not [string]::IsNullOrEmpty($SparkJobDefinitionEncodedPlatformContent)) { # Initialize definition if it doesn't exist if (-not $body.definition) { $body.definition = @{ format = "SparkJobDefinitionV1" parts = @() } } # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $SparkJobDefinitionEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Create Spark Job Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" Write-Message -Message "Response Code: $statusCode" -Level Debug } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Spark Job Definition '$SparkJobDefinitionName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Spark Job Definition '$SparkJobDefinitionName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Spark Job Definition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/New-FabricSparkJobDefinition.ps1' 215 #Region './Public/Spark Job Definition/Remove-FabricSparkJobDefinition.ps1' -1 <# .SYNOPSIS Removes an SparkJobDefinition from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove an SparkJobDefinition from the specified workspace using the provided WorkspaceId and SparkJobDefinitionId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the SparkJobDefinition will be removed. .PARAMETER SparkJobDefinitionId The unique identifier of the SparkJobDefinition to be removed. .EXAMPLE Remove-FabricSparkJobDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" This example removes the SparkJobDefinition with ID "SparkJobDefinition-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricSparkJobDefinition { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sparkJobDefinitions/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkJobDefinitionId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove SparkJobDefinition")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle response if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Spark Job Definition '$SparkJobDefinitionId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete SparkJobDefinition '$SparkJobDefinitionId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Remove-FabricSparkJobDefinition.ps1' 78 #Region './Public/Spark Job Definition/Start-FabricSparkJobDefinitionOnDemand.ps1' -1 <# .SYNOPSIS Starts a Fabric Spark Job Definition on demand. .DESCRIPTION This function initiates a Spark Job Definition on demand within a specified workspace. It constructs the appropriate API endpoint URL and makes a POST request to start the job. The function can optionally wait for the job to complete based on the 'waitForCompletion' parameter. .PARAMETER WorkspaceId The ID of the workspace where the Spark Job Definition is located. This parameter is mandatory. .PARAMETER SparkJobDefinitionId The ID of the Spark Job Definition to be started. This parameter is mandatory. .PARAMETER JobType The type of job to be started. The default value is 'sparkjob'. This parameter is optional. .PARAMETER waitForCompletion A boolean flag indicating whether to wait for the job to complete. The default value is $false. This parameter is optional. .EXAMPLE Start-FabricSparkJobDefinitionOnDemand -WorkspaceId "workspace123" -SparkJobDefinitionId "jobdef456" -waitForCompletion $true .NOTES Ensure that the necessary authentication tokens are valid before running this function. The function logs detailed messages for debugging and informational purposes. #> function Start-FabricSparkJobDefinitionOnDemand { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('sparkjob')] [string]$JobType = "sparkjob", [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$waitForCompletion = $false ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/SparkJobDefinitions/{2}/jobs/instances?jobType={3}" -f $FabricConfig.BaseUrl, $WorkspaceId , $SparkJobDefinitionId, $JobType Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Start Spark Job Definition on demand")){ # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } Write-Message -Message "Response Code: $statusCode" -Level Debug # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Spark Job Definition on demand successfully initiated for SparkJobDefinition '$SparkJobDefinition.displayName'." -Level Info return $response } 202 { Write-Message -Message "Spark Job Definition on demand accepted and is now running in the background. Job execution is in progress." -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug if ($waitForCompletion -eq $true) { Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location -retryAfter $retryAfter Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug return $operationStatus } else { Write-Message -Message "The operation is running asynchronously." -Level Info Write-Message -Message "Use the returned details to check the operation status." -Level Info Write-Message -Message "To wait for the operation to complete, set the 'waitForCompletion' parameter to true." -Level Info $operationDetails = [PSCustomObject]@{ OperationId = $operationId Location = $location RetryAfter = $retryAfter } return $operationDetails } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to start Spark Job Definition on demand. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Start-FabricSparkJobDefinitionOnDemand.ps1' 128 #Region './Public/Spark Job Definition/Update-FabricSparkJobDefinition.ps1' -1 <# .SYNOPSIS Updates an existing SparkJobDefinition in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing SparkJobDefinition in the specified workspace. It supports optional parameters for SparkJobDefinition description. .PARAMETER WorkspaceId The unique identifier of the workspace where the SparkJobDefinition exists. This parameter is optional. .PARAMETER SparkJobDefinitionId The unique identifier of the SparkJobDefinition to be updated. This parameter is mandatory. .PARAMETER SparkJobDefinitionName The new name of the SparkJobDefinition. This parameter is mandatory. .PARAMETER SparkJobDefinitionDescription An optional new description for the SparkJobDefinition. .EXAMPLE Update-FabricSparkJobDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" -SparkJobDefinitionName "Updated SparkJobDefinition" -SparkJobDefinitionDescription "Updated description" This example updates the SparkJobDefinition with ID "SparkJobDefinition-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSparkJobDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SparkJobDefinitionName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sparkJobDefinitions/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkJobDefinitionId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $SparkJobDefinitionName } if ($SparkJobDefinitionDescription) { $body.description = $SparkJobDefinitionDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update SparkJobDefinition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Spark Job Definition '$SparkJobDefinitionName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update SparkJobDefinition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Update-FabricSparkJobDefinition.ps1' 113 #Region './Public/Spark Job Definition/Update-FabricSparkJobDefinitionDefinition.ps1' -1 <# .SYNOPSIS Updates the definition of an existing SparkJobDefinition in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update the definition of an existing SparkJobDefinition in the specified workspace. It supports optional parameters for SparkJobDefinition definition and platform-specific definition. .PARAMETER WorkspaceId The unique identifier of the workspace where the SparkJobDefinition exists. This parameter is mandatory. .PARAMETER SparkJobDefinitionId The unique identifier of the SparkJobDefinition to be updated. This parameter is mandatory. .PARAMETER SparkJobDefinitionPathDefinition An optional path to the SparkJobDefinition definition file to upload. .PARAMETER SparkJobDefinitionPathPlatformDefinition An optional path to the platform-specific definition file to upload. .EXAMPLE Update-FabricSparkJobDefinitionDefinition -WorkspaceId "workspace-12345" -SparkJobDefinitionId "SparkJobDefinition-67890" -SparkJobDefinitionPathDefinition "C:\Path\To\SparkJobDefinitionDefinition.json" This example updates the definition of the SparkJobDefinition with ID "SparkJobDefinition-67890" in the workspace with ID "workspace-12345" using the provided definition file. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSparkJobDefinitionDefinition { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionPathDefinition, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkJobDefinitionPathPlatformDefinition ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/SparkJobDefinitions/{2}/updateDefinition" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkJobDefinitionId #if ($UpdateMetadata -eq $true) { if ($SparkJobDefinitionPathPlatformDefinition) { $apiEndpointUrl = "?updateMetadata=true" -f $apiEndpointUrl } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ definition = @{ format = "SparkJobDefinitionV1" parts = @() } } if ($SparkJobDefinitionPathDefinition) { $SparkJobDefinitionEncodedContent = Convert-ToBase64 -filePath $SparkJobDefinitionPathDefinition if (-not [string]::IsNullOrEmpty($SparkJobDefinitionEncodedContent)) { # Add new part to the parts array $body.definition.parts += @{ path = "SparkJobDefinitionV1.json" payload = $SparkJobDefinitionEncodedContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in SparkJobDefinition definition." -Level Error return $null } } if ($SparkJobDefinitionPathPlatformDefinition) { $SparkJobDefinitionEncodedPlatformContent = Convert-ToBase64 -filePath $SparkJobDefinitionPathPlatformDefinition if (-not [string]::IsNullOrEmpty($SparkJobDefinitionEncodedPlatformContent)) { # Add new part to the parts array $body.definition.parts += @{ path = ".platform" payload = $SparkJobDefinitionEncodedPlatformContent payloadType = "InlineBase64" } } else { Write-Message -Message "Invalid or empty content in platform definition." -Level Error return $null } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Spark Job Definition")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Update definition for Spark Job Definition '$SparkJobDefinitionId' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Update definition for Spark Job Definition '$SparkJobDefinitionId' accepted. Operation in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Spark Job Definition. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark Job Definition/Update-FabricSparkJobDefinitionDefinition.ps1' 189 #Region './Public/Spark/Get-FabricSparkCustomPool.ps1' -1 <# .SYNOPSIS Retrieves Spark custom pools from a specified workspace. .DESCRIPTION This function retrieves all Spark custom pools from a specified workspace using the provided WorkspaceId. It handles token validation, constructs the API URL, makes the API request, and processes the response. The function supports filtering by SparkCustomPoolId or SparkCustomPoolName, but not both simultaneously. .PARAMETER WorkspaceId The ID of the workspace from which to retrieve Spark custom pools. This parameter is mandatory. .PARAMETER SparkCustomPoolId The ID of the specific Spark custom pool to retrieve. This parameter is optional. .PARAMETER SparkCustomPoolName The name of the specific Spark custom pool to retrieve. This parameter is optional. .EXAMPLE Get-FabricSparkCustomPool -WorkspaceId "12345" This example retrieves all Spark custom pools from the workspace with ID "12345". .EXAMPLE Get-FabricSparkCustomPool -WorkspaceId "12345" -SparkCustomPoolId "pool1" This example retrieves the Spark custom pool with ID "pool1" from the workspace with ID "12345". .EXAMPLE Get-FabricSparkCustomPool -WorkspaceId "12345" -SparkCustomPoolName "MyPool" This example retrieves the Spark custom pool with name "MyPool" from the workspace with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Handles continuation tokens to retrieve all Spark custom pools if there are multiple pages of results. Author: Tiago Balabuch #> function Get-FabricSparkCustomPool { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SparkCustomPoolId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SparkCustomPoolName ) try { # Step 1: Handle ambiguous input if ($SparkCustomPoolId -and $SparkCustomPoolName) { Write-Message -Message "Both 'SparkCustomPoolId' and 'SparkCustomPoolName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $SparkCustomPools = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/spark/pools" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $SparkCustomPools += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $SparkCustomPool = if ($SparkCustomPoolId) { $SparkCustomPools | Where-Object { $_.id -eq $SparkCustomPoolId } } elseif ($SparkCustomPoolName) { $SparkCustomPools | Where-Object { $_.name -eq $SparkCustomPoolName } } else { # Return all SparkCustomPools if no filter is provided Write-Message -Message "No filter provided. Returning all SparkCustomPools." -Level Debug $SparkCustomPools } # Step 9: Handle results if ($SparkCustomPool) { Write-Message -Message "SparkCustomPool found matching the specified criteria." -Level Debug return $SparkCustomPool } else { Write-Message -Message "No SparkCustomPool found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve SparkCustomPool. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/Get-FabricSparkCustomPool.ps1' 156 #Region './Public/Spark/Get-FabricSparkSettings.ps1' -1 <# .SYNOPSIS Retrieves Spark settings from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves Spark settings from a specified workspace using the provided WorkspaceId. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace from which to retrieve Spark settings. This parameter is mandatory. .EXAMPLE Get-FabricSparkSettings -WorkspaceId "workspace-12345" This example retrieves the Spark settings for the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricSparkSettings { [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $SparkSettings = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/spark/settings" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $SparkSettings += $response # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 9: Handle results if ($SparkSettings) { Write-Message -Message " Returning all Spark Settings." -Level Debug # Return all Spark Settings return $SparkSettings } else { Write-Message -Message "No SparkSettings found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve SparkSettings. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/Get-FabricSparkSettings.ps1' 117 #Region './Public/Spark/New-FabricSparkCustomPool.ps1' -1 <# .SYNOPSIS Creates a new Spark custom pool in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new Spark custom pool in the specified workspace. It supports various parameters for Spark custom pool configuration. .PARAMETER WorkspaceId The unique identifier of the workspace where the Spark custom pool will be created. This parameter is mandatory. .PARAMETER SparkCustomPoolName The name of the Spark custom pool to be created. This parameter is mandatory. .PARAMETER NodeFamily The family of nodes to be used in the Spark custom pool. This parameter is mandatory and must be 'MemoryOptimized'. .PARAMETER NodeSize The size of the nodes to be used in the Spark custom pool. This parameter is mandatory and must be one of 'Large', 'Medium', 'Small', 'XLarge', 'XXLarge'. .PARAMETER AutoScaleEnabled Specifies whether auto-scaling is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMinNodeCount The minimum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMaxNodeCount The maximum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationEnabled Specifies whether dynamic executor allocation is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMinExecutors The minimum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMaxExecutors The maximum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .EXAMPLE New-FabricSparkCustomPool -WorkspaceId "workspace-12345" -SparkCustomPoolName "New Spark Pool" -NodeFamily "MemoryOptimized" -NodeSize "Large" -AutoScaleEnabled $true -AutoScaleMinNodeCount 1 -AutoScaleMaxNodeCount 10 -DynamicExecutorAllocationEnabled $true -DynamicExecutorAllocationMinExecutors 1 -DynamicExecutorAllocationMaxExecutors 10 This example creates a new Spark custom pool named "New Spark Pool" in the workspace with ID "workspace-12345" with the specified configuration. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricSparkCustomPool { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SparkCustomPoolName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('MemoryOptimized')] [string]$NodeFamily, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Large', 'Medium', 'Small', 'XLarge', 'XXLarge')] [string]$NodeSize, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$AutoScaleEnabled, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$AutoScaleMinNodeCount, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$AutoScaleMaxNodeCount, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$DynamicExecutorAllocationEnabled, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMinExecutors, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMaxExecutors ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/spark/pools" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ name = $SparkCustomPoolName nodeFamily = $NodeFamily nodeSize = $NodeSize autoScale = @{ enabled = $AutoScaleEnabled minNodeCount = $AutoScaleMinNodeCount maxNodeCount = $AutoScaleMaxNodeCount } dynamicExecutorAllocation = @{ enabled = $DynamicExecutorAllocationEnabled minExecutors = $DynamicExecutorAllocationMinExecutors maxExecutors = $DynamicExecutorAllocationMaxExecutors } } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Create Spark Custom Pool")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "SparkCustomPool '$SparkCustomPoolName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "SparkCustomPool '$SparkCustomPoolName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId, -location $location Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create SparkCustomPool. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/New-FabricSparkCustomPool.ps1' 203 #Region './Public/Spark/Remove-FabricSparkCustomPool.ps1' -1 <# .SYNOPSIS Removes a Spark custom pool from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove a Spark custom pool from the specified workspace using the provided WorkspaceId and SparkCustomPoolId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the Spark custom pool will be removed. .PARAMETER SparkCustomPoolId The unique identifier of the Spark custom pool to be removed. .EXAMPLE Remove-FabricSparkCustomPool -WorkspaceId "workspace-12345" -SparkCustomPoolId "pool-67890" This example removes the Spark custom pool with ID "pool-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricSparkCustomPool { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkCustomPoolId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/spark/pools/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkCustomPoolId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Remove Spark Custom Pool")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Spark Custom Pool '$SparkCustomPoolId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete SparkCustomPool '$SparkCustomPoolId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/Remove-FabricSparkCustomPool.ps1' 80 #Region './Public/Spark/Update-FabricSparkCustomPool.ps1' -1 <# .SYNOPSIS Updates an existing Spark custom pool in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing Spark custom pool in the specified workspace. It supports various parameters for Spark custom pool configuration. .PARAMETER WorkspaceId The unique identifier of the workspace where the Spark custom pool exists. This parameter is mandatory. .PARAMETER SparkCustomPoolId The unique identifier of the Spark custom pool to be updated. This parameter is mandatory. .PARAMETER InstancePoolName The new name of the Spark custom pool. This parameter is mandatory. .PARAMETER NodeFamily The family of nodes to be used in the Spark custom pool. This parameter is mandatory and must be 'MemoryOptimized'. .PARAMETER NodeSize The size of the nodes to be used in the Spark custom pool. This parameter is mandatory and must be one of 'Large', 'Medium', 'Small', 'XLarge', 'XXLarge'. .PARAMETER AutoScaleEnabled Specifies whether auto-scaling is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMinNodeCount The minimum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMaxNodeCount The maximum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationEnabled Specifies whether dynamic executor allocation is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMinExecutors The minimum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMaxExecutors The maximum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .EXAMPLE Update-FabricSparkCustomPool -WorkspaceId "workspace-12345" -SparkCustomPoolId "pool-67890" -InstancePoolName "Updated Spark Pool" -NodeFamily "MemoryOptimized" -NodeSize "Large" -AutoScaleEnabled $true -AutoScaleMinNodeCount 1 -AutoScaleMaxNodeCount 10 -DynamicExecutorAllocationEnabled $true -DynamicExecutorAllocationMinExecutors 1 -DynamicExecutorAllocationMaxExecutors 10 This example updates the Spark custom pool with ID "pool-67890" in the workspace with ID "workspace-12345" with a new name and configuration. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSparkCustomPool { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SparkCustomPoolId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$InstancePoolName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('MemoryOptimized')] [string]$NodeFamily, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Large', 'Medium', 'Small', 'XLarge', 'XXLarge')] [string]$NodeSize, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$AutoScaleEnabled, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$AutoScaleMinNodeCount, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$AutoScaleMaxNodeCount, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$DynamicExecutorAllocationEnabled, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMinExecutors, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [int]$DynamicExecutorAllocationMaxExecutors ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/spark/pools/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkCustomPoolId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ name = $InstancePoolName nodeFamily = $NodeFamily nodeSize = $NodeSize autoScale = @{ enabled = $AutoScaleEnabled minNodeCount = $AutoScaleMinNodeCount maxNodeCount = $AutoScaleMaxNodeCount } dynamicExecutorAllocation = @{ enabled = $DynamicExecutorAllocationEnabled minExecutors = $DynamicExecutorAllocationMinExecutors maxExecutors = $DynamicExecutorAllocationMaxExecutors } } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update SparkCustomPool")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Spark Custom Pool '$SparkCustomPoolName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update SparkCustomPool. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/Update-FabricSparkCustomPool.ps1' 173 #Region './Public/Spark/Update-FabricSparkSettings.ps1' -1 <# .SYNOPSIS Updates an existing Spark custom pool in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing Spark custom pool in the specified workspace. It supports various parameters for Spark custom pool configuration. .PARAMETER WorkspaceId The unique identifier of the workspace where the Spark custom pool exists. This parameter is mandatory. .PARAMETER SparkSettingsId The unique identifier of the Spark custom pool to be updated. This parameter is mandatory. .PARAMETER InstancePoolName The new name of the Spark custom pool. This parameter is mandatory. .PARAMETER NodeFamily The family of nodes to be used in the Spark custom pool. This parameter is mandatory and must be 'MemoryOptimized'. .PARAMETER NodeSize The size of the nodes to be used in the Spark custom pool. This parameter is mandatory and must be one of 'Large', 'Medium', 'Small', 'XLarge', 'XXLarge'. .PARAMETER AutoScaleEnabled Specifies whether auto-scaling is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMinNodeCount The minimum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER AutoScaleMaxNodeCount The maximum number of nodes for auto-scaling in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationEnabled Specifies whether dynamic executor allocation is enabled for the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMinExecutors The minimum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .PARAMETER DynamicExecutorAllocationMaxExecutors The maximum number of executors for dynamic executor allocation in the Spark custom pool. This parameter is mandatory. .PARAMETER automaticLogEnabled Specifies whether automatic logging is enabled for the Spark custom pool. This parameter is optional. .PARAMETER notebookInteractiveRunEnabled Specifies whether notebook interactive run is enabled for the Spark custom pool. This parameter is optional. .PARAMETER customizeComputeEnabled Specifies whether compute customization is enabled for the Spark custom pool. This parameter is optional. .PARAMETER defaultPoolName The name of the default pool for the Spark custom pool. This parameter is optional. .PARAMETER defaultPoolType The type of the default pool for the Spark custom pool. This parameter is optional and must be either 'Workspace' or 'Capacity'. .PARAMETER starterPoolMaxNode The maximum number of nodes for the starter pool in the Spark custom pool. This parameter is optional. .PARAMETER starterPoolMaxExecutors The maximum number of executors for the starter pool in the Spark custom pool. This parameter is optional. .PARAMETER EnvironmentName The name of the environment for the Spark custom pool. This parameter is optional. .PARAMETER EnvironmentRuntimeVersion The runtime version of the environment for the Spark custom pool. This parameter is optional. .EXAMPLE Update-FabricSparkSettings -WorkspaceId "workspace-12345" -SparkSettingsId "pool-67890" -InstancePoolName "Updated Spark Pool" -NodeFamily "MemoryOptimized" -NodeSize "Large" -AutoScaleEnabled $true -AutoScaleMinNodeCount 1 -AutoScaleMaxNodeCount 10 -DynamicExecutorAllocationEnabled $true -DynamicExecutorAllocationMinExecutors 1 -DynamicExecutorAllocationMaxExecutors 10 This example updates the Spark custom pool with ID "pool-67890" in the workspace with ID "workspace-12345" with a new name and configuration. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricSparkSettings { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$automaticLogEnabled, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$notebookInteractiveRunEnabled, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$customizeComputeEnabled, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$defaultPoolName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('Workspace', 'Capacity')] [string]$defaultPoolType, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [int]$starterPoolMaxNode, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [int]$starterPoolMaxExecutors, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EnvironmentName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$EnvironmentRuntimeVersion ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/spark/settings" -f $FabricConfig.BaseUrl, $WorkspaceId, $SparkSettingsId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body # Construct the request body with optional properties $body = @{ } if ($PSBoundParameters.ContainsKey('automaticLogEnabled')) { $body.automaticLog = @{ enabled = $automaticLogEnabled } } if ($PSBoundParameters.ContainsKey('notebookInteractiveRunEnabled')) { $body.highConcurrency = @{ notebookInteractiveRunEnabled = $notebookInteractiveRunEnabled } } if ($PSBoundParameters.ContainsKey('customizeComputeEnabled') ) { $body.pool = @{ customizeComputeEnabled = $customizeComputeEnabled } } if ($PSBoundParameters.ContainsKey('defaultPoolName') -or $PSBoundParameters.ContainsKey('defaultPoolType')) { if ($PSBoundParameters.ContainsKey('defaultPoolName') -and $PSBoundParameters.ContainsKey('defaultPoolType')) { $body.pool = @{ defaultPool = @{ name = $defaultPoolName type = $defaultPoolType } } } else { Write-Message -Message "Both 'defaultPoolName' and 'defaultPoolType' must be provided together." -Level Error throw } } if ($PSBoundParameters.ContainsKey('EnvironmentName') -or $PSBoundParameters.ContainsKey('EnvironmentRuntimeVersion')) { $body.environment = @{ name = $EnvironmentName } } if ($PSBoundParameters.ContainsKey('EnvironmentRuntimeVersion')) { $body.environment = @{ runtimeVersion = $EnvironmentRuntimeVersion } } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update SparkSettings")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Spark Custom Pool '$SparkSettingsName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update SparkSettings. Error: $errorDetails" -Level Error } } #EndRegion './Public/Spark/Update-FabricSparkSettings.ps1' 234 #Region './Public/SQL Database/Get-FabricSQLDatabase.ps1' -1 function Get-FabricSQLDatabase { <# .SYNOPSIS Retrieves Fabric SQLDatabases .DESCRIPTION Retrieves Fabric SQLDatabases. Without the SQLDatabaseName or SQLDatabaseID parameter, all SQLDatabases are returned. If you want to retrieve a specific SQLDatabase, you can use the SQLDatabaseName or SQLDatabaseID parameter. These parameters cannot be used together. .PARAMETER WorkspaceId Id of the Fabric Workspace for which the SQLDatabases should be retrieved. The value for WorkspaceId is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .PARAMETER SQLDatabaseName The name of the KQLDatabase to retrieve. This parameter cannot be used together with SQLDatabaseID. .PARAMETER SQLDatabaseID The Id of the SQLDatabase to retrieve. This parameter cannot be used together with SQLDatabaseName. The value for SQLDatabaseID is a GUID. An example of a GUID is '12345678-1234-1234-1234-123456789012'. .EXAMPLE Get-FabricSQLDatabase ` -WorkspaceId '12345678-1234-1234-1234-123456789012' ` -SQLDatabaseName 'MySQLDatabase' This example will retrieve the SQLDatabase with the name 'MySQLDatabase'. .EXAMPLE Get-FabricSQLDatabase This example will retrieve all SQLDatabases in the workspace that is specified by the WorkspaceId. .EXAMPLE Get-FabricSQLDatabase ` -WorkspaceId '12345678-1234-1234-1234-123456789012' ` -SQLDatabaseId '12345678-1234-1234-1234-123456789012' This example will retrieve the SQLDatabase with the ID '12345678-1234-1234-1234-123456789012'. .NOTES Revision History: - 2025-03-06 - KNO: Init version of the function #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$WorkspaceId, [Alias("Name", "DisplayName")] [string]$SQLDatabaseName, [Alias("Id")] [string]$SQLDatabaseId ) Confirm-FabricAuthToken | Out-Null Write-Verbose "You can either use SQLDatabaseName or SQLDatabaseID not both. If both are used throw error" if ($PSBoundParameters.ContainsKey("SQLDatabaseName") -and $PSBoundParameters.ContainsKey("SQLDatabaseId")) { throw "Parameters SQLDatabaseName and SQLDatabaseId cannot be used together" } # Create SQLDatabase API $uri = "$($FabricSession.BaseApiUrl)/workspaces/$workspaceId/SqlDatabases" if ($SQLDatabaseId) { $uri = "$uri/$SQLDatabaseId" } $result = Invoke-RestMethod -Headers $FabricSession.HeaderParams -Uri $uri ##$databases.Where({$_.displayName -eq $body.displayName}).id return $result.value } #EndRegion './Public/SQL Database/Get-FabricSQLDatabase.ps1' 79 #Region './Public/SQL Database/New-FabricSQLDatabase.ps1' -1 <# .SYNOPSIS Creates a new SQL Database in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new SQL Database in the specified workspace. It supports optional parameters for SQL Database description and path definitions for the SQL Database content. .PARAMETER WorkspaceId The unique identifier of the workspace where the SQL Database will be created. .PARAMETER Name The name of the SQL Database to be created. .PARAMETER Description An optional description for the SQL Database. .EXAMPLE New-FabricSQLDatabase -WorkspaceId "workspace-12345" -Name "NewDatabase" .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Kamil Nowinski #> function New-FabricSQLDatabase { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_]*$')] [string]$Name, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$Description ) try { # Step 1: Ensure token validity Test-TokenExpired # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sqldatabases" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $Name } if ($Description) { $body.description = $Description } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Create SQL Database")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response Write-Message "RESPONSE: $response" -Level Debug Test-FabricApiResponse -response $response -responseHeader $responseHeader -statusCode $statusCode -Name $Name -TypeName 'SQL Database' } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create SQL Database. Error: $errorDetails" -Level Error } } #EndRegion './Public/SQL Database/New-FabricSQLDatabase.ps1' 97 #Region './Public/SQL Database/Remove-FabricSQLDatabase.ps1' -1 <# .SYNOPSIS Deletes a SQL Database from a specified workspace in Microsoft Fabric. .DESCRIPTION The `Remove-FabricSQLDatabase` function sends a DELETE request to the Fabric API to remove a specified SQLDatabase from a given workspace. .PARAMETER WorkspaceId (Mandatory) The ID of the workspace containing the SQLDatabase to delete. .PARAMETER SQLDatabaseId (Mandatory) The ID of the SQL Database to be deleted. .EXAMPLE Remove-FabricSQLDatabas -WorkspaceId "12345" -SQLDatabaseId "67890" Deletes the SQL Database with ID "67890" from workspace "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Validates token expiration before making the API request. Author: Kamil Nowinski #> function Remove-FabricSQLDatabase { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SQLDatabaseId ) try { # Step 1: Ensure token validity Confirm-FabricAuthToken | Out-Null Test-TokenExpired # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/sqldatabases/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $SQLDatabaseId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Delete SQL Database")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "SQL Database '$SQLDatabaseId' deleted successfully from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete SQL Database '$SQLDatabaseId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/SQL Database/Remove-FabricSQLDatabase.ps1' 81 #Region './Public/SQL Endpoints/Get-FabricSQLEndpoint.ps1' -1 <# .SYNOPSIS Retrieves SQL Endpoints from a specified workspace in Fabric. .DESCRIPTION The Get-FabricSQLEndpoint function retrieves SQL Endpoints from a specified workspace in Fabric. It supports filtering by SQL Endpoint ID or SQL Endpoint Name. If both filters are provided, an error message is returned. The function handles token validation, API requests with continuation tokens, and processes the response to return the desired SQL Endpoint(s). .PARAMETER WorkspaceId The ID of the workspace from which to retrieve SQL Endpoints. This parameter is mandatory. .PARAMETER SQLEndpointId The ID of the SQL Endpoint to retrieve. This parameter is optional but cannot be used together with SQLEndpointName. .PARAMETER SQLEndpointName The name of the SQL Endpoint to retrieve. This parameter is optional but cannot be used together with SQLEndpointId. .EXAMPLE Get-FabricSQLEndpoint -WorkspaceId "workspace123" -SQLEndpointId "endpoint456" .EXAMPLE Get-FabricSQLEndpoint -WorkspaceId "workspace123" -SQLEndpointName "MySQLEndpoint" .NOTES - This function requires the FabricConfig object to be properly configured with BaseUrl and FabricHeaders. - The function uses continuation tokens to handle paginated API responses. - If no filter parameters are provided, all SQL Endpoints in the specified workspace are returned. #> function Get-FabricSQLEndpoint { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SQLEndpointId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$SQLEndpointName ) try { # Step 1: Handle ambiguous input if ($SQLEndpointId -and $SQLEndpointName) { Write-Message -Message "Both 'SQLEndpointId' and 'SQLEndpointName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $SQLEndpoints = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/SQLEndpoints" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $SQLEndpoints += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $SQLEndpoint = if ($SQLEndpointId) { $SQLEndpoints | Where-Object { $_.Id -eq $SQLEndpointId } } elseif ($SQLEndpointName) { $SQLEndpoints | Where-Object { $_.DisplayName -eq $SQLEndpointName } } else { # Return all SQLEndpoints if no filter is provided Write-Message -Message "No filter provided. Returning all Paginated Reports." -Level Debug $SQLEndpoints } # Step 9: Handle results if ($SQLEndpoint) { Write-Message -Message "Paginated Report found matching the specified criteria." -Level Debug return $SQLEndpoint } else { Write-Message -Message "No Paginated Report found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Paginated Report. Error: $errorDetails" -Level Error } } #EndRegion './Public/SQL Endpoints/Get-FabricSQLEndpoint.ps1' 149 #Region './Public/Tenant/Get-FabricCapacityTenantSettingOverrides.ps1' -1 <# .SYNOPSIS Retrieves tenant setting overrides for a specific capacity or all capacities in the Fabric tenant. .DESCRIPTION The `Get-FabricCapacityTenantSettingOverrides` function retrieves tenant setting overrides for a specific capacity or all capacities in the Fabric tenant by making a GET request to the appropriate API endpoint. If a `capacityId` is provided, the function retrieves overrides for that specific capacity. Otherwise, it retrieves overrides for all capacities. .PARAMETER capacityId The ID of the capacity for which tenant setting overrides should be retrieved. If not provided, overrides for all capacities will be retrieved. .EXAMPLE Get-FabricCapacityTenantSettingOverrides Returns all capacities tenant setting overrides. .EXAMPLE Get-FabricCapacityTenantSettingOverrides -capacityId "12345" Returns tenant setting overrides for the capacity with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricCapacityTenantSettingOverrides { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$capacityId ) try { # Step 1: Validate authentication token before making API requests Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving capacity tenant setting overrides if ($capacityId) { $apiEndpointURI = "{0}/admin/capacities/{1}/delegatedTenantSettingOverrides" -f $FabricConfig.BaseUrl, $capacityId $message = "Successfully retrieved tenant setting overrides for capacity ID: $capacityId." } else { $apiEndpointURI = "{0}/admin/capacities/delegatedTenantSettingOverrides" -f $FabricConfig.BaseUrl $message = "Successfully retrieved capacity tenant setting overrides." } Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Invoke the Fabric API to retrieve capacity tenant setting overrides $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get # Step 4: Check if any capacity tenant setting overrides were retrieved and handle results accordingly if ($response) { Write-Message -Message $message -Level Debug return $response } else { Write-Message -Message "No capacity tenant setting overrides found." -Level Warning return $null } } catch { # Step 5: Log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Error retrieving capacity tenant setting overrides: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Get-FabricCapacityTenantSettingOverrides.ps1' 71 #Region './Public/Tenant/Get-FabricDomainTenantSettingOverrides.ps1' -1 <# .SYNOPSIS Retrieves tenant setting overrides for a specific domain or all capacities in the Fabric tenant. .DESCRIPTION The `Get-FabricDomainTenantSettingOverrides` function retrieves tenant setting overrides for all domains in the Fabric tenant by making a GET request to the designated API endpoint. The function ensures token validity before making the request and handles the response appropriately. .EXAMPLE Get-FabricDomainTenantSettingOverrides Fetches tenant setting overrides for all domains in the Fabric tenant. .NOTES - Requires the `$FabricConfig` global configuration, which must include `BaseUrl` and `FabricHeaders`. - Ensures token validity by invoking `Test-TokenExpired` before making the API request. - Logs detailed messages for debugging and error handling. Author: Tiago Balabuch #> function Get-FabricDomainTenantSettingOverrides { [CmdletBinding()] param ( ) try { # Step 1: Validate authentication token before making API requests Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving domain tenant setting overrides $apiEndpointURI = "{0}/admin/domains/delegatedTenantSettingOverrides" -f $FabricConfig.BaseUrl Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Invoke the Fabric API to retrieve domain tenant setting overrides $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get # Step 4: Check if any domain tenant setting overrides were retrieved and handle results accordingly if ($response) { Write-Message -Message "Successfully retrieved domain tenant setting overrides." -Level Debug return $response } else { Write-Message -Message "No domain tenant setting overrides found." -Level Warning return $null } } catch { # Step 5: Log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Error retrieving domain tenant setting overrides: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Get-FabricDomainTenantSettingOverrides.ps1' 54 #Region './Public/Tenant/Get-FabricTenantSetting.ps1' -1 <# .SYNOPSIS Retrieves tenant settings from the Fabric environment. .DESCRIPTION The `Get-FabricTenantSetting` function retrieves tenant settings for a Fabric environment by making a GET request to the appropriate API endpoint. Optionally, it filters the results by the `SettingTitle` parameter. .PARAMETER SettingTitle (Optional) The title of a specific tenant setting to filter the results. .EXAMPLE Get-FabricTenantSetting Returns all tenant settings. .EXAMPLE Get-FabricTenantSetting -SettingTitle "SomeSetting" Returns the tenant setting with the title "SomeSetting". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Is-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricTenantSetting { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$SettingTitle ) try { # Step 1: Validate authentication token before making API requests Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving tenant settings $apiEndpointURI = "{0}/admin/tenantsettings" -f $FabricConfig.BaseUrl Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Invoke the Fabric API to retrieve tenant settings $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get # Step 4: Filter tenant settings based on the provided SettingTitle parameter (if specified) $settings = if ($SettingTitle) { Write-Message -Message "Filtering tenant settings by title: '$SettingTitle'" -Level Debug $response.tenantSettings | Where-Object { $_.title -eq $SettingTitle } } else { Write-Message -Message "No filter specified. Retrieving all tenant settings." -Level Debug $response.tenantSettings } # Step 5: Check if any tenant settings were found and return results accordingly if ($settings) { Write-Message -Message "Tenant settings successfully retrieved." -Level Debug return $settings } else { Write-Message -Message "No tenant settings found matching the specified criteria." -Level Warning return $null } } catch { # Step 6: Log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Error retrieving tenant settings: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Get-FabricTenantSetting.ps1' 76 #Region './Public/Tenant/Get-FabricWorkspaceTenantSettingOverrides.ps1' -1 <# .SYNOPSIS Retrieves tenant setting overrides for all workspaces in the Fabric tenant. .DESCRIPTION The `Get-FabricWorkspaceTenantSettingOverrides` function retrieves tenant setting overrides for all workspaces in the Fabric tenant by making a GET request to the appropriate API endpoint. The function validates the authentication token before making the request and handles the response accordingly. .EXAMPLE Get-FabricWorkspaceTenantSettingOverrides Returns all workspaces tenant setting overrides. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricWorkspaceTenantSettingOverrides { [CmdletBinding()] param ( ) try { # Step 1: Validate authentication token before making API requests Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving workspaces tenant setting overrides $apiEndpointURI = "{0}/admin/workspaces/delegatedTenantSettingOverrides" -f $FabricConfig.BaseUrl Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Invoke the Fabric API to retrieve workspaces tenant setting overrides $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get # Step 4: Check if any workspaces tenant setting overrides were retrieved and handle results accordingly if ($response) { Write-Message -Message "Successfully retrieved workspaces tenant setting overrides." -Level Debug return $response } else { Write-Message -Message "No workspaces tenant setting overrides found." -Level Warning return $null } } catch { # Step 5: Log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Error retrieving workspaces tenant setting overrides: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Get-FabricWorkspaceTenantSettingOverrides.ps1' 53 #Region './Public/Tenant/Revoke-FabricCapacityTenantSettingOverrides.ps1' -1 <# .SYNOPSIS Removes a tenant setting override from a specific capacity in the Fabric tenant. .DESCRIPTION The `Revoke-FabricCapacityTenantSettingOverrides` function deletes a specific tenant setting override for a given capacity in the Fabric tenant by making a DELETE request to the appropriate API endpoint. .PARAMETER capacityId The unique identifier of the capacity from which the tenant setting override will be removed. .PARAMETER tenantSettingName The name of the tenant setting override to be removed. .EXAMPLE Revoke-FabricCapacityTenantSettingOverrides -capacityId "12345" -tenantSettingName "ExampleSetting" Removes the tenant setting override named "ExampleSetting" from the capacity with ID "12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Revoke-FabricCapacityTenantSettingOverrides { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$capacityId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$tenantSettingName ) try { # Step 1: Validate authentication token before making API requests Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Step 2: Construct the API endpoint URL for retrieving capacity tenant setting overrides $apiEndpointURI = "{0}/admin/capacities/{1}/delegatedTenantSettingOverrides/{2}" -f $FabricConfig.BaseUrl, $capacityId, $tenantSettingName Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug if ($PSCmdlet.ShouldProcess("$tenantSettingName" , "Revoke")) { # Step 3: Invoke the Fabric API to retrieve capacity tenant setting overrides $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Delete } Write-Message -Message "Successfully removed the tenant setting override '$tenantSettingName' from the capacity with ID '$capacityId'." -Level Info return $response } catch { # Step 5: Log detailed error information if the API request fails $errorDetails = $_.Exception.Message Write-Message -Message "Error retrieving capacity tenant setting overrides: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Revoke-FabricCapacityTenantSettingOverrides.ps1' 61 #Region './Public/Tenant/Update-FabricCapacityTenantSettingOverrides.ps1' -1 <# .SYNOPSIS Updates tenant setting overrides for a specified capacity ID. .DESCRIPTION The `Update-FabricCapacityTenantSettingOverrides` function updates tenant setting overrides in a Fabric environment by making a POST request to the appropriate API endpoint. It allows specifying settings such as enabling tenant settings, delegating to a workspace, and including or excluding security groups. .PARAMETER CapacityId (Mandatory) The ID of the capacity for which the tenant setting overrides are being updated. .PARAMETER SettingTitle (Mandatory) The title of the tenant setting to be updated. .PARAMETER EnableTenantSetting (Mandatory) Indicates whether the tenant setting should be enabled. .PARAMETER DelegateToWorkspace (Optional) Specifies the workspace to which the setting should be delegated. .PARAMETER EnabledSecurityGroups (Optional) A JSON array of security groups to be enabled, each containing `graphId` and `name` properties. .PARAMETER ExcludedSecurityGroups (Optional) A JSON array of security groups to be excluded, each containing `graphId` and `name` properties. .EXAMPLE Update-FabricCapacityTenantSettingOverrides -CapacityId "12345" -SettingTitle "SomeSetting" -EnableTenantSetting "true" Updates the tenant setting "SomeSetting" for the capacity with ID "12345" and enables it. .EXAMPLE Update-FabricCapacityTenantSettingOverrides -CapacityId "12345" -SettingTitle "SomeSetting" -EnableTenantSetting "true" -EnabledSecurityGroups @(@{graphId="1";name="Group1"},@{graphId="2";name="Group2"}) Updates the tenant setting "SomeSetting" for the capacity with ID "12345", enables it, and specifies security groups to include. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricCapacityTenantSettingOverrides { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CapacityId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SettingTitle, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$EnableTenantSetting, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$DelegateToWorkspace, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Object]$EnabledSecurityGroups, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Object]$ExcludedSecurityGroups ) try { # Validate authentication token Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Validate Security Groups if provided if ($EnabledSecurityGroups) { foreach ($enabledGroup in $EnabledSecurityGroups) { if (-not ($enabledGroup.PSObject.Properties.Name -contains 'graphId' -and $enabledGroup.PSObject.Properties.Name -contains 'name')) { throw "Each enabled security group must contain 'graphId' and 'name' properties." } } } if ($ExcludedSecurityGroups) { foreach ($excludedGroup in $ExcludedSecurityGroups) { if (-not ($excludedGroup.PSObject.Properties.Name -contains 'graphId' -and $excludedGroup.PSObject.Properties.Name -contains 'name')) { throw "Each excluded security group must contain 'graphId' and 'name' properties." } } } # Construct API endpoint URL $apiEndpointURI = "{0}/admin/capacities/{1}/delegatedTenantSettingOverrides" -f $FabricConfig.BaseUrl, $CapacityId Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Construct request body $body = @{ EnableTenantSetting = $EnableTenantSetting SettingTitle = $SettingTitle } if ($DelegateToWorkspace) { $body.delegateToWorkspace = $DelegateToWorkspace } if ($EnabledSecurityGroups) { $body.enabledSecurityGroups = $EnabledSecurityGroups } if ($ExcludedSecurityGroups) { $body.excludedSecurityGroups = $ExcludedSecurityGroups } # Convert body to JSON $bodyJson = $body | ConvertTo-Json -Depth 4 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Update Tenant Setting Overrides")){ # Invoke Fabric API request $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -method Post ` -body $bodyJson } Write-Message -Message "Successfully updated capacity tenant setting overrides for CapacityId: $CapacityId and SettingTitle: $SettingTitle." -Level Info return $response } catch { $errorDetails = $_.Exception.Message Write-Message -Message "Error updating tenant settings: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Update-FabricCapacityTenantSettingOverrides.ps1' 149 #Region './Public/Tenant/Update-FabricTenantSetting.ps1' -1 <# .SYNOPSIS Updates tenant setting overrides for a specified capacity ID. .DESCRIPTION The `Update-FabricCapacityTenantSettingOverrides` function updates tenant setting overrides in a Fabric environment by making a POST request to the appropriate API endpoint. It allows specifying settings such as enabling tenant settings, delegating to a workspace, and including or excluding security groups. .PARAMETER CapacityId (Mandatory) The ID of the capacity for which the tenant setting overrides are being updated. .PARAMETER SettingTitle (Mandatory) The title of the tenant setting to be updated. .PARAMETER EnableTenantSetting (Mandatory) Indicates whether the tenant setting should be enabled. .PARAMETER DelegateToWorkspace (Optional) Specifies the workspace to which the setting should be delegated. .PARAMETER EnabledSecurityGroups (Optional) A JSON array of security groups to be enabled, each containing `graphId` and `name` properties. .PARAMETER ExcludedSecurityGroups (Optional) A JSON array of security groups to be excluded, each containing `graphId` and `name` properties. .EXAMPLE Update-FabricCapacityTenantSettingOverrides -CapacityId "12345" -SettingTitle "SomeSetting" -EnableTenantSetting "true" Updates the tenant setting "SomeSetting" for the capacity with ID "12345" and enables it. .EXAMPLE Update-FabricCapacityTenantSettingOverrides -CapacityId "12345" -SettingTitle "SomeSetting" -EnableTenantSetting "true" -EnabledSecurityGroups @(@{graphId="1";name="Group1"},@{graphId="2";name="Group2"}) Updates the tenant setting "SomeSetting" for the capacity with ID "12345", enables it, and specifies security groups to include. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricCapacityTenantSettingOverrides { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TenantSettingName, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [bool]$EnableTenantSetting, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$DelegateToCapacity, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$DelegateToDomain, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [bool]$DelegateToWorkspace, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Object]$EnabledSecurityGroups, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Object]$ExcludedSecurityGroups, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Object]$Properties ) try { # Validate authentication token Write-Message -Message "Validating authentication token..." -Level Debug Test-TokenExpired Write-Message -Message "Authentication token is valid." -Level Debug # Validate Security Groups if provided if ($EnabledSecurityGroups) { foreach ($enabledGroup in $EnabledSecurityGroups) { if (-not ($enabledGroup.PSObject.Properties.Name -contains 'graphId' -and $enabledGroup.PSObject.Properties.Name -contains 'name')) { throw "Each enabled security group must contain 'graphId' and 'name' properties." } } } if ($ExcludedSecurityGroups) { foreach ($excludedGroup in $ExcludedSecurityGroups) { if (-not ($excludedGroup.PSObject.Properties.Name -contains 'graphId' -and $excludedGroup.PSObject.Properties.Name -contains 'name')) { throw "Each excluded security group must contain 'graphId' and 'name' properties." } } } # Validate Security Groups if provided if ($Properties) { foreach ($property in $Properties) { if (-not ($property.PSObject.Properties.Name -contains 'name' -and $property.PSObject.Properties.Name -contains 'type' -and $property.PSObject.Properties.Name -contains 'value')) { throw "Each property object must include 'name', 'type', and 'value' properties to be valid." } } } # Construct API endpoint URL $apiEndpointURI = "{0}/admin/tenantsettings/{1}/update" -f $FabricConfig.BaseUrl, $TenantSettingName Write-Message -Message "Constructed API Endpoint: $apiEndpointURI" -Level Debug # Construct request body $body = @{ EnableTenantSetting = $EnableTenantSetting } if ($DelegateToCapacity) { $body.delegateToCapacity = $DelegateToCapacity } if ($DelegateToDomain) { $body.delegateToDomain = $DelegateToDomain } if ($DelegateToWorkspace) { $body.delegateToWorkspace = $DelegateToWorkspace } if ($EnabledSecurityGroups) { $body.enabledSecurityGroups = $EnabledSecurityGroups } if ($ExcludedSecurityGroups) { $body.excludedSecurityGroups = $ExcludedSecurityGroups } if ($Properties) { $body.properties = $Properties } # Convert body to JSON $bodyJson = $body | ConvertTo-Json -Depth 5 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Update Tenant Setting")) { # Invoke Fabric API request $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -method Post ` -body $bodyJson } Write-Message -Message "Successfully updated tenant setting." -Level Info return $response } catch { $errorDetails = $_.Exception.Message Write-Message -Message "Error updating tenant settings: $errorDetails" -Level Error } } #EndRegion './Public/Tenant/Update-FabricTenantSetting.ps1' 186 #Region './Public/Users/Get-FabricUserListAccessEntities.ps1' -1 <# .SYNOPSIS Retrieves access entities for a specified user in Microsoft Fabric. .DESCRIPTION This function retrieves a list of access entities associated with a specified user in Microsoft Fabric. It supports filtering by entity type and handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER UserId The unique identifier of the user whose access entities are to be retrieved. This parameter is mandatory. .PARAMETER Type The type of access entity to filter the results by. This parameter is optional and supports predefined values such as 'CopyJob', 'Dashboard', 'DataPipeline', etc. .EXAMPLE Get-FabricUserListAccessEntities -UserId "user-12345" This example retrieves all access entities associated with the user having ID "user-12345". .EXAMPLE Get-FabricUserListAccessEntities -UserId "user-12345" -Type "Dashboard" This example retrieves only the 'Dashboard' access entities associated with the user having ID "user-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricUserListAccessEntities { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$UserId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet('CopyJob', ' Dashboard', 'DataPipeline', 'Datamart', 'Environment', 'Eventhouse', 'Eventstream', 'GraphQLApi', 'KQLDashboard', 'KQLDatabase', 'KQLQueryset', 'Lakehouse', 'MLExperiment', 'MLModel', 'MirroredDatabase', 'MountedDataFactory', 'Notebook', 'PaginatedReport', 'Reflex', 'Report', 'SQLDatabase', 'SQLEndpoint', 'SemanticModel', 'SparkJobDefinition', 'VariableLibrary', 'Warehouse')] [string]$Type ) try { Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 4: Loop to retrieve all capacities with continuation token $apiEndpointURI = "{0}admin/users/{1}/access" -f $FabricConfig.BaseUrl, $UserId if ($Type) { $apiEndpointURI += "?type=$Type" } $response = Invoke-FabricAPIRequest ` -BaseURI $apiEndpointURI ` -Headers $FabricConfig.FabricHeaders ` -Method Get return $response } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Warehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Users/Get-FabricUserListAccessEntities.ps1' 68 #Region './Public/Utils/Convert-FromBase64.ps1' -1 function Convert-FromBase64 { <# .SYNOPSIS Decodes a Base64-encoded string into its original text representation. .DESCRIPTION The Convert-FromBase64 function takes a Base64-encoded string as input, decodes it into a byte array, and converts it back into a UTF-8 encoded string. It is useful for reversing Base64 encoding applied to text or other data. .PARAMETER Base64String The Base64-encoded string that you want to decode. .EXAMPLE Convert-FromBase64 -Base64String "SGVsbG8sIFdvcmxkIQ==" Output: Hello, World! .EXAMPLE $encodedString = "U29tZSBlbmNvZGVkIHRleHQ=" Convert-FromBase64 -Base64String $encodedString Output: Some encoded text .NOTES This function assumes the Base64 input is a valid UTF-8 encoded string. Any decoding errors will throw a descriptive error message. #> param ( [Parameter(Mandatory = $true)] [string]$Base64String ) try { # Step 1: Convert the Base64 string to a byte array $bytes = [Convert]::FromBase64String($Base64String) # Step 2: Convert the byte array back to a UTF-8 string $decodedString = [System.Text.Encoding]::UTF8.GetString($bytes) # Step 3: Return the decoded string return $decodedString } catch { # Step 4: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "An error occurred while decoding from Base64: $errorDetails" -Level Error throw "An error occurred while decoding from Base64: $_" } } #EndRegion './Public/Utils/Convert-FromBase64.ps1' 51 #Region './Public/Utils/Convert-ToBase64.ps1' -1 function Convert-ToBase64 { <# .SYNOPSIS Encodes the content of a file into a Base64-encoded string. .DESCRIPTION The Convert-ToBase64 function takes a file path as input, reads the file's content as a byte array, and converts it into a Base64-encoded string. This is useful for embedding binary data (e.g., images, documents) in text-based formats such as JSON or XML. .PARAMETER filePath The full path to the file whose contents you want to encode into Base64. .EXAMPLE Convert-ToBase64 -filePath "C:\Path\To\File.txt" Output: VGhpcyBpcyBhbiBlbmNvZGVkIGZpbGUu .EXAMPLE $encodedContent = Convert-ToBase64 -filePath "C:\Path\To\Image.jpg" $encodedContent | Set-Content -Path "C:\Path\To\EncodedImage.txt" This saves the Base64-encoded content of the image to a text file. .NOTES - Ensure the file exists at the specified path before running this function. - Large files may cause memory constraints due to full loading into memory. Tiago Balabuch #> [CmdletBinding()] [OutputType([System.String])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$filePath ) try { # Step 1: Reading all the bytes from the file #$bytes = [System.Text.Encoding]::UTF8.GetBytes($InputString) Write-Message -Message "Reading all the bytes from the file specified: $filePath" -Level Debug $fileBytes = [System.IO.File]::ReadAllBytes($filePath) # Step 2: Convert the byte array to Base64 string Write-Message -Message "Convert the byte array to Base64 string" -Level Debug $base64String = [Convert]::ToBase64String($fileBytes) # Step 3: Return the encoded string Write-Message -Message "Return the encoded string for the file: $filePath" -Level Debug return $base64String } catch { # Step 4: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "An error occurred while encoding to Base64: $errorDetails" -Level Error throw "An error occurred while encoding to Base64: $_" } } #EndRegion './Public/Utils/Convert-ToBase64.ps1' 61 #Region './Public/Utils/Get-FabricLongRunningOperation.ps1' -1 function Get-FabricLongRunningOperation { <# .SYNOPSIS Monitors the status of a long-running operation in Microsoft Fabric. .DESCRIPTION The Get-FabricLongRunningOperation function queries the Microsoft Fabric API to check the status of a long-running operation. It periodically polls the operation until it reaches a terminal state (Succeeded or Failed). .PARAMETER operationId The unique identifier of the long-running operation to be monitored. .PARAMETER location The URL provided in the Location header of the initial request. This is used to check the status of the operation. .PARAMETER retryAfter The interval (in seconds) to wait between polling the operation status. The default is 5 seconds. .EXAMPLE Get-FabricLongRunningOperation -operationId "12345-abcd-67890-efgh" -retryAfter 10 This command polls the status of the operation with the given operationId every 10 seconds until it completes. .NOTES - Requires the `$FabricConfig` global object, including `BaseUrl` and `FabricHeaders`. AUTHOR Tiago Balabuch #> param ( [Parameter(Mandatory = $false)] [string]$operationId, [Parameter(Mandatory = $false)] [string]$location, [Parameter(Mandatory = $false)] [int]$retryAfter = 5 ) # Step 1: Construct the API URL if ($location) { # Use the Location header to define the operationUrl $apiEndpointUrl = $location } else { $apiEndpointUrl = "https://api.fabric.microsoft.com/v1/operations/{0}" -f $operationId } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug try { do { # Step 2: Wait before the next request if ($retryAfter) { Start-Sleep -Seconds $retryAfter } else { Start-Sleep -Seconds 5 # Default retry interval if no Retry-After header } # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -ResponseHeadersVariable responseHeader ` -StatusCodeVariable statusCode # Step 3: Parse the response $jsonOperation = $response | ConvertTo-Json $operation = $jsonOperation | ConvertFrom-Json # Log status for debugging Write-Message -Message "Operation Status: $($operation.status)" -Level Debug } while ($operation.status -notin @("Succeeded", "Completed", "Failed")) # Step 5: Return the operation result return $operation } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "An error occurred while checking the operation: $errorDetails" -Level Error throw } } #EndRegion './Public/Utils/Get-FabricLongRunningOperation.ps1' 88 #Region './Public/Utils/Get-FabricLongRunningOperationResult.ps1' -1 function Get-FabricLongRunningOperationResult { <# .SYNOPSIS Retrieves the result of a completed long-running operation from the Microsoft Fabric API. .DESCRIPTION The Get-FabricLongRunningOperationResult function queries the Microsoft Fabric API to fetch the result of a specific long-running operation. This is typically used after confirming the operation has completed successfully. .PARAMETER operationId The unique identifier of the completed long-running operation whose result you want to retrieve. .EXAMPLE Get-FabricLongRunningOperationResult -operationId "12345-abcd-67890-efgh" This command fetches the result of the operation with the specified operationId. .NOTES - Ensure the Fabric API headers (e.g., authorization tokens) are defined in $FabricConfig.FabricHeaders. - This function does not handle polling. Ensure the operation is in a terminal state before calling this function. AUTHOR Tiago Balabuch #> param ( [Parameter(Mandatory = $true)] [string]$operationId ) # Step 1: Construct the API URL $apiEndpointUrl = "https://api.fabric.microsoft.com/v1/operations/{0}/result" -f $operationId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug try { # Step 2: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 3: Return the result Write-Message -Message "Result response code: $statusCode" -Level Debug Write-Message -Message "Result return: $response" -Level Debug # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Debug Write-Message -Message "Error: $($response.message)" -Level Debug Write-Message -Message "Error Details: $($response.moreDetails)" -Level Debug Write-Message "Error Code: $($response.errorCode)" -Level Debug } return $response } catch { # Step 3: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "An error occurred while returning the operation result: $errorDetails" -Level Error throw } } #EndRegion './Public/Utils/Get-FabricLongRunningOperationResult.ps1' 66 #Region './Public/Utils/Invoke-FabricAPIRequest_duplicate.ps1' -1 function Invoke-FabricAPIRequest_duplicate { <# .SYNOPSIS Sends an HTTP request to a Fabric API endpoint and retrieves the response. Takes care of: authentication, 429 throttling, Long-Running-Operation (LRO) response .DESCRIPTION The Invoke-FabricAPIRequest function is used to send an HTTP request to a Fabric API endpoint and retrieve the response. It handles various aspects such as authentication, 429 throttling, and Long-Running-Operation (LRO) response. .PARAMETER authToken The authentication token to be used for the request. If not provided, it will be obtained using the Get-FabricAuthToken function. .PARAMETER uri The URI of the Fabric API endpoint to send the request to. .PARAMETER method The HTTP method to be used for the request. Valid values are 'Get', 'Post', 'Delete', 'Put', and 'Patch'. The default value is 'Get'. .PARAMETER body The body of the request, if applicable. .PARAMETER contentType The content type of the request. The default value is 'application/json; charset=utf-8'. .PARAMETER timeoutSec The timeout duration for the request in seconds. The default value is 240 seconds. .PARAMETER outFile The file path to save the response content to, if applicable. .PARAMETER retryCount The number of times to retry the request in case of a 429 (Too Many Requests) error. The default value is 0. .EXAMPLE Invoke-FabricAPIRequest -uri "/api/resource" -method "Get" This example sends a GET request to the "/api/resource" endpoint of the Fabric API. .EXAMPLE Invoke-FabricAPIRequest -authToken "abc123" -uri "/api/resource" -method "Post" -body $requestBody This example sends a POST request to the "/api/resource" endpoint of the Fabric API with a request body. .NOTES This function requires the Get-FabricAuthToken function to be defined in the same script or module. This function was originally written by Rui Romano. https://github.com/RuiRomano/fabricps-pbip #> param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [hashtable]$Headers, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$BaseURI, [Parameter(Mandatory = $true)] [ValidateSet('Get', 'Post', 'Delete', 'Put', 'Patch')] [string] $Method, [Parameter(Mandatory = $false)] [string] $Body, [Parameter(Mandatory = $false)] [string] $ContentType = "application/json; charset=utf-8" ) $continuationToken = $null $results = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } do { $apiEndpointURI = $BaseURI if ($null -ne $continuationToken) { $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) if ($BaseURI -like "*`?*") { # URI already has parameters, append with & $apiEndpointURI = "$BaseURI&continuationToken=$encodedToken" } else { # No existing parameters, append with ? $apiEndpointURI = "$BaseURI?continuationToken=$encodedToken" } } Write-Message -Message "Calling API: $apiEndpointURI" -Level Debug $invokeParams = @{ Headers = $Headers Uri = $apiEndpointURI Method = $Method ErrorAction = 'Stop' SkipHttpErrorCheck = $true ResponseHeadersVariable = 'responseHeader' StatusCodeVariable = 'statusCode' # TimeoutSec = $timeoutSec } if ($method -in @('Post', 'Put', 'Patch') -and $body) { $invokeParams.Body = $body $invokeParams.ContentType = $contentType } $response = Invoke-RestMethod @invokeParams switch ($statusCode) { 200 { Write-Message -Message "API call succeeded." -Level Debug # Step 5: Handle and log the response if ($response) { if ($response.PSObject.Properties.Name -contains 'value') { $results += $response.value } elseif ($response.PSObject.Properties.Name -contains 'accessEntities') { $results += $response.accessEntities } else { $results += $response } $continuationToken = $null if ($response.PSObject.Properties.Match("continuationToken")) { $continuationToken = $response.continuationToken } } else { Write-Message -Message "No data in response" -Level Debug $continuationToken = $null } } 201 { Write-Message -Message "Resource created successfully." -Level Info return $response } 202 { # Step 6: Handle long-running operations Write-Message -Message "Request accepted. Provisioning in progress." -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] # Need to implement a retry mechanism for long running operations # [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId', Location: '$location'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId -location $location Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation succeeded. Fetching result." -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation result: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } 400 { $errorMsg = "Bad Request" } 401 { $errorMsg = "Unauthorized" } 403 { $errorMsg = "Forbidden" } 404 { $errorMsg = "Not Found" } 409 { $errorMsg = "Conflict" } 429 { $errorMsg = "Too Many Requests" } 500 { $errorMsg = "Internal Server Error" } default { $errorMsg = "Unexpected response code: $statusCode" } } if ($statusCode -notin 200, 201, 202) { Write-Message -Message "$errorMsg : $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message -Message "Error Code: $($response.errorCode)" -Level Error throw "API request failed with status code $statusCode." } } while ($null -ne $continuationToken) return $results } #EndRegion './Public/Utils/Invoke-FabricAPIRequest_duplicate.ps1' 180 #Region './Public/Utils/Set-FabricApiHeaders.ps1' -1 function Set-FabricApiHeaders { <# .SYNOPSIS Sets the Fabric API headers with a valid token for the specified Azure tenant. .DESCRIPTION The `Set-FabricApiHeaders` function logs into the specified Azure tenant, retrieves an access token for the Fabric API, and sets the necessary headers for subsequent API requests. It also updates the token expiration time and global tenant ID. .PARAMETER TenantId The Azure tenant ID for which the access token is requested. .PARAMETER AppId The Azure app ID for which the service principal access token is requested. .PARAMETER AppSecret The Azure App secret for which the service principal access token is requested. .EXAMPLE Set-FabricApiHeaders -TenantId "your-tenant-id" Logs in to Azure with the specified tenant ID, retrieves an access token for the current user, and configures the Fabric headers. .EXAMPLE $tenantId = "999999999-99999-99999-9999-999999999999" $appId = "888888888-88888-88888-8888-888888888888" $appSecret = "your-app-secret" $secureAppSecret = $appSecret | ConvertTo-SecureString -AsPlainText -Force Set-FabricApiHeader -TenantId $tenantId -AppId $appId -AppSecret $secureAppSecret Logs in to Azure with the specified tenant ID, retrieves an access token for the service principal, and configures the Fabric headers. .NOTES - Ensure the `Connect-AzAccount` and `Get-AzAccessToken` commands are available (Azure PowerShell module required). - Relies on a global `$FabricConfig` object for storing headers and token metadata. AUTHOR Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$TenantId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$AppId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [System.Security.SecureString]$AppSecret ) try { # Step 1: Connect to the Azure account Write-Message -Message "Logging in to Azure tenant: $TenantId" -Level Info # Step 2: Performing validation checks on the parameters passed to a function or script. # Checks if 'AppId' is provided without 'AppSecret' and vice versa. if ($PSBoundParameters.ContainsKey('AppId') -and -not $PSBoundParameters.ContainsKey('AppSecret')) { Write-Message -Message "AppSecret is required when using AppId: $AppId" -Level Error throw "AppSecret is required when using AppId." } if ($PSBoundParameters.ContainsKey('AppSecret') -and -not $PSBoundParameters.ContainsKey('AppId')) { Write-Message -Message "AppId is required when using AppSecret." -Level Error throw "AppId is required when using AppId." } # Step 3: Connect to the Azure account # Using AppId and AppSecret if ($PSBoundParameters.ContainsKey('AppId') -and $PSBoundParameters.ContainsKey('AppSecret')) { Write-Message -Message "Logging in using the AppId: $AppId" -Level Debug Write-Message -Message "Logging in using the AppId: $AppId" -Level Info $psCredential = [pscredential]::new($AppId, $AppSecret) Connect-AzAccount -ServicePrincipal -Credential $psCredential -Tenant $tenantId } # Using the current user else { Write-Message -Message "Logging in using the current user" -Level Debug Write-Message -Message "Logging in using the current user" -Level Info Connect-AzAccount -Tenant $TenantId -ErrorAction Stop | Out-Null } ## Step 4: Retrieve the access token for the Fabric API Write-Message -Message "Retrieve the access token for the Fabric API: $TenantId" -Level Debug $fabricToken = Get-AzAccessToken -AsSecureString -ResourceUrl $FabricConfig.ResourceUrl -ErrorAction Stop -WarningAction SilentlyContinue ## Step 5: Extract the plain token from the secure string Write-Message -Message "Extract the plain token from the secure string" -Level Debug $plainToken = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto( [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($fabricToken.Token) ) if ($PSCmdlet.ShouldProcess("Set the headers in the global configuration $($TenantId)")) { ## Step 6: Set the headers in the global configuration $FabricConfig.FabricHeaders = @{ 'Content-Type' = 'application/json' 'Authorization' = "Bearer $plainToken" } } ## Step 7: Update token metadata in the global configuration Write-Message -Message "Update token metadata in the global configuration" -Level Debug if ($PSCmdlet.ShouldProcess("Update token metadata in the global configuration")) { $FabricConfig.TokenExpiresOn = $fabricToken.ExpiresOn $FabricConfig.TenantIdGlobal = $TenantId } Write-Message -Message "Fabric token successfully configured." -Level Info } catch { # Step 8: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to set Fabric token: $errorDetails" -Level Error throw "Unable to configure Fabric token. Ensure tenant and API configurations are correct." } } #EndRegion './Public/Utils/Set-FabricApiHeaders.ps1' 127 #Region './Public/Utils/Test-FabricApiResponse.ps1' -1 function Test-FabricApiResponse { <# .SYNOPSIS Tests the response from a Fabric API call and handles long-running operations. .DESCRIPTION Tests the response from a Fabric API call and handles long-running operations. It checks the status code and processes the response accordingly. .PARAMETER statusCode The HTTP status code returned from the API call. .PARAMETER response The response body from the API call. .PARAMETER responseHeader The response headers from the API call. .PARAMETER Name The name of the resource being created or updated. .PARAMETER typeName The type of resource being created or updated (default: 'Fabric Item'). .EXAMPLE Test-FabricApiResponse -statusCode 201 -response $response -responseHeader $header -Name "MyResource" -typeName "Fabric Item" Handles the response from a Fabric API call with a 201 status code, indicating successful creation of a resource. .EXAMPLE Test-FabricApiResponse -statusCode 202 -response $response -responseHeader $header -Name "MyResource" -typeName "Fabric Item" Handles the response from a Fabric API call with a 202 status code, indicating that the request has been accepted for processing. .NOTES - This function is designed to be used within the context of a Fabric API client. - It requires the `Write-Message` function to log messages at different levels (Info, Debug, Error). - The function handles long-running operations by checking the status of the operation and retrieving the result if it has succeeded. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $statusCode, [Parameter(Mandatory = $false)] $response, [Parameter(Mandatory = $false)] $responseHeader, [Parameter(Mandatory = $false)] $Name, [Parameter(Mandatory = $false)] $typeName = 'Fabric Item' ) switch ($statusCode) { 201 { Write-Message -Message "$typeName '$Name' created successfully!" -Level Info return $response } 202 { Write-Message -Message "$typeName '$Name' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } #EndRegion './Public/Utils/Test-FabricApiResponse.ps1' 85 #Region './Public/Warehouse/Get-FabricWarehouse.ps1' -1 <# .SYNOPSIS Retrieves warehouse details from a specified Microsoft Fabric workspace. .DESCRIPTION This function retrieves warehouse details from a specified workspace using either the provided WarehouseId or WarehouseName. It handles token validation, constructs the API URL, makes the API request, and processes the response. .PARAMETER WorkspaceId The unique identifier of the workspace where the warehouse exists. This parameter is mandatory. .PARAMETER WarehouseId The unique identifier of the warehouse to retrieve. This parameter is optional. .PARAMETER WarehouseName The name of the warehouse to retrieve. This parameter is optional. .EXAMPLE Get-FabricWarehouse -WorkspaceId "workspace-12345" -WarehouseId "warehouse-67890" This example retrieves the warehouse details for the warehouse with ID "warehouse-67890" in the workspace with ID "workspace-12345". .EXAMPLE Get-FabricWarehouse -WorkspaceId "workspace-12345" -WarehouseName "My Warehouse" This example retrieves the warehouse details for the warehouse named "My Warehouse" in the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricWarehouse { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WarehouseId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$WarehouseName ) try { # Step 1: Handle ambiguous input if ($WarehouseId -and $WarehouseName) { Write-Message -Message "Both 'WarehouseId' and 'WarehouseName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables # Step 4: Loop to retrieve all capacities with continuation token $apiEndpointURI = "workspaces/{0}/warehouses" -f $WorkspaceId $apiParams = @{ Uri = $apiEndpointURI Method = 'Get' } $Warehouses = (Invoke-FabricAPIRequest @apiParams).Value # Step 8: Filter results based on provided parameters $Warehouse = if ($WarehouseId) { $Warehouses | Where-Object { $_.Id -eq $WarehouseId } } elseif ($WarehouseName) { $Warehouses | Where-Object { $_.DisplayName -eq $WarehouseName } } else { # Return all Warehouses if no filter is provided Write-Message -Message "No filter provided. Returning all Warehouses." -Level Debug $Warehouses } # Step 9: Handle results if ($Warehouse) { Write-Message -Message "Warehouse found matching the specified criteria." -Level Debug return $Warehouse } else { Write-Message -Message "No Warehouse found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve Warehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Warehouse/Get-FabricWarehouse.ps1' 98 #Region './Public/Warehouse/New-FabricWarehouse.ps1' -1 <# .SYNOPSIS Creates a new warehouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a POST request to the Microsoft Fabric API to create a new warehouse in the specified workspace. It supports optional parameters for warehouse description. .PARAMETER WorkspaceId The unique identifier of the workspace where the warehouse will be created. This parameter is mandatory. .PARAMETER WarehouseName The name of the warehouse to be created. This parameter is mandatory. .PARAMETER WarehouseDescription An optional description for the warehouse. .EXAMPLE New-FabricWarehouse -WorkspaceId "workspace-12345" -WarehouseName "New Warehouse" -WarehouseDescription "Description of the new warehouse" This example creates a new warehouse named "New Warehouse" in the workspace with ID "workspace-12345" with the provided description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function New-FabricWarehouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$WarehouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WarehouseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointURI = "workspaces/{0}/warehouses" -f $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $WarehouseName } if ($WarehouseDescription) { $body.description = $WarehouseDescription } $bodyJson = $body | ConvertTo-Json -Depth 10 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Create Warehouse")) { # Step 4: Make the API request $apiParams = @{ Uri = $apiEndpointURI Method = 'Post' Body = $bodyJson } $response = Invoke-FabricAPIRequest @apiParams } Write-Message -Message "Data Warehouse created successfully!" -Level Info return $response } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create Warehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Warehouse/New-FabricWarehouse.ps1' 92 #Region './Public/Warehouse/Remove-FabricWarehouse.ps1' -1 <# .SYNOPSIS Removes a warehouse from a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a DELETE request to the Microsoft Fabric API to remove a warehouse from the specified workspace using the provided WorkspaceId and WarehouseId. .PARAMETER WorkspaceId The unique identifier of the workspace from which the warehouse will be removed. .PARAMETER WarehouseId The unique identifier of the warehouse to be removed. .EXAMPLE Remove-FabricWarehouse -WorkspaceId "workspace-12345" -WarehouseId "warehouse-67890" This example removes the warehouse with ID "warehouse-67890" from the workspace with ID "workspace-12345". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricWarehouse { [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WarehouseId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointURI = "{0}/workspaces/{1}/warehouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $WarehouseId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Delete Warehouse")) { # Step 3: Make the API request $response = Invoke-FabricAPIRequest ` -Headers $FabricConfig.FabricHeaders ` -BaseURI $apiEndpointURI ` -method Delete ` } Write-Message -Message "Warehouse '$WarehouseId' deleted successfully from workspace '$WorkspaceId'." -Level Info return $response } catch { # Step 5: Log and handle errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to delete Warehouse '$WarehouseId' from workspace '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Warehouse/Remove-FabricWarehouse.ps1' 69 #Region './Public/Warehouse/Update-FabricWarehouse.ps1' -1 <# .SYNOPSIS Updates an existing warehouse in a specified Microsoft Fabric workspace. .DESCRIPTION This function sends a PATCH request to the Microsoft Fabric API to update an existing warehouse in the specified workspace. It supports optional parameters for warehouse description. .PARAMETER WorkspaceId The unique identifier of the workspace where the warehouse exists. This parameter is optional. .PARAMETER WarehouseId The unique identifier of the warehouse to be updated. This parameter is mandatory. .PARAMETER WarehouseName The new name of the warehouse. This parameter is mandatory. .PARAMETER WarehouseDescription An optional new description for the warehouse. .EXAMPLE Update-FabricWarehouse -WorkspaceId "workspace-12345" -WarehouseId "warehouse-67890" -WarehouseName "Updated Warehouse" -WarehouseDescription "Updated description" This example updates the warehouse with ID "warehouse-67890" in the workspace with ID "workspace-12345" with a new name and description. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricWarehouse { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WarehouseId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$WarehouseName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WarehouseDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointURI = "{0}/workspaces/{1}/warehouses/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $WarehouseId Write-Message -Message "API Endpoint: $apiEndpointURI" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $WarehouseName } if ($WarehouseDescription) { $body.description = $WarehouseDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointURI, "Update Warehouse")) { $response = Invoke-FabricAPIRequest ` -Headers $FabricConfig.FabricHeaders ` -BaseURI $apiEndpointURI ` -method Patch ` -body $bodyJson } # Step 6: Handle results Write-Message -Message "Warehouse '$WarehouseName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update Warehouse. Error: $errorDetails" -Level Error } } #EndRegion './Public/Warehouse/Update-FabricWarehouse.ps1' 100 #Region './Public/Workspace/Add-FabricWorkspaceCapacityAssignment.ps1' -1 <# .SYNOPSIS Assigns a Fabric workspace to a specified capacity. .DESCRIPTION The `Add-FabricWorkspaceCapacityAssignment` function sends a POST request to assign a workspace to a specific capacity. .PARAMETER WorkspaceId The unique identifier of the workspace to be assigned. .PARAMETER CapacityId The unique identifier of the capacity to which the workspace should be assigned. .EXAMPLE Add-FabricWorkspaceCapacityAssignment -WorkspaceId "workspace123" -CapacityId "capacity456" Assigns the workspace with ID "workspace123" to the capacity "capacity456". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricWorkspaceCapacityAssignment { [CmdletBinding()] [Alias("Assign-FabricWorkspaceCapacity")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CapacityId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/assignToCapacity" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ capacityId = $CapacityId } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 4 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 202) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Successfully assigned workspace with ID '$WorkspaceId' to capacity with ID '$CapacityId'." -Level Info } catch { # Step 6: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to assign workspace with ID '$WorkspaceId' to capacity with ID '$CapacityId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Add-FabricWorkspaceCapacityAssignment.ps1' 84 #Region './Public/Workspace/Add-FabricWorkspaceIdentity.ps1' -1 <# .SYNOPSIS Provisions an identity for a Fabric workspace. .DESCRIPTION The `Add-FabricWorkspaceIdentity` function provisions an identity for a specified workspace by making an API call. .PARAMETER WorkspaceId The unique identifier of the workspace for which the identity will be provisioned. .EXAMPLE Add-FabricWorkspaceIdentity -WorkspaceId "workspace123" Provisions a Managed Identity for the workspace with ID "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricWorkspaceIdentity { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/provisionIdentity" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 4: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Workspace identity was successfully provisioned for workspace '$WorkspaceId'." -Level Info return $response } 202 { Write-Message -Message "Workspace identity provisioning accepted for workspace '$WorkspaceId'. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] [string]$location = $responseHeader["Location"] [string]$retryAfter = $responseHeader["Retry-After"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Location: '$location'" -Level Debug Write-Message -Message "Retry-After: '$retryAfter'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 5: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to provision workspace identity. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Add-FabricWorkspaceIdentity.ps1' 100 #Region './Public/Workspace/Add-FabricWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Assigns a role to a principal for a specified Fabric workspace. .DESCRIPTION The `Add-FabricWorkspaceRoleAssignments` function assigns a role (e.g., Admin, Contributor, Member, Viewer) to a principal (e.g., User, Group, ServicePrincipal) in a Fabric workspace by making a POST request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace. .PARAMETER PrincipalId The unique identifier of the principal (User, Group, etc.) to assign the role. .PARAMETER PrincipalType The type of the principal. Allowed values: Group, ServicePrincipal, ServicePrincipalProfile, User. .PARAMETER WorkspaceRole The role to assign to the principal. Allowed values: Admin, Contributor, Member, Viewer. .EXAMPLE Add-FabricWorkspaceRoleAssignment -WorkspaceId "workspace123" -PrincipalId "principal123" -PrincipalType "User" -WorkspaceRole "Admin" Assigns the Admin role to the user with ID "principal123" in the workspace "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Add-FabricWorkspaceRoleAssignment { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$PrincipalId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Group', 'ServicePrincipal', 'ServicePrincipalProfile', 'User')] [string]$PrincipalType, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Admin', 'Contributor', 'Member', 'Viewer')] [string]$WorkspaceRole ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/roleAssignments" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ principal = @{ id = $PrincipalId type = $PrincipalType } role = $WorkspaceRole } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 4 Write-Message -Message "Request Body: $bodyJson" -Level Debug # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 5: Validate the response code if ($statusCode -ne 201) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle empty response if (-not $response) { Write-Message -Message "No data returned from the API." -Level Warning return $null } Write-Message -Message "Role '$WorkspaceRole' assigned to principal '$PrincipalId' successfully in workspace '$WorkspaceId'." -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to assign role. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Add-FabricWorkspaceRoleAssignment.ps1' 113 #Region './Public/Workspace/Get-FabricWorkspace.ps1' -1 <# .SYNOPSIS Retrieves details of a Microsoft Fabric workspace by its ID or name. .DESCRIPTION The `Get-FabricWorkspace` function fetches workspace details from the Fabric API. It supports filtering by WorkspaceId or WorkspaceName. .PARAMETER WorkspaceId The unique identifier of the workspace to retrieve. .PARAMETER WorkspaceName The display name of the workspace to retrieve. .EXAMPLE Get-FabricWorkspace -WorkspaceId "workspace123" Fetches details of the workspace with ID "workspace123". .EXAMPLE Get-FabricWorkspace -WorkspaceName "MyWorkspace" Fetches details of the workspace with the name "MyWorkspace". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. - Returns the matching workspace details or all workspaces if no filter is provided. Author: Tiago Balabuch #> function Get-FabricWorkspace { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_\- ]*$')] [string]$WorkspaceName ) try { # Step 1: Handle ambiguous input if ($WorkspaceId -and $WorkspaceName) { Write-Message -Message "Both 'WorkspaceId' and 'WorkspaceName' were provided. Please specify only one." -Level Error return $null } # Step 2: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $workspaces = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces" -f $FabricConfig.BaseUrl do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $workspaces += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $workspace = if ($WorkspaceId) { $workspaces | Where-Object { $_.Id -eq $WorkspaceId } } elseif ($WorkspaceName) { $workspaces | Where-Object { $_.DisplayName -eq $WorkspaceName } } else { # Return all workspaces if no filter is provided Write-Message -Message "No filter provided. Returning all workspaces." -Level Debug $workspaces } # Step 9: Handle results if ($workspace) { Write-Message -Message "Workspace found matching the specified criteria." -Level Debug return $workspace } else { Write-Message -Message "No workspace found matching the provided criteria." -Level Warning return $null } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve workspace. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Get-FabricWorkspace.ps1' 144 #Region './Public/Workspace/Get-FabricWorkspaceDatasetRefreshes.ps1' -1 function Get-FabricWorkspaceDatasetRefreshes { <# .SYNOPSIS Retrieves the refresh history of all datasets in a specified PowerBI workspace. .DESCRIPTION The Get-FabricWorkspaceDatasetRefreshes function uses the PowerBI cmdlets to retrieve the refresh history of all datasets in a specified workspace. It uses the workspace ID to get the workspace and its datasets, and then retrieves the refresh history for each dataset. .PARAMETER WorkspaceID The ID of the PowerBI workspace. This is a mandatory parameter. .EXAMPLE Get-FabricWorkspaceDatasetRefreshes -WorkspaceID "12345678-90ab-cdef-1234-567890abcdef" This command retrieves the refresh history of all datasets in the workspace with the specified ID. .INPUTS String. You can pipe a string that contains the workspace ID to Get-FabricWorkspaceDatasetRefreshes. .OUTPUTS Array. Get-FabricWorkspaceDatasetRefreshes returns an array of refresh history objects. .NOTES Alias: Get-PowerBIWorkspaceDatasetRefreshes, Get-FabWorkspaceDatasetRefreshes #> # Define a function to get the refresh history of all datasets in a PowerBI workspace # Set aliases for the function [Alias("Get-FabWorkspaceDatasetRefreshes")] param( # Define a mandatory parameter for the workspace ID [Parameter(Mandatory = $true)] [string]$WorkspaceID ) Confirm-FabricAuthToken | Out-Null # Get the workspace using the workspace ID $wsp = Get-FabricWorkspace -workspaceid $WorkspaceID # Initialize an array to store the refresh history $refs = @() # Get all datasets in the workspace $datasets = Get-FabricDataset -workspaceid $wsp.Id # Loop over each dataset foreach ($dataset in $datasets) { # Get the refresh history of the dataset and add it to the array $refs += Get-FabricDatasetRefreshes -datasetid $dataset.Id -workspaceId $wsp.Id } # Return the refresh history array return $refs } #EndRegion './Public/Workspace/Get-FabricWorkspaceDatasetRefreshes.ps1' 54 #Region './Public/Workspace/Get-FabricWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Retrieves role assignments for a specified Fabric workspace. .DESCRIPTION The `Get-FabricWorkspaceRoleAssignments` function fetches the role assignments associated with a Fabric workspace by making a GET request to the API. If `WorkspaceRoleAssignmentId` is provided, it retrieves the specific role assignment. .PARAMETER WorkspaceId The unique identifier of the workspace to fetch role assignments for. .PARAMETER WorkspaceRoleAssignmentId (Optional) The unique identifier of a specific role assignment to retrieve. .EXAMPLE Get-FabricWorkspaceRoleAssignments -WorkspaceId "workspace123" Fetches all role assignments for the workspace with the ID "workspace123". .EXAMPLE Get-FabricWorkspaceRoleAssignments -WorkspaceId "workspace123" -WorkspaceRoleAssignmentId "role123" Fetches the role assignment with the ID "role123" for the workspace "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Get-FabricWorkspaceRoleAssignment { [CmdletBinding()] [OutputType([System.Object[]])] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WorkspaceRoleAssignmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 3: Initialize variables $continuationToken = $null $workspaceRoles = @() if (-not ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "System.Web" })) { Add-Type -AssemblyName System.Web } # Step 4: Loop to retrieve all capacities with continuation token Write-Message -Message "Loop started to get continuation token" -Level Debug $baseApiEndpointUrl = "{0}/workspaces/{1}/roleAssignments" -f $FabricConfig.BaseUrl, $WorkspaceId do { # Step 5: Construct the API URL $apiEndpointUrl = $baseApiEndpointUrl if ($null -ne $continuationToken) { # URL-encode the continuation token $encodedToken = [System.Web.HttpUtility]::UrlEncode($continuationToken) $apiEndpointUrl = "{0}?continuationToken={1}" -f $apiEndpointUrl, $encodedToken } Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 6: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Get ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" # Step 7: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message -Message "Error Details: $($response.moreDetails)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 8: Add data to the list if ($null -ne $response) { Write-Message -Message "Adding data to the list" -Level Debug $workspaceRoles += $response.value # Update the continuation token if present if ($response.PSObject.Properties.Match("continuationToken")) { Write-Message -Message "Updating the continuation token" -Level Debug $continuationToken = $response.continuationToken Write-Message -Message "Continuation token: $continuationToken" -Level Debug } else { Write-Message -Message "Updating the continuation token to null" -Level Debug $continuationToken = $null } } else { Write-Message -Message "No data received from the API." -Level Warning break } } while ($null -ne $continuationToken) Write-Message -Message "Loop finished and all data added to the list" -Level Debug # Step 8: Filter results based on provided parameters $roleAssignments = if ($WorkspaceRoleAssignmentId) { $workspaceRoles | Where-Object { $_.Id -eq $WorkspaceRoleAssignmentId } } else { $workspaceRoles } # Step 9: Handle results if ($roleAssignments) { Write-Message -Message "Found $($roleAssignments.Count) role assignments for WorkspaceId '$WorkspaceId'." -Level Debug # Transform data into custom objects $results = foreach ($obj in $roleAssignments) { [PSCustomObject]@{ ID = $obj.id PrincipalId = $obj.principal.id DisplayName = $obj.principal.displayName Type = $obj.principal.type UserPrincipalName = $obj.principal.userDetails.userPrincipalName aadAppId = $obj.principal.servicePrincipalDetails.aadAppId Role = $obj.role } } return $results } else { if ($WorkspaceRoleAssignmentId) { Write-Message -Message "No role assignment found with ID '$WorkspaceRoleAssignmentId' for WorkspaceId '$WorkspaceId'." -Level Warning } else { Write-Message -Message "No role assignments found for WorkspaceId '$WorkspaceId'." -Level Warning } return @() } } catch { # Step 10: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve role assignments for WorkspaceId '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Get-FabricWorkspaceRoleAssignment.ps1' 149 #Region './Public/Workspace/Get-FabricWorkspaceUsageMetricsData.ps1' -1 function Get-FabricWorkspaceUsageMetricsData { <# .SYNOPSIS Retrieves workspace usage metrics data. .DESCRIPTION The Get-FabricWorkspaceUsageMetricsData function retrieves workspace usage metrics. It supports multiple aliases for flexibility. .PARAMETER workspaceId The ID of the workspace. This is a mandatory parameter. .PARAMETER username The username. This is a mandatory parameter. .EXAMPLE Get-FabricWorkspaceUsageMetricsData -workspaceId "your-workspace-id" -username "your-username" This example retrieves the workspace usage metrics for a specific workspace given the workspace ID and username. .NOTES The function retrieves the PowerBI access token and creates a new usage metrics report. It then defines the names of the reports to retrieve, initializes an empty hashtable to store the reports, and for each report name, retrieves the report and adds it to the hashtable. It then returns the hashtable of reports. #> # This function retrieves workspace usage metrics. # Define aliases for the function for flexibility. [Alias("Get-FabWorkspaceUsageMetricsData")] # Define parameters for the workspace ID and username. param( [Parameter(Mandatory = $true)] [string]$workspaceId, [Parameter(Mandatory = $false)] [string]$username = "" ) # Create a new workspace usage metrics dataset. $datasetId = New-FabricWorkspaceUsageMetricsReport -workspaceId $workspaceId # Define the names of the reports to retrieve. $reportnames = @("'Workspace views'", "'Report pages'", "Users", "Reports", "'Report views'", "'Report page views'", "'Report load times'") # Initialize an empty hashtable to store the reports. $reports = @{ } # For each report name, retrieve the report and add it to the hashtable. if ($username -eq "") { foreach ($reportname in $reportnames) { $report = Get-FabricUsageMetricsQuery -DatasetID $datasetId -groupId $workspaceId -reportname $reportname $reports += @{ $reportname.replace("'", "") = $report } } } else { foreach ($reportname in $reportnames) { $report = Get-FabricUsageMetricsQuery -DatasetID $datasetId -groupId $workspaceId -reportname $reportname -ImpersonatedUser $username $reports += @{ $reportname.replace("'", "") = $report } } } # Return the hashtable of reports. return $reports } #EndRegion './Public/Workspace/Get-FabricWorkspaceUsageMetricsData.ps1' 60 #Region './Public/Workspace/Get-FabricWorkspaceUsers.ps1' -1 function Get-FabricWorkspaceUsers { <# .SYNOPSIS Retrieves the users of a workspace. .DESCRIPTION The Get-FabricWorkspaceUsers function retrieves the users of a workspace. It supports multiple aliases for flexibility. .PARAMETER WorkspaceId The ID of the workspace. This is a mandatory parameter for the 'WorkspaceId' parameter set. .PARAMETER Workspace The workspace object. This is a mandatory parameter for the 'WorkspaceObject' parameter set and can be piped into the function. .EXAMPLE Get-FabricWorkspaceUsers -WorkspaceId "your-workspace-id" This example retrieves the users of a workspace given the workspace ID. .EXAMPLE $workspace | Get-FabricWorkspaceUsers This example retrieves the users of a workspace given a workspace object. .NOTES The function defines parameters for the workspace ID and workspace object. If the parameter set name is 'WorkspaceId', it retrieves the workspace object. It then makes a GET request to the PowerBI API to retrieve the users of the workspace and returns the 'value' property of the response, which contains the users. #> # This function retrieves the users of a workspace. # Define aliases for the function for flexibility. [Alias("Get-FabWorkspaceUsers")] # Define parameters for the workspace ID and workspace object. param( [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceId')] [string]$WorkspaceId, [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceObject', ValueFromPipeline = $true )] $Workspace ) begin { Confirm-FabricAuthToken | Out-Null } process { # If the parameter set name is 'WorkspaceId', retrieve the workspace object. if ($PSCmdlet.ParameterSetName -eq 'WorkspaceId') { $workspace = Get-PowerBIWorkspace -Id $WorkspaceId } # Make a GET request to the PowerBI API to retrieve the users of the workspace. # The function returns the 'value' property of the response, which contains the users. return (Invoke-PowerBIRestMethod -Method get -Url ("groups/$($workspace.Id)/users") | ConvertFrom-Json).value } } #EndRegion './Public/Workspace/Get-FabricWorkspaceUsers.ps1' 58 #Region './Public/Workspace/New-FabricWorkspace.ps1' -1 function New-FabricWorkspace { <# .SYNOPSIS Creates a new Fabric workspace with the specified display name. .DESCRIPTION The `Add-FabricWorkspace` function creates a new workspace in the Fabric platform by sending a POST request to the API. It validates the display name and handles both success and error responses. .PARAMETER WorkspaceName The display name of the workspace to be created. Must only contain alphanumeric characters, spaces, and underscores. .PARAMETER WorkspaceDescription (Optional) A description for the workspace. This parameter is optional. .PARAMETER CapacityId (Optional) The ID of the capacity to be associated with the workspace. This parameter is optional. .EXAMPLE Add-FabricWorkspace -WorkspaceName "NewWorkspace" Creates a workspace named "NewWorkspace". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WorkspaceDescription, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$CapacityId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces" -f $FabricConfig.BaseUrl Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $WorkspaceName } if ($WorkspaceDescription) { $body.description = $WorkspaceDescription } if ($CapacityId) { $body.capacityId = $CapacityId } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 2 Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Create Workspace")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Handle and log the response switch ($statusCode) { 201 { Write-Message -Message "Workspace '$WorkspaceName' created successfully!" -Level Info return $response } 202 { Write-Message -Message "Workspace '$WorkspaceName' creation accepted. Provisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 6: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to create workspace. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/New-FabricWorkspace.ps1' 142 #Region './Public/Workspace/New-FabricWorkspaceUsageMetricsReport.ps1' -1 function New-FabricWorkspaceUsageMetricsReport { <# .SYNOPSIS Retrieves the workspace usage metrics dataset ID. .DESCRIPTION The New-FabricWorkspaceUsageMetricsReport function retrieves the workspace usage metrics dataset ID. It supports multiple aliases for flexibility. .PARAMETER workspaceId The ID of the workspace. This is a mandatory parameter. .EXAMPLE New-FabricWorkspaceUsageMetricsReport -workspaceId "your-workspace-id" This example retrieves the workspace usage metrics dataset ID for a specific workspace given the workspace ID. .NOTES The function retrieves the PowerBI access token and the Fabric API cluster URI. It then makes a GET request to the Fabric API to retrieve the workspace usage metrics dataset ID, parses the response and replaces certain keys to match the expected format, and returns the 'dbName' property of the first model in the response, which is the dataset ID. #> # This function retrieves the workspace usage metrics dataset ID. # Define aliases for the function for flexibility. [Alias("New-FabWorkspaceUsageMetricsReport")] [CmdletBinding(SupportsShouldProcess)] # Define a parameter for the workspace ID. param( [Parameter(Mandatory = $true)] [string]$workspaceId ) Confirm-FabricAuthToken | Out-Null # Retrieve the Fabric API cluster URI. $url = Get-FabricAPIclusterURI # Make a GET request to the Fabric API to retrieve the workspace usage metrics dataset ID. if ($PSCmdlet.ShouldProcess("Workspace Usage Metrics Report", "Retrieve")) { $data = Invoke-WebRequest -Uri "$url/$workspaceId/usageMetricsReportV2?experience=power-bi" -Headers $FabricSession.HeaderParams -ErrorAction SilentlyContinue # Parse the response and replace certain keys to match the expected format. $response = $data.Content.ToString().Replace("nextRefreshTime", "NextRefreshTime").Replace("lastRefreshTime", "LastRefreshTime") | ConvertFrom-Json # Return the 'dbName' property of the first model in the response, which is the dataset ID. return $response.models[0].dbName } else { return $null } } #EndRegion './Public/Workspace/New-FabricWorkspaceUsageMetricsReport.ps1' 49 #Region './Public/Workspace/Register-FabricWorkspaceToCapacity.ps1' -1 function Register-FabricWorkspaceToCapacity { <# .SYNOPSIS Sets a PowerBI workspace to a capacity. .DESCRIPTION The Register-FabricWorkspaceToCapacity function Sets a PowerBI workspace to a capacity. It supports multiple aliases for flexibility. .PARAMETER WorkspaceId The ID of the workspace to be Seted. This is a mandatory parameter. .PARAMETER Workspace The workspace object to be Seted. This is a mandatory parameter and can be piped into the function. .PARAMETER CapacityId The ID of the capacity to which the workspace will be Seted. This is a mandatory parameter. .EXAMPLE Register-FabricWorkspaceToCapacity -WorkspaceId "Workspace-GUID" -CapacityId "Capacity-GUID" This example Sets the workspace with ID "Workspace-GUID" to the capacity with ID "Capacity-GUID". .EXAMPLE $workspace | Register-FabricWorkspaceToCapacity -CapacityId "Capacity-GUID" This example Sets the workspace object stored in the $workspace variable to the capacity with ID "Capacity-GUID". The workspace object is piped into the function. .NOTES The function makes a POST request to the PowerBI API to Set the workspace to the capacity. The PowerBI access token is retrieved using the Get-PowerBIAccessToken function. #> # This function Sets a PowerBI workspace to a capacity. # It supports multiple aliases for flexibility. [Alias("Register-FabWorkspaceToCapacity")] [CmdletBinding(SupportsShouldProcess)] param( # WorkspaceId is a mandatory parameter. It represents the ID of the workspace to be Seted. [Parameter(ParameterSetName = 'WorkspaceId')] [string]$WorkspaceId, # Workspace is a mandatory parameter. It represents the workspace object to be Seted. # This parameter can be piped into the function. [Parameter(ParameterSetName = 'WorkspaceObject', ValueFromPipeline = $true)] $Workspace, # CapacityId is a mandatory parameter. It represents the ID of the capacity to which the workspace will be Seted. [Parameter(Mandatory = $true)] [string]$CapacityId ) Process { # If the parameter set name is 'WorkspaceObject', the workspace ID is extracted from the workspace object. if ($PSCmdlet.ParameterSetName -eq 'WorkspaceObject') { $workspaceid = $workspace.id } # The body of the request is created. It contains the capacity ID. $body = @{ capacityId = $CapacityId } Confirm-FabricAuthToken | Out-Null # The workspace is Seted to the capacity by making a POST request to the PowerBI API. # The function returns the value property of the response. if ($PSCmdlet.ShouldProcess("Set workspace $workspaceid to capacity $CapacityId")) { #return (Invoke-FabricAPIRequest -Uri "workspaces/$($workspaceID)/assignToCapacity" -Method POST -Body $body).value return Invoke-WebRequest -Headers $FabricSession.HeaderParams -Method POST -Uri "$($FabricSession.BaseApiUrl)/workspaces/$($workspaceID)/assignToCapacity" -Body $body } } } #EndRegion './Public/Workspace/Register-FabricWorkspaceToCapacity.ps1' 72 #Region './Public/Workspace/Remove-FabricWorkspace.ps1' -1 <# .SYNOPSIS Deletes an existing Fabric workspace by its workspace ID. .DESCRIPTION The `Remove-FabricWorkspace` function deletes a workspace in the Fabric platform by sending a DELETE request to the API. It validates the workspace ID and handles both success and error responses. .PARAMETER WorkspaceId The unique identifier of the workspace to be deleted. .EXAMPLE Remove-FabricWorkspace -WorkspaceId "workspace123" Deletes the workspace with the ID "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricWorkspace { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Delete Workspace")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Workspace '$WorkspaceId' deleted successfully!" -Level Info return $null } catch { # Step 5: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to retrieve capacity. Error: $errorDetails" -Level Error return $null } } #EndRegion './Public/Workspace/Remove-FabricWorkspace.ps1' 75 #Region './Public/Workspace/Remove-FabricWorkspaceCapacityAssignment.ps1' -1 <# .SYNOPSIS Unassigns a Fabric workspace from its capacity. .DESCRIPTION The `Remove-FabricWorkspaceCapacityAssignment` function sends a POST request to unassign a workspace from its assigned capacity. .PARAMETER WorkspaceId The unique identifier of the workspace to be unassigned from its capacity. .EXAMPLE Remove-FabricWorkspaceCapacityAssignment -WorkspaceId "workspace123" Unassigns the workspace with ID "workspace123" from its capacity. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricWorkspaceCapacityAssignment { [CmdletBinding(SupportsShouldProcess)] [Alias("Unassign-FabricWorkspaceCapacity")] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/unassignFromCapacity" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Message if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Unassign Workspace from Capacity")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 202) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Workspace capacity has been successfully unassigned from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to unassign workspace from capacity. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Remove-FabricWorkspaceCapacityAssignment.ps1' 74 #Region './Public/Workspace/Remove-FabricWorkspaceIdentity.ps1' -1 <# .SYNOPSIS Deprovisions the Managed Identity for a specified Fabric workspace. .DESCRIPTION The `Remove-FabricWorkspaceCapacity` function deprovisions the Managed Identity from the given workspace by calling the appropriate API endpoint. .PARAMETER WorkspaceId The unique identifier of the workspace from which the identity will be removed. .EXAMPLE Remove-FabricWorkspaceCapacity -WorkspaceId "workspace123" Deprovisions the Managed Identity for the workspace with ID "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricWorkspaceIdentity { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/deprovisionIdentity" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Deprovision Identity")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Post ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Handle and log the response switch ($statusCode) { 200 { Write-Message -Message "Workspace identity was successfully deprovisioned for workspace '$WorkspaceId'." -Level Info return $response.value } 202 { Write-Message -Message "Workspace identity deprovisioning accepted for workspace '$WorkspaceId'. Deprovisioning in progress!" -Level Info [string]$operationId = $responseHeader["x-ms-operation-id"] Write-Message -Message "Operation ID: '$operationId'" -Level Debug Write-Message -Message "Getting Long Running Operation status" -Level Debug $operationStatus = Get-FabricLongRunningOperation -operationId $operationId Write-Message -Message "Long Running Operation status: $operationStatus" -Level Debug # Handle operation result if ($operationStatus.status -eq "Succeeded") { Write-Message -Message "Operation Succeeded" -Level Debug Write-Message -Message "Getting Long Running Operation result" -Level Debug $operationResult = Get-FabricLongRunningOperationResult -operationId $operationId Write-Message -Message "Long Running Operation status: $operationResult" -Level Debug return $operationResult } else { Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Debug Write-Message -Message "Operation failed. Status: $($operationStatus)" -Level Error return $operationStatus } } default { Write-Message -Message "Unexpected response code: $statusCode" -Level Error Write-Message -Message "Error details: $($response.message)" -Level Error throw "API request failed with status code $statusCode." } } } catch { # Step 5: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to deprovision workspace identity. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Remove-FabricWorkspaceIdentity.ps1' 108 #Region './Public/Workspace/Remove-FabricWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Removes a role assignment from a Fabric workspace. .DESCRIPTION The `Remove-FabricWorkspaceRoleAssignment` function deletes a specific role assignment from a Fabric workspace by making a DELETE request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace. .PARAMETER WorkspaceRoleAssignmentId The unique identifier of the role assignment to be removed. .EXAMPLE Remove-FabricWorkspaceRoleAssignment -WorkspaceId "workspace123" -WorkspaceRoleAssignmentId "role123" Removes the role assignment with the ID "role123" from the workspace "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Remove-FabricWorkspaceRoleAssignment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceRoleAssignmentId ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/roleAssignments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $WorkspaceRoleAssignmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Delete Role Assignment")) { # Step 3: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Delete ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 4: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } Write-Message -Message "Role assignment '$WorkspaceRoleAssignmentId' successfully removed from workspace '$WorkspaceId'." -Level Info } catch { # Step 5: Capture and log error details $errorDetails = $_.Exception.Message Write-Message -Message "Failed to remove role assignments for WorkspaceId '$WorkspaceId'. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Remove-FabricWorkspaceRoleAssignment.ps1' 81 #Region './Public/Workspace/Unregister-FabricWorkspaceToCapacity.ps1' -1 <# .SYNOPSIS Unregisters a workspace from a capacity. .DESCRIPTION The Unregister-FabricWorkspaceToCapacity function unregisters a workspace from a capacity in PowerBI. It can be used to remove a workspace from a capacity, allowing it to be assigned to a different capacity or remain unassigned. .PARAMETER WorkspaceId Specifies the ID of the workspace to be unregistered from the capacity. This parameter is mandatory when using the 'WorkspaceId' parameter set. .PARAMETER Workspace Specifies the workspace object to be unregistered from the capacity. This parameter is mandatory when using the 'WorkspaceObject' parameter set. The workspace object can be piped into the function. .EXAMPLE Unregister-FabricWorkspaceToCapacity -WorkspaceId "12345678" Unregisters the workspace with ID "12345678" from the capacity. .EXAMPLE Get-FabricWorkspace | Unregister-FabricWorkspaceToCapacity Unregisters the workspace objects piped from Get-FabricWorkspace from the capacity. .INPUTS System.Management.Automation.PSCustomObject .OUTPUTS System.Object .NOTES Author: Your Name Date: Today's Date #> function Unregister-FabricWorkspaceToCapacity { [Alias("Unregister-FabWorkspaceToCapacity")] [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceId')] [string]$WorkspaceId, [Parameter(Mandatory = $true, ParameterSetName = 'WorkspaceObject', ValueFromPipeline = $true)] $Workspace ) begin { Confirm-FabricAuthToken | Out-Null } Process { if ($PSCmdlet.ParameterSetName -eq 'WorkspaceObject') { $workspaceid = $workspace.id } if ($PSCmdlet.ShouldProcess("Unassigns workspace $workspaceid from a capacity")) { return Invoke-WebRequest -Headers $FabricSession.HeaderParams -Method POST -Uri "$($FabricSession.BaseApiUrl)/workspaces/$($workspaceID)/unassignFromCapacity" #return (Invoke-FabricAPIRequest -Uri "workspaces/$workspaceid/unassignFromCapacity" -Method POST).value } } } #EndRegion './Public/Workspace/Unregister-FabricWorkspaceToCapacity.ps1' 59 #Region './Public/Workspace/Update-FabricWorkspace.ps1' -1 <# .SYNOPSIS Updates the properties of a Fabric workspace. .DESCRIPTION The `Update-FabricWorkspace` function updates the name and/or description of a specified Fabric workspace by making a PATCH request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace to be updated. .PARAMETER WorkspaceName The new name for the workspace. .PARAMETER WorkspaceDescription (Optional) The new description for the workspace. .EXAMPLE Update-FabricWorkspace -WorkspaceId "workspace123" -WorkspaceName "NewWorkspaceName" Updates the name of the workspace with the ID "workspace123" to "NewWorkspaceName". .EXAMPLE Update-FabricWorkspace -WorkspaceId "workspace123" -WorkspaceName "NewName" -WorkspaceDescription "Updated description" Updates both the name and description of the workspace "workspace123". .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricWorkspace { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidatePattern('^[a-zA-Z0-9_ ]*$')] [string]$WorkspaceName, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [string]$WorkspaceDescription ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}" -f $FabricConfig.BaseUrl, $WorkspaceId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Debug # Step 3: Construct the request body $body = @{ displayName = $WorkspaceName } if ($WorkspaceDescription) { $body.description = $WorkspaceDescription } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Workspace")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle results Write-Message -Message "Workspace '$WorkspaceName' updated successfully!" -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update workspace. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Update-FabricWorkspace.ps1' 112 #Region './Public/Workspace/Update-FabricWorkspaceRoleAssignment.ps1' -1 <# .SYNOPSIS Updates the role assignment for a specific principal in a Fabric workspace. .DESCRIPTION The `Update-FabricWorkspaceRoleAssignment` function updates the role assigned to a principal in a workspace by making a PATCH request to the API. .PARAMETER WorkspaceId The unique identifier of the workspace where the role assignment exists. .PARAMETER WorkspaceRoleAssignmentId The unique identifier of the role assignment to be updated. .PARAMETER WorkspaceRole The new role to assign to the principal. Must be one of the following: - Admin - Contributor - Member - Viewer .EXAMPLE Update-FabricWorkspaceRoleAssignment -WorkspaceId "workspace123" -WorkspaceRoleAssignmentId "assignment456" -WorkspaceRole "Admin" Updates the role assignment to "Admin" for the specified workspace and role assignment. .NOTES - Requires `$FabricConfig` global configuration, including `BaseUrl` and `FabricHeaders`. - Calls `Test-TokenExpired` to ensure token validity before making the API request. Author: Tiago Balabuch #> function Update-FabricWorkspaceRoleAssignment { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$WorkspaceRoleAssignmentId, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [ValidateSet('Admin', 'Contributor', 'Member', 'Viewer')] [string]$WorkspaceRole ) try { # Step 1: Ensure token validity Write-Message -Message "Validating token..." -Level Debug Test-TokenExpired Write-Message -Message "Token validation completed." -Level Debug # Step 2: Construct the API URL $apiEndpointUrl = "{0}/workspaces/{1}/roleAssignments/{2}" -f $FabricConfig.BaseUrl, $WorkspaceId, $WorkspaceRoleAssignmentId Write-Message -Message "API Endpoint: $apiEndpointUrl" -Level Message # Step 3: Construct the request body $body = @{ role = $WorkspaceRole } # Convert the body to JSON $bodyJson = $body | ConvertTo-Json -Depth 4 -Compress Write-Message -Message "Request Body: $bodyJson" -Level Debug if ($PSCmdlet.ShouldProcess($apiEndpointUrl, "Update Role Assignment")) { # Step 4: Make the API request $response = Invoke-RestMethod ` -Headers $FabricConfig.FabricHeaders ` -Uri $apiEndpointUrl ` -Method Patch ` -Body $bodyJson ` -ContentType "application/json" ` -ErrorAction Stop ` -SkipHttpErrorCheck ` -ResponseHeadersVariable "responseHeader" ` -StatusCodeVariable "statusCode" } # Step 5: Validate the response code if ($statusCode -ne 200) { Write-Message -Message "Unexpected response code: $statusCode from the API." -Level Error Write-Message -Message "Error: $($response.message)" -Level Error Write-Message "Error Code: $($response.errorCode)" -Level Error return $null } # Step 6: Handle empty response if (-not $response) { Write-Message -Message "No data returned from the API." -Level Warning return $null } Write-Message -Message "Role assignment $WorkspaceRoleAssignmentId updated successfully in workspace '$WorkspaceId'." -Level Info return $response } catch { # Step 7: Handle and log errors $errorDetails = $_.Exception.Message Write-Message -Message "Failed to update role assignment. Error: $errorDetails" -Level Error } } #EndRegion './Public/Workspace/Update-FabricWorkspaceRoleAssignment.ps1' 112 |