Welcome to Microsoft Fabric 101 series – your comprehensive guide to mastering Microsoft Fabric. This series of articles and videos is designed to help you understand and effectively use Microsoft Fabric, whether you’re a beginner or looking to deepen your knowledge. We’ll cover everything from the basics of setting up and configuring your Fabric tenant to advanced features and best practices.
Prerequisite articles:
- Introduction to Microsoft Fabric – all you need to know
- Microsoft Fabric 101 Episode 1: Enabling Microsoft Fabric
- Microsoft Fabric 101 Episode 2: Creating Fabric Capacity using portal and Terraform
Series:
YT: link
Blog: link
Let’s get started on this exciting journey!
In today’s episode, we’ll discuss scaling and pausing/resuming Fabric capacity. Choosing a specific SKU doesn’t mean you’re stuck with it forever.
Introduction
Before we begin, here are a few important facts to know:
- Consider using Reservations to save money (link) especially if your capacity will be active most of the time.
- All described operations apply to FSKU, not PSKU (Power BI Premium).
- When pausing capacity, any remaining cumulative overages and smoothed operations are summed and added to your Azure bill.
You can always pause Fabric capacity when it’s not in use or scale it up or down according to your needs. This can be done easily via the Azure portal using the graphical interface. Simply select the appropriate capacity and click one of the available buttons at the top:
A similar experience applies to scaling, where you can select the appropriate SKU from the list. Scaling to an SKU below F64 typically takes just a few seconds, while higher levels may take longer.
It’s simple, isn’t it? But can we automate this operation? Yes, we can—and in most cases, we want to.
Automation
App registration
For automation, we typically create a dedicated credential, such as a service principal, to run all the code because it offers several benefits:
- It’s not tied to any individual.
- It’s managed by Microsoft Entra.
- It provides a secure way to handle credentials and permissions.
- It enables fine-grained access control to resources.
To create it, go to the Azure portal and search for App registrations, as shown in the image below:
Then, click on New registration:
Registering the application in our case is straightforward. Simply give it a meaningful name. The other options aren’t relevant for us, so you can leave them at their default settings and click Register.
After a few seconds, the app will be registered, along with the Service Principal associated with it. The most important details can be found on the Overview page, where you’ll see the Application (client) ID and Directory (tenant) ID—both of which will be useful later. We also need to assign a secret value that we’ll use in our script. To do this, select Certificates & secrets.
Click New client secret and specify an expiration date that aligns with your company policy. Provide a descriptive name for the secret to indicate its purpose, as an app or service principal may have multiple secrets used for different purposes.
Our service principal is ready, so now we need to assign it the appropriate permissions. To perform operations like scaling, the credential must be added as a capacity or fabric administrator. In the Azure portal, select the capacity, then go to the Capacity administrators tab where you can add the previously created Service Principal.
To pause and resume the capacity, the service principal must have the following granular permissions:
Microsoft.Fabric/capacities/read
Microsoft.Fabric/capacities/write
Microsoft.Fabric/suspend/action
Microsoft.Fabric/resume/action
If you prefer a less specific approach, you can assign the service principal the Contributor built-in role on the fabric capacity resource.
Script
Now, let’s write our PowerShell script. Keep in mind that this is just one method; you can also use Logic Apps, Python, or any other approach you prefer.
In our scenario, we need to provide basic information such as tenant ID, client ID, and client secret. I’ll store these in variables. While it’s best practice to use a secure store like Key Vault for secrets (rather than keeping them in clear text), I’ll use clear text here for simplicity and visibility.
I also included an operation
variable with three possible values:
resume
suspend
scale
This way, one script can handle all operations. Additionally, there are two more variables: sku
, which specifies the Fabric SKU for scaling (not used for operations other than scale), and uri
, which contains the base URI for sending requests.
$tenantId = "deca7fb5-bee9-4134-9d26-e222fb2fe976" $clientId = "5e789679-d979-4def-86f7-ae238c82f2c2" $clientSecret = "xyz" $operation = "resume" $sku = "F4" $uri = "https://management.azure.com/subscriptions/f6996f9a-a352-4b64-8ab1-865c9f9c4c9b/resourceGroups/rg-fabric-demos/providers/Microsoft.Fabric/capacities/fabcapacityseequality01"
The next section of the script is designed to obtain an OAuth 2.0 access token from Azure Active Directory (AAD)/Entra using client credentials, and then prepare the headers for a subsequent API request.
The first step is to define the Request Body:
$body = @{ grant_type = "client_credentials" client_id = $clientId client_secret = $clientSecret resource = "https://management.azure.com/" }
Here, we create a hashtable $body
containing the necessary parameters for the OAuth 2.0 token request:
grant_type
: Specifies the type of OAuth 2.0 grant. In this case, it is set to"client_credentials"
.client_id
: The client ID of the application requesting the token.client_secret
: The client secret associated with the application.resource
: The resource for which the token is requested, in this case, the Azure Management API.
Next, we will attempt to obtain the access token:
try { $tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -ContentType "application/x-www-form-urlencoded" -Body $body $accessToken = $tokenResponse.access_token
This code attempts to obtain an access token by making a POST request to the Azure AD token endpoint:
Invoke-RestMethod
is used to send the request.- The response,
$tokenResponse
, is expected to contain the access token in theaccess_token
field. - The access token is then extracted and stored in the
$accessToken
variable.
Next, we need to prepare the header for our request:
# Headers for the PATCH request $headers = @{ Authorization = "Bearer $accessToken" "Content-Type" = "application/json" }
The Authorization
header is set to "Bearer $accessToken"
, where $accessToken
is the token obtained in the previous step. The Content-Type
header is set to "application/json"
, indicating that the request body will be in JSON format.
Next, a switch
statement handles different operations (scale
, resume
, suspend
) based on the value of the $operation
variable.
Scale operation
"scale" { $uri = $uri+"?api-version=2023-11-01" $method = "Patch" $body = @{ properties = @{ administration = @{ # Add your administration properties here } } sku = @{ name = $sku tier = "Fabric" } tags = @{ # Add your resource tags here } } | ConvertTo-Json }
- URI: Appends the API version query parameter to the
$uri
. - Method: Sets the HTTP method to
Patch
. - Body: Constructs a JSON body with
properties
,sku
, andtags
. The body is then converted to JSON format usingConvertTo-Json
.- properties: Contains an administration object where additional properties can be added.
- sku: Specifies the SKU name and tier, with the tier set to
"Fabric"
. - tags: Placeholder for resource tags.
Resume operation:
"resume" { $uri = $uri + "/resume?api-version=2023-11-01" Write-Output $uri $method = "Post" $body = $null }
- URI: Appends
/resume
and the API version query parameter to the$uri
. - Output: Prints the modified URI to the output.
- Method: Sets the HTTP method to
Post
. - Body: Sets the body to
null
, as no body is required for this operation.
Suspend operation:
"suspend" { $uri = $uri + "/suspend?api-version=2023-11-01" Write-Output $uri $method = "Post" $body = $null }
- URI: Appends
/suspend
and the API version query parameter to the$uri
. - Output: Prints the modified URI to the output.
- Method: Sets the HTTP method to
Post
. - Body: Sets the body to
null
, as no body is required for this operation.
Invoke the API
$response = Invoke-RestMethod -Method $method -Uri $uri -Headers $headers -Body $body
The Invoke-RestMethod
cmdlet is used to make the HTTP request. The method (such as GET or POST), URI, headers, and body of the request are passed as parameters.
if ($response) { $response } else { Write-Output "No content returned in the response." }
This block checks if the $response
variable contains any data. If $response
is not null
, it outputs the response. If $response
is null
, it outputs a message indicating that no content was returned.
catch { Write-Error "An error occurred: $_" }
This catch
block handles any exceptions that occur during the API call. If an error occurs, it writes an error message to the output, including the error details ($_
).
Below, you can see that the script works as expected:
Below you can find entire script and video, I hope you find it useful.
$tenantId = "deca7fa5-1111-2222-9d26-eb2fe976" $clientId = "5e876669-d979-4def-86f7-ae238f2c2" $clientSecret = "secret" $operation = "resume" $sku = "F4" $uri = "https://management.azure.com/subscriptions/f6996f9a-a352-4b64-8ab1-865c9f9c4c9b/resourceGroups/rg-fabric-demos/providers/Microsoft.Fabric/capacities/fabcapacityseequality01" # Authenticate using the service principal $body = @{ grant_type = "client_credentials" client_id = $clientId client_secret = $clientSecret resource = "https://management.azure.com/" } try { $tokenResponse = Invoke-RestMethod -Method Post -Uri "https://login.microsoftonline.com/$tenantId/oauth2/token" -ContentType "application/x-www-form-urlencoded" -Body $body $accessToken = $tokenResponse.access_token # Headers for the PATCH request $headers = @{ Authorization = "Bearer $accessToken" "Content-Type" = "application/json" } # Determine the URI and method based on the operation switch ($operation) { "scale" { $uri = $uri+"?api-version=2023-11-01" $method = "Patch" $body = @{ properties = @{ administration = @{ # Add your administration properties here } } sku = @{ name = $sku tier = "Fabric" } tags = @{ # Add your resource tags here } } | ConvertTo-Json } "resume" { $uri = $uri + "/resume?api-version=2023-11-01" Write-Output $uri $method = "Post" $body = $null } "suspend" { $uri = $uri + "/suspend?api-version=2023-11-01" Write-Output $uri $method = "Post" $body = $null } default { throw "Invalid operation: $operation" } } # Invoke the API with the determined method and URI $response = Invoke-RestMethod -Method $method -Uri $uri -Headers $headers -Body $body # Output the response if ($response) { $response } else { Write-Output "No content returned in the response." } } catch { Write-Error "An error occurred: $_" }
- Avoiding Issues: Monitoring Query Pushdowns in Databricks Federated Queries - October 27, 2024
- Microsoft Fabric: Using Workspace Identity for Authentication - September 25, 2024
- Executing SQL queries from Azure DevOps using Service Connection credentials - August 28, 2024
Last comments