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

Commit 4ef967b

Browse files
f-alizadaFarhad Alizada
and
Farhad Alizada
authored
Parametrize backend proxy (#787)
* Parametrize backend proxy Co-authored-by: Farhad Alizada <[email protected]>
1 parent 3b04442 commit 4ef967b

File tree

13 files changed

+282
-1
lines changed

13 files changed

+282
-1
lines changed

src/ArmTemplates/Common/Constants/GlobalConstants.cs

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public static class ParameterNames
4444
public const string SecretValues = "secretValues";
4545
public const string IdentityProvidersSecretValues = "identityProviders";
4646
public const string OpenIdConnectProvidersSecretValues = "openIdConnectProviders";
47+
public const string BackendProxy = "backendProxy";
4748
}
4849

4950
public static class ParameterPrefix
@@ -54,5 +55,6 @@ public static class ParameterPrefix
5455
public const string LogResourceId = "LogResourceId";
5556
public const string Backend = "Backend";
5657
public const string ApiOauth2Scope = "ApiOauth2Scope";
58+
public const string BackendProxy = "BackendProxy";
5759
}
5860
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// --------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License.
4+
// --------------------------------------------------------------------------
5+
6+
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Backend
7+
{
8+
public class BackendProxyParameters
9+
{
10+
public string Url { get; set; }
11+
12+
public string Username { get; set; }
13+
14+
public string Password { get; set; }
15+
}
16+
}

src/ArmTemplates/Common/Templates/Backend/BackendTemplateResources.cs

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ public class BackendTemplateResources : ITemplateResources
1515

1616
public IDictionary<string, BackendApiParameters> BackendNameParametersCache { get; set; } = new Dictionary<string, BackendApiParameters>();
1717

18+
public IDictionary<string, BackendProxyParameters> BackendProxyParametersCache { get; set; } = new Dictionary<string, BackendProxyParameters>();
19+
1820
public TemplateResource[] BuildTemplateResources()
1921
{
2022
return this.Backends.ToArray();

src/ArmTemplates/Common/Templates/Builders/TemplateBuilder.Backend.cs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public TemplateBuilder AddParameterizedBackendSettings(ExtractorParameters extra
2121
Type = "object"
2222
};
2323
this.template.Parameters.Add(ParameterNames.BackendSettings, extractBackendParametersProperties);
24+
this.template.Parameters.Add(ParameterNames.BackendProxy, extractBackendParametersProperties);
2425
}
2526

2627
return this;

src/ArmTemplates/Extractor/EntityExtractors/BackendExtractor.cs

+21
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,27 @@ void SaveBackendApiParametersToCache()
134134
{
135135
backendTemplate.TypedResources.BackendNameParametersCache.Add(backendValidName, backendApiParameters);
136136
}
137+
138+
if (backendResource.Properties.Proxy != null)
139+
{
140+
var proxyUniqueId = $"{backendResource.Properties.Proxy.Url}_{backendResource.Properties.Proxy.Username}";
141+
var backendProxyParameterName = NamingHelper.GenerateValidParameterName(proxyUniqueId, ParameterPrefix.BackendProxy);
142+
143+
if (!backendTemplate.TypedResources.BackendProxyParametersCache.ContainsKey(backendProxyParameterName))
144+
{
145+
var backendProxyParameters = new BackendProxyParameters
146+
{
147+
Url = backendResource.Properties.Proxy.Url,
148+
Username = backendResource.Properties.Proxy.Username,
149+
Password = backendResource.Properties.Proxy.Password
150+
};
151+
backendTemplate.TypedResources.BackendProxyParametersCache.Add(backendProxyParameterName, backendProxyParameters);
152+
}
153+
154+
backendResource.Properties.Proxy.Url = $"[parameters('{ParameterNames.BackendProxy}').{backendProxyParameterName}.url]";
155+
backendResource.Properties.Proxy.Username = $"[parameters('{ParameterNames.BackendProxy}').{backendProxyParameterName}.username]";
156+
backendResource.Properties.Proxy.Password = $"[parameters('{ParameterNames.BackendProxy}').{backendProxyParameterName}.password]";
157+
}
137158
}
138159
}
139160

