Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

fix: Extractor/exclude product api from apis template #856

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,12 @@ public async Task<Template<GroupTemplateResources>> GenerateGroupsTemplateAsync(
/// <returns>generated products template</returns>
public async Task<Template<ProductTemplateResources>> GenerateProductsTemplateAsync(
string singleApiName,
string baseFilesGenerationDirectory,
List<ProductApiTemplateResource> productApiResources)
string baseFilesGenerationDirectory)
{
this.logger.LogInformation("Started generation of products template...");

var productTemplate = await this.productExtractor.GenerateProductsTemplateAsync(
singleApiName, productApiResources, baseFilesGenerationDirectory, this.extractorParameters);
singleApiName, baseFilesGenerationDirectory, this.extractorParameters);

if (productTemplate?.HasResources() == true)
{
Expand Down Expand Up @@ -1164,7 +1163,7 @@ await foreach (var apiRevision in this.apiRevisionExtractor.GetApiRevisionsAsync

var globalServicePolicyTemplate = await this.GeneratePolicyTemplateAsync(baseFilesGenerationDirectory);
var productApiTemplate = await this.GenerateProductApisTemplateAsync(singleApiName, multipleApiNames, baseFilesGenerationDirectory);
var productTemplate = await this.GenerateProductsTemplateAsync(singleApiName, baseFilesGenerationDirectory, apiTemplate.TypedResources.ApiProducts);
var productTemplate = await this.GenerateProductsTemplateAsync(singleApiName, baseFilesGenerationDirectory);
var apiVersionSetTemplate = await this.GenerateApiVersionSetTemplateAsync(singleApiName, baseFilesGenerationDirectory, apiTemplate.TypedResources.Apis);
var authorizationServerTemplate = await this.GenerateAuthorizationServerTemplateAsync(singleApiName, baseFilesGenerationDirectory, apiTemplate.TypedResources.Apis);
var tagTemplate = await this.GenerateTagTemplateAsync(singleApiName, apiTemplate.TypedResources, productTemplate.TypedResources, baseFilesGenerationDirectory);
Expand Down
6 changes: 0 additions & 6 deletions src/ArmTemplates/Extractor/EntityExtractors/APIExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,6 @@ public async Task<ApiTemplateResources> GetApiRelatedTemplateResourcesAsync(stri
apiTemplateResources.ApiPolicies.Add(apiPolicyResource);
}

var apiProducts = await this.productApisExtractor.GenerateSingleApiTemplateAsync(apiName, extractorParameters, addDependsOnParameter: true);
if (!apiProducts.IsNullOrEmpty())
{
apiTemplateResources.ApiProducts = apiProducts;
}

var apiTags = await this.tagExtractor.GenerateTagResourcesLinkedToApiAsync(apiName, extractorParameters);
if (!apiTags.IsNullOrEmpty())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,5 @@ public interface IProductApisExtractor
string singleApiName,
List<string> multipleApiNames,
ExtractorParameters extractorParameters);

Task<List<ProductApiTemplateResource>> GenerateSingleApiTemplateAsync(
string singleApiName,
ExtractorParameters extractorParameters,
bool addDependsOnParameter = false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public interface IProductExtractor
{
Task<Template<ProductTemplateResources>> GenerateProductsTemplateAsync(
string singleApiName,
List<ProductApiTemplateResource> productApiTemplateResources,
string baseFilesGenerationDirectory,
ExtractorParameters extractorParameters);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public class MasterTemplateExtractor : IMasterTemplateExtractor
// api dependsOn
var apiDependsOn = new List<string>();
var productApiDependsOn = new List<string>();
var productsDependsOn = new List<string>();
var apiTagDependsOn = new List<string>();
var globalPolicyDependsOn = new List<string>();

Expand All @@ -86,6 +87,7 @@ public class MasterTemplateExtractor : IMasterTemplateExtractor
const string NamedValuesTemplateName = "namedValuesTemplate";

dependsOnNamedValues = new string[] { $"[resourceId('{ResourceTypeConstants.ArmDeployments}', '{NamedValuesTemplateName}')]" };
productsDependsOn.AddRange(dependsOnNamedValues);
globalPolicyDependsOn.AddRange(dependsOnNamedValues);
apiDependsOn.Add($"[resourceId('{ResourceTypeConstants.ArmDeployments}', '{NamedValuesTemplateName}')]");
var namedValuesUri = this.GenerateLinkedTemplateUri(fileNames.NamedValues, extractorParameters);
Expand Down Expand Up @@ -139,16 +141,27 @@ public class MasterTemplateExtractor : IMasterTemplateExtractor
masterResources.DeploymentResources.Add(apiVersionSetDeployment);
}

if (groupTemplateResources?.HasContent() == true)
{
this.logger.LogDebug("Adding groups to master template");
const string GroupsTemplate = "groupsTemplate";
productsDependsOn.Add($"[resourceId('{ResourceTypeConstants.ArmDeployments}', '{GroupsTemplate}')]");

var groupsUri = this.GenerateLinkedTemplateUri(fileNames.Groups, extractorParameters);
var groupsDeployment = CreateLinkedMasterTemplateResource(GroupsTemplate, groupsUri, Array.Empty<string>());

masterResources.DeploymentResources.Add(groupsDeployment);
}

if (productsTemplateResources?.HasContent() == true)
{
this.logger.LogDebug("Adding products to master template");
const string ProductsTemplate = "productsTemplate";

apiDependsOn.Add($"[resourceId('{ResourceTypeConstants.ArmDeployments}', '{ProductsTemplate}')]");
productApiDependsOn.Add($"[resourceId('{ResourceTypeConstants.ArmDeployments}', '{ProductsTemplate}')]");
var productsUri = this.GenerateLinkedTemplateUri(fileNames.Products, extractorParameters);

var productDeployment = CreateLinkedMasterTemplateResource(ProductsTemplate, productsUri, dependsOnNamedValues);
var productDeployment = CreateLinkedMasterTemplateResource(ProductsTemplate, productsUri, productsDependsOn.ToArray());

if (extractorParameters.PolicyXMLBaseUrl is not null)
{
Expand Down Expand Up @@ -269,17 +282,6 @@ public class MasterTemplateExtractor : IMasterTemplateExtractor
masterResources.DeploymentResources.Add(apiTagsDeployment);
}

if (groupTemplateResources?.HasContent() == true)
{
this.logger.LogDebug("Adding groups to master template");
const string GroupsTemplate = "groupsTemplate";

var groupsUri = this.GenerateLinkedTemplateUri(fileNames.Groups, extractorParameters);
var groupsDeployment = CreateLinkedMasterTemplateResource(GroupsTemplate, groupsUri, Array.Empty<string>());

masterResources.DeploymentResources.Add(groupsDeployment);
}

if (identityProviderTemplateResources?.HasContent() == true)
{
this.logger.LogDebug("Adding identity providers to master template");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ async Task<List<ProductApiTemplateResource>> GenerateMultipleApisTemplateAsync(L
}

productApiResources.Add(productApi);

}
}
catch (Exception ex)
Expand Down
13 changes: 9 additions & 4 deletions src/ArmTemplates/Extractor/EntityExtractors/ProductExtractor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public class ProductExtractor : IProductExtractor

public async Task<Template<ProductTemplateResources>> GenerateProductsTemplateAsync(
string singleApiName,
List<ProductApiTemplateResource> productApiTemplateResources,
string baseFilesGenerationDirectory,
ExtractorParameters extractorParameters)
{
Expand All @@ -61,15 +60,21 @@ public class ProductExtractor : IProductExtractor
.AddPolicyProperties(extractorParameters)
.Build<ProductTemplateResources>();

var products = await this.productsClient.GetAllAsync(extractorParameters);
var allProducts = await this.productsClient.GetAllAsync(extractorParameters);

foreach (var productTemplateResource in products)
List<ProductApiTemplateResource> apiProducts = new List<ProductApiTemplateResource>();
if (!singleApiName.IsNullOrEmpty())
{
apiProducts = await this.productsClient.GetAllLinkedToApiAsync(singleApiName, extractorParameters);
}

foreach (var productTemplateResource in allProducts)
{
productTemplateResource.Name = $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{productTemplateResource.NewName}')]";
productTemplateResource.ApiVersion = GlobalConstants.ApiVersion;

// only extract the product if this is a full extraction, or in the case of a single api, if it is found in products associated with the api
if (singleApiName == null || productApiTemplateResources.Any(p => p.Name.Contains($"/{productTemplateResource.NewName}/")))
if (singleApiName == null || apiProducts.Any(p => p.Name.Equals(productTemplateResource.NewName)))
{
this.logger.LogDebug("'{0}' product found", productTemplateResource.OriginalName);
productsTemplate.TypedResources.Products.Add(productTemplateResource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public async Task GenerateAPIVersionSetTemplates_GeneratesApiTemplates()

var mockedProductExtractor = new Mock<IProductExtractor>(MockBehavior.Strict);
mockedProductExtractor
.Setup(x => x.GenerateProductsTemplateAsync(It.IsAny<string>(), It.IsAny<List<ProductApiTemplateResource>>(), It.IsAny<string>(), It.IsAny<ExtractorParameters>()))
.Setup(x => x.GenerateProductsTemplateAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<ExtractorParameters>()))
.ReturnsAsync(new Template<ProductTemplateResources>()
{
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public async Task GenerateApiTemplates_ProperlyLaysTheInformation()
apiTemplate.Parameters.Should().ContainKey(ParameterNames.ApiLoggerId);
apiTemplate.Parameters.Should().ContainKey(ParameterNames.PolicyXMLBaseUrl);
apiTemplate.Parameters.Should().ContainKey(ParameterNames.PolicyXMLSasToken);
apiTemplate.Resources.Count().Should().Be(33);
apiTemplate.Resources.Count().Should().Be(30);

// apis
apiTemplate.TypedResources.Apis.Count().Should().Be(3);
Expand All @@ -133,11 +133,6 @@ public async Task GenerateApiTemplates_ProperlyLaysTheInformation()
apiTemplate.TypedResources.Tags.Count().Should().Be(6);
apiTemplate.TypedResources.Tags.All(x => x.Type == ResourceTypeConstants.APITag).Should().BeTrue();

// api products
apiTemplate.TypedResources.ApiProducts.Count().Should().Be(3);
apiTemplate.TypedResources.ApiProducts.All(x => x.Type == ResourceTypeConstants.ProductApi).Should().BeTrue();
apiTemplate.TypedResources.ApiProducts.All(x => x.Properties is not null).Should().BeTrue();

// api policies
apiTemplate.TypedResources.ApiPolicies.Count().Should().Be(3);
apiTemplate.TypedResources.ApiPolicies.All(x => x.Properties is not null).Should().BeTrue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Commands.Executors;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Utils;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Constants;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Builders;
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.EntityExtractors;
Expand Down Expand Up @@ -77,5 +78,115 @@ public async Task GenerateProductApisTemplates_ProperlyLaysTheInformation()
productApi.DependsOn.Should().BeNullOrEmpty();
}
}

[Fact]
public async Task GenerateProductApisTemplates_GeneratesAllRelatedProductApis_GivenApiNameParameterProvided()
{
// arrange
var apiName = "api-name";
var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(GenerateProductApisTemplates_GeneratesAllRelatedProductApis_GivenApiNameParameterProvided));

var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration(apiName: apiName);
var extractorParameters = new ExtractorParameters(extractorConfig);

var getSingleApiResponseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementGetApiContract_success_response.json");
var getRelatedProductsResponseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListApiProducts_success_response.json");
var mockedApisClient = await MockApisClient.GetMockedHttpApiClient(
new MockClientConfiguration(responseFileLocation: getSingleApiResponseFileLocation, urlPath: $"apis/{apiName}?api-version={GlobalConstants.ApiVersion}"));
var mockedApiClientUtils = new ApiClientUtils(mockedApisClient, this.GetTestLogger<ApiClientUtils>());

var mockedServiceApisProductsApiClient = await MockProductsClient.GetMockedHttpProductClient(
new MockClientConfiguration(responseFileLocation: getRelatedProductsResponseFileLocation)
);

var productApisExtractor = new ProductApisExtractor(
this.GetTestLogger<ProductApisExtractor>(),
mockedServiceApisProductsApiClient,
mockedApisClient,
new TemplateBuilder());

var extractorExecutor = ExtractorExecutor.BuildExtractorExecutor(
this.GetTestLogger<ExtractorExecutor>(),
productApisExtractor: productApisExtractor);
extractorExecutor.SetExtractorParameters(extractorParameters);

// act
var productApisTemplate = await extractorExecutor.GenerateProductApisTemplateAsync(
singleApiName: apiName,
multipleApiNames: It.IsAny<List<string>>(),
currentTestDirectory);

// assert
File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.ProductAPIs)).Should().BeTrue();

productApisTemplate.Parameters.Should().ContainKey(ParameterNames.ApimServiceName);
productApisTemplate.TypedResources.ProductApis.Count().Should().Be(1);
productApisTemplate.Resources.Count().Should().Be(1);

foreach (var productApi in productApisTemplate.TypedResources.ProductApis)
{
productApi.ApiVersion.Should().Be(GlobalConstants.ApiVersion);
productApi.Name.Should().NotBeNullOrEmpty();
productApi.Name.Contains($"/{apiName}").Should().BeTrue();
productApi.Type.Should().Be(ResourceTypeConstants.ProductApi);
productApi.Properties.DisplayName.Should().NotBeNullOrEmpty();
productApi.Properties.Description.Should().NotBeNullOrEmpty();
productApi.DependsOn.Should().BeNullOrEmpty();
}
}

[Fact]
public async Task GenerateProductApisTemplates_GeneratesAllRelatedProductApis_GivenAllApisAreExtracted()
{
// arrange
var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(GenerateProductApisTemplates_GeneratesAllRelatedProductApis_GivenAllApisAreExtracted));

var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration(apiName: string.Empty);
var extractorParameters = new ExtractorParameters(extractorConfig);

var getAllApisResponseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListApis_success_response.json");
var getRelatedProductsResponseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListApiProducts_success_response.json");
var mockedApisClient = await MockApisClient.GetMockedHttpApiClient(
new MockClientConfiguration(responseFileLocation: getAllApisResponseFileLocation));
var mockedApiClientUtils = new ApiClientUtils(mockedApisClient, this.GetTestLogger<ApiClientUtils>());

var mockedServiceApisProductsApiClient = await MockProductsClient.GetMockedHttpProductClient(
new MockClientConfiguration(responseFileLocation: getRelatedProductsResponseFileLocation)
);

var productApisExtractor = new ProductApisExtractor(
this.GetTestLogger<ProductApisExtractor>(),
mockedServiceApisProductsApiClient,
mockedApisClient,
new TemplateBuilder());

var extractorExecutor = ExtractorExecutor.BuildExtractorExecutor(
this.GetTestLogger<ExtractorExecutor>(),
productApisExtractor: productApisExtractor);
extractorExecutor.SetExtractorParameters(extractorParameters);

// act
var productApisTemplate = await extractorExecutor.GenerateProductApisTemplateAsync(
singleApiName: null,
multipleApiNames: It.IsAny<List<string>>(),
currentTestDirectory);

// assert
File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.ProductAPIs)).Should().BeTrue();

productApisTemplate.Parameters.Should().ContainKey(ParameterNames.ApimServiceName);
productApisTemplate.TypedResources.ProductApis.Count().Should().Be(4);
productApisTemplate.Resources.Count().Should().Be(4);

foreach (var productApi in productApisTemplate.TypedResources.ProductApis)
{
productApi.ApiVersion.Should().Be(GlobalConstants.ApiVersion);
productApi.Name.Should().NotBeNullOrEmpty();
productApi.Type.Should().Be(ResourceTypeConstants.ProductApi);
productApi.Properties.DisplayName.Should().NotBeNullOrEmpty();
productApi.Properties.Description.Should().NotBeNullOrEmpty();
productApi.DependsOn.Should().BeNullOrEmpty();
}
}
}
}
Loading