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

Commit 254a260

Browse files
springcompMaxime LABELLE
andauthored
Fixed deploying multiple versions of the same API (#575)
* '#562 - Supports deploying multiple versions of an api sequentially. * #562 - Fixed odd conflict on existing path when deploying multiple versions of the same api. Co-authored-by: Maxime LABELLE <maxime.labelle@chanel.com>
1 parent 7911271 commit 254a260

File tree

3 files changed

+73
-6
lines changed

3 files changed

+73
-6
lines changed

src/APIM_ARMTemplate/apimtemplate/Commands/Create.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ public CreateCommand()
135135
List<Template> apiTemplates = new List<Template>();
136136
Console.WriteLine("Creating API templates");
137137
Console.WriteLine("------------------------------------------");
138+
139+
IDictionary<string, string[]> apiVersions = APITemplateCreator.GetApiVersionSets(creatorConfig);
140+
138141
foreach (APIConfig api in creatorConfig.apis)
139142
{
140143
if (considerAllApiForDeployments || preferredApis.Contains(api.name))
@@ -155,7 +158,8 @@ public CreateCommand()
155158
name = api.name,
156159
isSplit = apiTemplateCreator.isSplitAPI(api),
157160
dependsOnGlobalServicePolicies = creatorConfig.policy != null,
158-
dependsOnVersionSets = api.apiVersionSetId != null,
161+
dependsOnVersionSets = api.apiVersionSetId != null,
162+
dependsOnVersion = masterTemplateCreator.GetDependsOnPreviousApiVersion(api, apiVersions),
159163
dependsOnProducts = api.products != null,
160164
dependsOnTags = api.tags != null,
161165
dependsOnLoggers = await masterTemplateCreator.DetermineIfAPIDependsOnLoggerAsync(api, fileReader),
@@ -234,4 +238,4 @@ public CreateCommand()
234238
});
235239
}
236240
}
237-
}
241+
}

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using apimtemplate.Creator.Utilities;
66
using System.Net;
77
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extract;
8+
using System.Linq;
89

910
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Create
1011
{
@@ -238,7 +239,20 @@ public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig
238239
}
239240
apiTemplateResource.properties.format = format;
240241
apiTemplateResource.properties.value = value;
241-
apiTemplateResource.properties.path = api.suffix;
242+
243+
// #562: deploying multiple versions of an API may fail because while trying to deploy the initial template
244+
// overwrite the initial template’s path property to a dummy value
245+
// this value will be restored when the subsequent template is deployed
246+
247+
if (isSplit && isInitial)
248+
{
249+
apiTemplateResource.properties.path = api.suffix + $"/{Guid.NewGuid():n}";
250+
}
251+
else
252+
{
253+
apiTemplateResource.properties.path = api.suffix;
254+
}
255+
242256
if (!String.IsNullOrEmpty(api.serviceUrl))
243257
{
244258
apiTemplateResource.properties.serviceUrl = MakeServiceUrl(api);
@@ -247,6 +261,22 @@ public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig
247261
return apiTemplateResource;
248262
}
249263

