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

Commit b7f4bed

Browse files
authored
[Extractor] Add multiple APIs extraction option / refactor code to clean up extract.cs (#293)
* [Refactor] Add validation check and refactor code * [Refactor] Move all helper methods * [Extractor] Add multiple APIs functionality
1 parent 9c6b584 commit b7f4bed

File tree

4 files changed

+338
-275
lines changed

4 files changed

+338
-275
lines changed
Lines changed: 12 additions & 273 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
using System;
22
using McMaster.Extensions.CommandLineUtils;
3-
using System.Collections.Generic;
43
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common;
5-
using System.Linq;
6-
using Newtonsoft.Json.Linq;
7-
using System.Threading.Tasks;
84

95
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extract
106
{
@@ -25,32 +21,15 @@ public ExtractCommand()
2521

2622
try
2723
{
28-
if (extractorConfig.sourceApimName == null) throw new Exception("Missing parameter <sourceApimName>.");
29-
if (extractorConfig.destinationApimName == null) throw new Exception("Missing parameter <destinationApimName>.");
30-
if (extractorConfig.resourceGroup == null) throw new Exception("Missing parameter <resourceGroup>.");
31-
if (extractorConfig.fileFolder == null) throw new Exception("Missing parameter <filefolder>.");
24+
//validation check
25+
ExtractorUtils.validationCheck(extractorConfig);
3226

3327
string singleApiName = extractorConfig.apiName;
3428
bool splitAPIs = extractorConfig.splitAPIs != null && extractorConfig.splitAPIs.Equals("true");
3529
bool hasVersionSetName = extractorConfig.apiVersionSetName != null;
3630
bool hasSingleApi = singleApiName != null;
3731
bool includeRevisions = extractorConfig.includeAllRevisions != null && extractorConfig.includeAllRevisions.Equals("true");
38-
39-
// validaion check
40-
if (splitAPIs && hasSingleApi)
41-
{
42-
throw new Exception("Can't use splitAPIs and apiName at same time");
43-
}
44-
45-
if (splitAPIs && hasVersionSetName)
46-
{
47-
throw new Exception("Can't use splitAPIs and apiVersionSetName at same time");
48-
}
49-
50-
if (hasSingleApi && hasVersionSetName)
51-
{
52-
throw new Exception("Can't use apiName and apiVersionSetName at same time");
53-
}
32+
bool hasMultipleAPIs = extractorConfig.mutipleAPIs != null;
5433

5534
// start running extractor
5635
Console.WriteLine("API Management Template");
@@ -64,17 +43,22 @@ public ExtractCommand()
6443
if (splitAPIs)
6544
{
6645
// create split api templates for all apis in the sourceApim
67-
await this.GenerateSplitAPITemplates(extractorConfig, fileNameGenerator, fileWriter, fileNames);
46+
await ExtractorUtils.GenerateSplitAPITemplates(extractorConfig, fileNameGenerator, fileWriter, fileNames);
6847
}
6948
else if (hasVersionSetName)
7049
{
7150
// create split api templates and aggregated api templates for this apiversionset
72-
await this.GenerateAPIVersionSetTemplates(extractorConfig, fileNameGenerator, fileNames, fileWriter);
51+
await ExtractorUtils.GenerateAPIVersionSetTemplates(extractorConfig, fileNameGenerator, fileNames, fileWriter);
52+
}
53+
else if (hasMultipleAPIs)
54+
{
55+
// generate templates for multiple APIs
56+
await ExtractorUtils.GenerateMultipleAPIsTemplates(extractorConfig, fileNameGenerator, fileWriter, fileNames);
7357
}
7458
else if (hasSingleApi && includeRevisions)
7559
{
7660
// handle singel API include Revision extraction
77-
await this.GenerateSingleAPIWithRevisionsTemplates(extractorConfig, singleApiName, fileNameGenerator, fileWriter, fileNames);
61+
await ExtractorUtils.GenerateSingleAPIWithRevisionsTemplates(extractorConfig, singleApiName, fileNameGenerator, fileWriter, fileNames);
7862
}
7963
else
8064
{
@@ -87,7 +71,7 @@ public ExtractCommand()
8771
{
8872
Console.WriteLine("Executing full extraction ...");
8973
}
90-
await this.GenerateTemplates(new Extractor(extractorConfig), singleApiName, null, fileNameGenerator, fileNames, fileWriter, null);
74+
await ExtractorUtils.GenerateTemplates(new Extractor(extractorConfig), singleApiName, null, fileNameGenerator, fileNames, fileWriter, null);
9175
}
9276
Console.WriteLine("Templates written to output location");
9377
Console.WriteLine("Press any key to exit process:");
@@ -102,250 +86,5 @@ public ExtractCommand()
10286
}
10387
});
10488
}
105-
106-
/* three condistions to use this function:
107-
1. singleApiName is null, then generate one master template for the multipleAPIs in multipleApiNams
108-
2. multipleApiNams is null, then generate separate folder and master template for each API
109-
3. when both singleApiName and multipleApiNams is null, then generate one master template to link all apis in the sourceapim
110-
*/
111-
private async Task GenerateTemplates(
112-
Extractor exc,
113-
string singleApiName,
114-
List<string> multipleAPINames,
115-
FileNameGenerator fileNameGenerator,
116-
FileNames fileNames,
117-
FileWriter fileWriter,
118-
Template apiTemplate)
119-
{
120-
if (singleApiName != null && multipleAPINames != null)
121-
{
122-
throw new Exception("can't specify single API and multiple APIs to extract at the same time");
123-
}
124-
// initialize entity extractor classes
125-
APIExtractor apiExtractor = new APIExtractor(fileWriter);
126-
APIVersionSetExtractor apiVersionSetExtractor = new APIVersionSetExtractor();
127-
AuthorizationServerExtractor authorizationServerExtractor = new AuthorizationServerExtractor();
128-
BackendExtractor backendExtractor = new BackendExtractor();
129-
LoggerExtractor loggerExtractor = new LoggerExtractor();
130-
PolicyExtractor policyExtractor = new PolicyExtractor(fileWriter);
131-
PropertyExtractor propertyExtractor = new PropertyExtractor();
132-
TagExtractor tagExtractor = new TagExtractor();
133-
ProductExtractor productExtractor = new ProductExtractor(fileWriter);
134-
MasterTemplateExtractor masterTemplateExtractor = new MasterTemplateExtractor();
135-
136-
// read parameters
137-
string sourceApim = exc.sourceApimName;
138-
string resourceGroup = exc.resourceGroup;
139-
string destinationApim = exc.destinationApimName;
140-
string linkedBaseUrl = exc.linkedTemplatesBaseUrl;
141-
string policyXMLBaseUrl = exc.policyXMLBaseUrl;
142-
string dirName = exc.fileFolder;
143-
List<string> multipleApiNames = multipleAPINames;
144-
string linkedUrlQueryString = exc.linkedTemplatesUrlQueryString;
145-
146-
// extract templates from apim service
147-
Template globalServicePolicyTemplate = await policyExtractor.GenerateGlobalServicePolicyTemplateAsync(sourceApim, resourceGroup, policyXMLBaseUrl, dirName);
148-
if (apiTemplate == null)
149-
{
150-
apiTemplate = await apiExtractor.GenerateAPIsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, multipleApiNames, policyXMLBaseUrl, dirName);
151-
}
152-
List<TemplateResource> apiTemplateResources = apiTemplate.resources.ToList();
153-
Template apiVersionSetTemplate = await apiVersionSetExtractor.GenerateAPIVersionSetsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl);
154-
Template authorizationServerTemplate = await authorizationServerExtractor.GenerateAuthorizationServersARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl);
155-
Template loggerTemplate = await loggerExtractor.GenerateLoggerTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl);
156-
Template productTemplate = await productExtractor.GenerateProductsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl, dirName);
157-
List<TemplateResource> productTemplateResources = productTemplate.resources.ToList();
158-
Template namedValueTemplate = await propertyExtractor.GenerateNamedValuesTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl);
159-
Template tagTemplate = await tagExtractor.GenerateTagsTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, productTemplateResources, policyXMLBaseUrl);
160-
List<TemplateResource> namedValueResources = namedValueTemplate.resources.ToList();
161-
Template backendTemplate = await backendExtractor.GenerateBackendsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, namedValueResources, policyXMLBaseUrl);
162-
163-
// create parameters file
164-
Template templateParameters = masterTemplateExtractor.CreateMasterTemplateParameterValues(destinationApim, linkedBaseUrl, linkedUrlQueryString, policyXMLBaseUrl);
165-
166-
// write templates to output file location
167-
string apiFileName = fileNameGenerator.GenerateExtractorAPIFileName(singleApiName, sourceApim);
168-
fileWriter.WriteJSONToFile(apiTemplate, String.Concat(@dirName, apiFileName));
169-
// won't generate template when there is no resources
170-
if (apiVersionSetTemplate.resources.Count() != 0)
171-
{
172-
fileWriter.WriteJSONToFile(apiVersionSetTemplate, String.Concat(@dirName, fileNames.apiVersionSets));
173-
}
174-
if (backendTemplate.resources.Count() != 0)
175-
{
176-
fileWriter.WriteJSONToFile(backendTemplate, String.Concat(@dirName, fileNames.backends));
177-
}
178-
if (authorizationServerTemplate.resources.Count() != 0)
179-
{
180-
fileWriter.WriteJSONToFile(authorizationServerTemplate, String.Concat(@dirName, fileNames.authorizationServers));
181-
}
182-
if (productTemplate.resources.Count() != 0)
183-
{
184-
fileWriter.WriteJSONToFile(productTemplate, String.Concat(@dirName, fileNames.products));
185-
}
186-
if (tagTemplate.resources.Count() != 0)
187-
{
188-
fileWriter.WriteJSONToFile(tagTemplate, String.Concat(@dirName, fileNames.tags));
189-
}
190-
if (namedValueTemplate.resources.Count() != 0)
191-
{
192-
fileWriter.WriteJSONToFile(namedValueTemplate, String.Concat(@dirName, fileNames.namedValues));
193-
}
194-
if (globalServicePolicyTemplate.resources.Count() != 0)
195-
{
196-
fileWriter.WriteJSONToFile(globalServicePolicyTemplate, String.Concat(@dirName, fileNames.globalServicePolicy));
197-
}
198-
if (linkedBaseUrl != null)
199-
{
200-
// create a master template that links to all other templates
201-
Template masterTemplate = masterTemplateExtractor.GenerateLinkedMasterTemplate(
202-
apiTemplate, globalServicePolicyTemplate, apiVersionSetTemplate, productTemplate,
203-
loggerTemplate, backendTemplate, authorizationServerTemplate, namedValueTemplate,
204-
tagTemplate, fileNames, apiFileName, linkedUrlQueryString, policyXMLBaseUrl);
205-
206-
fileWriter.WriteJSONToFile(masterTemplate, String.Concat(@dirName, fileNames.linkedMaster));
207-
}
208-
209-
// write parameters to outputLocation
210-
fileWriter.WriteJSONToFile(templateParameters, String.Concat(dirName, fileNames.parameters));
211-
}
212-
213-
// this function will generate master template for each API within this version set and an extra master template to link these apis
214-
public async Task GenerateAPIVersionSetTemplates(ExtractorConfig exc, FileNameGenerator fileNameGenerator, FileNames fileNames, FileWriter fileWriter)
215-
{
216-
// get api dictionary and check api version set
217-
var apiDictionary = await this.GetAllAPIsDictionary(exc.sourceApimName, exc.resourceGroup, fileWriter);
218-
if (!apiDictionary.ContainsKey(exc.apiVersionSetName))
219-
{
220-
throw new Exception("API Version Set with this name doesn't exist");
221-
}
222-
else
223-
{
224-
foreach (string apiName in apiDictionary[exc.apiVersionSetName])
225-
{
226-
// generate seperate folder for each API
227-
string apiFileFolder = String.Concat(@exc.fileFolder, $@"/{apiName}");
228-
System.IO.Directory.CreateDirectory(apiFileFolder);
229-
await this.GenerateTemplates(new Extractor(exc, apiFileFolder), apiName, null, fileNameGenerator, fileNames, fileWriter, null);
230-
}
231-
232-
// create master templates for this apiVersionSet
233-
string versionSetFolder = String.Concat(@exc.fileFolder, fileNames.versionSetMasterFolder);
234-
System.IO.Directory.CreateDirectory(versionSetFolder);
235-
await this.GenerateTemplates(new Extractor(exc, versionSetFolder), null, apiDictionary[exc.apiVersionSetName], fileNameGenerator, fileNames, fileWriter, null);
236-
237-
Console.WriteLine($@"Finish extracting APIVersionSet {exc.apiVersionSetName}");
238-
239-
}
240-
}
241-
242-
// this function will generate split api templates / folders for each api in this sourceApim
243-
public async Task GenerateSplitAPITemplates(ExtractorConfig exc, FileNameGenerator fileNameGenerator, FileWriter fileWriter, FileNames fileNames)
244-
{
245-
// Generate folders based on all apiversionset
246-
var apiDictionary = await this.GetAllAPIsDictionary(exc.sourceApimName, exc.resourceGroup, fileWriter);
247-
248-
// Generate templates based on each API/APIversionSet
249-
foreach (KeyValuePair<string, List<string>> versionSetEntry in apiDictionary)
250-
{
251-
string apiFileFolder = exc.fileFolder;
252-
253-
// if it's APIVersionSet, generate the versionsetfolder for templates
254-
if (versionSetEntry.Value.Count > 1)
255-
{
256-
// this API has VersionSet
257-
string apiDisplayName = versionSetEntry.Key;
258-
259-
// create apiVersionSet folder
260-
apiFileFolder = String.Concat(@apiFileFolder, $@"/{apiDisplayName}");
261-
System.IO.Directory.CreateDirectory(apiFileFolder);
262-
263-
// create master templates for each apiVersionSet
264-
string versionSetFolder = String.Concat(@apiFileFolder, fileNames.versionSetMasterFolder);
265-
System.IO.Directory.CreateDirectory(versionSetFolder);
266-
await this.GenerateTemplates(new Extractor(exc, versionSetFolder), null, versionSetEntry.Value, fileNameGenerator, fileNames, fileWriter, null);
267-
268-
Console.WriteLine($@"Finish extracting APIVersionSet {versionSetEntry.Key}");
269-
}
270-
271-
// Generate templates for each api
272-
foreach (string apiName in versionSetEntry.Value)
273-
{
274-
// create folder for each API
275-
string tempFileFolder = String.Concat(@apiFileFolder, $@"/{apiName}");
276-
System.IO.Directory.CreateDirectory(tempFileFolder);
277-
// generate templates for each API
278-
await this.GenerateTemplates(new Extractor(exc, tempFileFolder), apiName, null, fileNameGenerator, fileNames, fileWriter, null);
279-
280-
Console.WriteLine($@"Finish extracting API {apiName}");
281-
}
282-
}
283-
}
284-
285-
public async Task GenerateSingleAPIWithRevisionsTemplates(ExtractorConfig exc, string apiName, FileNameGenerator fileNameGenerator, FileWriter fileWriter, FileNames fileNames)
286-
{
287-
Console.WriteLine("Extracting singleAPI {0} with revisions", apiName);
288-
289-
APIExtractor apiExtractor = new APIExtractor(fileWriter);
290-
// Get all revisions for this api
291-
string revisions = await apiExtractor.GetAPIRevisionsAsync(exc.sourceApimName, exc.resourceGroup, apiName);
292-
JObject revs = JObject.Parse(revisions);
293-
string currentRevision = null;
294-
List<string> revList = new List<string>();
295-
296-
// Generate seperate folder for each API revision
297-
for (int i = 0; i < ((JContainer)revs["value"]).Count; i++)
298-
{
299-
string apiID = ((JValue)revs["value"][i]["apiId"]).Value.ToString();
300-
string singleApiName = apiID.Split("/")[2];
301-
if (((JValue)revs["value"][i]["isCurrent"]).Value.ToString().Equals("True"))
302-
{
303-
currentRevision = singleApiName;
304-
}
305-
306-
string revFileFolder = String.Concat(@exc.fileFolder, $@"/{singleApiName}");
307-
System.IO.Directory.CreateDirectory(revFileFolder);
308-
await this.GenerateTemplates(new Extractor(exc, revFileFolder), singleApiName, null, fileNameGenerator, fileNames, fileWriter, null);
309-
revList.Add(singleApiName);
310-
}
311-
312-
if (currentRevision == null)
313-
{
314-
throw new Exception($"Revision {apiName} doesn't exist, something went wrong!");
315-
}
316-
// generate revisions master folder
317-
string revMasterFolder = String.Concat(@exc.fileFolder, fileNames.revisionMasterFolder);
318-
System.IO.Directory.CreateDirectory(revMasterFolder);
319-
Extractor revExc = new Extractor(exc, revMasterFolder);
320-
Template apiRevisionTemplate = await apiExtractor.GenerateAPIRevisionTemplateAsync(currentRevision, revList, apiName, revExc);
321-
await GenerateTemplates(revExc, null, null, fileNameGenerator, fileNames, fileWriter, apiRevisionTemplate);
322-
}
323-
324-
// this function will generate an api dictionary with apiName/versionsetName (if exist one) as key, list of apiNames as value
325-
public async Task<Dictionary<string, List<string>>> GetAllAPIsDictionary(string sourceApim, string resourceGroup, FileWriter fileWriter)
326-
{
327-
APIExtractor apiExtractor = new APIExtractor(fileWriter);
328-
// pull all apis from service
329-
string apis = await apiExtractor.GetAPIsAsync(sourceApim, resourceGroup);
330-
JObject oApi = JObject.Parse(apis);
331-
332-
// Generate folders based on all apiversionset
333-
var apiDictionary = new Dictionary<string, List<string>>();
334-
for (int i = 0; i < ((JContainer)oApi["value"]).Count; i++)
335-
{
336-
string apiDisplayName = ((JValue)oApi["value"][i]["properties"]["displayName"]).Value.ToString();
337-
if (!apiDictionary.ContainsKey(apiDisplayName))
338-
{
339-
List<string> apiVersionSet = new List<string>();
340-
apiVersionSet.Add(((JValue)oApi["value"][i]["name"]).Value.ToString());
341-
apiDictionary[apiDisplayName] = apiVersionSet;
342-
}
343-
else
344-
{
345-
apiDictionary[apiDisplayName].Add(((JValue)oApi["value"][i]["name"]).Value.ToString());
346-
}
347-
}
348-
return apiDictionary;
349-
}
35089
}
35190
}

0 commit comments

Comments
 (0)