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

Commit a8316e2

Browse files
committed
manipulate format and value for open api spec for v3 and yaml
1 parent 49c8058 commit a8316e2

File tree

6 files changed

+126
-26
lines changed

6 files changed

+126
-26
lines changed

src/APIM_ARMTemplate/apimtemplate.test/Creator/TemplateCreatorTests/APITemplateCreatorTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Test
99
public class APITemplateCreatorTests
1010
{
1111
[Fact]
12-
public void ShouldCreateInitialAPITemplateResourceFromCreatorConfig()
12+
public async void ShouldCreateInitialAPITemplateResourceFromCreatorConfig()
1313
{
1414
// arrange
1515
APITemplateCreator apiTemplateCreator = APITemplateCreatorFactory.GenerateAPITemplateCreator();
@@ -46,7 +46,7 @@ public void ShouldCreateInitialAPITemplateResourceFromCreatorConfig()
4646
creatorConfig.apis.Add(api);
4747

4848
// act
49-
APITemplateResource apiTemplateResource = apiTemplateCreator.CreateAPITemplateResource(api, true, true);
49+
APITemplateResource apiTemplateResource = await apiTemplateCreator.CreateAPITemplateResourceAsync(api, true, true);
5050

5151
// assert
5252
Assert.Equal($"[concat(parameters('ApimServiceName'), '/{api.name}')]", apiTemplateResource.name);
@@ -70,7 +70,7 @@ public void ShouldCreateInitialAPITemplateResourceFromCreatorConfig()
7070
}
7171

7272
[Fact]
73-
public void ShouldCreateSubsequentlAPITemplateResourceFromCreatorConfigWithCorrectContent()
73+
public async void ShouldCreateSubsequentlAPITemplateResourceFromCreatorConfigWithCorrectContent()
7474
{
7575
// arrange
7676
APITemplateCreator apiTemplateCreator = APITemplateCreatorFactory.GenerateAPITemplateCreator();
@@ -83,7 +83,7 @@ public void ShouldCreateSubsequentlAPITemplateResourceFromCreatorConfigWithCorre
8383
creatorConfig.apis.Add(api);
8484

8585
// act
86-
APITemplateResource apiTemplateResource = apiTemplateCreator.CreateAPITemplateResource(api, true, false);
86+
APITemplateResource apiTemplateResource = await apiTemplateCreator.CreateAPITemplateResourceAsync(api, true, false);
8787

8888
// assert
8989
Assert.Equal($"[concat(parameters('ApimServiceName'), '/{api.name}')]", apiTemplateResource.name);
@@ -92,7 +92,7 @@ public void ShouldCreateSubsequentlAPITemplateResourceFromCreatorConfigWithCorre
9292
}
9393

9494
[Fact]
95-
public void ShouldCreateUnifiedAPITemplateResourceFromCreatorConfig()
95+
public async void ShouldCreateUnifiedAPITemplateResourceFromCreatorConfig()
9696
{
9797
// arrange
9898
APITemplateCreator apiTemplateCreator = APITemplateCreatorFactory.GenerateAPITemplateCreator();
@@ -129,7 +129,7 @@ public void ShouldCreateUnifiedAPITemplateResourceFromCreatorConfig()
129129
creatorConfig.apis.Add(api);
130130

131131
// act
132-
APITemplateResource apiTemplateResource = apiTemplateCreator.CreateAPITemplateResource(api, false, true);
132+
APITemplateResource apiTemplateResource = await apiTemplateCreator.CreateAPITemplateResourceAsync(api, false, true);
133133

134134
// assert
135135
Assert.Equal($"[concat(parameters('ApimServiceName'), '/{api.name}')]", apiTemplateResource.name);
@@ -155,7 +155,7 @@ public void ShouldCreateUnifiedAPITemplateResourceFromCreatorConfig()
155155
}
156156

157157
[Fact]
158-
public void ShouldAppendRevisionToAPIName()
158+
public async void ShouldAppendRevisionToAPIName()
159159
{
160160
// arrange
161161
APITemplateCreator apiTemplateCreator = APITemplateCreatorFactory.GenerateAPITemplateCreator();
@@ -173,7 +173,7 @@ public void ShouldAppendRevisionToAPIName()
173173

174174
// act
175175
// the above api config will create a unified api template with a single resource
176-
List<Template> apiTemplates = apiTemplateCreator.CreateAPITemplates(api);
176+
List<Template> apiTemplates = await apiTemplateCreator.CreateAPITemplatesAsync(api);
177177
APITemplateResource apiTemplateResource = apiTemplates.FirstOrDefault().resources[0] as APITemplateResource;
178178

179179
// assert

src/APIM_ARMTemplate/apimtemplate/Commands/Create.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public CreateCommand()
7474
foreach (APIConfig api in creatorConfig.apis)
7575
{
7676
// create api templates from provided api config - if the api config contains a supplied apiVersion, split the templates into 2 for metadata and swagger content, otherwise create a unified template
77-
List<Template> apiTemplateSet = apiTemplateCreator.CreateAPITemplates(api);
77+
List<Template> apiTemplateSet = await apiTemplateCreator.CreateAPITemplatesAsync(api);
7878
apiTemplates.AddRange(apiTemplateSet);
7979
// create the relevant info that will be needed to properly link to the api template(s) from the master template
8080
apiInformation.Add(new LinkedMasterTemplateAPIInformation()

src/APIM_ARMTemplate/apimtemplate/Common/FileHandlers/FileReader.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ public async Task<CreatorConfig> ConvertConfigYAMLToCreatorConfigAsync(string co
3434
CreatorConfig yamlObject = JsonConvert.DeserializeObject<CreatorConfig>(jsonText);
3535
return yamlObject;
3636
}
37-
} else {
37+
}
38+
else
39+
{
3840
throw new Exception("Unable to fetch remote config YAML file.");
3941
}
4042
}
@@ -87,5 +89,18 @@ public async Task<string> RetrieveFileContentsAsync(string fileLocation)
8789
return RetrieveLocalFileContents(fileLocation);
8890
}
8991
}
92+
93+
public bool isJSON(string fileContents)
94+
{
95+
try
96+
{
97+
object deserializedFileContents = JsonConvert.DeserializeObject<object>(fileContents);
98+
return true;
99+
}
100+
catch (Exception ex)
101+
{
102+
return false;
103+
}
104+
}
90105
}
91106
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.IO;
4+
using System.Net.Http;
5+
using System.Threading.Tasks;
6+
7+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common
8+
{
9+
public class OpenAPISpecReader
10+
{
11+
public async Task<bool> isJSONOpenAPISpecVersionThreeAsync(string openApiSpecFileLocation)
12+
{
13+
// determine whether file location is local file path or remote url and read content
14+
Uri uriResult;
15+
bool isUrl = Uri.TryCreate(openApiSpecFileLocation, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
16+
if (isUrl)
17+
{
18+
19+
HttpClient client = new HttpClient();
20+
HttpResponseMessage response = await client.GetAsync(uriResult);
21+
if (response.IsSuccessStatusCode)
22+
{
23+
string fileContents = await response.Content.ReadAsStringAsync();
24+
OpenAPISpecWithVersion openAPISpecWithVersion = JsonConvert.DeserializeObject<OpenAPISpecWithVersion>(fileContents);
25+
// OASv3 has the property 'openapi' but not the property 'swagger'
26+
return openAPISpecWithVersion.Swagger != null ? false : true;
27+
}
28+
else
29+
{
30+
return false;
31+
}
32+
}
33+
else
34+
{
35+
string fileContents = File.ReadAllText(openApiSpecFileLocation);
36+
OpenAPISpecWithVersion openAPISpecWithVersion = JsonConvert.DeserializeObject<OpenAPISpecWithVersion>(fileContents);
37+
// OASv3 has the property 'openapi' but not the property 'swagger'
38+
return openAPISpecWithVersion.Swagger != null ? false : true;
39+
}
40+
}
41+
}
42+
43+
public class OpenAPISpecWithVersion
44+
{
45+
// OASv3 has the property 'swagger'
46+
[JsonProperty(PropertyName = "swagger")]
47+
public string Swagger { get; set; }
48+
// OASv3 has the property 'openapi'
49+
[JsonProperty(PropertyName = "openapi")]
50+
public string OpenAPISpec { get; set; }
51+
}
52+
53+
}

src/APIM_ARMTemplate/apimtemplate/Creator/TemplateCreators/APITemplateCreator.cs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System.Collections.Generic;
22
using System.Threading.Tasks;
3-
using Newtonsoft.Json;
43
using System;
54
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common;
65

@@ -23,7 +22,7 @@ public APITemplateCreator(FileReader fileReader, PolicyTemplateCreator policyTem
2322
this.releaseTemplateCreator = releaseTemplateCreator;
2423
}
2524

26-
public List<Template> CreateAPITemplates(APIConfig api)
25+
public async Task<List<Template>> CreateAPITemplatesAsync(APIConfig api)
2726
{
2827
// determine if api needs to be split into multiple templates
2928
bool isSplit = isSplitAPI(api);
@@ -43,18 +42,18 @@ public List<Template> CreateAPITemplates(APIConfig api)
4342
if (isSplit == true)
4443
{
4544
// create 2 templates, an initial template with metadata and a subsequent template with the swagger content
46-
apiTemplates.Add(CreateAPITemplate(api, isSplit, true));
47-
apiTemplates.Add(CreateAPITemplate(api, isSplit, false));
45+
apiTemplates.Add(await CreateAPITemplateAsync(api, isSplit, true));
46+
apiTemplates.Add(await CreateAPITemplateAsync(api, isSplit, false));
4847
}
4948
else
5049
{
5150
// create a unified template that includes both the metadata and swagger content
52-
apiTemplates.Add(CreateAPITemplate(api, isSplit, false));
51+
apiTemplates.Add(await CreateAPITemplateAsync(api, isSplit, false));
5352
}
5453
return apiTemplates;
5554
}
5655

57-
public Template CreateAPITemplate(APIConfig api, bool isSplit, bool isInitial)
56+
public async Task<Template> CreateAPITemplateAsync(APIConfig api, bool isSplit, bool isInitial)
5857
{
5958
// create empty template
6059
Template apiTemplate = CreateEmptyTemplate();
@@ -67,7 +66,7 @@ public Template CreateAPITemplate(APIConfig api, bool isSplit, bool isInitial)
6766

6867
List<TemplateResource> resources = new List<TemplateResource>();
6968
// create api resource
70-
APITemplateResource apiTemplateResource = this.CreateAPITemplateResource(api, isSplit, isInitial);
69+
APITemplateResource apiTemplateResource = await this.CreateAPITemplateResourceAsync(api, isSplit, isInitial);
7170
resources.Add(apiTemplateResource);
7271
// add the api child resources (api policies, diagnostics, etc) if this is the unified or subsequent template
7372
if (!isSplit || !isInitial)
@@ -102,7 +101,7 @@ public List<TemplateResource> CreateChildResourceTemplates(APIConfig api)
102101
return resources;
103102
}
104103

105-
public APITemplateResource CreateAPITemplateResource(APIConfig api, bool isSplit, bool isInitial)
104+
public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig api, bool isSplit, bool isInitial)
106105
{
107106
// create api resource
108107
APITemplateResource apiTemplateResource = new APITemplateResource()
@@ -147,15 +146,48 @@ public APITemplateResource CreateAPITemplateResource(APIConfig api, bool isSplit
147146
}
148147
if (!isSplit || !isInitial)
149148
{
150-
// add swagger properties for subsequent and unified templates
149+
// add open api spec properties for subsequent and unified templates
150+
string format;
151+
string value;
152+
153+
// determine if the open api spec is remote or local, yaml or json
151154
Uri uriResult;
155+
string fileContents = await this.fileReader.RetrieveFileContentsAsync(api.openApiSpec);
156+
bool isJSON = this.fileReader.isJSON(fileContents);
152157
bool isUrl = Uri.TryCreate(api.openApiSpec, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
153-
// used to escape sequences in local swagger json
154-
object deserializedFileContents = isUrl ? null : JsonConvert.DeserializeObject<object>(this.fileReader.RetrieveLocalFileContents(api.openApiSpec));
155-
// if openApiSpec is a url inline the url, if it is a local file inline the file contents
156-
apiTemplateResource.properties.format = isUrl ? "swagger-link-json" : "swagger-json";
157-
apiTemplateResource.properties.value = isUrl ? api.openApiSpec : JsonConvert.SerializeObject(deserializedFileContents);
158-
// supplied via optional arguments
158+
159+
if (isUrl == true)
160+
{
161+
value = api.openApiSpec;
162+
if (isJSON == true)
163+
{
164+
// open api spec is remote json file, use swagger-link-json for v2 and openapi-link for v3
165+
OpenAPISpecReader openAPISpecReader = new OpenAPISpecReader();
166+
bool isVersionThree = await openAPISpecReader.isJSONOpenAPISpecVersionThreeAsync(api.openApiSpec);
167+
format = isVersionThree == false ? "swagger-link-json" : "openapi-link";
168+
}
169+
else
170+
{
171+
// open api spec is remote yaml file
172+
format = "openapi-link";
173+
}
174+
} else
175+
{
176+
value = fileContents;
177+
if (isJSON == true)
178+
{
179+
// open api spec is local json file, use swagger-json for v2 and openapi+json for v3
180+
OpenAPISpecReader openAPISpecReader = new OpenAPISpecReader();
181+
bool isVersionThree = await openAPISpecReader.isJSONOpenAPISpecVersionThreeAsync(api.openApiSpec);
182+
format = isVersionThree == false ? "swagger-json" : "openapi+json";
183+
} else
184+
{
185+
// open api spec is local yaml file
186+
format = "openapi";
187+
}
188+
}
189+
apiTemplateResource.properties.format = format;
190+
apiTemplateResource.properties.value = value;
159191
apiTemplateResource.properties.path = api.suffix;
160192
}
161193
return apiTemplateResource;

src/APIM_ARMTemplate/apimtemplate/Properties/launchSettings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"profiles": {
33
"apimtemplate": {
44
"commandName": "Project",
5-
"commandLineArgs": "extract --sourceApimName LucasBlankLinked --destinationApimName LucasBlankUnlinked --resourceGroup LucasHuetHudsonInternal --fileFolder C:\\\\Users\\\\lucashh\\\\Desktop\\\\Projects\\\\APIM-ARM\\\\GeneratedTemplates\\\\Extractor\\\\SingleAPI --apiName firstAPI --policyXMLBaseUrl https://lucasarmtemplates.blob.core.windows.net/policies"
5+
"commandLineArgs": "create --configFile ./Creator/ExampleFiles/YAMLConfigs/validTesting.yml"
66
}
77
}
88
}

0 commit comments

Comments
 (0)