src/ArmTemplates/Extractor/EntityExtractors/MasterTemplateExtractor.cs

+7
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ public Template<MasterTemplateResources> GenerateLinkedMasterTemplate(
202202
{
203203
backendsDeployment.Properties.Parameters.Add(ParameterNames.BackendSettings,
204204
new TemplateParameterProperties() { Value = $"[parameters('{ParameterNames.BackendSettings}')]" });
205+
206+
backendsDeployment.Properties.Parameters.Add(ParameterNames.BackendProxy,
207+
new TemplateParameterProperties() { Value = $"[parameters('{ParameterNames.BackendProxy}')]" });
205208
}
206209

207210
masterResources.DeploymentResources.Add(backendsDeployment);
@@ -497,6 +500,10 @@ Dictionary<string, TemplateParameterProperties> CreateMasterTemplateParameters(E
497500
parameters.Add(
498501
ParameterNames.BackendSettings,
499502
new TemplateParameterProperties(metadataDescription: "The settings for the Backends", type: "object"));
503+
504+
parameters.Add(
505+
ParameterNames.BackendProxy,
506+
new TemplateParameterProperties(metadataDescription: "The proxies for the Backends", type: "object"));
500507
}
501508

502509
if (extractorParameters.ParametrizeApiOauth2Scope)

src/ArmTemplates/Extractor/EntityExtractors/ParametersExtractor.cs

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ async Task AddSecretValuesParameters()
268268
if (extractorParameters.ParameterizeBackend)
269269
{
270270
parameters.Add(ParameterNames.BackendSettings, new TemplateObjectParameterProperties() { Value = backendResources.BackendNameParametersCache });
271+
parameters.Add(ParameterNames.BackendProxy, new TemplateObjectParameterProperties() { Value = backendResources.BackendProxyParametersCache });
271272
}
272273

273274
return parametersTemplate;

tests/ArmTemplates.Tests/Extractor/Scenarios/ApiReleaseExtractorTests.cs

-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ public async Task GenerateAllCurrentApiReleaseTemplateAsync_ProperlyCreatesTempl
9191
apiReleasesTemplate.TypedResources.ApiReleases.Any(x => x.Properties.ApiId.Contains($"/apis/echo-api;rev=1")).Should().BeTrue();
9292
apiReleasesTemplate.TypedResources.ApiReleases.Any(x => x.Properties.ApiId.Contains($"/apis/5a7390baa5816a110435aee0;rev=1")).Should().BeTrue();
9393
apiReleasesTemplate.TypedResources.ApiReleases.Any(x => x.Properties.ApiId.Contains($"/apis/5a73933b8f27f7cc82a2d533;rev=1")).Should().BeTrue();
94-
9594
}
9695
}
9796
}

tests/ArmTemplates.Tests/Extractor/Scenarios/BackendExtractorTests.cs

+56
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public async Task GenerateBackendTemplates_ProperlyLaysTheInformation()
7272

7373
backendTemplate.Parameters.Should().ContainKey(ParameterNames.ApimServiceName);
7474
backendTemplate.Parameters.Should().ContainKey(ParameterNames.BackendSettings);
75+
backendTemplate.Parameters.Should().ContainKey(ParameterNames.BackendProxy);
7576