264+
internal static IDictionary<string, string[]> GetApiVersionSets(CreatorConfig creatorConfig)
265+
{
266+
var apiVersions = (creatorConfig.apiVersionSets ?? new List<APIVersionSetConfig>())
267+
.ToDictionary(v => v.id, v => new List<string>())
268+
;
269+
270+
foreach (var api in creatorConfig.apis.Where(a => !string.IsNullOrEmpty(a.apiVersionSetId)))
271+
apiVersions[api.apiVersionSetId].Add(api.name)
272+
;
273+
274+
return apiVersions.ToDictionary(
275+
kv => kv.Key,
276+
kv => kv.Value.OrderBy(v => v).ToArray()
277+
);
278+
}
279+
250280
private static string GetOpenApiSpecFormat(bool isUrl, bool isJSON, bool isVersionThree)
251281
{
252282
return isUrl

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

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public Template CreateLinkedMasterTemplate(CreatorConfig creatorConfig,
109109

110110
string initialAPIFileName = fileNameGenerator.GenerateCreatorAPIFileName(apiInfo.name, apiInfo.isSplit, true);
111111
string initialAPIUri = GenerateLinkedTemplateUri(creatorConfig, initialAPIFileName);
112-
string[] initialAPIDependsOn = CreateAPIResourceDependencies(globalServicePolicyTemplate, apiVersionSetTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, tagTemplate, apiInfo, previousAPIName);
112+
string[] initialAPIDependsOn = CreateAPIResourceDependencies(creatorConfig, globalServicePolicyTemplate, apiVersionSetTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, tagTemplate, apiInfo, previousAPIName);
113113
resources.Add(this.CreateLinkedMasterTemplateResource(initialAPIDeploymentResourceName, initialAPIUri, initialAPIDependsOn, originalAPIName, apiInfo.isServiceUrlParameterize));
114114

115115
string subsequentAPIFileName = fileNameGenerator.GenerateCreatorAPIFileName(apiInfo.name, apiInfo.isSplit, false);
@@ -128,7 +128,7 @@ public Template CreateLinkedMasterTemplate(CreatorConfig creatorConfig,
128128
string unifiedAPIDeploymentResourceName = $"{originalAPIName}-APITemplate";
129129
string unifiedAPIFileName = fileNameGenerator.GenerateCreatorAPIFileName(apiInfo.name, apiInfo.isSplit, true);
130130
string unifiedAPIUri = GenerateLinkedTemplateUri(creatorConfig, unifiedAPIFileName);
131-
string[] unifiedAPIDependsOn = CreateAPIResourceDependencies(globalServicePolicyTemplate, apiVersionSetTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, tagTemplate, apiInfo, previousAPIName);
131+
string[] unifiedAPIDependsOn = CreateAPIResourceDependencies(creatorConfig, globalServicePolicyTemplate, apiVersionSetTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, tagTemplate, apiInfo, previousAPIName);
132132
resources.Add(this.CreateLinkedMasterTemplateResource(unifiedAPIDeploymentResourceName, unifiedAPIUri, unifiedAPIDependsOn, originalAPIName, apiInfo.isServiceUrlParameterize));
133133

134134
// Set previous API name for dependency chain
@@ -140,7 +140,9 @@ public Template CreateLinkedMasterTemplate(CreatorConfig creatorConfig,
140140
return masterTemplate;
141141
}
142142

143-
public string[] CreateAPIResourceDependencies(Template globalServicePolicyTemplate,
143+
public string[] CreateAPIResourceDependencies(
144+
CreatorConfig creatorConfig,
145+
Template globalServicePolicyTemplate,
144146
Template apiVersionSetTemplate,
145147
Template productsTemplate,
146148
Template loggersTemplate,
@@ -179,6 +181,10 @@ public string[] CreateAPIResourceDependencies(Template globalServicePolicyTempla
179181
{
180182
apiDependsOn.Add("[resourceId('Microsoft.Resources/deployments', 'tagTemplate')]");
181183
}
184+
if (apiInfo.dependsOnVersion != null)
185+
{
186+
apiDependsOn.Add($"[resourceId('Microsoft.Resources/deployments', '{apiInfo.dependsOnVersion}-SubsequentAPITemplate')]");
187+
}
182188
if (previousAPI != null && apiInfo.dependsOnTags == true)
183189
{
184190
apiDependsOn.Add($"[resourceId('Microsoft.Resources/deployments', '{previousAPI}')]");
@@ -240,6 +246,32 @@ public MasterTemplateResource CreateLinkedMasterTemplateResource(string name, st
240246
return masterTemplateResource;
241247
}
242248

249+
public string GetDependsOnPreviousApiVersion(APIConfig api, IDictionary<string, string[]> apiVersions)
250+
{
251+
if (api?.apiVersionSetId == null)
252+
return null;
253+
254+
// get all apis associated with the same versionSet
255+
// versions must be deployed in sequence and thus
256+
// each api must depend on the previous version.
257+
258+
var versions = apiVersions.ContainsKey(api.apiVersionSetId)
259+
? apiVersions[api.apiVersionSetId]
260+
: null
261+
;
262+
263+
var index = Array.IndexOf(versions, api.name);
264+
var previous = index > 0
265+
? (int?)index - 1
266+
: null
267+
;
268+
269+
return previous.HasValue
270+
? versions[previous.Value]
271+
: null
272+
;
273+
}
274+
243275
public Dictionary<string, TemplateParameterProperties> CreateMasterTemplateParameters(CreatorConfig creatorConfig)
244276
{
245277
// used to create the parameter metatadata, etc (not value) for use in file with resources
@@ -417,6 +449,7 @@ public class LinkedMasterTemplateAPIInformation
417449
public bool dependsOnAuthorizationServers { get; set; }
418450
public bool dependsOnTags { get; set; }
419451
public bool isServiceUrlParameterize { get; set; }
452+
public string dependsOnVersion { get; set; }
420453
}
421454

422455
}

0 commit comments

Comments
 (0)