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

Commit 337d03b

Browse files
authored
Merge pull request #239 from Azure/lucashh-privatestorage
Lucashh privatestorage
2 parents 6e37a6b + 79b6ab0 commit 337d03b

File tree

14 files changed

+302
-55
lines changed

14 files changed

+302
-55
lines changed

src/APIM_ARMTemplate/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ The utility requires one argument, --configFile, which points to a yaml file tha
2222
|-----------------------|-----------------------|-----------------------|--------------------------------------------------|
2323
| version | string | Yes | Configuration version. |
2424
| apimServiceName | string | Yes | Name of the APIM service to deploy resources into. |
25+
| policy | string | No | Location of the global service policy XML file. Can be url or local file. |
2526
| apiVersionSets | Array<[APIVersionSetConfiguration](#APIVersionSetConfiguration)> | No | List of API Version Set configurations. |
2627
| apis | Array<[APIConfiguration](#APIConfiguration)> | Yes | List of API configurations. |
2728
| products | Array<[ProductConfiguration](#ProductConfiguration)> | No | List of Product configurations. |
@@ -31,6 +32,7 @@ The utility requires one argument, --configFile, which points to a yaml file tha
3132
| outputLocation | string | Yes | Local folder the utility will write templates to. |
3233
| linked | boolean | No | Determines whether the utility should create a master template that links to all generated templates. |
3334
| linkedTemplatesBaseUrl| string | No | Location that stores linked templates. Required if 'linked' is set to true. |
35+
| linkedTemplatesUrlQueryString| string | No | Query string appended to linked templates uris that enables retrieval from private storage. |
3436

3537
#### APIConfiguration
3638

@@ -101,6 +103,7 @@ The following is a full config.yml file with each property listed:
101103
```
102104
version: 0.0.1
103105
apimServiceName: myAPIMService
106+
policy: C:\Users\myUsername\Projects\azure-api-management-devops-example\src\APIM_ARMTemplate\apimtemplate\Creator\ExampleFiles\XMLPolicies\globalServicePolicy.xml
104107
apiVersionSets:
105108
- id: myAPIVersionSetID
106109
displayName: swaggerPetstoreVersionSetLinked
@@ -227,6 +230,7 @@ backends:
227230
outputLocation: C:\Users\myUsername\GeneratedTemplates
228231
linked: false
229232
linkedTemplatesBaseUrl : https://mystorageaccount.blob.core.windows.net/mycontainer
233+
linkedTemplatesUrlQueryString : ?sv=2018-03-28&ss=bfqt&srt=sco&sp=rwdlacup&se=2019-12-22T23:12:53Z&st=2019-09-09T14:12:53Z&spr=https&sig=uFTldJEYPH888QVzKb7q7eLq0Xt%2Bu35UTqpFGUYo6uc%3D
230234
```
231235

232236
<a name="creator2"></a>
@@ -273,6 +277,7 @@ az account set --subscription <subscription_id>
273277
| fileFolder | Yes | Path to output folder |
274278
| apiName | No | Name of API. If provided, Extractor executes single API extraction. Otherwise, Extractor executes full extraction. Note: This is the "Name" value as seen in the API settings, not "Display Name" and is case sensitive. |
275279
| linkedTemplatesBaseUrl| No | Linked templates remote location. If provided, Extractor generates master template and requires linked templates pushed to remote location. |
280+
| linkedTemplatesUrlQueryString | string | No | Query string appended to linked templates uris that enables retrieval from private storage. |
276281
| policyXMLBaseUrl | No | Policy XML files remote location. If provided, Extractor generates policies folder with xml files, and requires they be pushed to remote location. |
277282

278283
To run the Extractor with all arguments (executing a single API extraction with linked templates and policy file generation), use the following command:

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,21 @@ public class MasterTemplateCreatorTests
1111
public void ShouldCreateCorrectNumberOfDeploymentResources()
1212
{
1313
// arrange
14-
CreatorConfig creatorConfig = new CreatorConfig() { apimServiceName = "apimService" };
14+
CreatorConfig creatorConfig = new CreatorConfig() { apimServiceName = "apimService", linked = true };
1515
MasterTemplateCreator masterTemplateCreator = new MasterTemplateCreator();
1616
Template apiVersionSetsTemplate = new Template();
17+
Template globalServicePolicyTemplate = new Template();
1718
Template productsTemplate = new Template();
1819
Template loggersTemplate = new Template();
1920
List<LinkedMasterTemplateAPIInformation> apiInfoList = new List<LinkedMasterTemplateAPIInformation>() { new LinkedMasterTemplateAPIInformation() { name = "api", isSplit = true } };
2021
FileNameGenerator fileNameGenerator = new FileNameGenerator();
2122
FileNames creatorFileNames = fileNameGenerator.GenerateFileNames(creatorConfig.apimServiceName);
2223

23-
// should create 5 resources (apiVersionSet, product, logger, both api templates)
24-
int count = 5;
24+
// should create 6 resources (globalServicePolicy, apiVersionSet, product, logger, both api templates)
25+
int count = 6;
2526

2627
// act
27-
Template masterTemplate = masterTemplateCreator.CreateLinkedMasterTemplate(apiVersionSetsTemplate, productsTemplate, loggersTemplate, null, null, apiInfoList, creatorFileNames, creatorConfig.apimServiceName, fileNameGenerator);
28+
Template masterTemplate = masterTemplateCreator.CreateLinkedMasterTemplate(creatorConfig, globalServicePolicyTemplate, apiVersionSetsTemplate, productsTemplate, loggersTemplate, null, null, apiInfoList, creatorFileNames, creatorConfig.apimServiceName, fileNameGenerator);
2829

2930
// assert
3031
Assert.Equal(count, masterTemplate.resources.Length);
@@ -55,13 +56,13 @@ public void ShouldCreateCorrectNumberOfParameterValuesWhenLinked()
5556
public void ShouldCreateCorrectNumberOfParametersWhenUnlinked()
5657
{
5758
// arrange
59+
CreatorConfig creatorConfig = new CreatorConfig() { apimServiceName = "apimService", linked = false };
5860
MasterTemplateCreator masterTemplateCreator = new MasterTemplateCreator();
59-
bool linked = false;
6061
// unlinked templates result in 1 value
6162
int count = 1;
6263

6364
// act
64-
Dictionary<string, TemplateParameterProperties> masterTemplateParameters = masterTemplateCreator.CreateMasterTemplateParameters(linked);
65+
Dictionary<string, TemplateParameterProperties> masterTemplateParameters = masterTemplateCreator.CreateMasterTemplateParameters(creatorConfig);
6566

6667
// assert
6768
Assert.Equal(count, masterTemplateParameters.Keys.Count);
@@ -84,5 +85,20 @@ public void ShouldCreateLinkedMasterTemplateResourceFromValues()
8485
Assert.Equal(uriLink, masterTemplateResource.properties.templateLink.uri);
8586
Assert.Equal(dependsOn, masterTemplateResource.dependsOn);
8687
}
88+
89+
[Fact]
90+
public void ShouldCreateCorrectLinkedUri()
91+
{
92+
// arrange
93+
MasterTemplateCreator masterTemplateCreator = new MasterTemplateCreator();
94+
CreatorConfig creatorConfig = new CreatorConfig() { apimServiceName = "apimService", linked = true, linkedTemplatesBaseUrl = "http://someurl.com", linkedTemplatesUrlQueryString = "?param=1" };
95+
string apiVersionSetFileName = "/versionSet1-apiVersionSets.template.json";
96+
97+
// act
98+
string linkedResourceUri = masterTemplateCreator.GenerateLinkedTemplateUri(creatorConfig, apiVersionSetFileName);
99+
100+
// assert
101+
Assert.Equal($"[concat(parameters('LinkedTemplatesBaseUrl'), '{apiVersionSetFileName}', parameters('LinkedTemplatesUrlQueryString'))]", linkedResourceUri);
102+
}
87103
}
88104
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,23 @@ namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Test
77
{
88
public class PolicyTemplateCreatorTests
99
{
10+
[Fact]
11+
public void ShouldCreateGlobalServicePolicyTemplateResourceFromCreatorConfigWithCorrectContent()
12+
{
13+
// arrange
14+
PolicyTemplateCreator policyTemplateCreator = PolicyTemplateCreatorFactory.GeneratePolicyTemplateCreator();
15+
CreatorConfig creatorConfig = new CreatorConfig() { policy = "http://someurl.com" };
16+
17+
// act
18+
Template policyTemplate = policyTemplateCreator.CreateGlobalServicePolicyTemplate(creatorConfig);
19+
PolicyTemplateResource policyTemplateResource = policyTemplate.resources[0] as PolicyTemplateResource;
20+
21+
// assert
22+
Assert.Equal($"[concat(parameters('ApimServiceName'), '/policy')]", policyTemplateResource.name);
23+
Assert.Equal("rawxml-link", policyTemplateResource.properties.format);
24+
Assert.Equal(creatorConfig.policy, policyTemplateResource.properties.value);
25+
}
26+
1027
[Fact]
1128
public void ShouldCreateAPIPolicyTemplateResourceFromCreatorConfigWithCorrectContent()
1229
{

src/APIM_ARMTemplate/apimtemplate/Commands/Create.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public CreateCommand()
5050
MasterTemplateCreator masterTemplateCreator = new MasterTemplateCreator();
5151

5252
// create templates from provided configuration
53+
Console.WriteLine("Creating global service policy template");
54+
Console.WriteLine("------------------------------------------");
55+
Template globalServicePolicyTemplate = creatorConfig.policy != null ? policyTemplateCreator.CreateGlobalServicePolicyTemplate(creatorConfig) : null;
5356
Console.WriteLine("Creating API version set template");
5457
Console.WriteLine("------------------------------------------");
5558
Template apiVersionSetsTemplate = creatorConfig.apiVersionSets != null ? apiVersionSetTemplateCreator.CreateAPIVersionSetTemplate(creatorConfig) : null;
@@ -81,6 +84,7 @@ public CreateCommand()
8184
{
8285
name = api.name,
8386
isSplit = apiTemplateCreator.isSplitAPI(api),
87+
dependsOnGlobalServicePolicies = creatorConfig.policy != null,
8488
dependsOnVersionSets = api.apiVersionSetId != null,
8589
dependsOnProducts = api.products != null,
8690
dependsOnLoggers = await masterTemplateCreator.DetermineIfAPIDependsOnLoggerAsync(api, fileReader),
@@ -96,17 +100,21 @@ public CreateCommand()
96100
if (creatorConfig.linked == true)
97101
{
98102
// create linked master template
99-
Template masterTemplate = masterTemplateCreator.CreateLinkedMasterTemplate(apiVersionSetsTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, apiInformation, fileNames, creatorConfig.apimServiceName, fileNameGenerator);
103+
Template masterTemplate = masterTemplateCreator.CreateLinkedMasterTemplate(creatorConfig, globalServicePolicyTemplate, apiVersionSetsTemplate, productsTemplate, loggersTemplate, backendsTemplate, authorizationServersTemplate, apiInformation, fileNames, creatorConfig.apimServiceName, fileNameGenerator);
100104
fileWriter.WriteJSONToFile(masterTemplate, String.Concat(creatorConfig.outputLocation, fileNames.linkedMaster));
101105
}
102106
foreach (Template apiTemplate in apiTemplates)
103107
{
104108
APITemplateResource apiResource = apiTemplate.resources.FirstOrDefault(resource => resource.type == ResourceTypeConstants.API) as APITemplateResource;
105-
APIConfig providedAPIConfiguration = creatorConfig.apis.FirstOrDefault(api => apiResource.properties.displayName.Equals(api.name, StringComparison.Ordinal));
109+
APIConfig providedAPIConfiguration = creatorConfig.apis.FirstOrDefault(api => apiResource.name.Contains(api.name, StringComparison.Ordinal));
106110
// if the api version is not null the api is split into multiple templates. If the template is split and the content value has been set, then the template is for a subsequent api
107111
string apiFileName = fileNameGenerator.GenerateCreatorAPIFileName(providedAPIConfiguration.name, apiTemplateCreator.isSplitAPI(providedAPIConfiguration), apiResource.properties.value == null, creatorConfig.apimServiceName);
108112
fileWriter.WriteJSONToFile(apiTemplate, String.Concat(creatorConfig.outputLocation, apiFileName));
109113
}
114+
if (globalServicePolicyTemplate != null)
115+
{
116+
fileWriter.WriteJSONToFile(globalServicePolicyTemplate, String.Concat(creatorConfig.outputLocation, fileNames.globalServicePolicy));
117+
}
110118
if (apiVersionSetsTemplate != null)
111119
{
112120
fileWriter.WriteJSONToFile(apiVersionSetsTemplate, String.Concat(creatorConfig.outputLocation, fileNames.apiVersionSets));

src/APIM_ARMTemplate/apimtemplate/Commands/Extract.cs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public ExtractCommand()
1919
var fileFolderName = this.Option("--fileFolder <filefolder>", "ARM Template files folder", CommandOptionType.SingleValue);
2020
var apiName = this.Option("--apiName <apiName>", "API name", CommandOptionType.SingleValue);
2121
var linkedTemplatesBaseUrlName = this.Option("--linkedTemplatesBaseUrl <linkedTemplatesBaseUrl>", "Creates a master template with links", CommandOptionType.SingleValue);
22+
var linkedTemplatesUrlQueryString = this.Option("--linkedTemplatesUrlQueryString <linkedTemplatesUrlQueryString>", "Query string appended to linked templates uris that enables retrieval from private storage", CommandOptionType.SingleValue);
2223
var policyXMLBaseUrlName = this.Option("--policyXMLBaseUrl <policyXMLBaseUrl>", "Writes policies to local XML files that require deployment to remote folder", CommandOptionType.SingleValue);
2324

2425
this.HelpOption();
@@ -33,17 +34,18 @@ public ExtractCommand()
3334
if (!fileFolderName.HasValue()) throw new Exception("Missing parameter <filefolder>.");
3435

3536
// isolate cli parameters
36-
string resourceGroup = resourceGroupName.Values[0].ToString();
37-
string sourceApim = sourceApimName.Values[0].ToString();
38-
string destinationApim = destinationAPIManagementName.Values[0].ToString();
39-
string fileFolder = fileFolderName.Values[0].ToString();
37+
string resourceGroup = resourceGroupName.Value().ToString();
38+
string sourceApim = sourceApimName.Value().ToString();
39+
string destinationApim = destinationAPIManagementName.Value().ToString();
40+
string fileFolder = fileFolderName.Value().ToString();
4041
string linkedBaseUrl = linkedTemplatesBaseUrlName.HasValue() ? linkedTemplatesBaseUrlName.Value().ToString() : null;
42+
string linkedUrlQueryString = linkedTemplatesUrlQueryString.HasValue() ? linkedTemplatesUrlQueryString.Value().ToString() : null;
4143
string policyXMLBaseUrl = policyXMLBaseUrlName.HasValue() ? policyXMLBaseUrlName.Value().ToString() : null;
4244
string singleApiName = null;
4345

4446
if (apiName.Values.Count > 0)
4547
{
46-
singleApiName = apiName.Values[0].ToString();
48+
singleApiName = apiName.Value().ToString();
4749
}
4850

4951
Console.WriteLine("API Management Template");
@@ -69,11 +71,13 @@ public ExtractCommand()
6971
AuthorizationServerExtractor authorizationServerExtractor = new AuthorizationServerExtractor();
7072
BackendExtractor backendExtractor = new BackendExtractor();
7173
LoggerExtractor loggerExtractor = new LoggerExtractor();
74+
PolicyExtractor policyExtractor = new PolicyExtractor(fileWriter);
7275
PropertyExtractor propertyExtractor = new PropertyExtractor();
7376
ProductExtractor productExtractor = new ProductExtractor(fileWriter);
7477
MasterTemplateExtractor masterTemplateExtractor = new MasterTemplateExtractor();
7578

7679
// extract templates from apim service
80+
Template globalServicePolicyTemplate = await policyExtractor.GenerateGlobalServicePolicyTemplateAsync(sourceApim, resourceGroup, policyXMLBaseUrl, fileFolder);
7781
Template apiTemplate = await apiExtractor.GenerateAPIsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, policyXMLBaseUrl, fileFolder);
7882
List<TemplateResource> apiTemplateResources = apiTemplate.resources.ToList();
7983
Template apiVersionSetTemplate = await apiVersionSetExtractor.GenerateAPIVersionSetsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, policyXMLBaseUrl);
@@ -85,7 +89,7 @@ public ExtractCommand()
8589
Template backendTemplate = await backendExtractor.GenerateBackendsARMTemplateAsync(sourceApim, resourceGroup, singleApiName, apiTemplateResources, namedValueResources, policyXMLBaseUrl);
8690

8791
// create parameters file
88-
Template templateParameters = masterTemplateExtractor.CreateMasterTemplateParameterValues(destinationApim, linkedBaseUrl, policyXMLBaseUrl);
92+
Template templateParameters = masterTemplateExtractor.CreateMasterTemplateParameterValues(destinationApim, linkedBaseUrl, linkedUrlQueryString, policyXMLBaseUrl);
8993

9094
// write templates to output file location
9195
string apiFileName = fileNameGenerator.GenerateExtractorAPIFileName(singleApiName, sourceApim);
@@ -96,11 +100,12 @@ public ExtractCommand()
96100
fileWriter.WriteJSONToFile(loggerTemplate, String.Concat(@fileFolder, fileNames.loggers));
97101
fileWriter.WriteJSONToFile(namedValueTemplate, String.Concat(@fileFolder, fileNames.namedValues));
98102
fileWriter.WriteJSONToFile(productTemplate, String.Concat(@fileFolder, fileNames.products));
103+
fileWriter.WriteJSONToFile(globalServicePolicyTemplate, String.Concat(@fileFolder, fileNames.globalServicePolicy));
99104

100105
if (linkedBaseUrl != null)
101106
{
102107
// create a master template that links to all other templates
103-
Template masterTemplate = masterTemplateExtractor.GenerateLinkedMasterTemplate(apiTemplate, apiVersionSetTemplate, productTemplate, loggerTemplate, backendTemplate, authorizationServerTemplate, namedValueTemplate, fileNames, apiFileName, policyXMLBaseUrl);
108+
Template masterTemplate = masterTemplateExtractor.GenerateLinkedMasterTemplate(apiTemplate, globalServicePolicyTemplate, apiVersionSetTemplate, productTemplate, loggerTemplate, backendTemplate, authorizationServerTemplate, namedValueTemplate, fileNames, apiFileName, linkedUrlQueryString, policyXMLBaseUrl);
104109
fileWriter.WriteJSONToFile(masterTemplate, String.Concat(@fileFolder, fileNames.linkedMaster));
105110
}
106111

src/APIM_ARMTemplate/apimtemplate/Common/Constants/ResourceTypeConstants.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal static class ResourceTypeConstants
1313
public const string APISchema = "Microsoft.ApiManagement/service/apis/schemas";
1414
public const string AuthorizationServer = "Microsoft.ApiManagement/service/authorizationServers";
1515
public const string Backend = "Microsoft.ApiManagement/service/backends";
16+
public const string GlobalServicePolicy = "Microsoft.ApiManagement/service/policies";
1617
public const string Logger = "Microsoft.ApiManagement/service/loggers";
1718
public const string ProductAPI = "Microsoft.ApiManagement/service/products/apis";
1819
public const string Product = "Microsoft.ApiManagement/service/products";

0 commit comments

Comments
 (0)