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

Commit aa944d4

Browse files
authored
implement gatewayExtractor and gatewayApiExtractor (#651)
* implement gatewayExtractor and gatewayApiExtrarctor * review fix Co-authored-by: Dmitrii Korolev <dmkorolev@microsoft.com>
1 parent 69eafc7 commit aa944d4

31 files changed

+873
-9
lines changed

src/ArmTemplates/Commands/Configurations/ExtractorConsoleAppConfiguration.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,8 @@ public class ExtractorConsoleAppConfiguration
8484

8585
[Option(longName: "paramBackend", HelpText = "Parameterize environment specific values from backend")]
8686
public string ParamBackend { get; set; }
87+
88+
[Option(longName: "extractGateways", HelpText = "Attempt to extract information about Self-Hosted gateways")]
89+
public string ExtractGateways { get; set; }
8790
}
8891
}

src/ArmTemplates/Commands/Executors/ExtractorExecutor.cs

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Apis;
99
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.ApiVersionSet;
1010
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.AuthorizationServer;
11+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Gateway;
12+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.GatewayApi;
1113
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Groups;
1214
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Logger;
1315
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Policy;
@@ -48,6 +50,8 @@ public class ExtractorExecutor
4850
readonly ITagExtractor tagExtractor;
4951
readonly IGroupExtractor groupExtractor;
5052
readonly IApiRevisionExtractor apiRevisionExtractor;
53+
readonly IGatewayExtractor gatewayExtractor;
54+
readonly IGatewayApiExtractor gatewayApiExtractor;
5155

5256
public ExtractorExecutor(
5357
ILogger<ExtractorExecutor> logger,
@@ -65,7 +69,9 @@ public ExtractorExecutor(
6569
ITagApiExtractor apiTagExtractor,
6670
ITagExtractor tagExtractor,
6771
IGroupExtractor groupExtractor,
68-
IApiRevisionExtractor apiRevisionExtractor)
72+
IApiRevisionExtractor apiRevisionExtractor,
73+
IGatewayExtractor gatewayExtractor,
74+
IGatewayApiExtractor gatewayApiExtractor)
6975
{
7076
this.logger = logger;
7177
this.apisClient = apisClient;
@@ -83,6 +89,8 @@ public ExtractorExecutor(
8389
this.tagExtractor = tagExtractor;
8490
this.groupExtractor = groupExtractor;
8591
this.apiRevisionExtractor = apiRevisionExtractor;
92+
this.gatewayExtractor = gatewayExtractor;
93+
this.gatewayApiExtractor = gatewayApiExtractor;
8694
}
8795

8896
/// <summary>
@@ -105,7 +113,9 @@ public static ExtractorExecutor BuildExtractorExecutor(
105113
ITagApiExtractor apiTagExtractor = null,
106114
ITagExtractor tagExtractor = null,
107115
IGroupExtractor groupExtractor = null,
108-
IApiRevisionExtractor apiRevisionExtractor = null)
116+
IApiRevisionExtractor apiRevisionExtractor = null,
117+
IGatewayExtractor gatewayExtractor = null,
118+
IGatewayApiExtractor gatewayApiExtractor = null)
109119
=> new ExtractorExecutor(
110120
logger,
111121
apisClient,
@@ -122,7 +132,9 @@ public static ExtractorExecutor BuildExtractorExecutor(
122132
apiTagExtractor,
123133
tagExtractor,
124134
groupExtractor,
125-
apiRevisionExtractor);
135+
apiRevisionExtractor,
136+
gatewayExtractor,
137+
gatewayApiExtractor);
126138

