Skip to content

Commit 2fd14a3

Browse files
committed
Configured the build to run the integration tests against the DevTest lab created by the build
1 parent b5499f4 commit 2fd14a3

File tree

9 files changed

+161
-126
lines changed

9 files changed

+161
-126
lines changed

.github/workflows/test_azure_devtest_labs_integration.yml

+15-10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
ARM_TEMPLATE_NAME: sqlcollaborative_AzureDataPipelineTools
2929
FUNCTIONS_PROJECT_NAME: DataPipelineTools.Functions
3030
BUILD_CONFIGURATION: Release
31+
RUN_SETTINGS_FILENAME: ./integrationTest.runsettings
3132

3233

3334
# Steps represent a sequence of tasks that will be executed as part of the job
@@ -157,12 +158,12 @@ jobs:
157158
# echo "::set-output name=DEPLOYMENTOUTPUT::$DEPLOYMENTOUTPUT"
158159
159160
echo "Deployment Outputs"
160-
echo "::set-output name=STORAGE_ACCOUNTCONNECTION_STRING::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageAccountConnectionString.value')"
161+
#echo "::set-output name=STORAGE_ACCOUNTCONNECTION_STRING::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageAccountConnectionString.value')"
161162
echo "::set-output name=STORAGE_ACCOUNT_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageAccountName.value')"
162163
echo "::set-output name=FUNCTIONS_APP_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppName.value')"
163164
echo "::set-output name=FUNCTIONS_APP_URI::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppUri.value')"
164165
echo "::set-output name=KEY_VAULT_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.keyVaultName.value')"
165-
echo "::set-output name=FUNCTIONS_APP_KEY::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppKey.value')"
166+
#echo "::set-output name=FUNCTIONS_APP_KEY::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppKey.value')"
166167
echo "::set-output name=RUN_SETTINGS::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.runSettings.value')"
167168
168169
echo "========================================================================================================================================================================================================"
@@ -172,22 +173,21 @@ jobs:
172173
# Runs a set of commands using the runners shell
173174
- name: Show create environment outputs
174175
run: |
175-
echo "ENVIRONMENT_INSTANCE_NAME: ${{ steps.create-devtest-labs-environment.outputs.ENVIRONMENT_INSTANCE_NAME }}"
176-
echo "ENVIRONMENT_INSTANCE_RESOURCE_GROUP_NAME: ${{ steps.create-devtest-labs-environment.outputs.ENVIRONMENT_INSTANCE_RESOURCE_GROUP_NAME }}"
176+
#echo "ENVIRONMENT_INSTANCE_NAME: ${{ steps.create-devtest-labs-environment.outputs.ENVIRONMENT_INSTANCE_NAME }}"
177+
#echo "ENVIRONMENT_INSTANCE_RESOURCE_GROUP_NAME: ${{ steps.create-devtest-labs-environment.outputs.ENVIRONMENT_INSTANCE_RESOURCE_GROUP_NAME }}"
177178
echo "FUNCTIONS_APP_NAME: ${{ steps.create-devtest-labs-environment.outputs.FUNCTIONS_APP_NAME }}"
178179
echo "FUNCTIONS_APP_URI: ${{ steps.create-devtest-labs-environment.outputs.FUNCTIONS_APP_URI }}"
179-
echo "FUNCTIONS_APP_KEY: ${{ steps.create-devtest-labs-environment.outputs.FUNCTIONS_APP_KEY }}"
180-
echo "STORAGE_ACCOUNTCONNECTION_STRING: ${{ steps.create-devtest-labs-environment.outputs.STORAGE_ACCOUNTCONNECTION_STRING }}"
180+
#echo "FUNCTIONS_APP_KEY: ${{ steps.create-devtest-labs-environment.outputs.FUNCTIONS_APP_KEY }}"
181+
#echo "STORAGE_ACCOUNTCONNECTION_STRING: ${{ steps.create-devtest-labs-environment.outputs.STORAGE_ACCOUNTCONNECTION_STRING }}"
181182
echo "STORAGE_ACCOUNT_NAME: ${{ steps.create-devtest-labs-environment.outputs.STORAGE_ACCOUNT_NAME }}"
182183
echo "KEY_VAULT_NAME: ${{ steps.create-devtest-labs-environment.outputs.KEY_VAULT_NAME }}"
183-
echo "RUN_SETTINGS: ${{ steps.create-devtest-labs-environment.outputs.RUN_SETTINGS }}"
184+
echo 'RUN_SETTINGS: ${{ steps.create-devtest-labs-environment.outputs.RUN_SETTINGS }}'
184185
185186

