Skip to content

Commit

Permalink
handle multiple templates in case of SQL DB (#2354)
Browse files Browse the repository at this point in the history
* sqldb arm template fix

* test case for next gen gp

---------

Co-authored-by: ROSHAN SAHU <[email protected]>
  • Loading branch information
sahuroshan and ROSHAN SAHU authored Apr 12, 2024
1 parent 5c5ccf6 commit e4c6ee6
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 39 deletions.
4 changes: 2 additions & 2 deletions Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
<PackageReference Update="Microsoft.Azure.Kusto.Data" Version="9.0.4" />
<PackageReference Update="Microsoft.Azure.Kusto.Language" Version="9.0.4" />
<PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.17]" />
<PackageReference Update="Microsoft.SqlServer.Migration.Assessment" Version="1.0.20240321.1" />
<PackageReference Update="Microsoft.SqlServer.Migration.Assessment" Version="1.0.20240410.1" />
<PackageReference Update="Microsoft.SqlServer.Migration.Logins" Version="1.0.20240222.1" />
<PackageReference Update="Microsoft.SqlServer.Management.QueryStoreModel" Version="163.55.1" />
<PackageReference Update="Microsoft.SqlServer.Management.SqlParser" Version="170.9.0" />
<PackageReference Update="Microsoft.SqlServer.Migration.Tde" Version="1.0.0-preview.1.0.20230914.107" />
<PackageReference Update="Microsoft.SqlServer.SqlTargetProvisioning" Version="1.0.20240321.1" />
<PackageReference Update="Microsoft.SqlServer.SqlTargetProvisioning" Version="1.0.20240410.1" />

<!-- Deprecated: TODO Migrate to Azure.Monitor.Query -->
<PackageReference Update="Microsoft.Azure.OperationalInsights" Version="1.0.0" />
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using System.Collections.Generic;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;

namespace Microsoft.SqlTools.Migration.Contracts
{
public class GetArmTemplateRequest
{
public static readonly
RequestType<string, string> Type =
RequestType<string, string>.Create("migration/getarmtemplate");
RequestType<string, List<string>> Type =
RequestType<string, List<string>>.Create("migration/getarmtemplate");
}
}
23 changes: 13 additions & 10 deletions src/Microsoft.SqlTools.Migration/MigrationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -607,21 +607,24 @@ internal async Task HandleEstablishUserMapping(
/// </summary>
internal async Task HandleGetArmTemplateRequest(
string skuRecommendationReportFilePath,
RequestContext<string> requestContext)
RequestContext<List<string>> requestContext)
{
try
{
ProvisioningScriptServiceProvider provider = new ProvisioningScriptServiceProvider();
List<SkuRecommendationResult> recommendations = ExtractSkuRecommendationReportAction.ExtractSkuRecommendationsFromReport(skuRecommendationReportFilePath);
SqlArmTemplate template = provider.GenerateProvisioningScript(recommendations);

string jsonOutput = JsonConvert.SerializeObject(
template,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Culture = CultureInfo.InvariantCulture }
);

await requestContext.SendResult(jsonOutput);
List<SqlArmTemplate> templateList = provider.GenerateProvisioningScript(recommendations);
List<string> armTemplates = new List<string>();
foreach (SqlArmTemplate template in templateList)
{
string jsonOutput = JsonConvert.SerializeObject(
template,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Culture = CultureInfo.InvariantCulture }
);
armTemplates.Add(jsonOutput);
}
await requestContext.SendResult(armTemplates);
}
catch (Exception e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
using Assert_ = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;
using Microsoft.SqlServer.Migration.SkuRecommendation.TargetProvisioning.Contracts;
using Microsoft.SqlServer.Migration.TargetProvisioning;
using Microsoft.SqlServer.Migration.SqlTargetProvisioning.Constants;


namespace Microsoft.SqlTools.Migration.IntegrationTests.Migration
{
Expand Down Expand Up @@ -163,13 +165,59 @@ public void GenerateProvisioningScript_DatabaseRecommendation_ReturnsDBArmTempla
var result = provisioningScriptserviceProvider.GenerateProvisioningScript(recs);

// Assert
Assert_.IsInstanceOfType(result, typeof(SqlArmTemplate));
Assert.AreEqual(result.resources.Count, 2);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Sql/servers").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Sql/servers/databases").Count(), 1);
Assert.AreEqual(result.parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result.parameters.Where(par => par.Key == "Collation for database testdb").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result.parameters.Count, 9);
Assert_.IsInstanceOfType(result[0], typeof(SqlArmTemplate));
Assert.AreEqual(result[0].resources.Count, 2);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Sql/servers").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Sql/servers/databases").Count(), 1);
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Collation for database testdb").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Count, 9);
}

