Unit tests for Azure scenarios (#495)

* Test firewall rule handling is able to process through the service layer

* Additional tests for authentication and the resource wrapper code

* Positive test case for CreateFirewallRule

* Fixed copyright and usings
This commit is contained in:
Kevin Cunnane
2017-10-12 17:23:34 -07:00
committed by GitHub
parent 14e3b3a3f6
commit b416951414
14 changed files with 536 additions and 139 deletions

View File

@@ -158,7 +158,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
if (subscriptions == null) if (subscriptions == null)
{ {
throw new FirewallRuleException(SR.FirewallRuleCreationFailed); throw new FirewallRuleException(SR.NoSubscriptionsFound);
} }
ServiceResponse<FirewallRuleResource> response = await AzureUtil.ExecuteGetAzureResourceAsParallel((object)null, ServiceResponse<FirewallRuleResource> response = await AzureUtil.ExecuteGetAzureResourceAsParallel((object)null,

View File

@@ -27,7 +27,15 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
Keys.Culture = value; Keys.Culture = value;
} }
} }
public static string NoSubscriptionsFound
{
get
{
return Keys.GetString(Keys.NoSubscriptionsFound);
}
}
public static string AzureServerNotFound public static string AzureServerNotFound
{ {
@@ -35,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
{ {
@@ -43,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
{ {
@@ -51,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
{ {
@@ -59,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
{ {
@@ -67,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
{ {
@@ -75,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
{ {
@@ -83,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
{ {
@@ -91,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
{ {
@@ -99,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
{ {
@@ -107,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
@@ -115,37 +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 AzureServerNotFound = "AzureServerNotFound"; public const string NoSubscriptionsFound = "NoSubscriptionsFound";
public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage"; public const string AzureServerNotFound = "AzureServerNotFound";
public const string DatabaseDiscoveryFailedErrorMessage = "DatabaseDiscoveryFailedErrorMessage"; public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
public const string FirewallRuleAccessForbidden = "FirewallRuleAccessForbidden"; public const string DatabaseDiscoveryFailedErrorMessage = "DatabaseDiscoveryFailedErrorMessage";
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed"; public const string FirewallRuleAccessForbidden = "FirewallRuleAccessForbidden";
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError"; public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
public const string InvalidIpAddress = "InvalidIpAddress"; public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
public const string InvalidServerTypeErrorMessage = "InvalidServerTypeErrorMessage"; public const string InvalidIpAddress = "InvalidIpAddress";
public const string LoadingExportableFailedGeneralErrorMessage = "LoadingExportableFailedGeneralErrorMessage"; public const string InvalidServerTypeErrorMessage = "InvalidServerTypeErrorMessage";
public const string FirewallRuleUnsupportedConnectionType = "FirewallRuleUnsupportedConnectionType"; public const string LoadingExportableFailedGeneralErrorMessage = "LoadingExportableFailedGeneralErrorMessage";
public const string FirewallRuleUnsupportedConnectionType = "FirewallRuleUnsupportedConnectionType";
private Keys() private Keys()
{ } { }
@@ -166,7 +177,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
{ {
return resourceManager.GetString(key, _culture); return resourceManager.GetString(key, _culture);
} }
} }
} }
} }

View File

@@ -117,44 +117,48 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="NoSubscriptionsFound" xml:space="preserve">
<value>No subscriptions were found for the currently logged in user account.</value>
<comment></comment>
</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</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>

View File

@@ -22,6 +22,7 @@
############################################################################ ############################################################################
# Azure Core DLL # Azure Core DLL
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
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}

View File

@@ -52,6 +52,11 @@
<target state="new">An error occurred while creating a new firewall rule: '{0}'</target> <target state="new">An error occurred while creating a new firewall rule: '{0}'</target>
<note></note> <note></note>
</trans-unit> </trans-unit>
<trans-unit id="NoSubscriptionsFound">
<source>No subscriptions were found for the currently logged in user account.</source>
<target state="new">No subscriptions were found for the currently logged in user account.</target>
<note></note>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureAuthenticationManager", "Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureAuthenticationManager",
1) 1)
] ]
class AzureAuthenticationManager : ExportableBase, IAzureAuthenticationManager public class AzureAuthenticationManager : ExportableBase, IAzureAuthenticationManager
{ {
private Dictionary<string, AzureUserAccount> accountsMap; private Dictionary<string, AzureUserAccount> accountsMap;
private string currentAccountId = null; private string currentAccountId = null;
@@ -88,38 +88,49 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
public AzureUserAccount CreateUserAccount(AccountTokenWrapper accountTokenWrapper) public AzureUserAccount CreateUserAccount(AccountTokenWrapper accountTokenWrapper)
{ {
Account account = accountTokenWrapper.Account; Account account = accountTokenWrapper.Account;
CommonUtil.CheckForNull(accountTokenWrapper.Account, nameof(account)); CommonUtil.CheckForNull(accountTokenWrapper, nameof(accountTokenWrapper));
CommonUtil.CheckForNull(account, nameof(account));
CommonUtil.CheckForNull(account.Key, nameof(account) + ".Key");
CommonUtil.CheckForNull(accountTokenWrapper.SecurityTokenMappings, nameof(account) + ".SecurityTokenMappings"); CommonUtil.CheckForNull(accountTokenWrapper.SecurityTokenMappings, nameof(account) + ".SecurityTokenMappings");
AzureUserAccount userAccount = new AzureUserAccount(); AzureUserAccount userAccount = new AzureUserAccount();
userAccount.UniqueId = account.Key.AccountId; userAccount.UniqueId = account.Key.AccountId;
userAccount.DisplayInfo = ToDisplayInfo(account); userAccount.DisplayInfo = ToDisplayInfo(account);
IList<IAzureTenant> tenants = new List<IAzureTenant>(); userAccount.NeedsReauthentication = account.IsStale;
foreach (Tenant tenant in account.Properties.Tenants) userAccount.AllTenants = ProcessTenants(accountTokenWrapper, account);
{
AccountSecurityToken token;
if (accountTokenWrapper.SecurityTokenMappings.TryGetValue(tenant.Id, out token))
{
AzureTenant azureTenant = new AzureTenant()
{
TenantId = tenant.Id,
AccountDisplayableId = tenant.DisplayName,
Resource = token.Resource,
AccessToken = token.Token,
TokenType = token.TokenType
};
tenants.Add(azureTenant);
}
// else ignore for now as we can't handle a request to get a tenant without an access key
}
userAccount.AllTenants = tenants;
return userAccount; return userAccount;
} }
private static IList<IAzureTenant> ProcessTenants(AccountTokenWrapper accountTokenWrapper, Account account)
{
IList<IAzureTenant> tenants = new List<IAzureTenant>();
if (account.Properties != null && account.Properties.Tenants != null)
{
foreach (Tenant tenant in account.Properties.Tenants)
{
AccountSecurityToken token;
if (accountTokenWrapper.SecurityTokenMappings.TryGetValue(tenant.Id, out token))
{
AzureTenant azureTenant = new AzureTenant()
{
TenantId = tenant.Id,
AccountDisplayableId = tenant.DisplayName,
Resource = token.Resource,
AccessToken = token.Token,
TokenType = token.TokenType
};
tenants.Add(azureTenant);
}
// else ignore for now as we can't handle a request to get a tenant without an access key
}
}
return tenants;
}
private AzureUserAccountDisplayInfo ToDisplayInfo(Account account) private AzureUserAccountDisplayInfo ToDisplayInfo(Account account)
{ {
return new AzureUserAccountDisplayInfo() return new AzureUserAccountDisplayInfo()
{ {
AccountDisplayName = account.DisplayInfo.DisplayName, AccountDisplayName = account.DisplayInfo != null ? account.DisplayInfo.DisplayName : account.Key.AccountId,
ProviderDisplayName = account.Key.ProviderId ProviderDisplayName = account.Key.ProviderId
}; };
} }

View File

@@ -20,7 +20,6 @@ using Microsoft.Rest;
using System.Globalization; using System.Globalization;
using Microsoft.Rest.Azure; using Microsoft.Rest.Azure;
using Microsoft.SqlTools.ResourceProvider.Core; using Microsoft.SqlTools.ResourceProvider.Core;
using System.Collections;
using System.Threading; using System.Threading;
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl

View File

@@ -81,7 +81,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
{ {
this.resourceGroupName = ParseResourceGroupNameFromId(); this.resourceGroupName = ParseResourceGroupNameFromId();
} }
return this.resourceGroupName; return this.resourceGroupName ?? string.Empty;
} }
set set
{ {

View File

@@ -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,7 +83,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
{ {
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError); return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
} }
} }
public static string AzureSubscriptionFailedErrorMessage public static string AzureSubscriptionFailedErrorMessage
{ {
@@ -91,7 +91,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
{ {
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage); return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
} }
} }
public static string UnsupportedAuthType public static string UnsupportedAuthType
{ {
@@ -99,7 +99,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
{ {
return Keys.GetString(Keys.UnsupportedAuthType); return Keys.GetString(Keys.UnsupportedAuthType);
} }
} }
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys public class Keys
@@ -107,34 +107,34 @@ 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 AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
public const string UnsupportedAuthType = "UnsupportedAuthType"; public const string UnsupportedAuthType = "UnsupportedAuthType";
private Keys() private Keys()
{ } { }
@@ -155,7 +155,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
{ {
return resourceManager.GetString(key, _culture); return resourceManager.GetString(key, _culture);
} }
} }
} }
} }

View File

@@ -120,37 +120,37 @@
<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"> <data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
<value>An error occurred while getting Azure subscriptions</value> <value>An error occurred while getting Azure subscriptions</value>
<comment></comment> <comment></comment>
</data> </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> </root>

View File

@@ -0,0 +1,113 @@
//
// 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.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ResourceProvider.Core;
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
{
public class AzureAuthenticationManagerTest
{
private Mock<IAzureResourceManager> resourceManagerMock;
private RegisteredServiceProvider serviceProvider;
public AzureAuthenticationManagerTest()
{
resourceManagerMock = new Mock<IAzureResourceManager>();
serviceProvider = new RegisteredServiceProvider();
serviceProvider.RegisterSingleService<IAzureResourceManager>(resourceManagerMock.Object);
}
[Fact]
public async Task CurrentUserShouldBeNullWhenUserIsNotSignedIn()
{
IAzureAuthenticationManager accountManager = await CreateAccountManager(null, null);
Assert.Null(await accountManager.GetCurrentAccountAsync());
}
[Fact]
public async Task GetSubscriptionShouldReturnEmptyWhenUserIsNotSignedIn()
{
IAzureAuthenticationManager accountManager = await CreateAccountManager(null, null);
IEnumerable<IAzureUserAccountSubscriptionContext> result =
await accountManager.GetSelectedSubscriptionsAsync();
Assert.False(result.Any());
}
[Fact]
public async Task GetSubscriptionShouldThrowWhenUserNeedsAuthentication()
{
var currentUserAccount = CreateAccount();
currentUserAccount.Account.IsStale = true;
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null);
await Assert.ThrowsAsync<UserNeedsAuthenticationException>(() => accountManager.GetSelectedSubscriptionsAsync());
}
[Fact]
public async Task GetSubscriptionShouldThrowIfFailed()
{
var currentUserAccount = CreateAccount();
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null, true);
await Assert.ThrowsAsync<ServiceFailedException>(() => accountManager.GetSelectedSubscriptionsAsync());
}
[Fact]
public async Task GetSubscriptionShouldReturnTheListSuccessfully()
{
List<IAzureUserAccountSubscriptionContext> subscriptions = new List<IAzureUserAccountSubscriptionContext> {
new Mock<IAzureUserAccountSubscriptionContext>().Object
};
var currentUserAccount = CreateAccount();
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, subscriptions, false);
IEnumerable<IAzureUserAccountSubscriptionContext> result =
await accountManager.GetSelectedSubscriptionsAsync();
Assert.True(result.Any());
}
private AccountTokenWrapper CreateAccount(bool needsReauthentication = false)
{
return new AccountTokenWrapper(new Account()
{
Key = new AccountKey()
{
AccountId = "MyAccount",
ProviderId = "MSSQL"
},
IsStale = needsReauthentication
},
new Dictionary<string, AccountSecurityToken>());
}
private async Task<AzureAuthenticationManager> CreateAccountManager(AccountTokenWrapper currentAccount,
IEnumerable<IAzureUserAccountSubscriptionContext> subscriptions, bool shouldFail = false)
{
AzureAuthenticationManager azureAuthenticationManager = new AzureAuthenticationManager();
azureAuthenticationManager.SetServiceProvider(serviceProvider);
if (currentAccount != null)
{
await azureAuthenticationManager.SetCurrentAccountAsync(currentAccount);
}
if (!shouldFail)
{
resourceManagerMock.Setup(x => x.GetSubscriptionContextsAsync(It.IsAny<IAzureUserAccount>())).Returns(Task.FromResult(subscriptions));
}
else
{
resourceManagerMock.Setup(x => x.GetSubscriptionContextsAsync(It.IsAny<IAzureUserAccount>())).Throws(new Exception());
}
return azureAuthenticationManager;
}
}
}

