From 28ec2cfb4ab8fa36b10312f860db9fea6cd785ff Mon Sep 17 00:00:00 2001 From: Hodayah Zargari Date: Thu, 11 Dec 2025 11:33:15 +0200 Subject: [PATCH 1/3] Kusto Follower Arm C# code update --- data-explorer/follower.md | 59 ++++++++++++++------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/data-explorer/follower.md b/data-explorer/follower.md index 6a8cd717a3..c96f94923f 100644 --- a/data-explorer/follower.md +++ b/data-explorer/follower.md @@ -3,7 +3,7 @@ title: Use follower database feature to attach databases in Azure Data Explorer description: Learn about how to attach databases in Azure Data Explorer using the follower database feature. ms.reviewer: gabilehner ms.topic: how-to -ms.date: 06/10/2025 +ms.date: 12/11/2025 ms.custom: - devx-track-azurepowershell - sfi-image-nochange @@ -99,43 +99,26 @@ You can optionally make the database name in the follower cluster different from ### C\# example ```csharp -var tenantId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Directory (tenant) ID -var clientId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Application ID -var clientSecret = "PlaceholderClientSecret"; //Client Secret -var followerSubscriptionId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; -var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret); -var resourceManagementClient = new ArmClient(credentials, followerSubscriptionId); -var followerResourceGroupName = "followerResourceGroup"; -var followerClusterName = "follower"; -var subscription = await resourceManagementClient.GetDefaultSubscriptionAsync(); -var resourceGroup = (await subscription.GetResourceGroupAsync(followerResourceGroupName)).Value; -var cluster = (await resourceGroup.GetKustoClusterAsync(followerClusterName)).Value; -var attachedDatabaseConfigurations = cluster.GetKustoAttachedDatabaseConfigurations(); -var attachedDatabaseConfigurationName = "attachedDatabaseConfiguration" -var leaderSubscriptionId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; -var leaderResourceGroup = "leaderResourceGroup"; -var leaderClusterName = "leader"; -var attachedDatabaseConfigurationData = new KustoAttachedDatabaseConfigurationData -{ - ClusterResourceId = new ResourceIdentifier($"/subscriptions/{leaderSubscriptionId}/resourceGroups/{leaderResourceGroup}/providers/Microsoft.Kusto/Clusters/{leaderClusterName}"), - DatabaseName = "", // Can be a specific database name in a leader cluster or * for all databases - DefaultPrincipalsModificationKind = KustoDatabaseDefaultPrincipalsModificationKind.Union, - Location = AzureLocation.NorthCentralUS -}; -// Table level sharing properties are not supported when using '*' all databases notation. -if (attachedDatabaseConfigurationData.DatabaseName != "*") -{ - // Set up the table level sharing properties - the following is just an example. - attachedDatabaseConfigurationData.TableLevelSharingProperties = new KustoDatabaseTableLevelSharingProperties(); - attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToInclude.Add("table1"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToExclude.Add("table2"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToExclude.Add("exTable1"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToInclude.Add("exTable2"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToInclude.Add("matTable1"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToExclude.Add("matTable2"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToInclude.Add("func1"); - attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToExclude.Add("func2"); -} +var followerClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "followerResourceGroup", clusterName: "follower"); +var leaderClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "leaderResourceGroup", clusterName: "leader"); +var attachedDatabaseConfigurationName = "attachedDatabaseConfiguration"; +var credentials = new ManagedIdentityCredential(); +var resourceManagementClient = new ArmClient(credentials); +var followerCluster = resourceManagementClient.GetKustoClusterResource(followerClusterId); +var attachedDatabaseConfigurations = followerCluster.GetKustoAttachedDatabaseConfigurations(); +var attachedDatabaseConfigurationData = new KustoAttachedDatabaseConfigurationData { ClusterResourceId = leaderClusterId, DatabaseName = "", // Can be a specific database name in a leader cluster or * for all databases +DefaultPrincipalsModificationKind = KustoDatabaseDefaultPrincipalsModificationKind.Union, Location = AzureLocation.NorthCentralUS }; // Table level sharing properties are not supported when using '*' all databases notation. +if (attachedDatabaseConfigurationData.DatabaseName != "*") +{ // Set up the table level sharing properties - the following is just an example. +attachedDatabaseConfigurationData.TableLevelSharingProperties = new KustoDatabaseTableLevelSharingProperties(); +attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToInclude.Add("table1"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToExclude.Add("table2"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToExclude.Add("exTable1"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToInclude.Add("exTable2"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToInclude.Add("matTable1"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToExclude.Add("matTable2"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToInclude.Add("func1"); +attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToExclude.Add("func2"); } await attachedDatabaseConfigurations.CreateOrUpdateAsync(WaitUntil.Completed, attachedDatabaseConfigurationName, attachedDatabaseConfigurationData); ``` From 55f3bcbc6a4ee0bb5c96381bf31a4e9d3fb71af4 Mon Sep 17 00:00:00 2001 From: Hodayah Zargari Date: Thu, 11 Dec 2025 12:15:09 +0200 Subject: [PATCH 2/3] formatting code and C# updated code in other sections --- data-explorer/follower.md | 98 ++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 53 deletions(-) diff --git a/data-explorer/follower.md b/data-explorer/follower.md index c96f94923f..687b44d7b6 100644 --- a/data-explorer/follower.md +++ b/data-explorer/follower.md @@ -99,26 +99,37 @@ You can optionally make the database name in the follower cluster different from ### C\# example ```csharp -var followerClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "followerResourceGroup", clusterName: "follower"); -var leaderClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "leaderResourceGroup", clusterName: "leader"); -var attachedDatabaseConfigurationName = "attachedDatabaseConfiguration"; -var credentials = new ManagedIdentityCredential(); -var resourceManagementClient = new ArmClient(credentials); -var followerCluster = resourceManagementClient.GetKustoClusterResource(followerClusterId); -var attachedDatabaseConfigurations = followerCluster.GetKustoAttachedDatabaseConfigurations(); -var attachedDatabaseConfigurationData = new KustoAttachedDatabaseConfigurationData { ClusterResourceId = leaderClusterId, DatabaseName = "", // Can be a specific database name in a leader cluster or * for all databases -DefaultPrincipalsModificationKind = KustoDatabaseDefaultPrincipalsModificationKind.Union, Location = AzureLocation.NorthCentralUS }; // Table level sharing properties are not supported when using '*' all databases notation. -if (attachedDatabaseConfigurationData.DatabaseName != "*") -{ // Set up the table level sharing properties - the following is just an example. -attachedDatabaseConfigurationData.TableLevelSharingProperties = new KustoDatabaseTableLevelSharingProperties(); -attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToInclude.Add("table1"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToExclude.Add("table2"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToExclude.Add("exTable1"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToInclude.Add("exTable2"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToInclude.Add("matTable1"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToExclude.Add("matTable2"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToInclude.Add("func1"); -attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToExclude.Add("func2"); } +var followerClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "followerResourceGroup", clusterName: "follower"); +var leaderClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "leaderResourceGroup", clusterName: "leader"); +var attachedDatabaseConfigurationName = "attachedDatabaseConfiguration"; + +var credentials = new ManagedIdentityCredential(); +var resourceManagementClient = new ArmClient(credentials); +var followerCluster = resourceManagementClient.GetKustoClusterResource(followerClusterId); +var attachedDatabaseConfigurations = followerCluster.GetKustoAttachedDatabaseConfigurations(); +var attachedDatabaseConfigurationData = new KustoAttachedDatabaseConfigurationData +{ + ClusterResourceId = leaderClusterId, + DatabaseName = "", // Can be a specific database name in a leader cluster or * for all databases + DefaultPrincipalsModificationKind = KustoDatabaseDefaultPrincipalsModificationKind.Union, + Location = AzureLocation.NorthCentralUS +}; + +// Table level sharing properties are not supported when using '*' all databases notation. +if (attachedDatabaseConfigurationData.DatabaseName != "*") +{ + // Set up the table level sharing properties - the following is just an example. + attachedDatabaseConfigurationData.TableLevelSharingProperties = new KustoDatabaseTableLevelSharingProperties(); + attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToInclude.Add("table1"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.TablesToExclude.Add("table2"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToExclude.Add("exTable1"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.ExternalTablesToInclude.Add("exTable2"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToInclude.Add("matTable1"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.MaterializedViewsToExclude.Add("matTable2"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToInclude.Add("func1"); + attachedDatabaseConfigurationData.TableLevelSharingProperties.FunctionsToExclude.Add("func2"); +} + await attachedDatabaseConfigurations.CreateOrUpdateAsync(WaitUntil.Completed, attachedDatabaseConfigurationName, attachedDatabaseConfigurationData); ``` @@ -430,20 +441,12 @@ To verify that the database was successfully attached, find your attached databa The follower cluster can detach any attached follower database as follows: ```csharp -var tenantId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Directory (tenant) ID -var clientId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Application ID -var clientSecret = "PlaceholderClientSecret"; //Client Secret -var followerSubscriptionId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; -var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret); -var resourceManagementClient = new ArmClient(credentials, followerSubscriptionId); -var followerResourceGroupName = "testrg"; -//The cluster and database attached database configuration are created as part of the prerequisites -var followerClusterName = "follower"; -var attachedDatabaseConfigurationsName = "attachedDatabaseConfiguration"; -var subscription = await resourceManagementClient.GetDefaultSubscriptionAsync(); -var resourceGroup = (await subscription.GetResourceGroupAsync(followerResourceGroupName)).Value; -var cluster = (await resourceGroup.GetKustoClusterAsync(followerClusterName)).Value; -var attachedDatabaseConfiguration = (await cluster.GetKustoAttachedDatabaseConfigurationAsync(attachedDatabaseConfigurationsName)).Value; +var attachedDatabaseConfigurationId = KustoAttachedDatabaseConfigurationResource.CreateResourceIdentifier( + subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "testrg", clusterName: "follower", + attachedDatabaseConfigurationName: "attachedDatabaseConfiguration"); +var credentials = new ManagedIdentityCredential(); +var resourceManagementClient = new ArmClient(credentials); +var attachedDatabaseConfiguration = resourceManagementClient.GetKustoAttachedDatabaseConfigurationResource(attachedDatabaseConfigurationId); await attachedDatabaseConfiguration.DeleteAsync(WaitUntil.Completed); ``` @@ -452,27 +455,16 @@ await attachedDatabaseConfiguration.DeleteAsync(WaitUntil.Completed); The leader cluster can detach any attached database as follows: ```csharp -var tenantId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Directory (tenant) ID -var clientId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; //Application ID -var clientSecret = "PlaceholderClientSecret"; //Client Secret -var leaderSubscriptionId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; -var credentials = new ClientSecretCredential(tenantId, clientId, clientSecret); -var resourceManagementClient = new ArmClient(credentials, leaderSubscriptionId); -var leaderResourceGroupName = "testrg"; -var leaderClusterName = "leader"; -var subscription = await resourceManagementClient.GetDefaultSubscriptionAsync(); -var resourceGroup = (await subscription.GetResourceGroupAsync(leaderResourceGroupName)).Value; -var cluster = (await resourceGroup.GetKustoClusterAsync(leaderClusterName)).Value; -var followerSubscriptionId = "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx"; -var followerResourceGroupName = "followerResourceGroup"; -//The cluster and attached database configuration that are created as part of the Prerequisites -var followerClusterName = "follower"; -var attachedDatabaseConfigurationsName = "attachedDatabaseConfiguration"; +var leaderClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "testrg", clusterName: "leader"); +var followerClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "followerResourceGroup", clusterName: "follower"); var followerDatabaseDefinition = new KustoFollowerDatabaseDefinition( - clusterResourceId: new ResourceIdentifier($"/subscriptions/{followerSubscriptionId}/resourceGroups/{followerResourceGroupName}/providers/Microsoft.Kusto/Clusters/{followerClusterName}"), - attachedDatabaseConfigurationName: attachedDatabaseConfigurationsName + clusterResourceId: followerClusterId, + attachedDatabaseConfigurationName: (string?)"attachedDatabaseConfiguration" ); -await cluster.DetachFollowerDatabasesAsync(WaitUntil.Completed, followerDatabaseDefinition); +var credentials = new ManagedIdentityCredential(); +var resourceManagementClient = new ArmClient(credentials); +var leaderCluster = resourceManagementClient.GetKustoClusterResource(leaderClusterId); +await leaderCluster.DetachFollowerDatabasesAsync(WaitUntil.Completed, followerDatabaseDefinition); ``` ## [Python](#tab/python) From a196132b09a960f5a653269f858fa5bffbaf6607 Mon Sep 17 00:00:00 2001 From: Hodayah Zargari Date: Thu, 11 Dec 2025 12:18:38 +0200 Subject: [PATCH 3/3] small fix --- data-explorer/follower.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-explorer/follower.md b/data-explorer/follower.md index 687b44d7b6..c1f1e898ef 100644 --- a/data-explorer/follower.md +++ b/data-explorer/follower.md @@ -459,7 +459,7 @@ var leaderClusterId = KustoClusterResource.CreateResourceIdentifier(subscription var followerClusterId = KustoClusterResource.CreateResourceIdentifier(subscriptionId: "xxxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxx", resourceGroupName: "followerResourceGroup", clusterName: "follower"); var followerDatabaseDefinition = new KustoFollowerDatabaseDefinition( clusterResourceId: followerClusterId, - attachedDatabaseConfigurationName: (string?)"attachedDatabaseConfiguration" + attachedDatabaseConfigurationName: "attachedDatabaseConfiguration" ); var credentials = new ManagedIdentityCredential(); var resourceManagementClient = new ArmClient(credentials);