186187
# Write the runsettings output from the ARM script into a file so that the integration tests can use it
187-
- name: Show create environment outputs
188+
- name: Write the DevTest Labs output runsettings to file
188189
run: |
189-
echo "${{ steps.create-devtest-labs-environment.outputs.RUN_SETTINGS }}" > ./integrationTest.runsettings
190-
190+
echo '${{ steps.create-devtest-labs-environment.outputs.RUN_SETTINGS }}' > ${{ env.RUN_SETTINGS_FILENAME }}
191191
# echo "ENVIRONMENT_INSTANCE_RESOURCES: ${{ steps.get-devtest-labs-environment-resources.outputs.ENVIRONMENT_INSTANCE_RESOURCES }}"
192192
# az lab arm-template show --resource-group $RESOURCE_GROUP
193193

@@ -242,4 +242,9 @@ jobs:
242242
package: './${{ env.FUNCTIONS_PROJECT_NAME }}/bin/${{ env.BUILD_CONFIGURATION }}'
243243

244244

245+
- name: Run Integration Tests
246+
run: dotnet test --no-build --configuration ${{ env.BUILD_CONFIGURATION }} --filter TestCategory=IntegrationTest --output ./output --verbosity normal --settings ${{ env.RUN_SETTINGS_FILENAME }}
247+
248+
249+
245250

Azure-DevTestLab/Environments/sqlcollaborative_AzureDataPipelineTools/azuredeploy.json

+26-14
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@
5151

5252
"keyVaultApiVersion": "2021-04-01-preview",
5353
"keyVaultName": "[concat('kv', substring(uniqueString(parameters('branch')), 0, 4), 'xxxx', substring(parameters('commit'), 0, min(length(parameters('commit')), 7)))]",
54-
"keyVaultSecret_ServicePrincipalClientSecret": "devopsServicePrincipalClientSecret",
54+
"keyVaultSecret_ServicePrincipalClientSecret": "DevopsServicePrincipalClientSecret",
5555
"keyVaultSecret_StorageSaSToken": "StorageSaSToken",
5656
"keyVaultSecret_StorageKey": "StorageKey",
57-
"keyVaultSecret_functionsKey": "functionsKey",
57+
"keyVaultSecret_functionsKey": "FunctionsKey",
58+
"keyVaultSecret_applicationsInsightsKey": "ApplicationsInsightsKey",
5859

5960
"applicationInsightsApiVersion": "2020-02-02-preview",
6061
"applicationInsightsName": "[concat('appinsights', substring(uniqueString(parameters('branch')), 0, 4), 'xxxx', substring(parameters('commit'), 0, min(length(parameters('commit')), 7)))]",
@@ -344,11 +345,19 @@
344345
"properties": {
345346
"value": "[listKeys(variables('adlsStorageAccountResourceId'), variables('storageAccountApiVersion')).keys[0].value]"
346347
}
348+
},
349+
{
350+
"type": "secrets",
351+
"apiVersion": "[variables('keyVaultApiVersion')]",
352+
"name": "[variables('keyVaultSecret_applicationsInsightsKey')]",
353+
"dependsOn": [
354+
"[concat('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]",
355+
"[resourceId('Microsoft.Web/sites', variables('functionsAppName'))]"
356+
],
357+
"properties": {
358+
"value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), variables('applicationInsightsApiVersion'), 'full').properties.InstrumentationKey]"
359+
}
347360
}
348-
349-
350-
351-
352361
]
353362
},
354363