View File

@@ -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 Microsoft.Azure.Management.Sql.Models;
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
{
public class AzureResourceWrapperTest
{
[Fact]
public void ShouldParseResourceGroupFromId()
{
// Given a resource with a known resource group
TrackedResource trackedResource = CreateMockResource(
"/subscriptions/aaaaaaaa-1234-cccc-dddd-a1234v12c23/resourceGroups/myresourcegroup/providers/Microsoft.Sql/servers/my-server",
"my-server",
"Microsoft.Sql");
// When I get the resource group name
AzureResourceWrapper resource = new AzureResourceWrapper(trackedResource);
string rgName = resource.ResourceGroupName;
// then I get it as expected
Assert.Equal("myresourcegroup", rgName);
}
[Fact]
public void ShouldHandleMissingResourceGroup()
{
// Given a resource without resource group in the ID
TrackedResource trackedResource = CreateMockResource(
"/subscriptions/aaaaaaaa-1234-cccc-dddd-a1234v12c23",
"my-server",
"Microsoft.Sql");
// When I get the resource group name
AzureResourceWrapper resource = new AzureResourceWrapper(trackedResource);
string rgName = resource.ResourceGroupName;
// then I get string.Empty
Assert.Equal(string.Empty, rgName);
}
private TrackedResource CreateMockResource(string id = null, string name = null, string type = null)
{
return new TrackedResource("Somewhere", id, name, type);
}
}
}