7677
backendTemplate.TypedResources.Backends.Should().HaveCount(1);
7778
backendTemplate.Resources.Should().HaveCount(1);
@@ -83,6 +84,61 @@ public async Task GenerateBackendTemplates_ProperlyLaysTheInformation()
8384
backendProperties.Should().NotBeNull();
8485
backendProperties.Url.Should().Contain(ParameterNames.BackendSettings);
8586
backendProperties.Protocol.Should().Contain(ParameterNames.BackendSettings);
87+
88+
backendProperties.Proxy.Password.Should().Contain(ParameterNames.BackendProxy);
89+
backendProperties.Proxy.Username.Should().Contain(ParameterNames.BackendProxy);
90+
backendProperties.Proxy.Url.Should().Contain(ParameterNames.BackendProxy);
91+
}
92+
93+
[Fact]
94+
public async Task GenerateBackendTemplate_ProperlyParsesAndGeneratesTemplate()
95+
{
96+
// arrange
97+
var responseFileLocation = Path.Combine(MockClientUtils.ApiClientJsonResponsesPath, "ApiManagementListBackends_success_response.json");
98+
var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(GenerateBackendTemplate_ProperlyParsesAndGeneratesTemplate));
99+
100+
var mockedClient = await MockBackendClient.GetMockedHttpApiClient(responseFileLocation);
101+
102+
var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration(
103+
apiName: string.Empty,
104+
paramBackend: "true");
105+
var extractorParameters = new ExtractorParameters(extractorConfig);
106+
107+
// mocked extractors
108+
var backendExtractor = new BackendExtractor(
109+
this.GetTestLogger<BackendExtractor>(),
110+
new TemplateBuilder(),
111+
null,
112+
mockedClient);
113+
114+
var extractorExecutor = ExtractorExecutor.BuildExtractorExecutor(
115+
this.GetTestLogger<ExtractorExecutor>(),
116+
backendExtractor: backendExtractor);
117+
extractorExecutor.SetExtractorParameters(extractorParameters);
118+
119+
// act
120+
var backendTemplate = await extractorExecutor.GenerateBackendTemplateAsync(null, null, null, currentTestDirectory);
121+
122+
// assert
123+
File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.Backends)).Should().BeTrue();
124+
125+
backendTemplate.Parameters.Should().ContainKey(ParameterNames.ApimServiceName);
126+
backendTemplate.Parameters.Should().ContainKey(ParameterNames.BackendSettings);
127+
backendTemplate.Parameters.Should().ContainKey(ParameterNames.BackendProxy);
128+
129+
130+
backendTemplate.TypedResources.Backends.Count().Should().Be(3);
131+
backendTemplate.TypedResources.Backends.All(x => x.Type.Equals(ResourceTypeConstants.Backend)).Should().BeTrue();
132+
133+
var proxyBackend1 = backendTemplate.TypedResources.Backends.First(x => x.Name.Contains("proxybackend1"));
134+
proxyBackend1.Properties.Proxy.Password.Should().Contain(ParameterNames.BackendProxy);
135+
proxyBackend1.Properties.Proxy.Username.Should().Contain(ParameterNames.BackendProxy);
136+
proxyBackend1.Properties.Proxy.Url.Should().Contain(ParameterNames.BackendProxy);
137+
138+
var proxyBackend2 = backendTemplate.TypedResources.Backends.First(x => x.Name.Contains("proxybackend2"));
139+
proxyBackend2.Properties.Proxy.Password.Should().Contain(ParameterNames.BackendProxy);
140+
proxyBackend2.Properties.Proxy.Username.Should().Contain(ParameterNames.BackendProxy);
141+
proxyBackend2.Properties.Proxy.Url.Should().Contain(ParameterNames.BackendProxy);
86142
}
87143
}
88144
}

tests/ArmTemplates.Tests/Extractor/Scenarios/MasterTemplateExtractorTests.cs

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ public async Task GenerateMasterTemplates_ProperlyLaysTheInformation()
179179
masterTemplate.Parameters.Should().ContainKey(ParameterNames.LoggerResourceId);
180180
masterTemplate.Parameters.Should().ContainKey(ParameterNames.NamedValueKeyVaultSecrets);
181181
masterTemplate.Parameters.Should().ContainKey(ParameterNames.BackendSettings);
182+
masterTemplate.Parameters.Should().ContainKey(ParameterNames.BackendProxy);
182183
masterTemplate.Parameters.Should().ContainKey(ParameterNames.PolicyXMLBaseUrl);
183184
masterTemplate.Parameters.Should().ContainKey(ParameterNames.PolicyXMLBaseUrl);
184185
masterTemplate.Parameters.Should().ContainKey(ParameterNames.ApiOauth2ScopeSettings);

