Skip to content

Added Better Error Handling #9403

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

Merged
merged 12 commits into from
Jun 14, 2019
Merged
18 changes: 18 additions & 0 deletions src/Peering/Peering.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScenarioTest.ResourceManage
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestFx", "..\..\tools\TestFx\TestFx.csproj", "{BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Resources", "..\Resources\Resources\Resources.csproj", "{E1F5201D-6067-430E-B303-4E367652991B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ResourceManager", "..\Resources\ResourceManager\ResourceManager.csproj", "{8058D403-06E3-4BED-8924-D166CE303961}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tags", "..\Resources\Tags\Tags.csproj", "{6BD4D521-DAFB-472B-A803-81F053AB1396}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -55,6 +61,18 @@ Global
{BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC80A1D0-FFA4-43D9-AA74-799F5CB54B58}.Release|Any CPU.Build.0 = Release|Any CPU
{E1F5201D-6067-430E-B303-4E367652991B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1F5201D-6067-430E-B303-4E367652991B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1F5201D-6067-430E-B303-4E367652991B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1F5201D-6067-430E-B303-4E367652991B}.Release|Any CPU.Build.0 = Release|Any CPU
{8058D403-06E3-4BED-8924-D166CE303961}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8058D403-06E3-4BED-8924-D166CE303961}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8058D403-06E3-4BED-8924-D166CE303961}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8058D403-06E3-4BED-8924-D166CE303961}.Release|Any CPU.Build.0 = Release|Any CPU
{6BD4D521-DAFB-472B-A803-81F053AB1396}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BD4D521-DAFB-472B-A803-81F053AB1396}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BD4D521-DAFB-472B-A803-81F053AB1396}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BD4D521-DAFB-472B-A803-81F053AB1396}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
23 changes: 15 additions & 8 deletions src/Peering/Peering/Az.Peering.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,25 @@ NestedModules = @('.\Microsoft.Azure.PowerShell.Cmdlets.Peering.dll')
FunctionsToExport = @()

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = 'Get-AzPeering', 'Get-AzPeerAsn', 'New-AzPeerAsn', 'New-AzPeering',
'Update-AzPeering', 'Set-AzPeeringExchangeConnectionObject',
'New-AzPeeringExchangeConnectionObject',
'Set-AzPeeringDirectConnectionObject',
'New-AzPeeringDirectConnectionObject', 'Get-AzPeeringLocation',
'Get-AzLegacyPeering', 'Set-AzPeerAsn', 'Remove-AzPeerAsn'
CmdletsToExport = 'Get-AzPeering',
'Get-AzPeerAsn',
'New-AzPeerAsn',
'New-AzPeering',
'Update-AzPeering',
'Set-AzPeeringExchangeConnectionObject',
'New-AzPeeringExchangeConnectionObject',
'Set-AzPeeringDirectConnectionObject',
'New-AzPeeringDirectConnectionObject',
'Get-AzPeeringLocation',
'Get-AzLegacyPeering',
'Set-AzPeerAsn',
'Remove-AzPeerAsn'

# Variables to export from this module
# VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
#AliasesToExport = @()