127139
public void SetExtractorParameters(ExtractorParameters extractorParameters)
128140
{
@@ -428,6 +440,70 @@ await FileWriter.SaveAsJsonAsync(
428440
return apiTagTemplate;
429441
}
430442

443+
/// <summary>
444+
/// Generates gateway template in the desired folder
445+
/// </summary>
446+
/// <param name="singleApiName">name of API to load gateway from</param>
447+
/// <param name="baseFilesGenerationDirectory">name of base folder where to save output files</param>
448+
/// <returns>generated gateway template</returns>
449+
public async Task<Template<GatewayTemplateResources>> GenerateGatewayTemplateAsync(
450+
string singleApiName,
451+
string baseFilesGenerationDirectory)
452+
{
453+
if (!this.extractorParameters.ExtractGateways)
454+
{
455+
this.logger.LogInformation("Skipping GatewayTemplate generation because of configuration parameter");
456+
return null;
457+
}
458+
459+
this.logger.LogInformation("Started generation of gateway template...");
460+
var gatewayTemplate = await this.gatewayExtractor.GenerateGatewayTemplateAsync(singleApiName, this.extractorParameters);
461+
462+
if (gatewayTemplate?.HasResources() == true)
463+
{
464+
await FileWriter.SaveAsJsonAsync(
465+
gatewayTemplate,
466+
directory: baseFilesGenerationDirectory,
467+
fileName: this.extractorParameters.FileNames.Gateway);
468+
}
469+
470+
this.logger.LogInformation("Finished generation of gateway template...");
471+
return gatewayTemplate;
472+
}
473+
474+
/// <summary>
475+
/// Generates gateway-api template in the desired folder
476+
/// </summary>
477+
/// <param name="singleApiName">name of API to load gateway-api from</param>
478+
/// /// <param name="multipleApiNames">multiple API names to load gateway-api from</param>
479+
/// <param name="baseFilesGenerationDirectory">name of base folder where to save output files</param>
480+
/// <returns>generated gateway-api template</returns>
481+
public async Task<Template<GatewayApiTemplateResources>> GenerateGatewayApiTemplateAsync(
482+
string singleApiName,
483+
List<string> multipleApiNames,
484+
string baseFilesGenerationDirectory)
485+
{
486+
if (!this.extractorParameters.ExtractGateways)
487+
{
488+
this.logger.LogInformation("Skipping gateway-api template generation because of configuration parameter");
489+
return null;
490+
}
491+
492+
this.logger.LogInformation("Started generation of gateway-api template...");
493+
var gatewayApiTemplate = await this.gatewayApiExtractor.GenerateGatewayApiTemplateAsync(singleApiName, multipleApiNames, this.extractorParameters);
494+
495+
if (gatewayApiTemplate?.HasResources() == true)
496+
{
497+
await FileWriter.SaveAsJsonAsync(
498+
gatewayApiTemplate,
499+
directory: baseFilesGenerationDirectory,
500+
fileName: this.extractorParameters.FileNames.GatewayApi);
501+
}
502+
503+
this.logger.LogInformation("Finished generation of gateway-api template...");
504+
return gatewayApiTemplate;
505+
}
506+
431507
/// <summary>
432508
/// Generates split api templates / folders for each api in this sourceApim
433509
/// </summary>
@@ -629,6 +705,7 @@ async Task GenerateTemplates(
629705
var tagTemplate = await this.GenerateTagTemplateAsync(singleApiName, apiTemplate.TypedResources, productTemplate.TypedResources, baseFilesGenerationDirectory);
630706
var apiTagTemplate = await this.GenerateApiTagTemplateAsync(singleApiName, multipleApiNames, baseFilesGenerationDirectory);
631707
await this.GenerateGroupsTemplateAsync(baseFilesGenerationDirectory);
708+
await this.GenerateGatewayTemplateAsync(singleApiName, baseFilesGenerationDirectory);
632709

633710
// not refactored
634711
Dictionary<string, object> apiLoggerId = null;

src/ArmTemplates/Common/API/Clients/Abstractions/IApisClient.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,7 @@ public interface IApisClient
1818
Task<List<ApiTemplateResource>> GetAllAsync(ExtractorParameters extractorParameters);
1919

2020
Task<List<ApiTemplateResource>> GetAllLinkedToProductAsync(string productName, ExtractorParameters extractorParameters);
21+
22+
Task<List<ApiTemplateResource>> GetAllLinkedToGatewayAsync(string gatewayName, ExtractorParameters extractorParameters);
2123
}
2224
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// --------------------------------------------------------------------------
2+
// <copyright file="IGatewayClient.cs" company="Microsoft">
3+
// Copyright (c) Microsoft Corporation. All rights reserved.
4+
// </copyright>
5+
// --------------------------------------------------------------------------
6+
7+
using System.Collections.Generic;
8+
using System.Threading.Tasks;
9+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Gateway;
10+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
11+
12+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions
13+
{
14+
public interface IGatewayClient
15+
{
16+
Task<List<GatewayTemplateResource>> GetAllAsync(ExtractorParameters extractorParameters);
17+
18+
Task<bool> DoesApiReferenceGatewayAsync(string singleApiName, string gatewayName, ExtractorParameters extractorParameters);
19+
}
20+
}

src/ArmTemplates/Common/API/Clients/Apis/ApisClient.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class ApisClient : ApiClientBase, IApisClient
1919
const string GetSingleApiRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/apis/{4}?api-version={5}";
2020
const string GetAllApisRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/apis?api-version={4}";
2121
const string GetAllApisLinkedToProductRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/products/{4}/apis?api-version={5}";
22+
const string GetApisLinkedToGatewayRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/gateways/{4}/apis?api-version={5}";
2223

2324
public async Task<ApiTemplateResource> GetSingleAsync(string apiName, ExtractorParameters extractorParameters)
2425
{
@@ -48,5 +49,15 @@ public async Task<List<ApiTemplateResource>> GetAllLinkedToProductAsync(string p
4849
var response = await this.CallApiManagementAsync<GetApisResponse>(azToken, requestUrl);
4950
return response.Apis;
5051
}
52+
53+
public async Task<List<ApiTemplateResource>> GetAllLinkedToGatewayAsync(string gatewayName, ExtractorParameters extractorParameters)
54+
{
55+
var (azToken, azSubId) = await this.Auth.GetAccessToken();
56+
string requestUrl = string.Format(GetApisLinkedToGatewayRequest,
57+
this.BaseUrl, azSubId, extractorParameters.ResourceGroup, extractorParameters.SourceApimName, gatewayName, GlobalConstants.ApiVersion);
58+
59+
var response = await this.CallApiManagementAsync<GetApisResponse>(azToken, requestUrl);
60+
return response.Apis;
61+
}
5162
}
5263
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// --------------------------------------------------------------------------
2+
// <copyright file="GatewayClient.cs" company="Microsoft">
3+
// Copyright (c) Microsoft Corporation. All rights reserved.
4+
// </copyright>
5+
// --------------------------------------------------------------------------
6+
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
using System.Threading.Tasks;
10+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions;
11+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Gateway.Responses;
12+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Constants;
13+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Extensions;
14+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Gateway;
15+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
16+
using Microsoft.Extensions.Logging;
17+
18+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Gateway
19+
{
20+
public class GatewayClient : ApiClientBase, IGatewayClient
21+
{
22+
const string GetAllGatewaysRequest = "{0}/subscriptions/{1}/resourceGroups/{2}/providers/Microsoft.ApiManagement/service/{3}/gateways?api-version={4}";
23+
24+
readonly ILogger<GatewayClient> logger;
25+
readonly IApisClient apisClient;
26+
27+
public GatewayClient(
28+
ILogger<GatewayClient> logger,
29+
IApisClient apisClient)
30+
{
31+
this.logger = logger;
32+
this.apisClient = apisClient;
33+
}
34+
35+
public async Task<List<GatewayTemplateResource>> GetAllAsync(ExtractorParameters extractorParameters)
36+
{
37+
var (azToken, azSubId) = await this.Auth.GetAccessToken();
38+
39+
string requestUrl = string.Format(GetAllGatewaysRequest,
40+
this.BaseUrl, azSubId, extractorParameters.ResourceGroup, extractorParameters.SourceApimName, GlobalConstants.ApiVersion);
41+
42+
var response = await this.CallApiManagementAsync<GetGatewaysResponse>(azToken, requestUrl);
43+
return response.Gateways;
44+
}
45+
46+
/// <summary>
47+
/// Checks whether a given single API is referenced by a gateway
48+
/// </summary>
49+
/// <returns>true, if api references a gateway</returns>
50+
public async Task<bool> DoesApiReferenceGatewayAsync(string singleApiName, string gatewayName, ExtractorParameters extractorParameters)
51+
{
52+
var gatewayApis = await this.apisClient.GetAllLinkedToGatewayAsync(gatewayName, extractorParameters);
53+
54+
if (gatewayApis.IsNullOrEmpty())
55+
{
56+
this.logger.LogDebug("Did not find any api linked to the gateway");
57+
return false;
58+
}
59+
60+
return gatewayApis.Any(gatewayApi => gatewayApi.Name == singleApiName);
61+
}
62+
}
63+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// --------------------------------------------------------------------------
2+
// <copyright file="GetGatewaysResponse.cs" company="Microsoft">
3+
// Copyright (c) Microsoft Corporation. All rights reserved.
4+
// </copyright>
5+
// --------------------------------------------------------------------------
6+
7+
using System.Collections.Generic;
8+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Gateway;
9+
using Newtonsoft.Json;
10+
11+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Gateway.Responses
12+
{
13+
public class GetGatewaysResponse
14+
{
15+
[JsonProperty("value")]
16+
public List<GatewayTemplateResource> Gateways { get; set; }
17+
18+
public int Count { get; set; }
19+
}
20+
}

src/ArmTemplates/Common/Constants/ResourceTypeConstants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@ public static class ResourceTypeConstants
2626
public const string Property = "Microsoft.ApiManagement/service/namedValues";
2727
public const string Subscription = "Microsoft.ApiManagement/service/subscriptions";
2828
public const string Tag = "Microsoft.ApiManagement/service/tags";
29+
public const string Gateway = "Microsoft.ApiManagement/service/gateways";
30+
public const string GatewayApi = "Microsoft.ApiManagement/service/gateways/apis";
2931
}
3032
}

src/ArmTemplates/Common/FileHandlers/FileNameGenerator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public static FileNames GenerateFileNames(string baseFileName)
2727
Tags = $@"{baseFileName}tags.template.json",
2828
Products = $@"{baseFileName}products.template.json",
2929
ProductAPIs = $@"{baseFileName}productAPIs.template.json",
30+
Gateway = $@"{baseFileName}gateways.template.json",
31+
GatewayApi = $@"{baseFileName}gateways-apis.template.json",
3032
ApiTags = $@"{baseFileName}apiTags.template.json",
3133
Parameters = $@"\{baseFileName}parameters.json",
3234
LinkedMaster = $@"\{baseFileName}master.template.json",

src/ArmTemplates/Common/FileHandlers/FileNames.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ public class FileNames
2323
public string Groups { get; set; }
2424

2525
public string ApiTags { get; set; }
26-
26+
27+
public string Gateway { get; set; }
28+
29+
public string GatewayApi { get; set; }
30+
2731
public string Parameters { get; set; }
2832

2933
// linked property outputs 1 master template

0 commit comments

Comments
 (0)