tests/ArmTemplates.Tests/Extractor/Scenarios/ParametersExtractorTests.cs

+59
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.IdentityProviders;
2121
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Tests.Moqs.IdentityProviderClients;
2222
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.OpenIdConnectProviders;
23+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Backend;
2324

2425
namespace Microsoft.Azure.Management.ApiManagement.ArmTemplates.Tests.Extractor.Scenarios
2526
{
@@ -432,5 +433,63 @@ public void CreateResourceTemplateParameterTemplate_ProperlyGeneratesTemplate_Wi
432433
resourceTemplateParameterTemplate.Parameters["parameter1"].Should().NotBeNull();
433434
resourceTemplateParameterTemplate.Parameters["parameter2"].Should().NotBeNull();
434435
}
436+
437+
[Fact]
438+
public async Task CreateResourceTemplateParameterTemplate_ProperlyGeneratesTemplate_WithBackendProxySettings()
439+
{
440+
// arrange
441+
var currentTestDirectory = Path.Combine(this.OutputDirectory, nameof(CreateResourceTemplateParameterTemplate_ProperlyGeneratesTemplate_WithBackendProxySettings));
442+
443+
var extractorConfig = this.GetDefaultExtractorConsoleAppConfiguration(paramBackend: "true");
444+
var extractorParameters = new ExtractorParameters(extractorConfig);
445+
var extractorExecutor = this.GetExtractorInstance(extractorParameters, null);
446+
447+
var backends = new BackendTemplateResources()
448+
{
449+
BackendNameParametersCache = new Dictionary<string, BackendApiParameters>()
450+
{
451+
{ "key1", new BackendApiParameters() { Protocol = "protocol", ResourceId = "resourceId", Url = "url" } }
452+
},
453+
BackendProxyParametersCache = new Dictionary<string, BackendProxyParameters>()
454+
{
455+
{ "key1", new BackendProxyParameters() { Username = "username", Url = "url" } }
456+
},
457+
Backends = new List<BackendTemplateResource>()
458+
{
459+
{
460+
new BackendTemplateResource
461+
{
462+
Name = "test"
463+
}
464+
}
465+
}
466+
};
467+
468+
// act
469+
var parametersTemplate = await extractorExecutor.GenerateParametersTemplateAsync(null, null, backends, null, new IdentityProviderResources(), new OpenIdConnectProviderResources(), currentTestDirectory);
470+
471+
File.Exists(Path.Combine(currentTestDirectory, extractorParameters.FileNames.Parameters)).Should().BeTrue();
472+
473+
parametersTemplate.Parameters.Should().ContainKey(ParameterNames.BackendProxy);
474+
parametersTemplate.Parameters.Should().ContainKey(ParameterNames.BackendSettings);
475+
476+
var backendProxyParameters = (TemplateObjectParameterProperties)parametersTemplate.Parameters[ParameterNames.BackendProxy];
477+
var backendProxyParameterValues = (Dictionary<string, BackendProxyParameters>)backendProxyParameters.Value;
478+
479+
backendProxyParameterValues.Should().NotBeNull();
480+
backendProxyParameterValues.ContainsKey("key1").Should().BeTrue();
481+
backendProxyParameterValues["key1"].Username.Should().Be("username");
482+
backendProxyParameterValues["key1"].Url.Should().Be("url");
483+
484+
485+
var backendSettingsParameters = (TemplateObjectParameterProperties)parametersTemplate.Parameters[ParameterNames.BackendSettings];
486+
var backendSettingsParameterValues = (Dictionary<string, BackendApiParameters>)backendSettingsParameters.Value;
487+
488+
backendSettingsParameterValues.Should().NotBeNull();
489+
backendSettingsParameterValues.ContainsKey("key1").Should().BeTrue();
490+
backendSettingsParameterValues["key1"].Protocol.Should().Be("protocol");
491+
backendSettingsParameterValues["key1"].ResourceId.Should().Be("resourceId");
492+
backendSettingsParameterValues["key1"].Url.Should().Be("url");
493+
}
435494
}
436495
}

