Skip to content

Commit

Permalink
Make E2E setup errors actionable for developers. (Azure#4705)
Browse files Browse the repository at this point in the history
Right now it is very hard to setup E2E test on a local box. Docs need updates and not all error messages are useful.

In this PR I'm trying to improve most of the cases where we can encounter E2E setup error.
  • Loading branch information
vadim-kovalyov authored Mar 26, 2021
1 parent 40ddfff commit 1ef8fbf
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 20 deletions.
10 changes: 5 additions & 5 deletions test/Microsoft.Azure.Devices.Edge.Test/Provisioning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ string DeriveDeviceKey(byte[] groupKey, string registrationId)
[Category("CentOsSafe")]
public async Task DpsSymmetricKey()
{
string idScope = Context.Current.DpsIdScope.Expect(() => new InvalidOperationException("Missing DPS ID scope"));
string groupKey = Context.Current.DpsGroupKey.Expect(() => new InvalidOperationException("Missing DPS enrollment group key"));
string idScope = Context.Current.DpsIdScope.Expect(() => new InvalidOperationException("Missing DPS ID scope (check dpsIdScope in context.json)"));
string groupKey = Context.Current.DpsGroupKey.Expect(() => new InvalidOperationException("Missing DPS enrollment group key (check DPS_GROUP_KEY env var)"));
string registrationId = DeviceId.Current.Generate();

string deviceKey = this.DeriveDeviceKey(Convert.FromBase64String(groupKey), registrationId);
Expand Down Expand Up @@ -84,10 +84,10 @@ await this.daemon.ConfigureAsync(
public async Task DpsX509()
{
(string, string, string) rootCa =
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing root CA keys"));
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing DPS ID scope (check rootCaPrivateKeyPath in context.json)"));
string caCertScriptPath =
Context.Current.CaCertScriptPath.Expect(() => new InvalidOperationException("Missing CA cert script path"));
string idScope = Context.Current.DpsIdScope.Expect(() => new InvalidOperationException("Missing DPS ID scope"));
Context.Current.CaCertScriptPath.Expect(() => new InvalidOperationException("Missing CA cert script path (check caCertScriptPath in context.json)"));
string idScope = Context.Current.DpsIdScope.Expect(() => new InvalidOperationException("Missing DPS ID scope (check dpsIdScope in context.json)"));
string registrationId = DeviceId.Current.Generate();

CancellationToken token = this.TestToken;
Expand Down
7 changes: 5 additions & 2 deletions test/Microsoft.Azure.Devices.Edge.Test/SetupFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ public Task AfterAllAsync() => TryFinally.DoAsync(
await this.daemon.UninstallAsync(token);

// Delete test certs, keys, etc.
Directory.Delete(FixedPaths.E2E_TEST_DIR, true);
if (Directory.Exists(FixedPaths.E2E_TEST_DIR))
{
Directory.Delete(FixedPaths.E2E_TEST_DIR, true);
}
},
"Completed end-to-end test teardown"),
() =>
Expand Down Expand Up @@ -179,7 +182,7 @@ public class TestCertificates
public static async Task<(TestCertificates, CertificateAuthority ca)> GenerateCertsAsync(string deviceId, CancellationToken token)
{
string scriptPath = Context.Current.CaCertScriptPath.Expect(
() => new System.InvalidOperationException("Missing CA cert script path"));
() => new System.InvalidOperationException("Missing CA cert script path (check caCertScriptPath in context.json)"));
(string, string, string) rootCa = Context.Current.RootCaKeys.Expect(
() => new System.InvalidOperationException("Missing root CA"));

Expand Down
21 changes: 13 additions & 8 deletions test/Microsoft.Azure.Devices.Edge.Test/helpers/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ IEnumerable<Registry> GetAndValidateRegistries()

// If any container registry arguments (server, username, password)
// are given, then they must *all* be given, otherwise throw an error.
Preconditions.CheckNonWhiteSpace(address, nameof(address));
Preconditions.CheckNonWhiteSpace(username, nameof(username));
Preconditions.CheckNonWhiteSpace(password, nameof(password));
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(address), $"Container registry address is missing from context.json.");
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(username), $"Container registry username is missing from context.json.");
Preconditions.CheckArgument(
!string.IsNullOrWhiteSpace(password),
$"Container registry password is missing. Please set E2E_REGISTRIES__0__PASSWORD " +
"env var (preferable) or place it in context.json");

result.Add(new Registry(address, username, password));
}
Expand All @@ -62,11 +65,11 @@ IEnumerable<Registry> GetAndValidateRegistries()
!string.IsNullOrWhiteSpace(key) ||
!string.IsNullOrWhiteSpace(password))
{
Preconditions.CheckNonWhiteSpace(certificate, nameof(certificate));
Preconditions.CheckNonWhiteSpace(key, nameof(key));
Preconditions.CheckNonWhiteSpace(password, nameof(password));
Preconditions.CheckArgument(File.Exists(certificate));
Preconditions.CheckArgument(File.Exists(key));
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(certificate), $"rootCaCertificatePath is missing from context.json.");
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(key), $"rootCaPrivateKeyPath is missing from context.json.");
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(password), $"ROOT_CA_PASSWORD is missing from environment or context.json.");
Preconditions.CheckArgument(File.Exists(certificate), "rootCaCertificatePath file does not exist");
Preconditions.CheckArgument(File.Exists(key), "rootCaPrivateKeyPath file does not exist");
return Option.Some((certificate, key, password));
}