@@ -584,22 +593,25 @@
584593
' <Parameter name=\"UseFunctionsEmulator\" value=\"true\" />',
585594
' <Parameter name=\"FunctionsAppName\" value=\"', variables('functionsAppName'), '\" />',
586595
' <Parameter name=\"FunctionsAppUrl\" value=\"', reference(resourceId('Microsoft.Web/sites', variables('functionsAppName')), variables('functionsAppApiVersion'), 'full').properties.hostNames[0], '\" />',
587-
' <Parameter name=\"FunctionsAppKey\" value=\"', listKeys(concat(resourceId('Microsoft.Web/sites', variables('functionsAppName')), '/host/default/'), variables('functionsAppApiVersion')).functionKeys.default, '\" />',
588-
' <Parameter name=\"FunctionsAppKeyName\" value=\"', variables('keyVaultSecret_functionsKey'), '\" />',
589596
' <Parameter name=\"StorageAccountName\" value=\"', variables('adlsStorageAccountName'), '\" />',
590597
' <Parameter name=\"StorageContainerName\" value=\"', parameters('adlsStorageAccountContainerName'), '\" />',
591598
' <Parameter name=\"KeyVaultName\" value=\"', variables('keyVaultName'), '\" />',
592599
' <Parameter name=\"ServicePrincipalName\" value=\"', parameters('devopsServicePrincipalCredentials').client_id, '\" />',
593-
' <Parameter name=\"ServicePrincipalSecret\" value=\"', parameters('devopsServicePrincipalCredentials').client_secret, '\" />',
594-
' <Parameter name=\"ServicePrincipalNameKeyName\" value=\"', variables('keyVaultSecret_ServicePrincipalClientSecret'), '\" />',
595-
' <Parameter name=\"StorageContainerSasToken\" value=\"', replace(listAccountSas(variables('adlsStorageAccountName'), variables('storageAccountApiVersion'), parameters('adlsStorageAccountSasProperties')).accountSasToken, '&', '&amp;'), '\" />',
596-
' <Parameter name=\"StorageContainerSasTokenKeyName\" value=\"', variables('keyVaultSecret_StorageSaSToken'), '\" />',
597-
' <Parameter name=\"StorageAccountAccessKey\" value=\"', listKeys(variables('adlsStorageAccountResourceId'), variables('storageAccountApiVersion')).keys[0].value, '\" />',
598-
' <Parameter name=\"StorageAccountAccessKeyKeyName\" value=\"', variables('keyVaultSecret_StorageKey'), '\" />',
600+
' <Parameter name=\"ApplicationInsightsName\" value=\"', reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), variables('applicationInsightsApiVersion'), 'full').properties.Name, '\" />',
601+
602+
' <Parameter name=\"KeyVaultSecretFunctionsAppKey\" value=\"', variables('keyVaultSecret_functionsKey'), '\" />',
603+
' <Parameter name=\"KeyVaultSecretServicePrincipalSecretKey\" value=\"', variables('keyVaultSecret_ServicePrincipalClientSecret'), '\" />',
604+
' <Parameter name=\"KeyVaultSecretStorageContainerSasToken\" value=\"', variables('keyVaultSecret_StorageSaSToken'), '\" />',
605+
' <Parameter name=\"KeyVaultSecretStorageAccountAccessKey\" value=\"', variables('keyVaultSecret_StorageKey'), '\" />',
606+
' <Parameter name=\"KeyVaultSecretApplicationInsightsKey\" value=\"', variables('keyVaultSecret_applicationsInsightsKey'), '\" />',
599607
' </TestRunParameters>',
600608
'</RunSettings>'
601609
)
602610
]"
611+
// ' <Parameter name=\"FunctionsAppKey\" value=\"', listKeys(concat(resourceId('Microsoft.Web/sites', variables('functionsAppName')), '/host/default/'), variables('functionsAppApiVersion')).functionKeys.default, '\" />',
612+
// ' <Parameter name=\"ServicePrincipalSecret\" value=\"', parameters('devopsServicePrincipalCredentials').client_secret, '\" />',
613+
// ' <Parameter name=\"StorageContainerSasToken\" value=\"', replace(listAccountSas(variables('adlsStorageAccountName'), variables('storageAccountApiVersion'), parameters('adlsStorageAccountSasProperties')).accountSasToken, '&', '&amp;'), '\" />',
614+
// ' <Parameter name=\"StorageAccountAccessKey\" value=\"', listKeys(variables('adlsStorageAccountResourceId'), variables('storageAccountApiVersion')).keys[0].value, '\" />',
603615
}
604616
}
605617
}

DataPipelineTools.Functions.Tests/DataLake/DataLakeFunctions/Integration/DataLakeGetItemsIntegrationTests.cs

