From 2f0a63a75a3adbae6a1def6cf80b975f65d8e8dc Mon Sep 17 00:00:00 2001 From: f-alizada <104755925+f-alizada@users.noreply.github.com> Date: Tue, 28 Feb 2023 12:33:42 +0100 Subject: [PATCH] Determine the sku for groups extraction (#870) Co-authored-by: Farhad Alizada --- .../Commands/Executors/ExtractorExecutor.cs | 11 +++- .../EntityExtractors/GroupExtractor.cs | 6 ++ .../EntityExtractors/ProductExtractor.cs | 7 +- .../Extractor/Models/ExtractorParameters.cs | 7 ++ .../Extractor/Models/SKUValues.cs | 30 +++++++++ .../Scenarios/GroupExtractorTests.cs | 28 ++++++++ .../Scenarios/ProductsExtractorTests.cs | 64 ++++++++++++++++++- 7 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 src/ArmTemplates/Extractor/Models/SKUValues.cs diff --git a/src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs b/src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs index 14ee07d3..a9321673 100644 --- a/src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs +++ b/src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs @@ -878,6 +878,13 @@ public async Task> GenerateApiManagement if (apiManagementServiceTemplate?.HasResources() == true) { + + var typedService = apiManagementServiceTemplate.TypedResources.ApiManagementServices.FirstOrDefault(); + if (typedService.Sku is not null) + { + this.extractorParameters.SetSkuType(typedService.Sku.Name); + } + await FileWriter.SaveAsJsonAsync( apiManagementServiceTemplate, directory: baseFilesGenerationDirectory, @@ -1156,6 +1163,9 @@ async Task GenerateTemplates( { throw new SingleAndMultipleApisCanNotExistTogetherException("Can't specify single API and multiple APIs to extract at the same time"); } + + // Fetch ApiManagement Service instance template + await this.GenerateApiManagementServiceTemplate(baseFilesGenerationDirectory); var apisToExtract = await this.GetApiNamesToExtract(singleApiName, multipleApiNames); // generate different templates using extractors and write to output @@ -1179,7 +1189,6 @@ async Task GenerateTemplates( var apiReleasesTemplate = await this.GenerateApiReleasesTemplateAsync(baseFilesGenerationDirectory); await this.GenerateGatewayTemplateAsync(singleApiName, baseFilesGenerationDirectory); await this.GenerateGatewayApiTemplateAsync(singleApiName, multipleApiNames, baseFilesGenerationDirectory); - await this.GenerateApiManagementServiceTemplate(baseFilesGenerationDirectory); var parametersTemplate = await this.GenerateParametersTemplateAsync(apisToExtract, loggerTemplate.TypedResources, backendTemplate.TypedResources, namedValueTemplate.TypedResources, identityProviderTemplate.TypedResources, openIdConnectProviderTemplate.TypedResources, baseFilesGenerationDirectory); diff --git a/src/ArmTemplates/Extractor/EntityExtractors/GroupExtractor.cs b/src/ArmTemplates/Extractor/EntityExtractors/GroupExtractor.cs index f31535f9..3873bf39 100644 --- a/src/ArmTemplates/Extractor/EntityExtractors/GroupExtractor.cs +++ b/src/ArmTemplates/Extractor/EntityExtractors/GroupExtractor.cs @@ -40,6 +40,12 @@ public async Task> GenerateGroupsTemplateAsync( .GenerateTemplateWithApimServiceNameProperty() .Build(); + if (SKUTypes.IsConsumption(extractorParameters.CurrentSKU)) + { + this.logger.LogInformation("Skipping generation of groups template for consumption sku..."); + return groupsTemplate; + } + var allGroups = await this.groupsClient.GetAllAsync(extractorParameters); if (allGroups.IsNullOrEmpty()) { diff --git a/src/ArmTemplates/Extractor/EntityExtractors/ProductExtractor.cs b/src/ArmTemplates/Extractor/EntityExtractors/ProductExtractor.cs index c86e4bf5..814998a3 100644 --- a/src/ArmTemplates/Extractor/EntityExtractors/ProductExtractor.cs +++ b/src/ArmTemplates/Extractor/EntityExtractors/ProductExtractor.cs @@ -159,6 +159,12 @@ async Task AddGroupsLinkedToProductResources( { var productResourceId = new string[] { $"[resourceId('Microsoft.ApiManagement/service/products', parameters('{ParameterNames.ApimServiceName}'), '{productTemplateResource.NewName}')]" }; + if (SKUTypes.IsConsumption(extractorParameters.CurrentSKU)) + { + this.logger.LogInformation("Skipping generation of groups resources attached to groups for consumption sku..."); + return ; + } + try { var groupsLinkedToProduct = await this.groupsClient.GetAllLinkedToProductAsync(productTemplateResource.OriginalName, extractorParameters); @@ -178,6 +184,5 @@ async Task AddGroupsLinkedToProductResources( throw; } } - } } diff --git a/src/ArmTemplates/Extractor/Models/ExtractorParameters.cs b/src/ArmTemplates/Extractor/Models/ExtractorParameters.cs index 9d077a8f..e9cef119 100644 --- a/src/ArmTemplates/Extractor/Models/ExtractorParameters.cs +++ b/src/ArmTemplates/Extractor/Models/ExtractorParameters.cs @@ -96,6 +96,13 @@ public record ExtractorParameters public Dictionary ApiParameters { get; private set; } + public string CurrentSKU { get; private set; } + + public void SetSkuType(string sku) + { + this.CurrentSKU = sku; + } + public ExtractorParameters(ExtractorConsoleAppConfiguration extractorConfig) { this.SourceApimName = extractorConfig.SourceApimName; diff --git a/src/ArmTemplates/Extractor/Models/SKUValues.cs b/src/ArmTemplates/Extractor/Models/SKUValues.cs new file mode 100644 index 00000000..109944b8 --- /dev/null +++ b/src/ArmTemplates/Extractor/Models/SKUValues.cs @@ -0,0 +1,30 @@ +// -------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// -------------------------------------------------------------------------- + + +using System; + +namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models +{ + public class SKUTypes + { + public const string Basic = "Basic"; + public const string Consumption = "Consumption"; + public const string Developer = "Developer"; + public const string Isolated = "Isolated"; + public const string Premium = "Premium"; + public const string Standard = "Standard"; + + public static bool IsConsumption(string skuValue) + { + if (string.IsNullOrEmpty(skuValue)) + { + return false; + } + + return skuValue.Equals(Consumption, StringComparison.CurrentCultureIgnoreCase); + } + } +} diff --git a/tests/ArmTemplates.Tests/Extractor/Scenarios/GroupExtractorTests.cs b/tests/ArmTemplates.Tests/Extractor/Scenarios/GroupExtractorTests.cs index 1acec541..cba5ad7d 100644 --- a/tests/ArmTemplates.Tests/Extractor/Scenarios/GroupExtractorTests.cs +++ b/tests/ArmTemplates.Tests/Extractor/Scenarios/GroupExtractorTests.cs @@ -94,5 +94,33 @@ public async Task GenerateGroupsTemplates_ProperlyParsesResponse() groupTemplate.TypedResources.Groups.Count().Should().Be(4); groupTemplate.TypedResources.Groups.First(x => x.Properties.DisplayName.Equals("AwesomeGroup for test")).Should().NotBeNull(); } + + [Fact] + public async Task GenerateGroupsTemplates_ForConsumptionSku_ShouldNotReturnAnyGroup() + { + // arrange + var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(GenerateGroupsTemplates_ForConsumptionSku_ShouldNotReturnAnyGroup)); + + var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration(); + var extractorParameters = new ExtractorParameters(extractorConfig); + extractorParameters.SetSkuType(SKUTypes.Consumption); + var fileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListGroups_success_response.json"); + var mockedGroupsClient = await MockGroupsClient.GetMockedHttpGroupClient(new MockClientConfiguration(responseFileLocation: fileLocation)); + var groupExtractor = new GroupExtractor(this.GetTestLogger(), new TemplateBuilder(), mockedGroupsClient); + + var extractorExecutor = ExtractorExecutor.BuildExtractorExecutor( + this.GetTestLogger(), + groupExtractor: groupExtractor); + extractorExecutor.SetExtractorParameters(extractorParameters); + + // act + var groupTemplate = await extractorExecutor.GenerateGroupsTemplateAsync(currentTestDirectory); + + // assert + File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.Groups)).Should().BeFalse(); + + groupTemplate.Parameters.Should().ContainKey(ParameterNames.ApimServiceName); + groupTemplate.TypedResources.Groups.Count().Should().Be(0); + } } } diff --git a/tests/ArmTemplates.Tests/Extractor/Scenarios/ProductsExtractorTests.cs b/tests/ArmTemplates.Tests/Extractor/Scenarios/ProductsExtractorTests.cs index e2e7bda9..ac25b389 100644 --- a/tests/ArmTemplates.Tests/Extractor/Scenarios/ProductsExtractorTests.cs +++ b/tests/ArmTemplates.Tests/Extractor/Scenarios/ProductsExtractorTests.cs @@ -175,7 +175,7 @@ public async Task GenerateProductsTemplates_GeneratesTemplatesCorrectly_GivenApi ); //default values - var mockedGroupsClient = MockGroupsClient.GetMockedApiClientWithEmptyValues(); + var mockedGroupsClient = MockGroupsClient.GetMockedApiClientWithDefaultValues(); var mockedTagClient = MockTagClient.GetMockedApiClientWithEmptytValues(); var mockedPolicyClient = MockPolicyClient.GetMockedApiClientWithEmptyValues(); @@ -212,6 +212,68 @@ public async Task GenerateProductsTemplates_GeneratesTemplatesCorrectly_GivenApi productResources.Count.Should().Be(2); productResources.Any(x => x.OriginalName == "unlimited").Should().BeTrue(); productResources.Any(x => x.OriginalName == "starter").Should().BeTrue(); + + var attachedGroups = templateResources.Where(x => x.Type == ResourceTypeConstants.ProductGroup).ToList(); + attachedGroups.Count.Should().Be(4); + } + + [Fact] + public async Task GenerateProductsTemplates_GeneratesTemplatesCorrectly_GivenConsumptionSku() + { + // arrange + var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(GenerateProductsTemplates_GeneratesTemplatesCorrectly_GivenConsumptionSku)); + var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration( + apiName: null + ); + var extractorParameters = new ExtractorParameters(extractorConfig); + extractorParameters.SetSkuType(SKUTypes.Consumption); + + var getAlldProductsResponseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListProducts_success_response.json"); + var mockedProductsClient = await MockProductsClient.GetMockedHttpProductClient( + new MockClientConfiguration(responseFileLocation: getAlldProductsResponseFileLocation, urlPath: $"{MockSourceApimName}/products?api-version={GlobalConstants.ApiVersion}") + ); + + //default values + var mockedGroupsClient = MockGroupsClient.GetMockedApiClientWithDefaultValues(); + var mockedTagClient = MockTagClient.GetMockedApiClientWithEmptytValues(); + + var mockedPolicyClient = MockPolicyClient.GetMockedApiClientWithEmptyValues(); + var mockedPolicyExtractor = new PolicyExtractor(this.GetTestLogger(), mockedPolicyClient, new TemplateBuilder()); + + var productExtractor = new ProductExtractor( + this.GetTestLogger(), + mockedPolicyExtractor, + mockedProductsClient, + mockedGroupsClient, + mockedTagClient, + new TemplateBuilder()); + + var extractorExecutor = ExtractorExecutor.BuildExtractorExecutor( + this.GetTestLogger(), + productExtractor: productExtractor); + extractorExecutor.SetExtractorParameters(extractorParameters); + + // act + var productTemplate = await extractorExecutor.GenerateProductsTemplateAsync( + singleApiName: null, + currentTestDirectory); + + // assert + // generated product template files + File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.Products)).Should().BeTrue(); + + var templateParameters = productTemplate.Parameters; + templateParameters.Should().ContainKey(ParameterNames.ApimServiceName); + + var templateResources = productTemplate.Resources; + // product resource + var productResources = templateResources.Where(x => x.Type == ResourceTypeConstants.Product).ToList(); + productResources.Count.Should().Be(2); + productResources.Any(x => x.OriginalName == "unlimited").Should().BeTrue(); + productResources.Any(x => x.OriginalName == "starter").Should().BeTrue(); + + var attachedGroups = templateResources.Where(x => x.Type == ResourceTypeConstants.ProductGroup).ToList(); + attachedGroups.Count.Should().Be(0); } } }