View File

@@ -45,7 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
} }
[Fact] [Fact]
public async Task GetShouldReturnEmptyGivenNotSubscriptionFound() public async Task GetShouldReturnEmptyGivenNoSubscriptionFound()
{ {
Dictionary<string, List<string>> subscriptionToDatabaseMap = new Dictionary<string, List<string>>(); Dictionary<string, List<string>> subscriptionToDatabaseMap = new Dictionary<string, List<string>>();

View File

@@ -3,17 +3,30 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
using Microsoft.SqlTools.Hosting.Protocol; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.Extensibility; using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ResourceProvider.Core; using Microsoft.SqlTools.Hosting.Protocol;
using Moq;
using Microsoft.SqlTools.ResourceProvider; using Microsoft.SqlTools.ResourceProvider;
using Microsoft.SqlTools.ResourceProvider.Core;
using Microsoft.SqlTools.ResourceProvider.Core.Authentication; using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
using Microsoft.SqlTools.ResourceProvider.DefaultImpl;
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
{ {
public class ResourceProviderServiceTests public class ResourceProviderServiceTests
{ {
private const int SqlAzureFirewallBlockedErrorNumber = 40615;
private const int SqlAzureLoginFailedErrorNumber = 18456;
private string errorMessageWithIp = "error Message with 1.2.3.4 as IP address";
public ResourceProviderServiceTests() public ResourceProviderServiceTests()
{ {
HostMock = new Mock<IProtocolEndpoint>(); HostMock = new Mock<IProtocolEndpoint>();
@@ -34,7 +47,194 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
protected ResourceProviderService ResourceProviderService { get; private set; } protected ResourceProviderService ResourceProviderService { get; private set; }
[Fact]
public async Task TestHandleFirewallRuleIgnoresNonMssqlProvider()
{
// Given a non-MSSQL provider
var handleFirewallParams = new HandleFirewallRuleParams()
{
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
ErrorMessage = errorMessageWithIp,
ConnectionTypeId = "Other"
};
// 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) =>
{
// Then I expect the response to be false and no IP information to be sent
Assert.NotNull(response);
Assert.False(response.Result);
Assert.Null(response.IpAddress);
Assert.Equal(Microsoft.SqlTools.ResourceProvider.Core.SR.FirewallRuleUnsupportedConnectionType, response.ErrorMessage);
});
}
[Fact]
public async Task TestHandleFirewallRuleSupportsMssqlProvider()
{
// Given a firewall error for the MSSQL provider
var handleFirewallParams = new HandleFirewallRuleParams()
{
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
ErrorMessage = errorMessageWithIp,
ConnectionTypeId = "MSSQL"
};
// 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) =>
{
// Then I expect the response to be true and the IP address to be extracted
Assert.NotNull(response);
Assert.True(response.Result);
Assert.Equal("1.2.3.4", response.IpAddress);
Assert.Null(response.ErrorMessage);
});
}
[Fact]
public async Task TestHandleFirewallRuleIgnoresNonFirewallErrors()
{
// Given a login error for the MSSQL provider
var handleFirewallParams = new HandleFirewallRuleParams()
{
ErrorCode = SqlAzureLoginFailedErrorNumber,
ErrorMessage = errorMessageWithIp,
ConnectionTypeId = "MSSQL"
};
// 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) =>
{
// Then I expect the response to be false and no IP address to be defined
Assert.NotNull(response);
Assert.False(response.Result);
Assert.Equal(string.Empty, response.IpAddress);
Assert.Null(response.ErrorMessage);
});
}
[Fact]
public async Task TestHandleFirewallRuleDoesntBreakWithoutIp()
{
// Given a firewall error with no IP address in the error message
var handleFirewallParams = new HandleFirewallRuleParams()
{
ErrorCode = SqlAzureFirewallBlockedErrorNumber,
ErrorMessage = "No IP here",
ConnectionTypeId = "MSSQL"
};
// 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) =>
{
// Then I expect the response to be fakse as we require the known IP address to function
Assert.NotNull(response);
Assert.False(response.Result);
Assert.Equal(string.Empty, response.IpAddress);
Assert.Null(response.ErrorMessage);
});
}
[Fact]
public async Task TestCreateFirewallRuleBasicRequest()
{
// Given a firewall request for a valid subscription
string serverName = "myserver.database.windows.net";
var sub1Mock = new Mock<IAzureUserAccountSubscriptionContext>();
var sub2Mock = new Mock<IAzureUserAccountSubscriptionContext>();
var server = new SqlAzureResource(new Azure.Management.Sql.Models.Server("Somewhere",
"1234", "myserver", "SQLServer",
null, null, null, null, null, null, null,
fullyQualifiedDomainName: serverName));
var subsToServers = new List<Tuple<IAzureUserAccountSubscriptionContext, IEnumerable<IAzureSqlServerResource>>>()
{
Tuple.Create(sub1Mock.Object, Enumerable.Empty<IAzureSqlServerResource>()),
Tuple.Create(sub2Mock.Object, new IAzureSqlServerResource[] { server }.AsEnumerable())
};
var azureRmResponse = new FirewallRuleResponse()
{
Created = true,
StartIpAddress = null,
EndIpAddress = null
};
SetupDependencies(subsToServers, azureRmResponse);
// 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 be fakse as we require the known IP address to function
Assert.NotNull(response);
Assert.Null(response.ErrorMessage);
Assert.True(response.Result);
});
}
private void SetupDependencies(
IList<Tuple<IAzureUserAccountSubscriptionContext, IEnumerable<IAzureSqlServerResource>>> subsToServers,
FirewallRuleResponse response)
{
SetupCreateSession();
SetupReturnsSubscriptions(subsToServers.Select(s => s.Item1));
foreach(var s in subsToServers)
{
SetupAzureServers(s.Item1, s.Item2);
}
SetupFirewallResponse(response);
}
private void SetupReturnsSubscriptions(IEnumerable<IAzureUserAccountSubscriptionContext> subs)
{
AuthenticationManagerMock.Setup(a => a.GetSubscriptionsAsync()).Returns(() => Task.FromResult(subs));
}
private void SetupCreateSession()
{
ResourceManagerMock.Setup(r => r.CreateSessionAsync(It.IsAny<IAzureUserAccountSubscriptionContext>()))
.Returns((IAzureUserAccountSubscriptionContext sub) =>
{
var sessionMock = new Mock<IAzureResourceManagementSession>();
sessionMock.SetupProperty(s => s.SubscriptionContext, sub);
return Task.FromResult(sessionMock.Object);
});
}
private void SetupAzureServers(IAzureSubscriptionContext sub, IEnumerable<IAzureSqlServerResource> servers)
{
Func<IAzureResourceManagementSession, bool> isExpectedSub = (session) =>
{
return session.SubscriptionContext == sub;
};
ResourceManagerMock.Setup(r => r.GetSqlServerAzureResourcesAsync(
It.Is<IAzureResourceManagementSession>((session) => isExpectedSub(session))
)).Returns(() => Task.FromResult(servers));
}
private void SetupFirewallResponse(FirewallRuleResponse response)
{
ResourceManagerMock.Setup(r => r.CreateFirewallRuleAsync(
It.IsAny<IAzureResourceManagementSession>(),
It.IsAny<IAzureSqlServerResource>(),
It.IsAny<FirewallRuleRequest>())
).Returns(() => Task.FromResult(response));
}
private Account CreateAccount(bool needsReauthentication = false)
{
return new Account()
{
Key = new AccountKey()
{
AccountId = "MyAccount",
ProviderId = "MSSQL"
},
IsStale = needsReauthentication
};
}
} }
} }