Expand All @@ -78,13 +81,15 @@ IEnumerable<Registry> GetAndValidateRegistries()

this.CaCertScriptPath = Option.Maybe(Get("caCertScriptPath"));
this.ConnectionString = Get("IOT_HUB_CONNECTION_STRING");
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(this.ConnectionString), $"IOT_HUB_CONNECTION_STRING is missing from environment or context.json.");
this.ParentDeviceId = Option.Maybe(Get("parentDeviceId"));
this.DpsIdScope = Option.Maybe(Get("dpsIdScope"));
this.DpsGroupKey = Option.Maybe(Get("DPS_GROUP_KEY"));
this.EdgeAgentImage = Option.Maybe(Get("edgeAgentImage"));
this.EdgeHubImage = Option.Maybe(Get("edgeHubImage"));
this.DiagnosticsImage = Option.Maybe(Get("diagnosticsImage"));
this.EventHubEndpoint = Get("EVENT_HUB_ENDPOINT");
Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(this.EventHubEndpoint), $"EVENT_HUB_ENDPOINT is missing from environment or context.json.");
this.InstallerPath = Option.Maybe(Get("installerPath"));
this.LogFile = Option.Maybe(Get("logFile"));
this.MethodReceiverImage = Option.Maybe(Get("methodReceiverImage"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ protected async Task ConfigureDaemonAsync(
public async Task SetUpCertificatesAsync(CancellationToken token, DateTime startTime, string deviceId)
{
(string, string, string) rootCa =
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing root CA keys"));
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing DPS ID scope (check rootCaPrivateKeyPath in context.json)"));
string caCertScriptPath =
Context.Current.CaCertScriptPath.Expect(() => new InvalidOperationException("Missing CA cert script path"));
Context.Current.CaCertScriptPath.Expect(() => new InvalidOperationException("Missing CA cert script path (check caCertScriptPath in context.json)"));
string certId = Context.Current.Hostname.GetOrElse(deviceId);

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ await this.ConfigureDaemonAsync(
async Task<(X509Thumbprint, string, string)> CreateIdentityCertAsync(string deviceId, CancellationToken token)
{
(string, string, string) rootCa =
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing root CA keys"));
Context.Current.RootCaKeys.Expect(() => new InvalidOperationException("Missing DPS ID scope (check rootCaPrivateKeyPath in context.json)"));
string caCertScriptPath = Context.Current.CaCertScriptPath.Expect(
() => new InvalidOperationException("Missing CA cert script path"));
() => new InvalidOperationException("Missing CA cert script path (check caCertScriptPath in context.json)"));
string idScope = Context.Current.DpsIdScope.Expect(
() => new InvalidOperationException("Missing DPS ID scope"));
() => new InvalidOperationException("Missing DPS ID scope(check dpsIdScope in context.json)"));

CertificateAuthority ca = await CertificateAuthority.CreateAsync(
deviceId,
Expand Down

0 comments on commit 1ef8fbf

Please sign in to comment.