Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new device for tests that deploy configs #2753

Merged
merged 25 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5a0a27d
Remove private keywork per style guidelines
damonbarry Mar 25, 2020
f3b1fec
Don't explicitly call constructor with no args
damonbarry Mar 26, 2020
9ebc78b
Remove empty constructor
damonbarry Mar 26, 2020
3d1c727
Use a constant for x509 device suffix
damonbarry Mar 26, 2020
e0f56b6
Remove unused properties
damonbarry Mar 26, 2020
c8a6ffe
Create variable to eliminate duplication
damonbarry Mar 26, 2020
19708d2
Move SAS/X509 logic into appropriate fixtures
damonbarry Mar 26, 2020
cf5d4d3
Rename helper method
damonbarry Mar 26, 2020
3bc6d43
Move EdgeRuntime member into derived classes
damonbarry Mar 26, 2020
e1e2405
Create a new device for every SAS-manual test
damonbarry Mar 26, 2020
8f87ba4
Create device once in CustomCertificatesFixture
damonbarry Mar 28, 2020
a845bcb
Don't allow users to specify their own deviceId
damonbarry Mar 29, 2020
c5f2444
Add DeviceId class for centralized generation
damonbarry Mar 30, 2020
31f2de4
Update a comment
damonbarry Mar 30, 2020
10a0b0e
Remove unused ctor parameter
damonbarry Mar 30, 2020
395d23e
Don't double-increment DeviceId count
damonbarry Mar 30, 2020
ce65cdc
Remove TempSensor module name generator
damonbarry Mar 30, 2020
97f4049
Don't deploy vanilla agent in metrics test
damonbarry Mar 30, 2020
3ba46eb
Fix StyleCop errors
damonbarry Mar 30, 2020
98155c0
Give Pi more time to download docker images
damonbarry Mar 30, 2020
ded14f1
Revert "Give Pi more time to download docker images"
damonbarry Mar 30, 2020
0f18b42
Profile SAS provisioning in fixture not tests
damonbarry Mar 30, 2020
bd133fb
Merge branch 'master' into e2e-device-per-test
dylanbronson Apr 10, 2020
244ba7b
Changing priorityQueue test to take correct DeviceId
dylanbronson Apr 10, 2020
38684e5
Merge branch 'master' into e2e-device-per-test
dylanbronson Apr 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions test/Microsoft.Azure.Devices.Edge.Test.Common/DeviceId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Microsoft. All rights reserved.
namespace Microsoft.Azure.Devices.Edge.Test.Common
{
using System;
using System.Linq;
using System.Net;

public class DeviceId
{
int count;

static readonly Lazy<DeviceId> Default = new Lazy<DeviceId>(() => new DeviceId());

public static DeviceId Current => Default.Value;

public string BaseId { get; }

protected DeviceId()
{
string hostname = string.Concat(Dns.GetHostName().Take(34)).TrimEnd('-');
string timestamp = $"{DateTime.Now:yyMMdd'-'HHmmss'.'fff}";
this.BaseId = $"e2e-{hostname}-{timestamp}";
this.count = 0;
}

public string Generate()
{
// Max length of returned string is 60 chars. Some tests use the device ID as the basis
// for the Common Name (CN) of an x509 certificate, and the CN limit is 64 chars, so
// this gives tests the opportunity to safely append up to 4 additional characters.
++this.count;
if (this.count > 999)
{
throw new InvalidOperationException("Device ID counter exceeded 3 digits.");
}

return $"{this.BaseId}-{this.count:d3}";
}
}
}
10 changes: 6 additions & 4 deletions test/Microsoft.Azure.Devices.Edge.Test.Common/EdgeRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@ namespace Microsoft.Azure.Devices.Edge.Test.Common
public class EdgeRuntime
{
readonly Option<string> agentImage;
readonly string deviceId;
readonly Option<string> hubImage;
readonly IotHub iotHub;
readonly bool optimizeForPerformance;
readonly Option<Uri> proxy;
readonly Registries registries;

public string DeviceId { get; }

public EdgeRuntime(string deviceId, Option<string> agentImage, Option<string> hubImage, Option<Uri> proxy, Registries registries, bool optimizeForPerformance, IotHub iotHub)
{
this.agentImage = agentImage;
this.deviceId = deviceId;
this.hubImage = hubImage;
this.iotHub = iotHub;
this.optimizeForPerformance = optimizeForPerformance;
this.proxy = proxy;
this.registries = registries;

this.DeviceId = deviceId;
}

// DeployConfigurationAsync builds a configuration that includes Edge Agent, Edge Hub, and
Expand All @@ -39,7 +41,7 @@ public async Task<EdgeDeployment> DeployConfigurationAsync(
CancellationToken token,
bool stageSystemModules = true)
{
var builder = new EdgeConfigBuilder(this.deviceId);
var builder = new EdgeConfigBuilder(this.DeviceId);
builder.AddRegistryCredentials(this.registries);
builder.AddEdgeAgent(this.agentImage.OrDefault())
.WithEnvironment(new[] { ("RuntimeLogLevel", "debug") })
Expand All @@ -57,7 +59,7 @@ public async Task<EdgeDeployment> DeployConfigurationAsync(
{
await edgeConfiguration.DeployAsync(this.iotHub, token);
EdgeModule[] modules = edgeConfiguration.ModuleNames
.Select(id => new EdgeModule(id, this.deviceId, this.iotHub))
.Select(id => new EdgeModule(id, this.DeviceId, this.iotHub))
.ToArray();
await EdgeModule.WaitForStatusAsync(modules, EdgeModuleStatus.Running, token);
await edgeConfiguration.VerifyAsync(this.iotHub, token);
Expand Down
59 changes: 0 additions & 59 deletions test/Microsoft.Azure.Devices.Edge.Test.Common/IdentityLimits.cs

This file was deleted.

8 changes: 2 additions & 6 deletions test/Microsoft.Azure.Devices.Edge.Test.Common/LeafDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,8 @@ static async Task<LeafDevice> CreateWithSelfSignedCertAsync(
string edgeHostname,
CancellationToken token)
{
IdCertificates primary = await ca.GenerateIdentityCertificatesAsync(
IdentityLimits.CheckCommonName($"{leafDeviceId}-1"),
token);
IdCertificates secondary = await ca.GenerateIdentityCertificatesAsync(
IdentityLimits.CheckCommonName($"{leafDeviceId}-2"),
token);
IdCertificates primary = await ca.GenerateIdentityCertificatesAsync($"{leafDeviceId}-1", token);
IdCertificates secondary = await ca.GenerateIdentityCertificatesAsync($"{leafDeviceId}-2", token);

string[] streams = await Task.WhenAll(
new[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ string[] GetEdgeCertFileLocation(string deviceId)
}

public CaCertificates(string deviceId, string scriptPath)
: base()
{
var location = this.GetEdgeCertFileLocation(deviceId);
var files = OsPlatform.NormalizeFiles(location, scriptPath);
Expand All @@ -37,7 +36,6 @@ public CaCertificates(string deviceId, string scriptPath)
}

public CaCertificates(string certificatePath, string keyPath, string trustedCertsPath)
: base()
{
Preconditions.CheckArgument(File.Exists(certificatePath));
Preconditions.CheckArgument(File.Exists(keyPath));
Expand Down
3 changes: 1 addition & 2 deletions test/Microsoft.Azure.Devices.Edge.Test/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ public async Task QuickstartCerts()

await this.runtime.DeployConfigurationAsync(token);

string leafDeviceId =
IdentityLimits.CheckLeafId($"{Context.Current.DeviceId}-quickstart-certs");
string leafDeviceId = DeviceId.Current.Generate();

var leaf = await LeafDevice.CreateAsync(
leafDeviceId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ public async Task TransparentGateway(
{
CancellationToken token = this.TestToken;

string leafDeviceId = IdentityLimits.CheckLeafId(
$"{Context.Current.DeviceId}-{protocol}-{testAuth}");
string leafDeviceId = DeviceId.Current.Generate();

Option<string> parentId = testAuth == TestAuthenticationType.SasOutOfScope
? Option.None<string>()
: Option.Some(Context.Current.DeviceId.ToString());
: Option.Some(this.runtime.DeviceId);

var leaf = await LeafDevice.CreateAsync(
leafDeviceId,
Expand Down
14 changes: 3 additions & 11 deletions test/Microsoft.Azure.Devices.Edge.Test/Metrics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async Task ValidateMetrics()
CancellationToken token = this.TestToken;
await this.Deploy(token);

var result = await this.iotHub.InvokeMethodAsync(Context.Current.DeviceId, ModuleName, new CloudToDeviceMethod("ValidateMetrics", TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(300)), token);
var result = await this.iotHub.InvokeMethodAsync(this.runtime.DeviceId, ModuleName, new CloudToDeviceMethod("ValidateMetrics", TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(300)), token);
Assert.AreEqual(result.Status, (int)HttpStatusCode.OK);

string body = result.GetPayloadAsJson();
Expand All @@ -43,15 +43,7 @@ class Report

async Task Deploy(CancellationToken token)
{
// First deploy different agent image. This will force agent to update environment variables
await this.runtime.DeployConfigurationAsync(
builder =>
{
builder.GetModule(ConfigModuleName.EdgeAgent).WithSettings(("image", EdgeAgentBaseImage));
builder.RemoveModule(ConfigModuleName.EdgeHub);
}, token);

// Next deploy everything needed for this test, including a temporary image that will be removed later to bump the "stopped" metric
// First deploy everything needed for this test, including a temporary image that will be removed later to bump the "stopped" metric
string metricsValidatorImage = Context.Current.MetricsValidatorImage.Expect(() => new InvalidOperationException("Missing Metrics Validator image"));
await this.runtime.DeployConfigurationAsync(
builder =>
Expand All @@ -60,7 +52,7 @@ await this.runtime.DeployConfigurationAsync(
builder.AddMetricsValidatorConfig(metricsValidatorImage);
}, token);

// Finally remove the temporary image from the deployment
// Next remove the temporary image from the deployment
await this.runtime.DeployConfigurationAsync(
builder => { builder.AddMetricsValidatorConfig(metricsValidatorImage); },
token,
Expand Down
66 changes: 26 additions & 40 deletions test/Microsoft.Azure.Devices.Edge.Test/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,24 @@ namespace Microsoft.Azure.Devices.Edge.Test
[EndToEnd]
public class Module : SasManualProvisioningFixture
{
private sealed class TempSensorModule
{
public string Name { get; }
public string Image { get; }

private const string DefaultSensorImage = "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0";
private static int instanceCount = 0;

private TempSensorModule(int number)
{
this.Name = "tempSensor" + number.ToString();
this.Image = Context.Current.TempSensorImage.GetOrElse(DefaultSensorImage);
}

public static TempSensorModule GetInstance()
{
return new TempSensorModule(TempSensorModule.instanceCount++);
}
}
const string SensorName = "tempSensor";
const string DefaultSensorImage = "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0";

[Test]
public async Task TempSensor()
{
var tempSensorModule = TempSensorModule.GetInstance();
string sensorImage = Context.Current.TempSensorImage.GetOrElse(DefaultSensorImage);
CancellationToken token = this.TestToken;

EdgeDeployment deployment = await this.runtime.DeployConfigurationAsync(
builder =>
{
builder.AddModule(tempSensorModule.Name, tempSensorModule.Image)
builder.AddModule(SensorName, sensorImage)
.WithEnvironment(new[] { ("MessageCount", "1") });
},
token);

EdgeModule sensor = deployment.Modules[tempSensorModule.Name];
EdgeModule sensor = deployment.Modules[SensorName];
await sensor.WaitForEventsReceivedAsync(deployment.StartTime, token);

await sensor.UpdateDesiredPropertiesAsync(
Expand Down Expand Up @@ -82,69 +65,72 @@ await sensor.WaitForReportedPropertyUpdatesAsync(
[Test]
public async Task TempFilter()
{
string filterImage = Context.Current.TempFilterImage.Expect(() => new ArgumentException("tempFilterImage parameter is required for TempFilter test"));
const string filterName = "tempFilter";

const string filterModuleName = "tempFilter";
var tempSensorModule = TempSensorModule.GetInstance();
string filterImage = Context.Current.TempFilterImage.Expect(
() => new ArgumentException("tempFilterImage parameter is required for TempFilter test"));
string sensorImage = Context.Current.TempSensorImage.Expect(
() => new ArgumentException("tempSensorImage parameter is required for TempFilter test"));

CancellationToken token = this.TestToken;

EdgeDeployment deployment = await this.runtime.DeployConfigurationAsync(
builder =>
{
builder.AddModule(tempSensorModule.Name, tempSensorModule.Image)
builder.AddModule(SensorName, sensorImage)
.WithEnvironment(new[] { ("MessageCount", "1") });
builder.AddModule(filterModuleName, filterImage)
builder.AddModule(filterName, filterImage)
.WithEnvironment(new[] { ("TemperatureThreshold", "19") });
builder.GetModule(ModuleName.EdgeHub)
.WithDesiredProperties(new Dictionary<string, object>
{
["routes"] = new
{
TempFilterToCloud = "FROM /messages/modules/" + filterModuleName + "/outputs/alertOutput INTO $upstream",
TempSensorToTempFilter = "FROM /messages/modules/" + tempSensorModule.Name + "/outputs/temperatureOutput INTO BrokeredEndpoint('/modules/" + filterModuleName + "/inputs/input1')"
TempFilterToCloud = $"FROM /messages/modules/{filterName}/outputs/alertOutput INTO $upstream",
TempSensorToTempFilter = $"FROM /messages/modules/{SensorName}/outputs/temperatureOutput INTO BrokeredEndpoint('/modules/{filterName}/inputs/input1')"
}
} );
},
token);

EdgeModule filter = deployment.Modules[filterModuleName];
EdgeModule filter = deployment.Modules[filterName];
await filter.WaitForEventsReceivedAsync(deployment.StartTime, token);
}

[Test]
// Test Temperature Filter Function: https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-deploy-function
public async Task TempFilterFunc()
{
// Azure Fucntion Name: EdgeHubTrigger-CSharp
string filterFunc = Context.Current.TempFilterFuncImage.Expect(() => new ArgumentException("'tempFilterFuncImage' parameter is required for TempFilterFunc() test"));
const string filterFuncName = "tempFilterFunctions";

const string filterFuncModuleName = "tempFilterFunctions";
var tempSensorModule = TempSensorModule.GetInstance();
// Azure Function Name: EdgeHubTrigger-CSharp
string filterFuncImage = Context.Current.TempFilterFuncImage.Expect(
() => new ArgumentException("tempFilterFuncImage parameter is required for TempFilterFunc test"));
string sensorImage = Context.Current.TempSensorImage.Expect(
() => new ArgumentException("tempSensorImage parameter is required for TempFilterFunc test"));

CancellationToken token = this.TestToken;

EdgeDeployment deployment = await this.runtime.DeployConfigurationAsync(
builder =>
{
builder.AddModule(tempSensorModule.Name, tempSensorModule.Image)
builder.AddModule(SensorName, sensorImage)
.WithEnvironment(new[] { ("MessageCount", "1") });
builder.AddModule(filterFuncModuleName, filterFunc)
builder.AddModule(filterFuncName, filterFuncImage)
.WithEnvironment(new[] { ("AZURE_FUNCTIONS_ENVIRONMENT", "Development") });
builder.GetModule(ModuleName.EdgeHub)
.WithDesiredProperties(new Dictionary<string, object>
{
["routes"] = new
{
TempFilterFunctionsToCloud = "FROM /messages/modules/" + filterFuncModuleName + "/outputs/output1 INTO $upstream",
TempSensorToTempFilter = "FROM /messages/modules/" + tempSensorModule.Name + "/outputs/temperatureOutput " +
"INTO BrokeredEndpoint('/modules/" + filterFuncModuleName + "/inputs/input1')"
TempFilterFunctionsToCloud = $"FROM /messages/modules/{filterFuncName}/outputs/output1 INTO $upstream",
TempSensorToTempFilter = $"FROM /messages/modules/{SensorName}/outputs/temperatureOutput INTO BrokeredEndpoint('/modules/{filterFuncName}/inputs/input1')"
}
});
},
token);

EdgeModule filter = deployment.Modules[filterFuncModuleName];
EdgeModule filter = deployment.Modules[filterFuncName];
await filter.WaitForEventsReceivedAsync(deployment.StartTime, token);
}

Expand Down
2 changes: 1 addition & 1 deletion test/Microsoft.Azure.Devices.Edge.Test/PriorityQueues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private async Task<PriorityQueueTestStatus> PollUntilFinishedAsync(string module
do
{
await Task.Delay(TimeSpan.FromSeconds(5));
var result = await this.iotHub.InvokeMethodAsync(Context.Current.DeviceId, moduleName, new CloudToDeviceMethod("IsFinished", TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(300)), token);
var result = await this.iotHub.InvokeMethodAsync(this.runtime.DeviceId, moduleName, new CloudToDeviceMethod("IsFinished", TimeSpan.FromSeconds(300), TimeSpan.FromSeconds(300)), token);
Assert.AreEqual(result.Status, (int)HttpStatusCode.OK);
testStatus = JsonConvert.DeserializeObject<PriorityQueueTestStatus>(result.GetPayloadAsJson());
}
Expand Down
Loading