tests/ArmTemplates.Tests/Moqs/ApiClients/MockBackendClient.cs

+10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
// --------------------------------------------------------------------------
55

66
using System.Collections.Generic;
7+
using System.Threading.Tasks;
78
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Abstractions;
9+
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.API.Clients.Backend;
810
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Common.Templates.Backend;
911
using Microsoft.Azure.Management.ApiManagement.ArmTemplates.Extractor.Models;
1012
using Moq;
@@ -43,5 +45,13 @@ public static IBackendClient GetMockedApiClientWithDefaultValues()
4345

4446
return mockBackendClient.Object;
4547
}
48+
49+
public static async Task<IBackendClient> GetMockedHttpApiClient(string responseFileLocation)
50+
{
51+
var mockedClient = new Mock<BackendClient>(MockBehavior.Strict, await MockClientUtils.GenerateMockedIHttpClientFactoryWithResponse(responseFileLocation));
52+
MockClientUtils.MockAuthOfApiClient(mockedClient);
53+
54+
return mockedClient.Object;
55+
}
4656
}
4757
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
{
2+
"value": [
3+
{
4+
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/backends/proxybackend1",
5+
"type": "Microsoft.ApiManagement/service/backends",
6+
"name": "proxybackend1",
7+
"properties": {
8+
"description": "description5308",
9+
"url": "https://backendname2644/",
10+
"protocol": "http",
11+
"credentials": {
12+
"query": {
13+
"sv": [
14+
"xx",
15+
"bb",
16+
"cc"
17+
]
18+
},
19+
"header": {
20+
"x-my-1": [
21+
"val1",
22+
"val2"
23+
]
24+
},
25+
"authorization": {
26+
"scheme": "Basic",
27+
"parameter": "opensesma"
28+
}
29+
},
30+
"proxy": {
31+
"url": "http://192.168.1.1:8080",
32+
"username": "Contoso\\admin",
33+
"password": "<password>"
34+
},
35+
"tls": {
36+
"validateCertificateChain": false,
37+
"validateCertificateName": false
38+
}
39+
}
40+
},
41+
{
42+
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/backends/proxybackend2",
43+
"type": "Microsoft.ApiManagement/service/backends",
44+
"name": "proxybackend2",
45+
"properties": {
46+
"description": "description5308",
47+
"url": "https://backendname2644/",
48+
"protocol": "http",
49+
"credentials": {
50+
"query": {
51+
"sv": [
52+
"xx",
53+
"bb",
54+
"cc"
55+
]
56+
},
57+
"header": {
58+
"x-my-1": [
59+
"val1",
60+
"val2"
61+
]
62+
},
63+
"authorization": {
64+
"scheme": "Basic",
65+
"parameter": "opensesma"
66+
}
67+
},
68+
"proxy": {
69+
"url": "http://192.168.1.1:8080",
70+
"username": "Contoso\\admin",
71+
"password": "<password>"
72+
},
73+
"tls": {
74+
"validateCertificateChain": false,
75+
"validateCertificateName": false
76+
}
77+
}
78+
},
79+
{
80+
"id": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/backends/sfbackend",
81+
"type": "Microsoft.ApiManagement/service/backends",
82+
"name": "sfbackend",
83+
"properties": {
84+
"description": "Service Fabric Test App 1",
85+
"url": "fabric:/mytestapp/mytestservice",
86+
"protocol": "http",
87+
"properties": {
88+
"serviceFabricCluster": {
89+
"managementEndpoints": [
90+
"https://somecluster.com"
91+
],
92+
"clientCertificateId": "/subscriptions/subid/resourceGroups/rg1/providers/Microsoft.ApiManagement/service/apimService1/certificates/cert1",
93+
"serverX509Names": [
94+
{
95+
"name": "ServerCommonName1",
96+
"issuerCertificateThumbprint": "IssuerCertificateThumbprint1"
97+
}
98+
],
99+
"maxPartitionResolutionRetries": 5
100+
}
101+
}
102+
}
103+
}
104+
],
105+
"count": 3
106+
}

0 commit comments

Comments
 (0)