# DSC resources to export from this module
# DscResourcesToExport = @()
Expand All @@ -102,7 +109,7 @@ PrivateData = @{
PSData = @{

# Tags applied to this module. These help with module discovery in online galleries.
Tags = 'Azure','ARM','Network','Peering','PSModule','Exchange','Direct','PNI','Peer','Asn'
Tags = 'Azure','ARM','Network','Peering','PSModule', 'Exchange', 'Direct', 'PNI', 'Peer', 'Asn'

# A URL to the license for this module.
LicenseUri = 'https://aka.ms/azps-license'
Expand Down
7 changes: 4 additions & 3 deletions src/Peering/Peering/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
- Additional information about change #1
-->
## Upcoming Release

* Bug fix in IP Prefix validation to allow 0/30 for DirectConnection
* Bug fix to handle error messages from ARM and ERM
* Added Verbose comments for debugging
## Version 0.1.1
* Update version of AutoMapper library used
* Fix case sensitivity bug in `Get-AzPeeringLocation` for `-Kind` parameter

## Version 0.1.0
* Preview release for Microsoft Peering Service module
* Preview release for Microsoft Peering Service module
103 changes: 69 additions & 34 deletions src/Peering/Peering/Common/PeeringBaseCmdlet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Microsoft.Azure.PowerShell.Cmdlets.Peering.Common
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Net;
using System.Net.Sockets;

using Microsoft.Azure.Commands.Common.Authentication;
Expand Down Expand Up @@ -184,6 +185,7 @@ public PSPeeringLocation TopSPeeringLocation(object peering)
/// </exception>
public bool ValidBandwidth(int? bandwidthInMbps)
{
this.WriteVerbose($"validating bandwidth: {bandwidthInMbps}");
if (bandwidthInMbps <= 0)
throw new PSArgumentException(string.Format(Resources.Error_BandwidthTooLow, bandwidthInMbps));
if (bandwidthInMbps % Constants.MinRange != 0)
Expand Down Expand Up @@ -211,6 +213,7 @@ public bool ValidBandwidth(int? bandwidthInMbps)
/// </exception>
public bool ValidUpgradeBandwidth(int? startingBandwidth, int? newBandwidth)
{
this.WriteVerbose($"Starting bandwidth: {startingBandwidth} new bandwidth: {newBandwidth}");
if (!this.ValidBandwidth(newBandwidth))
return false;
if (newBandwidth <= (startingBandwidth ?? 0))
Expand All @@ -225,21 +228,40 @@ public bool ValidUpgradeBandwidth(int? startingBandwidth, int? newBandwidth)
/// <param name="routePrefix">
/// The route prefix.
/// </param>
/// <param name="PeeringType">
/// <param name="peeringType">
/// The InputObject Type.
/// </param>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public string ValidatePrefix(string routePrefix, string PeeringType)
public string ValidatePrefix(string routePrefix, string peeringType)
{
if (routePrefix != null)
{
this.WriteVerbose($"Validating route prefix: {routePrefix} for PeeringType:{peeringType}");
if (peeringType.Equals(Constants.Exchange))
{
if (routePrefix.Split('/').Length != 2) {
// Prefix if missing
var newRouteWithPrefix = IPAddress.Parse(routePrefix);
if(newRouteWithPrefix.AddressFamily == AddressFamily.InterNetwork)
{
routePrefix += "/32";
this.WriteVerbose($"Validating route prefix: {routePrefix} for PeeringType:{peeringType}");
}
if(newRouteWithPrefix.AddressFamily == AddressFamily.InterNetworkV6)
{
routePrefix += "/128";
this.WriteVerbose($"Validating route prefix: {routePrefix} for PeeringType:{peeringType}");
}

}
}
var prefix = RoutePrefix.GetValidPrefix(routePrefix);
switch (prefix.PrefixAddressFamily)
{
case AddressFamily.InterNetwork:
if (PeeringType.Equals(Constants.Exchange, StringComparison.OrdinalIgnoreCase))
if (peeringType.Equals(Constants.Exchange, StringComparison.OrdinalIgnoreCase))
{
if (prefix.PrefixMaskWidth != 32)
{
Expand All @@ -259,16 +281,14 @@ public string ValidatePrefix(string routePrefix, string PeeringType)
var actualPrefixBigInt = prefix.ActualPrefixBigInt;
if (prefix.Length == 4)
{
return prefix.StartOfPrefixBigInt + 1 == actualPrefixBigInt
return prefix.StartOfPrefixBigInt == actualPrefixBigInt
? routePrefix
: throw new PSArgumentException(
string.Format(
Resources.Error_InvalidPrefixRange,
routePrefix,
(prefix.StartOfPrefixBigInt + 1).ToIpAddress(
AddressFamily.InterNetwork),
(prefix.EndOfPrefixBigInt).ToIpAddress(
AddressFamily.InterNetwork)));
(prefix.StartOfPrefixBigInt).ToIpAddress(
AddressFamily.InterNetwork) + "/30"));
}
else if (prefix.Length == 2)
{
Expand All @@ -289,7 +309,7 @@ public string ValidatePrefix(string routePrefix, string PeeringType)

return routePrefix;
case AddressFamily.InterNetworkV6:
if (PeeringType.Equals(Constants.Exchange, StringComparison.OrdinalIgnoreCase))
if (peeringType.Equals(Constants.Exchange, StringComparison.OrdinalIgnoreCase))
{
if (prefix.PrefixMaskWidth != 128)
{
Expand Down Expand Up @@ -383,6 +403,7 @@ public string GetAzureRegion(string peeringLocation, string kind)
{
if (location.Name == peeringLocation)
{
this.WriteVerbose($"Region: {location.AzureRegion}");
return location.AzureRegion;
}
}
Expand All @@ -391,10 +412,7 @@ public string GetAzureRegion(string peeringLocation, string kind)
}
catch (ErrorResponseException ex)
{
var error = ex.Response.Content.Contains("\"error\": \"")
? JsonConvert.DeserializeObject<Dictionary<string, ErrorResponse>>(ex.Response.Content)
.FirstOrDefault().Value
: JsonConvert.DeserializeObject<ErrorResponse>(ex.Response.Content);
var error = this.GetErrorCodeAndMessageFromArmOrErm(ex);
throw new ErrorResponseException(string.Format(Resources.Error_CloudError, error.Code, error.Message));
}
}
Expand All @@ -420,26 +438,6 @@ public bool IsValidConnection(PSExchangeConnection connection)

if (connection.BgpSession == null)
throw new PSArgumentNullException(string.Format(Resources.Error_NullSession));
if (connection.BgpSession.PeerSessionIPv4Address == null
&& connection.BgpSession.MaxPrefixesAdvertisedV4 != null)
throw new PSArgumentException(
string.Format(Resources.Error_MustBeNull, "4", connection.BgpSession.MaxPrefixesAdvertisedV4));
if (connection.BgpSession.PeerSessionIPv6Address == null
&& connection.BgpSession.MaxPrefixesAdvertisedV6 != null)
throw new PSArgumentException(
string.Format(Resources.Error_MustBeNull, "6", connection.BgpSession.MaxPrefixesAdvertisedV6));
if (connection.BgpSession.MaxPrefixesAdvertisedV4 <= 0 && connection.BgpSession.SessionPrefixV4 != null)
throw new PSArgumentException(
string.Format(
Resources.Error_MustBeGreaterThanZero,
"4",
connection.BgpSession.MaxPrefixesAdvertisedV4));
if (connection.BgpSession.MaxPrefixesAdvertisedV6 <= 0 && connection.BgpSession.SessionPrefixV6 != null)
throw new PSArgumentException(
string.Format(
Resources.Error_MustBeGreaterThanZero,
"6",
connection.BgpSession.MaxPrefixesAdvertisedV6));
return true;
}

Expand All @@ -461,10 +459,47 @@ public bool IsValidConnection(PSDirectConnection connection)
throw new PSArgumentException(
string.Format(Resources.Error_InvalidFacilityId, connection.PeeringDBFacilityId));
}

if (connection.BgpSession == null)
throw new PSArgumentNullException(string.Format(Resources.Error_NullSession));
return this.ValidBandwidth(connection.BandwidthInMbps);
}

/// <summary>
/// The get error code and message from arm or erm.
/// </summary>
/// <param name="ex">
/// The ex.
/// </param>
/// <returns>
/// The <see cref="ErrorResponse"/>.
/// </returns>
public ErrorResponse GetErrorCodeAndMessageFromArmOrErm(ErrorResponseException ex)
{
ErrorResponse error = null;
try
{
var armError = JsonConvert.DeserializeObject<Dictionary<string, ErrorResponse>>(ex.Response.Content);
if (armError.Values.FirstOrDefault()?.Code != null)
{
error = new ErrorResponse(code: armError.Values.FirstOrDefault()?.Code, message: armError.Values.FirstOrDefault()?.Message);
}
}
catch
{
try
{
var ermError = JsonConvert.DeserializeObject<ErrorResponse>(ex.Response.Content);
if (ermError.Code != null)
{
error = new ErrorResponse(code: ermError.Code, message: ermError.Message);
}
}
catch
{
throw ex;
}
}
return error;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public override void Execute()
}
catch (ErrorResponseException ex)
{
var error = ex.Response.Content.Contains("\"error\\\":") ? JsonConvert.DeserializeObject<Dictionary<string, ErrorResponse>>(JsonConvert.DeserializeObject(ex.Response.Content).ToString()).FirstOrDefault().Value : JsonConvert.DeserializeObject<ErrorResponse>(ex.Response.Content);
var error = this.GetErrorCodeAndMessageFromArmOrErm(ex);
throw new ErrorResponseException(string.Format(Resources.Error_CloudError, error.Code, error.Message));
}
}
Expand All @@ -176,15 +176,12 @@ public override void Execute()
/// </returns>
private PSDirectConnection UpdatePeeringOffer()
{
if (this.InputObject is PSDirectConnection inputObject)
{
inputObject.BandwidthInMbps =
this.ValidUpgradeBandwidth(inputObject.BandwidthInMbps, this.BandwidthInMbps)
this.InputObject.BandwidthInMbps =
this.ValidUpgradeBandwidth(this.InputObject.BandwidthInMbps, this.BandwidthInMbps)
? this.BandwidthInMbps
: inputObject.BandwidthInMbps;
if (this.IsValidConnection(inputObject))
return inputObject;
}
: this.InputObject.BandwidthInMbps;
if (this.IsValidConnection(this.InputObject))
return this.InputObject;

throw new InvalidOperationException(string.Format(Resources.Error_WrongCommandForDirectObject));
}
Expand All @@ -197,12 +194,9 @@ private PSDirectConnection UpdatePeeringOffer()
/// </returns>
private PSDirectConnection UpdateMD5Authentication()
{
if (this.InputObject is PSDirectConnection inputObject)
{
inputObject.BgpSession.Md5AuthenticationKey = this.MD5AuthenticationKey;
if (this.IsValidConnection(inputObject))
return inputObject;
}
this.InputObject.BgpSession.Md5AuthenticationKey = this.MD5AuthenticationKey;
if (this.IsValidConnection(this.InputObject))
return this.InputObject;

throw new InvalidOperationException(string.Format(Resources.Error_WrongCommandForDirectObject));
}
Expand All @@ -215,14 +209,11 @@ private PSDirectConnection UpdateMD5Authentication()
/// </returns>
private PSDirectConnection UpdateIpV4Prefix()
{
if (this.InputObject is PSDirectConnection inputObject)
{
inputObject.BgpSession.MaxPrefixesAdvertisedV4 =
this.MaxPrefixesAdvertisedIPv4 == null ? inputObject.BgpSession.MaxPrefixesAdvertisedV4 : 20000;
inputObject.BgpSession.SessionPrefixV4 = this.ValidatePrefix(this.SessionPrefixV4, Constants.Direct);
if (this.IsValidConnection(inputObject))
return inputObject;
}
this.InputObject.BgpSession.MaxPrefixesAdvertisedV4 =
this.MaxPrefixesAdvertisedIPv4 == null ? this.InputObject.BgpSession.MaxPrefixesAdvertisedV4 : 20000;
this.InputObject.BgpSession.SessionPrefixV4 = this.ValidatePrefix(this.SessionPrefixV4, Constants.Direct);
if (this.IsValidConnection(this.InputObject))
return this.InputObject;

throw new InvalidOperationException(string.Format(Resources.Error_WrongCommandForDirectObject));
}
Expand All @@ -235,14 +226,11 @@ private PSDirectConnection UpdateIpV4Prefix()
/// </returns>
private PSDirectConnection UpdateIpV6Prefix()
{
if (this.InputObject is PSDirectConnection inputObject)
{
inputObject.BgpSession.MaxPrefixesAdvertisedV6 =
this.MaxPrefixesAdvertisedIPv6 == null ? inputObject.BgpSession.MaxPrefixesAdvertisedV6 : 2000;
inputObject.BgpSession.SessionPrefixV6 = this.ValidatePrefix(this.SessionPrefixV6, Constants.Direct);
if (this.IsValidConnection(inputObject))
return inputObject;
}
this.InputObject.BgpSession.MaxPrefixesAdvertisedV6 =
this.MaxPrefixesAdvertisedIPv6 == null ? this.InputObject.BgpSession.MaxPrefixesAdvertisedV6 : 2000;
this.InputObject.BgpSession.SessionPrefixV6 = this.ValidatePrefix(this.SessionPrefixV6, Constants.Direct);
if (this.IsValidConnection(this.InputObject))
return this.InputObject;

throw new InvalidOperationException(string.Format(Resources.Error_WrongCommandForDirectObject));
}
Expand Down
Loading