+10-9
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@ namespace DataPipelineTools.Functions.Tests.DataLake.DataLakeFunctions.Integrati
88
[Category(nameof(TestType.IntegrationTest))]
99
public class DataLakeGetItemsIntegrationTests: IntegrationTestBase
1010
{
11+
12+
1113
[SetUp]
1214
public void Setup()
1315
{
14-
16+
Logger.LogInformation($"Running tests in { (IsRunningOnCIServer ? "CI" : "local") } environment");
17+
Logger.LogInformation($"TestContext.Parameters.Count: { TestContext.Parameters.Count }");
1518
}
1619

17-
[Test]
18-
public void Test1()
19-
{
20-
Logger.LogInformation($"Running tests in { (IsRunningOnCIServer ? "CI": "local") } environment");
20+
//[Test]
21+
//public void Test_RunSettingsLoadedOk()
22+
//{
23+
// Assert.
2124

22-
23-
Logger.LogError("Integration tests not implemented yet.");
24-
Assert.Fail();
25-
}
25+
// //Assert.Fail("Integration tests not implemented yet.");
26+
//}
2627
}
2728
}
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1-
using DataPipelineTools.Tests.Common;
2-
using Microsoft.Extensions.Logging;
3-
using NUnit.Framework;
1+
//using DataPipelineTools.Tests.Common;
2+
//using Microsoft.Extensions.Logging;
3+
//using NUnit.Framework;
44

5-
namespace DataPipelineTools.Functions.Tests.DataLake.DataLakeFunctions.Unit
6-
{
7-
[TestFixture]
8-
[Category(nameof(TestType.IntegrationTest))]
9-
public class DataLakeGetItemsTests: IntegrationTestBase
10-
{
11-
[SetUp]
12-
public void Setup()
13-
{
14-
15-
}
5+
//namespace DataPipelineTools.Functions.Tests.DataLake.DataLakeFunctions.Unit
6+
//{
7+
// [TestFixture]
8+
// [Category(nameof(TestType.IntegrationTest))]
9+
// public class DataLakeGetItemsTests: IntegrationTestBase
10+
// {
11+
// [SetUp]
12+
// public void Setup()
13+
// {
14+
// Logger.LogInformation($"Running tests in { (IsRunningOnCIServer ? "CI": "local") } environment");
15+
// }
1616

17-
[Test]
18-
public void Test1()
19-
{
20-
Logger.LogInformation($"Running tests in { (IsRunningOnCIServer ? "CI": "local") } environment");
17+
// [Test]
18+
// public void Test_KeyVaultSecretsAreCorrect()
19+
// {
20+
// var servicePrincipalSecretPlainText = TestContext.Parameters["ServicePrincipalSecret"];
21+
// var servicePrincipalSecretKeyVault = GetKeyVaultSecretValue(TestContext.Parameters["ServicePrincipalSecretKeyName"]);
2122

22-
23-
Logger.LogError("Integration tests not implemented yet.");
24-
Assert.Fail();
25-
}
26-
}
27-
}
23+
// Assert.AreEqual(servicePrincipalSecretPlainText, servicePrincipalSecretKeyVault);
24+
// //Assert.Fail("Integration tests not implemented yet.");
25+
// }
26+
// }
27+
//}

DataPipelineTools.Functions.Tests/DataPipelineTools.Functions.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
</PropertyGroup>
1414

1515
<ItemGroup>
16+
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.2.0" />
1617
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
1718
<PackageReference Include="NUnit" Version="3.13.1" />
1819
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />

DataPipelineTools.Functions.Tests/IntegrationTestBase.cs

+84-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
2+
using System.Runtime.InteropServices.ComTypes;
3+
using Azure.Identity;
4+
using Azure.Security.KeyVault.Secrets;
45
using DataPipelineTools.Tests.Common;
6+
using Microsoft.Extensions.Logging;
7+
using NUnit.Framework;
58

