mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Improve error message handling (#497)
- Add special handling for token expired errors so they send with a clear flag that'll allow clients to take action on this case - Send error message instead of callstack for all messages, and ensure all resource manager paths send back inner exceptions so users can understand the true root cause.
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The exception is used if any operation fails as a request failed due to an expired token
|
||||||
|
/// </summary>
|
||||||
|
public class ExpiredTokenException : ServiceExceptionBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ServiceFailedException class.
|
||||||
|
/// </summary>
|
||||||
|
public ExpiredTokenException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ServiceFailedException class with a specified error message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The error message that explains the reason for the exception. </param>
|
||||||
|
public ExpiredTokenException(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ServiceFailedException class with a specified error message
|
||||||
|
/// and a reference to the inner exception that is the cause of this exception.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The error message that explains the reason for the exception. </param>
|
||||||
|
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference
|
||||||
|
/// (Nothing in Visual Basic) if no inner exception is specified</param>
|
||||||
|
public ExpiredTokenException(string message, Exception innerException)
|
||||||
|
: base(message, innerException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the ServiceFailedException class with serialized data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The SerializationInfo that holds the serialized object data about the exception being thrown.</param>
|
||||||
|
/// <param name="context">The StreamingContext that contains contextual information about the source or destination.</param>
|
||||||
|
public ExpiredTokenException(SerializationInfo info, StreamingContext context)
|
||||||
|
: base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,9 +50,11 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.Contracts
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CreateFirewallRuleResponse
|
public class CreateFirewallRuleResponse : TokenReliantResponse
|
||||||
{
|
{
|
||||||
public bool Result { get; set; }
|
/// <summary>
|
||||||
|
/// An error message for why the request failed, if any
|
||||||
|
/// </summary>
|
||||||
public string ErrorMessage { get; set; }
|
public string ErrorMessage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,6 +99,4 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.Contracts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string IpAddress { get; set; }
|
public string IpAddress { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ResourceProvider.Core.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Any response which relies on a token may indicated that the operation failed due to token being expired.
|
||||||
|
/// All operational response messages should inherit from this class in order to support a standard method for defining
|
||||||
|
/// this failure path
|
||||||
|
/// </summary>
|
||||||
|
public class TokenReliantResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Did this succeed?
|
||||||
|
/// </summary>
|
||||||
|
public bool Result { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this failed, was it due to a token expiring?
|
||||||
|
/// </summary>
|
||||||
|
public bool IsTokenExpiredFailure { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
Keys.Culture = value;
|
Keys.Culture = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string NoSubscriptionsFound
|
public static string NoSubscriptionsFound
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.NoSubscriptionsFound);
|
return Keys.GetString(Keys.NoSubscriptionsFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string AzureServerNotFound
|
public static string AzureServerNotFound
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.AzureServerNotFound);
|
return Keys.GetString(Keys.AzureServerNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string AzureSubscriptionFailedErrorMessage
|
public static string AzureSubscriptionFailedErrorMessage
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string DatabaseDiscoveryFailedErrorMessage
|
public static string DatabaseDiscoveryFailedErrorMessage
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.DatabaseDiscoveryFailedErrorMessage);
|
return Keys.GetString(Keys.DatabaseDiscoveryFailedErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleAccessForbidden
|
public static string FirewallRuleAccessForbidden
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleAccessForbidden);
|
return Keys.GetString(Keys.FirewallRuleAccessForbidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleCreationFailed
|
public static string FirewallRuleCreationFailed
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleCreationFailedWithError
|
public static string FirewallRuleCreationFailedWithError
|
||||||
{
|
{
|
||||||
@@ -83,7 +83,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string InvalidIpAddress
|
public static string InvalidIpAddress
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.InvalidIpAddress);
|
return Keys.GetString(Keys.InvalidIpAddress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string InvalidServerTypeErrorMessage
|
public static string InvalidServerTypeErrorMessage
|
||||||
{
|
{
|
||||||
@@ -99,7 +99,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.InvalidServerTypeErrorMessage);
|
return Keys.GetString(Keys.InvalidServerTypeErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string LoadingExportableFailedGeneralErrorMessage
|
public static string LoadingExportableFailedGeneralErrorMessage
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.LoadingExportableFailedGeneralErrorMessage);
|
return Keys.GetString(Keys.LoadingExportableFailedGeneralErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleUnsupportedConnectionType
|
public static string FirewallRuleUnsupportedConnectionType
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleUnsupportedConnectionType);
|
return Keys.GetString(Keys.FirewallRuleUnsupportedConnectionType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
public class Keys
|
public class Keys
|
||||||
@@ -123,40 +123,40 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.Core.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.Core.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
static CultureInfo _culture = null;
|
static CultureInfo _culture = null;
|
||||||
|
|
||||||
|
|
||||||
public const string NoSubscriptionsFound = "NoSubscriptionsFound";
|
public const string NoSubscriptionsFound = "NoSubscriptionsFound";
|
||||||
|
|
||||||
|
|
||||||
public const string AzureServerNotFound = "AzureServerNotFound";
|
public const string AzureServerNotFound = "AzureServerNotFound";
|
||||||
|
|
||||||
|
|
||||||
public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
|
public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string DatabaseDiscoveryFailedErrorMessage = "DatabaseDiscoveryFailedErrorMessage";
|
public const string DatabaseDiscoveryFailedErrorMessage = "DatabaseDiscoveryFailedErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleAccessForbidden = "FirewallRuleAccessForbidden";
|
public const string FirewallRuleAccessForbidden = "FirewallRuleAccessForbidden";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
||||||
|
|
||||||
|
|
||||||
public const string InvalidIpAddress = "InvalidIpAddress";
|
public const string InvalidIpAddress = "InvalidIpAddress";
|
||||||
|
|
||||||
|
|
||||||
public const string InvalidServerTypeErrorMessage = "InvalidServerTypeErrorMessage";
|
public const string InvalidServerTypeErrorMessage = "InvalidServerTypeErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string LoadingExportableFailedGeneralErrorMessage = "LoadingExportableFailedGeneralErrorMessage";
|
public const string LoadingExportableFailedGeneralErrorMessage = "LoadingExportableFailedGeneralErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleUnsupportedConnectionType = "FirewallRuleUnsupportedConnectionType";
|
public const string FirewallRuleUnsupportedConnectionType = "FirewallRuleUnsupportedConnectionType";
|
||||||
|
|
||||||
|
|
||||||
private Keys()
|
private Keys()
|
||||||
{ }
|
{ }
|
||||||
@@ -177,7 +177,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return resourceManager.GetString(key, _culture);
|
return resourceManager.GetString(key, _culture);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,45 +120,45 @@
|
|||||||
<data name="NoSubscriptionsFound" xml:space="preserve">
|
<data name="NoSubscriptionsFound" xml:space="preserve">
|
||||||
<value>No subscriptions were found for the currently logged in user account.</value>
|
<value>No subscriptions were found for the currently logged in user account.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AzureServerNotFound" xml:space="preserve">
|
<data name="AzureServerNotFound" xml:space="preserve">
|
||||||
<value>The server you specified {0} does not exist in any subscription in {1}. Either you have signed in with an incorrect account or your server was removed from subscription(s) in this account. Please check your account and try again.</value>
|
<value>The server you specified {0} does not exist in any subscription in {1}. Either you have signed in with an incorrect account or your server was removed from subscription(s) in this account. Please check your account and try again.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
|
<data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure subscriptions</value>
|
<value>An error occurred while getting Azure subscriptions: {0}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DatabaseDiscoveryFailedErrorMessage" xml:space="preserve">
|
<data name="DatabaseDiscoveryFailedErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting databases from servers of type {0} from {1}</value>
|
<value>An error occurred while getting databases from servers of type {0} from {1}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleAccessForbidden" xml:space="preserve">
|
<data name="FirewallRuleAccessForbidden" xml:space="preserve">
|
||||||
<value>{0} does not have permission to change the server firewall rule. Try again with a different account that is an Owner or Contributor of the Azure subscription or the server.</value>
|
<value>{0} does not have permission to change the server firewall rule. Try again with a different account that is an Owner or Contributor of the Azure subscription or the server.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||||
<value>An error occurred while creating a new firewall rule.</value>
|
<value>An error occurred while creating a new firewall rule.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
||||||
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidIpAddress" xml:space="preserve">
|
<data name="InvalidIpAddress" xml:space="preserve">
|
||||||
<value>Invalid IP address</value>
|
<value>Invalid IP address</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidServerTypeErrorMessage" xml:space="preserve">
|
<data name="InvalidServerTypeErrorMessage" xml:space="preserve">
|
||||||
<value>Server Type is invalid.</value>
|
<value>Server Type is invalid.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoadingExportableFailedGeneralErrorMessage" xml:space="preserve">
|
<data name="LoadingExportableFailedGeneralErrorMessage" xml:space="preserve">
|
||||||
<value>A required dll cannot be loaded. Please repair your application.</value>
|
<value>A required dll cannot be loaded. Please repair your application.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleUnsupportedConnectionType" xml:space="preserve">
|
<data name="FirewallRuleUnsupportedConnectionType" xml:space="preserve">
|
||||||
<value>Cannot open a firewall rule for the specified connection type</value>
|
<value>Cannot open a firewall rule for the specified connection type</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
# Azure Core DLL
|
# Azure Core DLL
|
||||||
NoSubscriptionsFound = No subscriptions were found for the currently logged in user account.
|
NoSubscriptionsFound = No subscriptions were found for the currently logged in user account.
|
||||||
AzureServerNotFound = The server you specified {0} does not exist in any subscription in {1}. Either you have signed in with an incorrect account or your server was removed from subscription(s) in this account. Please check your account and try again.
|
AzureServerNotFound = The server you specified {0} does not exist in any subscription in {1}. Either you have signed in with an incorrect account or your server was removed from subscription(s) in this account. Please check your account and try again.
|
||||||
AzureSubscriptionFailedErrorMessage = An error occurred while getting Azure subscriptions
|
AzureSubscriptionFailedErrorMessage = An error occurred while getting Azure subscriptions: {0}
|
||||||
DatabaseDiscoveryFailedErrorMessage = An error occurred while getting databases from servers of type {0} from {1}
|
DatabaseDiscoveryFailedErrorMessage = An error occurred while getting databases from servers of type {0} from {1}
|
||||||
FirewallRuleAccessForbidden = {0} does not have permission to change the server firewall rule. Try again with a different account that is an Owner or Contributor of the Azure subscription or the server.
|
FirewallRuleAccessForbidden = {0} does not have permission to change the server firewall rule. Try again with a different account that is an Owner or Contributor of the Azure subscription or the server.
|
||||||
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="AzureSubscriptionFailedErrorMessage">
|
<trans-unit id="AzureSubscriptionFailedErrorMessage">
|
||||||
<source>An error occurred while getting Azure subscriptions</source>
|
<source>An error occurred while getting Azure subscriptions: {0}</source>
|
||||||
<target state="new">An error occurred while getting Azure subscriptions</target>
|
<target state="new">An error occurred while getting Azure subscriptions</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|||||||
@@ -56,7 +56,16 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
{
|
{
|
||||||
return DoHandleCreateFirewallRuleRequest(firewallRule);
|
return DoHandleCreateFirewallRuleRequest(firewallRule);
|
||||||
};
|
};
|
||||||
await HandleRequest(requestHandler, requestContext, "HandleCreateFirewallRuleRequest");
|
Func<ExpiredTokenException, CreateFirewallRuleResponse> tokenExpiredHandler = (ExpiredTokenException ex) =>
|
||||||
|
{
|
||||||
|
return new CreateFirewallRuleResponse()
|
||||||
|
{
|
||||||
|
Result = false,
|
||||||
|
IsTokenExpiredFailure = true,
|
||||||
|
ErrorMessage = ex.Message
|
||||||
|
};
|
||||||
|
};
|
||||||
|
await HandleRequest(requestHandler, tokenExpiredHandler, requestContext, "HandleCreateFirewallRuleRequest");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CreateFirewallRuleResponse> DoHandleCreateFirewallRuleRequest(CreateFirewallRuleParams firewallRule)
|
private async Task<CreateFirewallRuleResponse> DoHandleCreateFirewallRuleRequest(CreateFirewallRuleParams firewallRule)
|
||||||
@@ -98,10 +107,10 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
}
|
}
|
||||||
return Task.FromResult(response);
|
return Task.FromResult(response);
|
||||||
};
|
};
|
||||||
await HandleRequest(requestHandler, requestContext, "HandleCreateFirewallRuleRequest");
|
await HandleRequest(requestHandler, null, requestContext, "HandleCreateFirewallRuleRequest");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleRequest<T>(Func<Task<T>> handler, RequestContext<T> requestContext, string requestType)
|
private async Task HandleRequest<T>(Func<Task<T>> handler, Func<ExpiredTokenException, T> expiredTokenHandler, RequestContext<T> requestContext, string requestType)
|
||||||
{
|
{
|
||||||
Logger.Write(LogLevel.Verbose, requestType);
|
Logger.Write(LogLevel.Verbose, requestType);
|
||||||
|
|
||||||
@@ -110,9 +119,25 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
|||||||
T result = await handler();
|
T result = await handler();
|
||||||
await requestContext.SendResult(result);
|
await requestContext.SendResult(result);
|
||||||
}
|
}
|
||||||
|
catch(ExpiredTokenException ex)
|
||||||
|
{
|
||||||
|
if (expiredTokenHandler != null)
|
||||||
|
{
|
||||||
|
// This is a special exception indicating the token(s) used to request resources had expired.
|
||||||
|
// Any Azure resource should have handling for this such as an error path that clearly indicates that a refresh is needed
|
||||||
|
T result = expiredTokenHandler(ex);
|
||||||
|
await requestContext.SendResult(result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No handling for expired tokens defined / expected
|
||||||
|
await requestContext.SendError(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await requestContext.SendError(ex.ToString());
|
// Send just the error message back for now as stack trace isn't useful
|
||||||
|
await requestContext.SendError(ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new ServiceFailedException(SR.AzureSubscriptionFailedErrorMessage, ex);
|
throw new ServiceFailedException(SR.FailedToGetAzureSubscriptionsErrorMessage, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = result ?? Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
result = result ?? Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
||||||
@@ -234,38 +234,25 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
|
|
||||||
private async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionFromServiceAsync(AzureUserAccount userAccount)
|
private async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionFromServiceAsync(AzureUserAccount userAccount)
|
||||||
{
|
{
|
||||||
|
CommonUtil.CheckForNull(userAccount, nameof(userAccount));
|
||||||
List<IAzureUserAccountSubscriptionContext> subscriptionList = new List<IAzureUserAccountSubscriptionContext>();
|
List<IAzureUserAccountSubscriptionContext> subscriptionList = new List<IAzureUserAccountSubscriptionContext>();
|
||||||
|
if (userAccount.NeedsReauthentication)
|
||||||
|
{
|
||||||
|
throw new ExpiredTokenException(SR.UserNeedsAuthenticationError);
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (userAccount != null && !userAccount.NeedsReauthentication)
|
IAzureResourceManager resourceManager = ServiceProvider.GetService<IAzureResourceManager>();
|
||||||
{
|
IEnumerable<IAzureUserAccountSubscriptionContext> contexts = await resourceManager.GetSubscriptionContextsAsync(userAccount);
|
||||||
IAzureResourceManager resourceManager = ServiceProvider.GetService<IAzureResourceManager>();
|
subscriptionList = contexts.ToList();
|
||||||
IEnumerable<IAzureUserAccountSubscriptionContext> contexts = await resourceManager.GetSubscriptionContextsAsync(userAccount);
|
|
||||||
subscriptionList = contexts.ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new UserNeedsAuthenticationException(SR.AzureSubscriptionFailedErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// TODO handle stale tokens
|
|
||||||
//catch (MissingSecurityTokenException missingSecurityTokenException)
|
|
||||||
//{
|
|
||||||
// //User needs to reauthenticate
|
|
||||||
// if (userAccount != null)
|
|
||||||
// {
|
|
||||||
// userAccount.NeedsReauthentication = true;
|
|
||||||
// }
|
|
||||||
// throw new UserNeedsAuthenticationException(SR.AzureSubscriptionFailedErrorMessage, missingSecurityTokenException);
|
|
||||||
//}
|
|
||||||
catch (ServiceExceptionBase)
|
catch (ServiceExceptionBase)
|
||||||
{
|
{
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new ServiceFailedException(SR.AzureSubscriptionFailedErrorMessage, ex);
|
throw new ServiceFailedException(SR.FailedToGetAzureSubscriptionsErrorMessage, ex);
|
||||||
}
|
}
|
||||||
return subscriptionList;
|
return subscriptionList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
public class AzureResourceManager : ExportableBase, IAzureResourceManager
|
public class AzureResourceManager : ExportableBase, IAzureResourceManager
|
||||||
{
|
{
|
||||||
private readonly Uri _resourceManagementUri = new Uri("https://management.azure.com/");
|
private readonly Uri _resourceManagementUri = new Uri("https://management.azure.com/");
|
||||||
|
private const string ExpiredTokenCode = "ExpiredAuthenticationToken";
|
||||||
|
|
||||||
public AzureResourceManager()
|
public AzureResourceManager()
|
||||||
{
|
{
|
||||||
// Duplicate the exportable attribute as at present we do not support filtering using extensiondescriptor.
|
// Duplicate the exportable attribute as at present we do not support filtering using extensiondescriptor.
|
||||||
@@ -91,16 +92,10 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
|
|
||||||
if (vsAzureResourceManagementSession != null)
|
if (vsAzureResourceManagementSession != null)
|
||||||
{
|
{
|
||||||
try
|
IEnumerable<Database> databaseListResponse = await ExecuteCloudRequest(
|
||||||
{
|
() => vsAzureResourceManagementSession.SqlManagementClient.Databases.ListByServerAsync(resourceGroupName, serverName),
|
||||||
IEnumerable<Database> databaseListResponse = await vsAzureResourceManagementSession.SqlManagementClient.Databases.ListByServerAsync(resourceGroupName, serverName);
|
SR.FailedToGetAzureDatabasesErrorMessage);
|
||||||
return databaseListResponse.Select(
|
return databaseListResponse.Select(x => new AzureResourceWrapper(x) { ResourceGroupName = resourceGroupName });
|
||||||
x => new AzureResourceWrapper(x) { ResourceGroupName = resourceGroupName });
|
|
||||||
}
|
|
||||||
catch(HttpOperationException ex)
|
|
||||||
{
|
|
||||||
throw new AzureResourceFailedException(SR.FailedToGetAzureDatabasesErrorMessage, ex.Response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -127,28 +122,17 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
AzureResourceManagementSession vsAzureResourceManagementSession = azureResourceManagementSession as AzureResourceManagementSession;
|
AzureResourceManagementSession vsAzureResourceManagementSession = azureResourceManagementSession as AzureResourceManagementSession;
|
||||||
if(vsAzureResourceManagementSession != null)
|
if(vsAzureResourceManagementSession != null)
|
||||||
{
|
{
|
||||||
// Note: Ideally wouldn't need to query resource groups, but the current impl requires it
|
IServersOperations serverOperations = vsAzureResourceManagementSession.SqlManagementClient.Servers;
|
||||||
// since any update will need the resource group name and it's not returned from the server.
|
IPage<Server> servers = await ExecuteCloudRequest(
|
||||||
// This has a very negative impact on perf, so we should investigate running these queries
|
() => serverOperations.ListAsync(),
|
||||||
// in parallel
|
SR.FailedToGetAzureSqlServersWithError);
|
||||||
|
if (servers != null)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
IServersOperations serverOperations = vsAzureResourceManagementSession.SqlManagementClient.Servers;
|
sqlServers.AddRange(servers.Select(server => {
|
||||||
IPage<Server> servers = await serverOperations.ListAsync();
|
var serverResource = new SqlAzureResource(server);
|
||||||
if (servers != null)
|
// TODO ResourceGroup name
|
||||||
{
|
return serverResource;
|
||||||
sqlServers.AddRange(servers.Select(server => {
|
}));
|
||||||
var serverResource = new SqlAzureResource(server);
|
|
||||||
// TODO ResourceGroup name
|
|
||||||
return serverResource;
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (HttpOperationException ex)
|
|
||||||
{
|
|
||||||
throw new AzureResourceFailedException(
|
|
||||||
string.Format(CultureInfo.CurrentCulture, SR.FailedToGetAzureSqlServersWithError, ex.Message), ex.Response.StatusCode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,33 +160,27 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
|
|
||||||
if (vsAzureResourceManagementSession != null)
|
if (vsAzureResourceManagementSession != null)
|
||||||
{
|
{
|
||||||
try
|
var firewallRule = new RestFirewallRule()
|
||||||
{
|
{
|
||||||
var firewallRule = new RestFirewallRule()
|
EndIpAddress = firewallRuleRequest.EndIpAddress.ToString(),
|
||||||
{
|
StartIpAddress = firewallRuleRequest.StartIpAddress.ToString()
|
||||||
EndIpAddress = firewallRuleRequest.EndIpAddress.ToString(),
|
};
|
||||||
StartIpAddress = firewallRuleRequest.StartIpAddress.ToString()
|
IFirewallRulesOperations firewallRuleOperations = vsAzureResourceManagementSession.SqlManagementClient.FirewallRules;
|
||||||
};
|
var firewallRuleResponse = await ExecuteCloudRequest(
|
||||||
IFirewallRulesOperations firewallRuleOperations = vsAzureResourceManagementSession.SqlManagementClient.FirewallRules;
|
() => firewallRuleOperations.CreateOrUpdateWithHttpMessagesAsync(
|
||||||
var firewallRuleResponse = await firewallRuleOperations.CreateOrUpdateWithHttpMessagesAsync(
|
azureSqlServer.ResourceGroupName ?? string.Empty,
|
||||||
azureSqlServer.ResourceGroupName ?? string.Empty,
|
azureSqlServer.Name,
|
||||||
azureSqlServer.Name,
|
firewallRuleRequest.FirewallRuleName,
|
||||||
firewallRuleRequest.FirewallRuleName,
|
firewallRule,
|
||||||
firewallRule,
|
GetCustomHeaders()),
|
||||||
GetCustomHeaders());
|
SR.FirewallRuleCreationFailedWithError);
|
||||||
var response = firewallRuleResponse.Body;
|
var response = firewallRuleResponse.Body;
|
||||||
return new FirewallRuleResponse()
|
return new FirewallRuleResponse()
|
||||||
{
|
|
||||||
StartIpAddress = response.StartIpAddress,
|
|
||||||
EndIpAddress = response.EndIpAddress,
|
|
||||||
Created = true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (HttpOperationException ex)
|
|
||||||
{
|
{
|
||||||
throw new AzureResourceFailedException(
|
StartIpAddress = response.StartIpAddress,
|
||||||
string.Format(CultureInfo.CurrentCulture, SR.FirewallRuleCreationFailedWithError, ex.Message), ex.Response.StatusCode);
|
EndIpAddress = response.EndIpAddress,
|
||||||
}
|
Created = true
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// else respond with failure case
|
// else respond with failure case
|
||||||
return new FirewallRuleResponse()
|
return new FirewallRuleResponse()
|
||||||
@@ -228,40 +206,6 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the azure resource groups for given subscription
|
|
||||||
/// </summary>
|
|
||||||
private async Task<IEnumerable<ResourceGroup>> GetResourceGroupsAsync(AzureResourceManagementSession vsAzureResourceManagementSession)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (vsAzureResourceManagementSession != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IResourceGroupsOperations resourceGroupOperations = vsAzureResourceManagementSession.ResourceManagementClient.ResourceGroups;
|
|
||||||
IPage<ResourceGroup> resourceGroupList = await resourceGroupOperations.ListAsync();
|
|
||||||
if (resourceGroupList != null)
|
|
||||||
{
|
|
||||||
return resourceGroupList.AsEnumerable();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (HttpOperationException ex)
|
|
||||||
{
|
|
||||||
throw new AzureResourceFailedException(string.Format(CultureInfo.CurrentCulture, SR.FailedToGetAzureResourceGroupsErrorMessage, ex.Message), ex.Response.StatusCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Enumerable.Empty<ResourceGroup>();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
TraceException(TraceEventType.Error, (int)TraceId.AzureResource, ex, "Failed to get azure resource groups");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all subscription contexts under a specific user account. Queries all tenants for the account and uses these to log in
|
/// Gets all subscription contexts under a specific user account. Queries all tenants for the account and uses these to log in
|
||||||
/// and retrieve subscription information as needed
|
/// and retrieve subscription information as needed
|
||||||
@@ -278,7 +222,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
var ex = response.Errors.First();
|
var ex = response.Errors.First();
|
||||||
throw new AzureResourceFailedException(
|
throw new AzureResourceFailedException(
|
||||||
string.Format(CultureInfo.CurrentCulture, SR.AzureSubscriptionFailedErrorMessage, ex.Message));
|
string.Format(CultureInfo.CurrentCulture, SR.FailedToGetAzureSubscriptionsErrorMessage, ex.Message));
|
||||||
}
|
}
|
||||||
contexts.AddRange(response.Data);
|
contexts.AddRange(response.Data);
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
@@ -318,20 +262,12 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
if (subscriptionClient != null)
|
if (subscriptionClient != null)
|
||||||
{
|
{
|
||||||
try
|
IPage<Subscription> subscriptionList = await ExecuteCloudRequest(
|
||||||
|
() => subscriptionClient.Subscriptions.ListAsync(),
|
||||||
|
SR.FailedToGetAzureSubscriptionsErrorMessage);
|
||||||
|
if (subscriptionList != null)
|
||||||
{
|
{
|
||||||
ISubscriptionsOperations subscriptionsOperations = subscriptionClient.Subscriptions;
|
return subscriptionList.AsEnumerable();
|
||||||
IPage<Subscription> subscriptionList = await subscriptionsOperations.ListAsync();
|
|
||||||
if (subscriptionList != null)
|
|
||||||
{
|
|
||||||
return subscriptionList.AsEnumerable();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (HttpOperationException ex)
|
|
||||||
{
|
|
||||||
throw new AzureResourceFailedException(
|
|
||||||
string.Format(CultureInfo.CurrentCulture, SR.AzureSubscriptionFailedErrorMessage, ex.Message), ex.Response.StatusCode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,5 +318,29 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
}
|
}
|
||||||
throw new NotSupportedException("This uses an unknown subscription type");
|
throw new NotSupportedException("This uses an unknown subscription type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<T> ExecuteCloudRequest<T>(Func<Task<T>> operation, string errorOccurredMsg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await operation();
|
||||||
|
}
|
||||||
|
catch(CloudException ex)
|
||||||
|
{
|
||||||
|
if (ex.Body != null && string.Equals(ExpiredTokenCode, ex.Body.Code, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Throw an expired token exception, which indicates that the operation could succeed if the user reauthenticates
|
||||||
|
throw new ExpiredTokenException(ex.Message);
|
||||||
|
}
|
||||||
|
throw new AzureResourceFailedException(
|
||||||
|
string.Format(CultureInfo.CurrentCulture, errorOccurredMsg, ex.Message), ex.Response.StatusCode);
|
||||||
|
}
|
||||||
|
catch (HttpOperationException ex)
|
||||||
|
{
|
||||||
|
throw new AzureResourceFailedException(
|
||||||
|
string.Format(CultureInfo.CurrentCulture, errorOccurredMsg, ex.Message), ex.Response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
Keys.Culture = value;
|
Keys.Culture = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static string FailedToGetAzureDatabasesErrorMessage
|
public static string FailedToGetAzureDatabasesErrorMessage
|
||||||
{
|
{
|
||||||
@@ -35,7 +35,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FailedToGetAzureDatabasesErrorMessage);
|
return Keys.GetString(Keys.FailedToGetAzureDatabasesErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FailedToGetAzureSubscriptionsErrorMessage
|
public static string FailedToGetAzureSubscriptionsErrorMessage
|
||||||
{
|
{
|
||||||
@@ -43,7 +43,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FailedToGetAzureSubscriptionsErrorMessage);
|
return Keys.GetString(Keys.FailedToGetAzureSubscriptionsErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FailedToGetAzureResourceGroupsErrorMessage
|
public static string FailedToGetAzureResourceGroupsErrorMessage
|
||||||
{
|
{
|
||||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FailedToGetAzureResourceGroupsErrorMessage);
|
return Keys.GetString(Keys.FailedToGetAzureResourceGroupsErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FailedToGetAzureSqlServersErrorMessage
|
public static string FailedToGetAzureSqlServersErrorMessage
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FailedToGetAzureSqlServersErrorMessage);
|
return Keys.GetString(Keys.FailedToGetAzureSqlServersErrorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FailedToGetAzureSqlServersWithError
|
public static string FailedToGetAzureSqlServersWithError
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FailedToGetAzureSqlServersWithError);
|
return Keys.GetString(Keys.FailedToGetAzureSqlServersWithError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleCreationFailed
|
public static string FirewallRuleCreationFailed
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string FirewallRuleCreationFailedWithError
|
public static string FirewallRuleCreationFailedWithError
|
||||||
{
|
{
|
||||||
@@ -83,15 +83,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string AzureSubscriptionFailedErrorMessage
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string UnsupportedAuthType
|
public static string UnsupportedAuthType
|
||||||
{
|
{
|
||||||
@@ -99,7 +91,23 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return Keys.GetString(Keys.UnsupportedAuthType);
|
return Keys.GetString(Keys.UnsupportedAuthType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string UserNotFoundError
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.UserNotFoundError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UserNeedsAuthenticationError
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.UserNeedsAuthenticationError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
public class Keys
|
public class Keys
|
||||||
@@ -107,34 +115,37 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.DefaultImpl.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.DefaultImpl.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||||
|
|
||||||
static CultureInfo _culture = null;
|
static CultureInfo _culture = null;
|
||||||
|
|
||||||
|
|
||||||
public const string FailedToGetAzureDatabasesErrorMessage = "FailedToGetAzureDatabasesErrorMessage";
|
public const string FailedToGetAzureDatabasesErrorMessage = "FailedToGetAzureDatabasesErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FailedToGetAzureSubscriptionsErrorMessage = "FailedToGetAzureSubscriptionsErrorMessage";
|
public const string FailedToGetAzureSubscriptionsErrorMessage = "FailedToGetAzureSubscriptionsErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FailedToGetAzureResourceGroupsErrorMessage = "FailedToGetAzureResourceGroupsErrorMessage";
|
public const string FailedToGetAzureResourceGroupsErrorMessage = "FailedToGetAzureResourceGroupsErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FailedToGetAzureSqlServersErrorMessage = "FailedToGetAzureSqlServersErrorMessage";
|
public const string FailedToGetAzureSqlServersErrorMessage = "FailedToGetAzureSqlServersErrorMessage";
|
||||||
|
|
||||||
|
|
||||||
public const string FailedToGetAzureSqlServersWithError = "FailedToGetAzureSqlServersWithError";
|
public const string FailedToGetAzureSqlServersWithError = "FailedToGetAzureSqlServersWithError";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
||||||
|
|
||||||
|
|
||||||
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
||||||
|
|
||||||
|
|
||||||
public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
|
public const string UnsupportedAuthType = "UnsupportedAuthType";
|
||||||
|
|
||||||
|
|
||||||
public const string UnsupportedAuthType = "UnsupportedAuthType";
|
public const string UserNotFoundError = "UserNotFoundError";
|
||||||
|
|
||||||
|
|
||||||
|
public const string UserNeedsAuthenticationError = "UserNeedsAuthenticationError";
|
||||||
|
|
||||||
|
|
||||||
private Keys()
|
private Keys()
|
||||||
{ }
|
{ }
|
||||||
@@ -155,7 +166,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
|||||||
{
|
{
|
||||||
return resourceManager.GetString(key, _culture);
|
return resourceManager.GetString(key, _culture);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,37 +120,41 @@
|
|||||||
<data name="FailedToGetAzureDatabasesErrorMessage" xml:space="preserve">
|
<data name="FailedToGetAzureDatabasesErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure databases</value>
|
<value>An error occurred while getting Azure databases</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToGetAzureSubscriptionsErrorMessage" xml:space="preserve">
|
<data name="FailedToGetAzureSubscriptionsErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure subscriptions: {0}</value>
|
<value>An error occurred while getting Azure subscriptions: {0}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToGetAzureResourceGroupsErrorMessage" xml:space="preserve">
|
<data name="FailedToGetAzureResourceGroupsErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure resource groups: {0}</value>
|
<value>An error occurred while getting Azure resource groups: {0}</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToGetAzureSqlServersErrorMessage" xml:space="preserve">
|
<data name="FailedToGetAzureSqlServersErrorMessage" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure Sql Servers</value>
|
<value>An error occurred while getting Azure Sql Servers</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FailedToGetAzureSqlServersWithError" xml:space="preserve">
|
<data name="FailedToGetAzureSqlServersWithError" xml:space="preserve">
|
||||||
<value>An error occurred while getting Azure Sql Servers: '{0}'</value>
|
<value>An error occurred while getting Azure Sql Servers: '{0}'</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||||
<value>An error occurred while creating a new firewall rule.</value>
|
<value>An error occurred while creating a new firewall rule.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
||||||
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
|
|
||||||
<value>An error occurred while getting Azure subscriptions</value>
|
|
||||||
<comment></comment>
|
|
||||||
</data>
|
|
||||||
<data name="UnsupportedAuthType" xml:space="preserve">
|
<data name="UnsupportedAuthType" xml:space="preserve">
|
||||||
<value>Unsupported account type '{0}' for this provider</value>
|
<value>Unsupported account type '{0}' for this provider</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="UserNotFoundError" xml:space="preserve">
|
||||||
|
<value>No user was found, cannot execute the operation</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="UserNeedsAuthenticationError" xml:space="preserve">
|
||||||
|
<value>The current user must be reauthenticated before executing this operation </value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
|
|||||||
@@ -29,5 +29,6 @@ FailedToGetAzureSqlServersErrorMessage = An error occurred while getting Azure S
|
|||||||
FailedToGetAzureSqlServersWithError = An error occurred while getting Azure Sql Servers: '{0}'
|
FailedToGetAzureSqlServersWithError = An error occurred while getting Azure Sql Servers: '{0}'
|
||||||
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
||||||
FirewallRuleCreationFailedWithError = An error occurred while creating a new firewall rule: '{0}'
|
FirewallRuleCreationFailedWithError = An error occurred while creating a new firewall rule: '{0}'
|
||||||
AzureSubscriptionFailedErrorMessage = An error occurred while getting Azure subscriptions
|
UnsupportedAuthType = Unsupported account type '{0}' for this provider
|
||||||
UnsupportedAuthType = Unsupported account type '{0}' for this provider
|
UserNotFoundError = No user was found, cannot execute the operation
|
||||||
|
UserNeedsAuthenticationError = The current user must be reauthenticated before executing this operation
|
||||||
@@ -22,11 +22,6 @@
|
|||||||
<target state="new">An error occurred while creating a new firewall rule.</target>
|
<target state="new">An error occurred while creating a new firewall rule.</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="AzureSubscriptionFailedErrorMessage">
|
|
||||||
<source>An error occurred while getting Azure subscriptions</source>
|
|
||||||
<target state="new">An error occurred while getting Azure subscriptions</target>
|
|
||||||
<note></note>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="UnsupportedAuthType">
|
<trans-unit id="UnsupportedAuthType">
|
||||||
<source>Unsupported account type '{0}' for this provider</source>
|
<source>Unsupported account type '{0}' for this provider</source>
|
||||||
<target state="new">Unsupported account type '{0}' for this provider</target>
|
<target state="new">Unsupported account type '{0}' for this provider</target>
|
||||||
@@ -47,6 +42,16 @@
|
|||||||
<target state="new">An error occurred while getting Azure subscriptions: {0}</target>
|
<target state="new">An error occurred while getting Azure subscriptions: {0}</target>
|
||||||
<note></note>
|
<note></note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="UserNeedsAuthenticationError">
|
||||||
|
<source>The current user must be reauthenticated before executing this operation </source>
|
||||||
|
<target state="new">The current user must be reauthenticated before executing this operation </target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="UserNotFoundError">
|
||||||
|
<source>No user was found, cannot execute the operation</source>
|
||||||
|
<target state="new">No user was found, cannot execute the operation</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -14,10 +14,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Completion
|
|||||||
public class AutoCompletionResultTest
|
public class AutoCompletionResultTest
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MetricsShouldGetSortedGivenUnSortedArray()
|
public void CompletionShouldRecordDuration()
|
||||||
{
|
{
|
||||||
AutoCompletionResult result = new AutoCompletionResult();
|
AutoCompletionResult result = new AutoCompletionResult();
|
||||||
int duration = 2000;
|
int duration = 200;
|
||||||
Thread.Sleep(duration);
|
Thread.Sleep(duration);
|
||||||
result.CompleteResult(new CompletionItem[] { });
|
result.CompleteResult(new CompletionItem[] { });
|
||||||
Assert.True(result.Duration >= duration);
|
Assert.True(result.Duration >= duration);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
|||||||
var currentUserAccount = CreateAccount();
|
var currentUserAccount = CreateAccount();
|
||||||
currentUserAccount.Account.IsStale = true;
|
currentUserAccount.Account.IsStale = true;
|
||||||
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null);
|
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null);
|
||||||
await Assert.ThrowsAsync<UserNeedsAuthenticationException>(() => accountManager.GetSelectedSubscriptionsAsync());
|
await Assert.ThrowsAsync<ExpiredTokenException>(() => accountManager.GetSelectedSubscriptionsAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
|
|||||||
// When I ask whether the service can process an error as a firewall rule request
|
// When I ask whether the service can process an error as a firewall rule request
|
||||||
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
await TestUtils.RunAndVerify<HandleFirewallRuleResponse>((context) => ResourceProviderService.ProcessHandleFirewallRuleRequest(handleFirewallParams, context), (response) =>
|
||||||
{
|
{
|
||||||
// Then I expect the response to be fakse as we require the known IP address to function
|
// Then I expect the response to be OK as we require the known IP address to function
|
||||||
Assert.NotNull(response);
|
Assert.NotNull(response);
|
||||||
Assert.False(response.Result);
|
Assert.False(response.Result);
|
||||||
Assert.Equal(string.Empty, response.IpAddress);
|
Assert.Equal(string.Empty, response.IpAddress);
|
||||||
@@ -168,10 +168,42 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
|
|||||||
(context) => ResourceProviderService.HandleCreateFirewallRuleRequest(createFirewallParams, context),
|
(context) => ResourceProviderService.HandleCreateFirewallRuleRequest(createFirewallParams, context),
|
||||||
(response) =>
|
(response) =>
|
||||||
{
|
{
|
||||||
// Then I expect the response to be fakse as we require the known IP address to function
|
// Then I expect the response to be OK as we require the known IP address to function
|
||||||
Assert.NotNull(response);
|
Assert.NotNull(response);
|
||||||
Assert.Null(response.ErrorMessage);
|
Assert.Null(response.ErrorMessage);
|
||||||
Assert.True(response.Result);
|
Assert.True(response.Result);
|
||||||
|
Assert.False(response.IsTokenExpiredFailure);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task TestCreateFirewallRuleHandlesTokenExpiration()
|
||||||
|
{
|
||||||
|
// Given the token has expired
|
||||||
|
string serverName = "myserver.database.windows.net";
|
||||||
|
var sub1Mock = new Mock<IAzureUserAccountSubscriptionContext>();
|
||||||
|
SetupCreateSession();
|
||||||
|
string expectedErrorMsg = "Token is expired";
|
||||||
|
AuthenticationManagerMock.Setup(a => a.GetSubscriptionsAsync()).ThrowsAsync(new ExpiredTokenException(expectedErrorMsg));
|
||||||
|
|
||||||
|
// When I request the firewall be created
|
||||||
|
var createFirewallParams = new CreateFirewallRuleParams()
|
||||||
|
{
|
||||||
|
ServerName = serverName,
|
||||||
|
StartIpAddress = "1.1.1.1",
|
||||||
|
EndIpAddress = "1.1.1.255",
|
||||||
|
Account = CreateAccount(),
|
||||||
|
SecurityTokenMappings = new Dictionary<string, AccountSecurityToken>()
|
||||||
|
};
|
||||||
|
await TestUtils.RunAndVerify<CreateFirewallRuleResponse>(
|
||||||
|
(context) => ResourceProviderService.HandleCreateFirewallRuleRequest(createFirewallParams, context),
|
||||||
|
(response) =>
|
||||||
|
{
|
||||||
|
// Then I expect the response to indicate that we failed due to token expiration
|
||||||
|
Assert.NotNull(response);
|
||||||
|
Assert.Equal(expectedErrorMsg, response.ErrorMessage);
|
||||||
|
Assert.True(response.IsTokenExpiredFailure);
|
||||||
|
Assert.False(response.Result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user