[Test]
public void GenerateProvisioningScript_DatabaseRecommendationLargeNumber_ReturnsDBArmTemplateList()
{
// Arrange
List<SkuRecommendationResult> recs = new List<SkuRecommendationResult>();
for (int i = 0; i < 125; i++)
{
var rec = new SkuRecommendationResult
{
SqlInstanceName = "TestServer",
DatabaseName = "TestDb" + i,
ServerCollation = serverLevelCollation,
DatabaseCollation = databaseLevelCollations["TestDb"],
TargetSku = new AzureSqlPaaSSku(
new AzureSqlSkuPaaSCategory(
AzureSqlTargetPlatform.AzureSqlDatabase,
AzureSqlPurchasingModel.vCore,
AzureSqlPaaSServiceTier.GeneralPurpose,
ComputeTier.Provisioned,
AzureSqlPaaSHardwareType.Gen5),
2,
i)
{
}
};

recs.Add(rec);
}

// Act
var result = provisioningScriptserviceProvider.GenerateProvisioningScript(recs);

// Assert
Assert_.AreEqual(result.Count, 1 + recs.Count / ArmConstants.AzureSqlDbProvisioningBatchSize);
foreach (var res in result)
{
Assert_.IsInstanceOfType(res, typeof(SqlArmTemplate));
Assert.IsTrue(res.resources.Count <= 51);
Assert.AreEqual(res.resources.Where(res => res.type == "Microsoft.Sql/servers").Count(), 1);
Assert.IsTrue(res.resources.Where(res => res.type == "Microsoft.Sql/servers/databases").Count() <= 50);
Assert.AreEqual(res.parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(res.parameters.Where(par => par.Key.StartsWith("Collation for database testdb")).FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.IsTrue(res.parameters.Count <= 256);
}
}

[Test]
Expand Down Expand Up @@ -200,14 +248,14 @@ public void GenerateProvisioningScript_ManagedInstanceRecommendation_ReturnsMIAr
var result = provisioningScriptserviceProvider.GenerateProvisioningScript(recs);

// Assert
Assert_.IsInstanceOfType(result, typeof(SqlArmTemplate));
Assert.AreEqual(result.resources.Count, 4);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/networkSecurityGroups").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/routeTables").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/virtualNetworks").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Sql/managedInstances").Count(), 1);
Assert.AreEqual(result.parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result.parameters.Count, 11);
Assert_.IsInstanceOfType(result[0], typeof(SqlArmTemplate));
Assert.AreEqual(result[0].resources.Count, 4);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/networkSecurityGroups").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/routeTables").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/virtualNetworks").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Sql/managedInstances").Count(), 1);
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Count, 11);
}

[Test]
Expand Down Expand Up @@ -268,16 +316,16 @@ public void GenerateProvisioningScript_VirtualMachineRecommendation_ReturnsVMArm
var result = provisioningScriptserviceProvider.GenerateProvisioningScript(recs);

// Assert
Assert_.IsInstanceOfType(result, typeof(SqlArmTemplate));
Assert.AreEqual(result.resources.Count, 6);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/networkSecurityGroups").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.SqlVirtualMachine/SqlVirtualMachines").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/virtualNetworks").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Compute/virtualMachines").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/publicIpAddresses").Count(), 1);
Assert.AreEqual(result.resources.Where(res => res.type == "Microsoft.Network/networkInterfaces").Count(), 1);
Assert.AreEqual(result.parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result.parameters.Count, 14);
Assert_.IsInstanceOfType(result[0], typeof(SqlArmTemplate));
Assert.AreEqual(result[0].resources.Count, 7);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/networkSecurityGroups").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.SqlVirtualMachine/SqlVirtualMachines").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/virtualNetworks").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Compute/virtualMachines").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/publicIpAddresses").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/networkInterfaces").Count(), 1);
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Count, 21);
// Add additional assertions based on the expected outcome for the virtual machine case
}

Expand Down Expand Up @@ -309,6 +357,48 @@ public void GenerateProvisioningScript_InvalidTargetPlatform_ThrowsArgumentExcep
Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsException<ArgumentException>(() => provisioningScriptserviceProvider.GenerateProvisioningScript(recs));
}

[Test]
public void GenerateProvisioningScript_ManagedInstanceRecommendation_NextGenGP_ReturnsMIArmTemplate()
{
// Arrange
var recs = new List<SkuRecommendationResult>
{
new SkuRecommendationResult
{
SqlInstanceName = "TestServer",
ServerCollation = serverLevelCollation,
TargetSku = new AzureSqlPaaSSku(
new AzureSqlSkuPaaSCategory(
AzureSqlTargetPlatform.AzureSqlManagedInstance,
AzureSqlPurchasingModel.vCore,
AzureSqlPaaSServiceTier.NextGenGeneralPurpose,
ComputeTier.Provisioned,
AzureSqlPaaSHardwareType.Gen5),
4,
32,
maxStorageIops: 300)
{
}
}
};

// Act
var result = provisioningScriptserviceProvider.GenerateProvisioningScript(recs);

// Assert
Assert_.IsInstanceOfType(result[0], typeof(SqlArmTemplate));
Assert.AreEqual(result[0].resources.Count, 4);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/networkSecurityGroups").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/routeTables").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Network/virtualNetworks").Count(), 1);
Assert.AreEqual(result[0].resources.Where(res => res.type == "Microsoft.Sql/managedInstances").Count(), 1);
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Where(par => par.Key == "Server collation").FirstOrDefault().Value.defaultValue, "Latin1_General_CI_AI");
Assert.AreEqual(result[0].parameters.Count, 12);
int maxStorageIOPS = result[0].parameters.Where(par => par.Key == "Max storage IOPS").Select(par => Convert.ToInt32(par.Value.defaultValue)).FirstOrDefault();
Assert.AreEqual(maxStorageIOPS, 300);
}


}
}

0 comments on commit e4c6ee6

Please sign in to comment.