69
namespace DataPipelineTools.Functions.Tests
710
{
@@ -10,6 +13,62 @@ namespace DataPipelineTools.Functions.Tests
1013
/// </summary>
1114
public abstract class IntegrationTestBase : TestBase
1215
{
16+
public IntegrationTestBase()
17+
{
18+
if (TestContext.Parameters.Count == 0)
19+
throw new ArgumentException("No setting file is configured for the integration tests.");
20+
}
21+
22+
protected bool UseFunctionsEmulator
23+
{
24+
get
25+
{
26+
var result = false;
27+
bool.TryParse(TestContext.Parameters["UseFunctionsEmulator"], out result);
28+
return result;
29+
}
30+
}
31+
32+
protected string FunctionsAppName => TestContext.Parameters["FunctionsAppName"];
33+
protected string FunctionsAppUrl => TestContext.Parameters["FunctionsAppUrl"];
34+
protected string StorageAccountName => TestContext.Parameters["StorageAccountName"];
35+
protected string StorageContainerName => TestContext.Parameters["StorageContainerName"];
36+
protected string KeyVaultName => TestContext.Parameters["KeyVaultName"];
37+
protected string ServicePrincipalName => TestContext.Parameters["ServicePrincipalName"];
38+
protected string ApplicationInsightsName => TestContext.Parameters["ApplicationInsightsName"];
39+
40+
41+
42+
43+
protected string FunctionsAppKey => TestContext.Parameters["FunctionsAppKey"] ?? GetKeyVaultSecretValue(TestContext.Parameters["KeyVaultSecretFunctionsAppKey"]);
44+
protected string ServicePrincipalSecretKey => TestContext.Parameters["ServicePrincipalSecretKey"] ?? GetKeyVaultSecretValue(TestContext.Parameters["KeyVaultSecretServicePrincipalSecretKey"]);
45+
protected string StorageContainerSasToken => TestContext.Parameters["StorageContainerSasToken"] ?? GetKeyVaultSecretValue(TestContext.Parameters["KeyVaultSecretStorageContainerSasToken"]);
46+
protected string StorageAccountAccessKey => TestContext.Parameters["StorageAccountAccessKey"] ?? GetKeyVaultSecretValue(TestContext.Parameters["KeyVaultSecretStorageAccountAccessKey"]);
47+
protected string ApplicationInsightsKey => TestContext.Parameters["ApplicationInsightsKey"] ?? GetKeyVaultSecretValue(TestContext.Parameters["KeyVaultSecretApplicationInsightsKey"]);
48+
49+
50+
[Test]
51+
public void Test_RunSettingsLoadedOk()
52+
{
53+
Assert.IsNotNull(UseFunctionsEmulator);
54+
Assert.IsNotNull(FunctionsAppName);
55+
Assert.IsNotNull(FunctionsAppUrl);
56+
Assert.IsNotNull(StorageAccountName);
57+
Assert.IsNotNull(StorageContainerName);
58+
Assert.IsNotNull(KeyVaultName);
59+
Assert.IsNotNull(ServicePrincipalName);
60+
Assert.IsNotNull(ApplicationInsightsName);
61+
Assert.IsNotNull(FunctionsAppKey);
62+
Assert.IsNotNull(ServicePrincipalSecretKey);
63+
Assert.IsNotNull(StorageContainerSasToken);
64+
Assert.IsNotNull(StorageAccountAccessKey);
65+
Assert.IsNotNull(ApplicationInsightsKey);
66+
67+
// Check that the StorageContainerSasToken got unquoted correctly
68+
Assert.IsFalse(StorageContainerSasToken.Contains("&amp;"));
69+
}
70+
71+
1372
protected bool IsRunningOnCIServer
1473
{
1574
get
@@ -31,5 +90,28 @@ protected void StartLocalFunctionsInstance()
3190
throw new NotImplementedException();
3291
}
3392

93+
protected string GetKeyVaultSecretValue(string secretName)
94+
{
95+
/* For some reason the DefaultAzureCredential (SharedTokenCacheCredential / VisualStudioCredential) returns a 403 trying to access the key vault, even when access policies are configured correctly
96+
* We either use one of the following to authenticate:
97+
* - var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions{ ExcludeSharedTokenCacheCredential = true, ExcludeVisualStudioCredential = true});
98+
* - var credential = new ChainedTokenCredential(new ManagedIdentityCredential(), new AzureCliCredential());
99+
*
100+
* See here for more info: https://docs.microsoft.com/en-us/answers/questions/74848/access-denied-to-first-party-service.html
101+
*/
102+
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions { ExcludeSharedTokenCacheCredential = true, ExcludeVisualStudioCredential = true });
103+
104+
if (string.IsNullOrWhiteSpace(KeyVaultName))
105+
throw new ArgumentException("The run setting file does not have a value for 'KeyVaultName'");
106+
107+
var keyVaultUri = $"https://{KeyVaultName}.vault.azure.net";
108+
var client = new SecretClient(new Uri(keyVaultUri), credential);
109+
var result = client.GetSecretAsync(secretName).Result;
110+
111+
return result?.Value?.Value;
112+
}
113+
114+
115+
34116
}
35117
}

0 commit comments

Comments
 (0)