mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Create Firewall Rule support with a simple Resource Provider implementation
Implementation of the resource provider APIs in order to support Create Firewall Rule. Provides definition for a ResourceProvider and Authentication service. The ResourceProvider supports firewall rules for now, and since authentication is routed through that method it will call into the auth service to set up the current account to be used. Additional notes: - Fixed deserialization by adding an Accept header. This shouldn't be necessary, but for some reason the firewall rule defaults to XML without this - Use generic server list and parse the ID to get the resource group, avoiding a large number of extra calls for each RG - Errors now include error message from the API
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"MainProjects": [
|
||||
"Microsoft.SqlTools.ServiceLayer",
|
||||
"Microsoft.SqlTools.Credentials",
|
||||
"Microsoft.Sqltools.Serialization"
|
||||
"Microsoft.SqlTools.Serialization",
|
||||
"Microsoft.SqlTools.ResourceProvider"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -35,7 +35,4 @@
|
||||
<EmbeddedResource Include="Localization\sr.resx" />
|
||||
<None Include="Localization\sr.strings" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Utility\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -38,9 +38,19 @@ namespace Microsoft.SqlTools.Extensibility
|
||||
"microsoftsqltoolsservicelayer.dll"
|
||||
};
|
||||
|
||||
return CreateFromAssembliesInDirectory(inclusionList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a service provider by loading a set of named assemblies, expected to be in the current working directory
|
||||
/// </summary>
|
||||
/// <param name="inclusionList">full DLL names, as a string enumerable</param>
|
||||
/// <returns><see cref="ExtensionServiceProvider"/> instance</returns>
|
||||
public static ExtensionServiceProvider CreateFromAssembliesInDirectory(IEnumerable<string> inclusionList)
|
||||
{
|
||||
string assemblyPath = typeof(ExtensionStore).GetTypeInfo().Assembly.Location;
|
||||
string directory = Path.GetDirectoryName(assemblyPath);
|
||||
|
||||
|
||||
AssemblyLoadContext context = new AssemblyLoader(directory);
|
||||
var assemblyPaths = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly);
|
||||
|
||||
@@ -49,20 +59,20 @@ namespace Microsoft.SqlTools.Extensibility
|
||||
{
|
||||
// skip DLL files not in inclusion list
|
||||
bool isInList = false;
|
||||
foreach (var item in inclusionList)
|
||||
foreach (var item in inclusionList)
|
||||
{
|
||||
if (path.EndsWith(item, StringComparison.OrdinalIgnoreCase))
|
||||
if (path.EndsWith(item, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isInList = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInList)
|
||||
if (!isInList)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
assemblies.Add(
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
namespace Microsoft.SqlTools.Utility
|
||||
{
|
||||
public class GeneralRequestDetails
|
||||
{
|
||||
@@ -17,7 +16,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
Options = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
internal T GetOptionValue<T>(string name)
|
||||
public T GetOptionValue<T>(string name)
|
||||
{
|
||||
T result = default(T);
|
||||
if (Options != null && Options.ContainsKey(name))
|
||||
@@ -37,7 +36,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static T GetValueAs<T>(object value)
|
||||
public static T GetValueAs<T>(object value)
|
||||
{
|
||||
T result = default(T);
|
||||
|
||||
@@ -54,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
else if (typeof(T).IsEnum)
|
||||
{
|
||||
object enumValue;
|
||||
if (Enum.TryParse(typeof(T), value.ToString(), out enumValue))
|
||||
if (TryParseEnum<T>(typeof(T), value.ToString(), out enumValue))
|
||||
{
|
||||
value = (T)enumValue;
|
||||
}
|
||||
@@ -63,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
else if (value != null && (typeof(T).IsEnum))
|
||||
{
|
||||
object enumValue;
|
||||
if (Enum.TryParse(typeof(T), value.ToString(), out enumValue))
|
||||
if (TryParseEnum<T>(typeof(T), value.ToString(), out enumValue))
|
||||
{
|
||||
value = enumValue;
|
||||
}
|
||||
@@ -73,6 +72,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method exists because in NetStandard the Enum.TryParse methods that accept in a type
|
||||
/// are not present, and the generic TryParse method requires the type T to be non-nullable which
|
||||
/// is hard to check. This is different to the NetCore definition for some reason.
|
||||
/// It seems easier to implement our own than work around this.
|
||||
/// </summary>
|
||||
private static bool TryParseEnum<T>(Type t, string value, out object enumValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
enumValue = Enum.Parse(t, value);
|
||||
return true;
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
enumValue = default(T);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SetOptionValue<T>(string name, T value)
|
||||
{
|
||||
Options = Options ?? new Dictionary<string, object>();
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
{
|
||||
internal class AccountOptionsHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the IsMsAccount option
|
||||
/// </summary>
|
||||
internal const string IsMsAccount = "IsMsAccount";
|
||||
/// <summary>
|
||||
/// The name of the Tenants option
|
||||
/// </summary>
|
||||
internal const string Tenants = "Tentants";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// 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.ResourceProvider.Core.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains an account and related token information usable for login purposes
|
||||
/// </summary>
|
||||
public class AccountTokenWrapper
|
||||
{
|
||||
public AccountTokenWrapper(Account account, Dictionary<string, AccountSecurityToken> securityTokenMappings)
|
||||
{
|
||||
Account = account;
|
||||
SecurityTokenMappings = securityTokenMappings;
|
||||
}
|
||||
/// <summary>
|
||||
/// Account defining a connected service login
|
||||
/// </summary>
|
||||
public Account Account { get; private set; }
|
||||
/// <summary>
|
||||
/// Token mappings from tentant ID to their access token
|
||||
/// </summary>
|
||||
public Dictionary<string, AccountSecurityToken> SecurityTokenMappings { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// User account authentication information to be used by <see cref="IAccountManager" />
|
||||
/// </summary>
|
||||
public interface IAzureTenant
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique Id for the tenant
|
||||
/// </summary>
|
||||
string TenantId
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display ID
|
||||
/// </summary>
|
||||
string AccountDisplayableId
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,14 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains information about an Azure user account
|
||||
/// </summary>
|
||||
public interface IAzureUserAccount : IEquatable<IAzureUserAccount>, IUserAccount
|
||||
public interface IAzureUserAccount : IEquatable<IAzureUserAccount>, IUserAccount
|
||||
{
|
||||
/// <summary>
|
||||
/// User Account Display Info
|
||||
@@ -20,11 +21,19 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.Authentication
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tenant Id
|
||||
/// Primary Tenant Id
|
||||
/// </summary>
|
||||
string TenantId
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All tenant IDs
|
||||
/// </summary>
|
||||
IList<IAzureTenant> AllTenants
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// 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.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.Hosting;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Extensibility;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
{
|
||||
|
||||
[Export(typeof(IHostedService))]
|
||||
public class AuthenticationService : HostedService<AuthenticationService>, IComposableService
|
||||
{
|
||||
/// <summary>
|
||||
/// The default constructor is required for MEF-based composable services
|
||||
/// </summary>
|
||||
public AuthenticationService()
|
||||
{
|
||||
}
|
||||
|
||||
public override void InitializeService(IProtocolEndpoint serviceHost)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "AuthenticationService initialized");
|
||||
}
|
||||
|
||||
public async Task<IUserAccount> SetCurrentAccountAsync(Account account, Dictionary<string, AccountSecurityToken> securityTokenMappings)
|
||||
{
|
||||
var authManager = ServiceProvider.GetService<IAzureAuthenticationManager>();
|
||||
// Ideally in the future, would have a factory to create the user account and tenant info without knowing
|
||||
// which implementation is which. For expediency, will directly define these in this instance.
|
||||
return await authManager.SetCurrentAccountAsync(new AccountTokenWrapper(account, securityTokenMappings));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// An object, usable in <see cref="CreateFirewallRuleRequest"/>s and other messages
|
||||
/// </summary>
|
||||
public class Account
|
||||
{
|
||||
/// <summary>
|
||||
/// The key that identifies the account
|
||||
/// </summary>
|
||||
public AccountKey Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Display information for the account
|
||||
/// </summary>
|
||||
public AccountDisplayInfo DisplayInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Customizable properties, which will include the access token or similar authentication support
|
||||
/// </summary>
|
||||
public AccountProperties Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the account needs refreshing
|
||||
/// </summary>
|
||||
public bool IsStale { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Azure-specific properties. Note that ideally with would reuse GeneralRequestDetails but
|
||||
/// this isn't feasible right now as that is specific to having an Options property to hang it off
|
||||
/// </summary>
|
||||
public class AccountProperties
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Is this a Microsoft account, such as live.com, or not?
|
||||
/// </summary>
|
||||
internal bool IsMsAccount
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tenants for each object
|
||||
/// </summary>
|
||||
public IEnumerable<Tenant> Tenants
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a key that identifies an account.
|
||||
/// </summary>
|
||||
public class AccountKey
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifier of the provider
|
||||
/// </summary>
|
||||
public string ProviderId { get; set; }
|
||||
|
||||
// Note: ignoring ProviderArgs as it's not relevant
|
||||
|
||||
/// <summary>
|
||||
/// Identifier for the account, unique to the provider
|
||||
/// </summary>
|
||||
public string AccountId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents display information for an account.
|
||||
/// </summary>
|
||||
public class AccountDisplayInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// A display name that offers context for the account, such as "Contoso".
|
||||
/// </summary>
|
||||
|
||||
public string ContextualDisplayName { get; set; }
|
||||
|
||||
// Note: ignoring ContextualLogo as it's not needed
|
||||
|
||||
/// <summary>
|
||||
/// A display name that identifies the account, such as "user@contoso.com".
|
||||
/// </summary
|
||||
public string DisplayName { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a tenant (an Azure Active Directory instance) to which a user has access
|
||||
/// </summary>
|
||||
public class Tenant
|
||||
{
|
||||
/// <summary>
|
||||
/// Globally unique identifier of the tenant
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
/// <summary>
|
||||
/// Display name of the tenant
|
||||
/// </summary>
|
||||
public string DisplayName { get; set; }
|
||||
/// <summary>
|
||||
/// Identifier of the user in the tenant
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains key information about a Token used to log in to a resource provider
|
||||
/// </summary>
|
||||
public class AccountSecurityToken
|
||||
{
|
||||
/// <summary>
|
||||
/// Expiration time for the token
|
||||
/// </summary>
|
||||
public string ExpiresOn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// URI defining the root for resource lookup
|
||||
/// </summary>
|
||||
public string Resource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The actual token
|
||||
/// </summary>
|
||||
public string Token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of token being sent - for example "Bearer" for most resource queries
|
||||
/// </summary>
|
||||
public string TokenType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// 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>
|
||||
/// A request to open up a firewall rule
|
||||
/// </summary>
|
||||
public class CreateFirewallRuleRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<CreateFirewallRuleParams, CreateFirewallRuleResponse> Type =
|
||||
RequestType<CreateFirewallRuleParams, CreateFirewallRuleResponse>.Create("resource/createFirewallRule");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A FirewallRule object, usable in <see cref="CreateFirewallRuleRequest"/>s and other messages
|
||||
/// </summary>
|
||||
public class CreateFirewallRuleParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Account information to use in connecting to Azure
|
||||
/// </summary>
|
||||
public Account Account { get; set; }
|
||||
/// <summary>
|
||||
/// Per-tenant token mappings. Ideally would be set independently of this call, but for
|
||||
/// now this allows us to get the tokens necessary to find a server and open a firewall rule
|
||||
/// </summary>
|
||||
public Dictionary<string,AccountSecurityToken> SecurityTokenMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fully qualified name of the server to create a new firewall rule on
|
||||
/// </summary>
|
||||
public string ServerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Start of the IP address range
|
||||
/// </summary>
|
||||
public string StartIpAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// End of the IP address range
|
||||
/// </summary>
|
||||
public string EndIpAddress { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class CreateFirewallRuleResponse
|
||||
{
|
||||
public bool Result { get; set; }
|
||||
public string ErrorMessage { get; set; }
|
||||
}
|
||||
|
||||
public class CanHandleFirewallRuleRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<HandleFirewallRuleParams, HandleFirewallRuleResponse> Type =
|
||||
RequestType<HandleFirewallRuleParams, HandleFirewallRuleResponse>.Create("resource/handleFirewallRule");
|
||||
}
|
||||
|
||||
public class HandleFirewallRuleParams
|
||||
{
|
||||
/// <summary>
|
||||
/// The error code used to defined the error type
|
||||
/// </summary>
|
||||
public int ErrorCode { get; set; }
|
||||
/// <summary>
|
||||
/// The error message from which to parse the IP address
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; }
|
||||
/// <summary>
|
||||
/// The connection type, for example MSSQL
|
||||
/// </summary>
|
||||
public string ConnectionTypeId { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Response to the check for Firewall rule support given an error message
|
||||
/// </summary>
|
||||
public class HandleFirewallRuleResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Can this be handled?
|
||||
/// </summary>
|
||||
public bool Result { get; set; }
|
||||
/// <summary>
|
||||
/// If not, why?
|
||||
/// </summary>
|
||||
public string ErrorMessage { get; set; }
|
||||
/// <summary>
|
||||
/// If it can be handled, is there a default IP address to send back so users
|
||||
/// can tell what their blocked IP is?
|
||||
/// </summary>
|
||||
public string IpAddress { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.FirewallRule;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Extensibility;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
@@ -49,5 +49,13 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
);
|
||||
|
||||
Task<IAzureResourceManagementSession> CreateSessionAsync(IAzureUserAccountSubscriptionContext subscriptionContext);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// <param name="userAccount">Account whose subscriptions should be queried</param>
|
||||
/// </summary>
|
||||
Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionContextsAsync(IAzureUserAccount userAccount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Data.SqlClient;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
internal interface IFirewallErrorParser
|
||||
{
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
/// <summary>
|
||||
/// The response that's created by firewall rule parser
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Net;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception used by firewall service to indicate when firewall rule operation fails
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
/// <summary>
|
||||
/// Includes all the information needed to create a firewall rule
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
/// <summary>
|
||||
/// Includes azure resource and subscription needed to create firewall rule
|
||||
@@ -2,7 +2,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
/// <summary>
|
||||
/// The response that's created when the firewall rule creation request is complete
|
||||
@@ -9,7 +9,7 @@ using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core.Firewall
|
||||
{
|
||||
|
||||
public interface IFirewallRuleService
|
||||
@@ -89,7 +89,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FirewallRuleException(SR.FirewallRuleCreationFailed, ex);
|
||||
throw new FirewallRuleException(string.Format(CultureInfo.CurrentCulture, SR.FirewallRuleCreationFailedWithError, ex.Message), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Microsoft.SqlTools.ResourceProvider.Core.FirewallRule
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FirewallRuleException(SR.FirewallRuleCreationFailed, ex);
|
||||
throw new FirewallRuleException(string.Format(CultureInfo.CurrentCulture, SR.FirewallRuleCreationFailedWithError, ex.Message), ex);
|
||||
}
|
||||
|
||||
return new FirewallRuleResponse()
|
||||
240
src/Microsoft.SqlTools.ResourceProvider.Core/Localization/sr.cs
Normal file → Executable file
240
src/Microsoft.SqlTools.ResourceProvider.Core/Localization/sr.cs
Normal file → Executable file
@@ -1,104 +1,120 @@
|
||||
// WARNING:
|
||||
// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0
|
||||
// from information in sr.strings
|
||||
// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN
|
||||
//
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Globalization;
|
||||
// WARNING:
|
||||
// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0
|
||||
// from information in sr.strings
|
||||
// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN
|
||||
//
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Globalization;
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SR
|
||||
{
|
||||
protected SR()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.Culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
Keys.Culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SR
|
||||
{
|
||||
protected SR()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.Culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
Keys.Culture = value;
|
||||
}
|
||||
|
||||
public static string AzureServerNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.AzureServerNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string AzureServerNotFound
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.AzureServerNotFound);
|
||||
}
|
||||
|
||||
public static string AzureSubscriptionFailedErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string AzureSubscriptionFailedErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
||||
}
|
||||
|
||||
public static string DatabaseDiscoveryFailedErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.DatabaseDiscoveryFailedErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string DatabaseDiscoveryFailedErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.DatabaseDiscoveryFailedErrorMessage);
|
||||
}
|
||||
|
||||
public static string FirewallRuleAccessForbidden
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleAccessForbidden);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FirewallRuleAccessForbidden
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleAccessForbidden);
|
||||
}
|
||||
|
||||
public static string FirewallRuleCreationFailed
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FirewallRuleCreationFailed
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||
}
|
||||
|
||||
public static string FirewallRuleCreationFailedWithError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string InvalidIpAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.InvalidIpAddress);
|
||||
}
|
||||
|
||||
public static string InvalidIpAddress
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.InvalidIpAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public static string InvalidServerTypeErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.InvalidServerTypeErrorMessage);
|
||||
}
|
||||
|
||||
public static string InvalidServerTypeErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.InvalidServerTypeErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string LoadingExportableFailedGeneralErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.LoadingExportableFailedGeneralErrorMessage);
|
||||
}
|
||||
|
||||
public static string LoadingExportableFailedGeneralErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.LoadingExportableFailedGeneralErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
{
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.Core.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
public static string FirewallRuleUnsupportedConnectionType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleUnsupportedConnectionType);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
{
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.Core.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
|
||||
public const string AzureServerNotFound = "AzureServerNotFound";
|
||||
@@ -116,6 +132,9 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
||||
|
||||
|
||||
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
||||
|
||||
|
||||
public const string InvalidIpAddress = "InvalidIpAddress";
|
||||
|
||||
|
||||
@@ -125,25 +144,28 @@ namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
public const string LoadingExportableFailedGeneralErrorMessage = "LoadingExportableFailedGeneralErrorMessage";
|
||||
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
public const string FirewallRuleUnsupportedConnectionType = "FirewallRuleUnsupportedConnectionType";
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetString(string key)
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetString(string key)
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
294
src/Microsoft.SqlTools.ResourceProvider.Core/Localization/sr.resx
Normal file → Executable file
294
src/Microsoft.SqlTools.ResourceProvider.Core/Localization/sr.resx
Normal file → Executable file
@@ -1,152 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype=">text/microsoft-resx</resheader>
|
||||
<resheader name="version=">2.0</resheader>
|
||||
<resheader name="reader=">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer=">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1="><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing=">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64=">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64=">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata=">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true=">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded=">
|
||||
<xsd:element name="metadata=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly=">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<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>
|
||||
<comment></comment>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype=">text/microsoft-resx</resheader>
|
||||
<resheader name="version=">2.0</resheader>
|
||||
<resheader name="reader=">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer=">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1="><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing=">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64=">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64=">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata=">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true=">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded=">
|
||||
<xsd:element name="metadata=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly=">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<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>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure subscriptions</value>
|
||||
<comment></comment>
|
||||
<data name="AzureSubscriptionFailedErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure subscriptions</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="DatabaseDiscoveryFailedErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting databases from servers of type {0} from {1}</value>
|
||||
<comment></comment>
|
||||
<data name="DatabaseDiscoveryFailedErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting databases from servers of type {0} from {1}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<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>
|
||||
<comment></comment>
|
||||
<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>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule.</value>
|
||||
<comment></comment>
|
||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="InvalidIpAddress" xml:space="preserve">
|
||||
<value>Invalid IP address</value>
|
||||
<comment></comment>
|
||||
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="InvalidServerTypeErrorMessage" xml:space="preserve">
|
||||
<value>Server Type is invalid.</value>
|
||||
<comment></comment>
|
||||
<data name="InvalidIpAddress" xml:space="preserve">
|
||||
<value>Invalid IP address</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="LoadingExportableFailedGeneralErrorMessage" xml:space="preserve">
|
||||
<value>A required dll cannot be loaded. Please repair your application.</value>
|
||||
<comment></comment>
|
||||
<data name="InvalidServerTypeErrorMessage" xml:space="preserve">
|
||||
<value>Server Type is invalid.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="LoadingExportableFailedGeneralErrorMessage" xml:space="preserve">
|
||||
<value>A required dll cannot be loaded. Please repair your application.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FirewallRuleUnsupportedConnectionType" xml:space="preserve">
|
||||
<value>Cannot open a firewall rule for the specified connection type</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -27,6 +27,8 @@ AzureSubscriptionFailedErrorMessage = An error occurred while getting Azure subs
|
||||
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.
|
||||
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
||||
FirewallRuleCreationFailedWithError = An error occurred while creating a new firewall rule: '{0}'
|
||||
InvalidIpAddress = Invalid IP address
|
||||
InvalidServerTypeErrorMessage = Server Type is invalid.
|
||||
LoadingExportableFailedGeneralErrorMessage = A required dll cannot be loaded. Please repair your application.
|
||||
FirewallRuleUnsupportedConnectionType = Cannot open a firewall rule for the specified connection type
|
||||
@@ -42,6 +42,16 @@
|
||||
<target state="new">An error occurred while creating a new firewall rule.</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FirewallRuleUnsupportedConnectionType">
|
||||
<source>Cannot open a firewall rule for the specified connection type</source>
|
||||
<target state="new">Cannot open a firewall rule for the specified connection type</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FirewallRuleCreationFailedWithError">
|
||||
<source>An error occurred while creating a new firewall rule: '{0}'</source>
|
||||
<target state="new">An error occurred while creating a new firewall rule: '{0}'</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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.Composition;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.Hosting;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.Core
|
||||
{
|
||||
|
||||
[Export(typeof(IHostedService))]
|
||||
public class ResourceProviderService : HostedService<ResourceProviderService>, IComposableService
|
||||
{
|
||||
private const string MssqlProviderId = "MSSQL";
|
||||
|
||||
private FirewallRuleService firewallRuleService;
|
||||
/// <summary>
|
||||
/// The default constructor is required for MEF-based composable services
|
||||
/// </summary>
|
||||
public ResourceProviderService()
|
||||
{
|
||||
}
|
||||
|
||||
public override void InitializeService(IProtocolEndpoint serviceHost)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "ResourceProvider initialized");
|
||||
serviceHost.SetRequestHandler(CreateFirewallRuleRequest.Type, HandleCreateFirewallRuleRequest);
|
||||
serviceHost.SetRequestHandler(CanHandleFirewallRuleRequest.Type, ProcessHandleFirewallRuleRequest);
|
||||
|
||||
firewallRuleService = new FirewallRuleService()
|
||||
{
|
||||
AuthenticationManager = ServiceProvider.GetService<IAzureAuthenticationManager>(),
|
||||
ResourceManager = ServiceProvider.GetService<IAzureResourceManager>()
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a firewall rule creation request. It does this by matching the server name to an Azure Server resource,
|
||||
/// then issuing the command to create a new firewall rule for the specified IP address against that instance
|
||||
/// </summary>
|
||||
/// <param name="firewallRule"></param>
|
||||
/// <param name="requestContext"></param>
|
||||
/// <returns></returns>
|
||||
public async Task HandleCreateFirewallRuleRequest(CreateFirewallRuleParams firewallRule, RequestContext<CreateFirewallRuleResponse> requestContext)
|
||||
{
|
||||
Func<Task<CreateFirewallRuleResponse>> requestHandler = () =>
|
||||
{
|
||||
return DoHandleCreateFirewallRuleRequest(firewallRule);
|
||||
};
|
||||
await HandleRequest(requestHandler, requestContext, "HandleCreateFirewallRuleRequest");
|
||||
}
|
||||
|
||||
private async Task<CreateFirewallRuleResponse> DoHandleCreateFirewallRuleRequest(CreateFirewallRuleParams firewallRule)
|
||||
{
|
||||
var result = new CreateFirewallRuleResponse();
|
||||
// Note: currently not catching the exception. Expect the caller to this message to handle error cases by
|
||||
// showing the error string and responding with a clean failure message to the user
|
||||
try
|
||||
{
|
||||
AuthenticationService authService = ServiceProvider.GetService<AuthenticationService>();
|
||||
IUserAccount account = await authService.SetCurrentAccountAsync(firewallRule.Account, firewallRule.SecurityTokenMappings);
|
||||
FirewallRuleResponse response = await firewallRuleService.CreateFirewallRuleAsync(firewallRule.ServerName, firewallRule.StartIpAddress, firewallRule.EndIpAddress);
|
||||
result.Result = true;
|
||||
}
|
||||
catch(FirewallRuleException ex)
|
||||
{
|
||||
result.Result = false;
|
||||
result.ErrorMessage = ex.Message;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task ProcessHandleFirewallRuleRequest(HandleFirewallRuleParams canHandleRuleParams, RequestContext<HandleFirewallRuleResponse> requestContext)
|
||||
{
|
||||
Func<Task<HandleFirewallRuleResponse>> requestHandler = () =>
|
||||
{
|
||||
HandleFirewallRuleResponse response = new HandleFirewallRuleResponse();
|
||||
if (!MssqlProviderId.Equals(canHandleRuleParams.ConnectionTypeId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
response.Result = false;
|
||||
response.ErrorMessage = SR.FirewallRuleUnsupportedConnectionType;
|
||||
}
|
||||
else
|
||||
{
|
||||
FirewallErrorParser parser = new FirewallErrorParser();
|
||||
FirewallParserResponse parserResponse = parser.ParseErrorMessage(canHandleRuleParams.ErrorMessage, canHandleRuleParams.ErrorCode);
|
||||
response.Result = parserResponse.FirewallRuleErrorDetected;
|
||||
response.IpAddress = parserResponse.BlockedIpAddress != null ? parserResponse.BlockedIpAddress.ToString() : string.Empty;
|
||||
}
|
||||
return Task.FromResult(response);
|
||||
};
|
||||
await HandleRequest(requestHandler, requestContext, "HandleCreateFirewallRuleRequest");
|
||||
}
|
||||
|
||||
private async Task HandleRequest<T>(Func<Task<T>> handler, RequestContext<T> requestContext, string requestType)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, requestType);
|
||||
|
||||
try
|
||||
{
|
||||
T result = await handler();
|
||||
await requestContext.SendResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await requestContext.SendError(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,316 @@
|
||||
//
|
||||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Contracts;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Extensibility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Implementation for <see cref="IAzureAuthenticationManager" />.
|
||||
/// Provides functionality to authenticate to Azure and discover associated accounts and subscriptions
|
||||
/// </summary>
|
||||
[Exportable(
|
||||
ServerTypes.SqlServer,
|
||||
Categories.Azure,
|
||||
typeof(IAzureAuthenticationManager),
|
||||
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureAuthenticationManager",
|
||||
1)
|
||||
]
|
||||
class AzureAuthenticationManager : ExportableBase, IAzureAuthenticationManager
|
||||
{
|
||||
private Dictionary<string, AzureUserAccount> accountsMap;
|
||||
private string currentAccountId = null;
|
||||
private IEnumerable<IAzureUserAccountSubscriptionContext> _selectedSubscriptions = null;
|
||||
private readonly object _selectedSubscriptionsLockObject = new object();
|
||||
private readonly ConcurrentCache<IEnumerable<IAzureUserAccountSubscriptionContext>> _subscriptionCache =
|
||||
new ConcurrentCache<IEnumerable<IAzureUserAccountSubscriptionContext>>();
|
||||
|
||||
|
||||
public AzureAuthenticationManager()
|
||||
{
|
||||
Metadata = new ExportableMetadata(
|
||||
ServerTypes.SqlServer,
|
||||
Categories.Azure,
|
||||
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureAuthenticationManager",
|
||||
1);
|
||||
accountsMap = new Dictionary<string, AzureUserAccount>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<IAzureUserAccount> UserAccounts
|
||||
{
|
||||
get { return accountsMap.Values; }
|
||||
}
|
||||
|
||||
public bool HasLoginDialog
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set current logged in user
|
||||
/// </summary>
|
||||
public async Task<IUserAccount> SetCurrentAccountAsync(object account)
|
||||
{
|
||||
CommonUtil.CheckForNull(account, nameof(account));
|
||||
AccountTokenWrapper accountTokenWrapper = account as AccountTokenWrapper;
|
||||
if (accountTokenWrapper != null)
|
||||
{
|
||||
AzureUserAccount userAccount = CreateUserAccount(accountTokenWrapper);
|
||||
accountsMap[userAccount.UniqueId] = userAccount;
|
||||
currentAccountId = userAccount.UniqueId;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ServiceFailedException(string.Format(CultureInfo.CurrentCulture, SR.UnsupportedAuthType, account.GetType().Name));
|
||||
}
|
||||
OnCurrentAccountChanged();
|
||||
return await GetCurrentAccountAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public for testing purposes. Creates an Azure account with the correct set of mappings for tenants etc.
|
||||
/// </summary>
|
||||
/// <param name="accountTokenWrapper"></param>
|
||||
/// <returns></returns>
|
||||
public AzureUserAccount CreateUserAccount(AccountTokenWrapper accountTokenWrapper)
|
||||
{
|
||||
Account account = accountTokenWrapper.Account;
|
||||
CommonUtil.CheckForNull(accountTokenWrapper.Account, nameof(account));
|
||||
CommonUtil.CheckForNull(accountTokenWrapper.SecurityTokenMappings, nameof(account) + ".SecurityTokenMappings");
|
||||
AzureUserAccount userAccount = new AzureUserAccount();
|
||||
userAccount.UniqueId = account.Key.AccountId;
|
||||
userAccount.DisplayInfo = ToDisplayInfo(account);
|
||||
IList<IAzureTenant> tenants = new List<IAzureTenant>();
|
||||
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
|
||||
}
|
||||
userAccount.AllTenants = tenants;
|
||||
return userAccount;
|
||||
}
|
||||
|
||||
private AzureUserAccountDisplayInfo ToDisplayInfo(Account account)
|
||||
{
|
||||
return new AzureUserAccountDisplayInfo()
|
||||
{
|
||||
AccountDisplayName = account.DisplayInfo.DisplayName,
|
||||
ProviderDisplayName = account.Key.ProviderId
|
||||
};
|
||||
}
|
||||
|
||||
private void OnCurrentAccountChanged()
|
||||
{
|
||||
lock (_selectedSubscriptionsLockObject)
|
||||
{
|
||||
_selectedSubscriptions = null;
|
||||
}
|
||||
if (CurrentAccountChanged != null)
|
||||
{
|
||||
CurrentAccountChanged(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The event to be raised when the current account is changed
|
||||
/// </summary>
|
||||
public event EventHandler CurrentAccountChanged;
|
||||
|
||||
public Task<IUserAccount> AddUserAccountAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IUserAccount> AuthenticateAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IUserAccount> GetCurrentAccountAsync()
|
||||
{
|
||||
var account = await GetCurrentAccountInternalAsync();
|
||||
return account;
|
||||
}
|
||||
|
||||
private Task<AzureUserAccount> GetCurrentAccountInternalAsync()
|
||||
{
|
||||
|
||||
AzureUserAccount account = null;
|
||||
if (currentAccountId != null
|
||||
&& accountsMap.TryGetValue(currentAccountId, out account))
|
||||
{
|
||||
// TODO is there more needed here?
|
||||
}
|
||||
return Task.FromResult<AzureUserAccount>(account);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSelectedSubscriptionsAsync()
|
||||
{
|
||||
return _selectedSubscriptions ?? await GetSubscriptionsAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns user's subscriptions
|
||||
/// </summary>
|
||||
public async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionsAsync()
|
||||
{
|
||||
var result = Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
||||
bool userNeedsAuthentication = await GetUserNeedsReauthenticationAsync();
|
||||
if (!userNeedsAuthentication)
|
||||
{
|
||||
AzureUserAccount currentUser = await GetCurrentAccountInternalAsync();
|
||||
if (currentUser != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = await GetSubscriptionsFromCacheAsync(currentUser);
|
||||
}
|
||||
catch (ServiceExceptionBase)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ServiceFailedException(SR.AzureSubscriptionFailedErrorMessage, ex);
|
||||
}
|
||||
}
|
||||
result = result ?? Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionsFromCacheAsync(AzureUserAccount user)
|
||||
{
|
||||
var result = Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
result = _subscriptionCache.Get(user.UniqueId);
|
||||
if (result == null)
|
||||
{
|
||||
result = await GetSubscriptionFromServiceAsync(user);
|
||||
_subscriptionCache.UpdateCache(user.UniqueId, result);
|
||||
}
|
||||
}
|
||||
result = result ?? Enumerable.Empty<IAzureUserAccountSubscriptionContext>();
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionFromServiceAsync(AzureUserAccount userAccount)
|
||||
{
|
||||
List<IAzureUserAccountSubscriptionContext> subscriptionList = new List<IAzureUserAccountSubscriptionContext>();
|
||||
|
||||
try
|
||||
{
|
||||
if (userAccount != null && !userAccount.NeedsReauthentication)
|
||||
{
|
||||
IAzureResourceManager resourceManager = ServiceProvider.GetService<IAzureResourceManager>();
|
||||
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)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ServiceFailedException(SR.AzureSubscriptionFailedErrorMessage, ex);
|
||||
}
|
||||
return subscriptionList;
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> GetUserNeedsReauthenticationAsync()
|
||||
{
|
||||
// for now, we don't support handling stale auth objects
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the selected subscriptions given the ids
|
||||
/// </summary>
|
||||
public async Task<bool> SetSelectedSubscriptionsAsync(IEnumerable<string> subscriptionIds)
|
||||
{
|
||||
IEnumerable<IAzureUserAccountSubscriptionContext> subscriptions = await GetSubscriptionsAsync();
|
||||
List<IAzureUserAccountSubscriptionContext> subscriptionList = subscriptions.ToList();
|
||||
|
||||
List<IAzureUserAccountSubscriptionContext> newSelectedSubscriptions = subscriptionIds == null
|
||||
? subscriptionList
|
||||
: subscriptionList.Where(x => subscriptionIds.Contains(x.Subscription.SubscriptionId)).ToList();
|
||||
|
||||
//If the current account changes during setting selected subscription, none of the ids should be found
|
||||
//so we just reset the selected subscriptions
|
||||
if (subscriptionIds != null && subscriptionIds.Any() && newSelectedSubscriptions.Count == 0)
|
||||
{
|
||||
newSelectedSubscriptions = subscriptionList;
|
||||
}
|
||||
lock (_selectedSubscriptionsLockObject)
|
||||
{
|
||||
if (!SelectedSubscriptionsEquals(newSelectedSubscriptions))
|
||||
{
|
||||
_selectedSubscriptions = newSelectedSubscriptions;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool SelectedSubscriptionsEquals(List<IAzureUserAccountSubscriptionContext> newSelectedSubscriptions)
|
||||
{
|
||||
if (_selectedSubscriptions != null && _selectedSubscriptions.Count() == newSelectedSubscriptions.Count)
|
||||
{
|
||||
return newSelectedSubscriptions.All(subscription => _selectedSubscriptions.Contains(subscription));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find a subscription given subscription id
|
||||
/// </summary>
|
||||
public bool TryParseSubscriptionIdentifier(string value, out IAzureSubscriptionIdentifier subscription)
|
||||
{
|
||||
// TODO can port this over from the VS implementation if needed, but for now disabling as we don't serialize / deserialize subscriptions
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ using Microsoft.Azure.Management.Sql;
|
||||
using Microsoft.Azure.Management.Sql.Models;
|
||||
using RestFirewallRule = Microsoft.Azure.Management.Sql.Models.FirewallRule;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.FirewallRule;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Extensibility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Microsoft.Rest;
|
||||
using System.Globalization;
|
||||
using Microsoft.Rest.Azure;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using System.Collections;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
@@ -31,7 +32,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
ServerTypes.SqlServer,
|
||||
Categories.Azure,
|
||||
typeof(IAzureResourceManager),
|
||||
"Microsoft.SqlServer.ConnectionServices.Azure.Impl.VsAzureResourceManager",
|
||||
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureResourceManager",
|
||||
1)
|
||||
]
|
||||
public class AzureResourceManager : ExportableBase, IAzureResourceManager
|
||||
@@ -45,18 +46,24 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
Metadata = new ExportableMetadata(
|
||||
ServerTypes.SqlServer,
|
||||
Categories.Azure,
|
||||
"Microsoft.SqlServer.ConnectionServices.Azure.Impl.VsAzureResourceManager");
|
||||
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.AzureResourceManager");
|
||||
}
|
||||
|
||||
public async Task<IAzureResourceManagementSession> CreateSessionAsync(IAzureUserAccountSubscriptionContext subscriptionContext)
|
||||
public Task<IAzureResourceManagementSession> CreateSessionAsync(IAzureUserAccountSubscriptionContext subscriptionContext)
|
||||
{
|
||||
CommonUtil.CheckForNull(subscriptionContext, "subscriptionContext");
|
||||
try
|
||||
{
|
||||
ServiceClientCredentials credentials = await CreateCredentialsAsync(subscriptionContext);
|
||||
SqlManagementClient sqlManagementClient = new SqlManagementClient(_resourceManagementUri, credentials);
|
||||
ResourceManagementClient resourceManagementClient = new ResourceManagementClient(_resourceManagementUri, credentials);
|
||||
return new AzureResourceManagementSession(sqlManagementClient, resourceManagementClient, subscriptionContext);
|
||||
ServiceClientCredentials credentials = CreateCredentials(subscriptionContext);
|
||||
SqlManagementClient sqlManagementClient = new SqlManagementClient(credentials)
|
||||
{
|
||||
SubscriptionId = subscriptionContext.Subscription.SubscriptionId
|
||||
};
|
||||
ResourceManagementClient resourceManagementClient = new ResourceManagementClient(credentials)
|
||||
{
|
||||
SubscriptionId = subscriptionContext.Subscription.SubscriptionId
|
||||
};
|
||||
return Task.FromResult<IAzureResourceManagementSession>(new AzureResourceManagementSession(sqlManagementClient, resourceManagementClient, subscriptionContext));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -120,27 +127,29 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
AzureResourceManagementSession vsAzureResourceManagementSession = azureResourceManagementSession as AzureResourceManagementSession;
|
||||
if(vsAzureResourceManagementSession != null)
|
||||
{
|
||||
IEnumerable<ResourceGroup> resourceGroupNames = await GetResourceGroupsAsync(vsAzureResourceManagementSession);
|
||||
if (resourceGroupNames != null)
|
||||
// Note: Ideally wouldn't need to query resource groups, but the current impl requires it
|
||||
// since any update will need the resource group name and it's not returned from the server.
|
||||
// This has a very negative impact on perf, so we should investigate running these queries
|
||||
// in parallel
|
||||
|
||||
try
|
||||
{
|
||||
foreach (ResourceGroup resourceGroupExtended in resourceGroupNames)
|
||||
IServersOperations serverOperations = vsAzureResourceManagementSession.SqlManagementClient.Servers;
|
||||
IPage<Server> servers = await serverOperations.ListAsync();
|
||||
if (servers != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
IServersOperations serverOperations = vsAzureResourceManagementSession.SqlManagementClient.Servers;
|
||||
IPage<Server> servers = await serverOperations.ListByResourceGroupAsync(resourceGroupExtended.Name);
|
||||
if (servers != null)
|
||||
{
|
||||
sqlServers.AddRange(servers.Select(x =>
|
||||
new SqlAzureResource(x) { ResourceGroupName = resourceGroupExtended.Name }));
|
||||
}
|
||||
}
|
||||
catch (HttpOperationException ex)
|
||||
{
|
||||
throw new AzureResourceFailedException(SR.FailedToGetAzureSqlServersErrorMessage, ex.Response.StatusCode);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
@@ -175,21 +184,24 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
StartIpAddress = firewallRuleRequest.StartIpAddress.ToString()
|
||||
};
|
||||
IFirewallRulesOperations firewallRuleOperations = vsAzureResourceManagementSession.SqlManagementClient.FirewallRules;
|
||||
var firewallRuleResponse = await firewallRuleOperations.CreateOrUpdateAsync(
|
||||
azureSqlServer.ResourceGroupName,
|
||||
var firewallRuleResponse = await firewallRuleOperations.CreateOrUpdateWithHttpMessagesAsync(
|
||||
azureSqlServer.ResourceGroupName ?? string.Empty,
|
||||
azureSqlServer.Name,
|
||||
firewallRuleRequest.FirewallRuleName,
|
||||
firewallRule);
|
||||
firewallRule,
|
||||
GetCustomHeaders());
|
||||
var response = firewallRuleResponse.Body;
|
||||
return new FirewallRuleResponse()
|
||||
{
|
||||
StartIpAddress = firewallRuleResponse.StartIpAddress,
|
||||
EndIpAddress = firewallRuleResponse.EndIpAddress,
|
||||
StartIpAddress = response.StartIpAddress,
|
||||
EndIpAddress = response.EndIpAddress,
|
||||
Created = true
|
||||
};
|
||||
}
|
||||
catch (HttpOperationException ex)
|
||||
{
|
||||
throw new AzureResourceFailedException(SR.FirewallRuleCreationFailed, ex.Response.StatusCode);
|
||||
throw new AzureResourceFailedException(
|
||||
string.Format(CultureInfo.CurrentCulture, SR.FirewallRuleCreationFailedWithError, ex.Message), ex.Response.StatusCode);
|
||||
}
|
||||
}
|
||||
// else respond with failure case
|
||||
@@ -200,11 +212,22 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TraceException(TraceEventType.Error, (int) TraceId.AzureResource, ex, "Failed to get databases");
|
||||
TraceException(TraceEventType.Error, (int) TraceId.AzureResource, ex, "Failed to create firewall rule");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string,List<string>> GetCustomHeaders()
|
||||
{
|
||||
// For some unknown reason the firewall rule method defaults to returning XML. Fixes this by adding an Accept header
|
||||
// ensuring it's always JSON
|
||||
var headers = new Dictionary<string,List<string>>();
|
||||
headers["Accept"] = new List<string>() {
|
||||
"application/json"
|
||||
};
|
||||
return headers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the azure resource groups for given subscription
|
||||
/// </summary>
|
||||
@@ -226,7 +249,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
}
|
||||
catch (HttpOperationException ex)
|
||||
{
|
||||
throw new AzureResourceFailedException(SR.FailedToGetAzureResourceGroupsErrorMessage, ex.Response.StatusCode);
|
||||
throw new AzureResourceFailedException(string.Format(CultureInfo.CurrentCulture, SR.FailedToGetAzureResourceGroupsErrorMessage, ex.Message), ex.Response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,18 +262,104 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public async Task<IEnumerable<IAzureUserAccountSubscriptionContext>> GetSubscriptionContextsAsync(IAzureUserAccount userAccount)
|
||||
{
|
||||
List<IAzureUserAccountSubscriptionContext> contexts = new List<IAzureUserAccountSubscriptionContext>();
|
||||
foreach (IAzureTenant tenant in userAccount.AllTenants)
|
||||
{
|
||||
AzureTenant azureTenant = tenant as AzureTenant;
|
||||
if (azureTenant != null)
|
||||
{
|
||||
ServiceClientCredentials credentials = CreateCredentials(azureTenant);
|
||||
using (SubscriptionClient client = new SubscriptionClient(_resourceManagementUri, credentials))
|
||||
{
|
||||
IEnumerable<Subscription> subs = await GetSubscriptionsAsync(client);
|
||||
contexts.AddRange(subs.Select(sub =>
|
||||
{
|
||||
AzureSubscriptionIdentifier subId = new AzureSubscriptionIdentifier(userAccount, azureTenant.TenantId, sub.SubscriptionId, _resourceManagementUri);
|
||||
AzureUserAccountSubscriptionContext context = new AzureUserAccountSubscriptionContext(subId, credentials);
|
||||
return context;
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
return contexts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the azure resource groups for given subscription
|
||||
/// </summary>
|
||||
private async Task<IEnumerable<Subscription>> GetSubscriptionsAsync(SubscriptionClient subscriptionClient)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (subscriptionClient != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
ISubscriptionsOperations subscriptionsOperations = subscriptionClient.Subscriptions;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return Enumerable.Empty<Subscription>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TraceException(TraceEventType.Error, (int)TraceId.AzureResource, ex, "Failed to get azure resource groups");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates credential instance for given subscription
|
||||
/// </summary>
|
||||
private Task<ServiceClientCredentials> CreateCredentialsAsync(IAzureUserAccountSubscriptionContext subscriptionContext)
|
||||
private ServiceClientCredentials CreateCredentials(IAzureTenant tenant)
|
||||
{
|
||||
AzureTenant azureTenant = tenant as AzureTenant;
|
||||
|
||||
if (azureTenant != null)
|
||||
{
|
||||
TokenCredentials credentials;
|
||||
if (!string.IsNullOrWhiteSpace(azureTenant.TokenType))
|
||||
{
|
||||
credentials = new TokenCredentials(azureTenant.AccessToken, azureTenant.TokenType);
|
||||
}
|
||||
else
|
||||
{
|
||||
credentials = new TokenCredentials(azureTenant.AccessToken);
|
||||
}
|
||||
|
||||
return credentials;
|
||||
}
|
||||
throw new NotSupportedException("This uses an unknown subscription type");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates credential instance for given subscription
|
||||
/// </summary>
|
||||
private ServiceClientCredentials CreateCredentials(IAzureUserAccountSubscriptionContext subscriptionContext)
|
||||
{
|
||||
AzureUserAccountSubscriptionContext azureUserSubContext =
|
||||
subscriptionContext as AzureUserAccountSubscriptionContext;
|
||||
|
||||
if (azureUserSubContext != null)
|
||||
{
|
||||
return Task.FromResult(azureUserSubContext.Credentials);
|
||||
return azureUserSubContext.Credentials;
|
||||
}
|
||||
throw new NotSupportedException("This uses an unknown subscription type");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
/// </summary>
|
||||
public class AzureResourceWrapper : IAzureResource
|
||||
{
|
||||
public const string ResourceGroupsPart = "resourceGroups";
|
||||
private string resourceGroupName;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the resource
|
||||
/// </summary>
|
||||
@@ -71,7 +74,39 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
/// <summary>
|
||||
/// Resource Group Name
|
||||
/// </summary>
|
||||
public string ResourceGroupName { get; set; }
|
||||
public string ResourceGroupName {
|
||||
get
|
||||
{
|
||||
if (this.resourceGroupName == null)
|
||||
{
|
||||
this.resourceGroupName = ParseResourceGroupNameFromId();
|
||||
}
|
||||
return this.resourceGroupName;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.resourceGroupName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string ParseResourceGroupNameFromId()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
{
|
||||
string[] idParts = Id.Split('/');
|
||||
|
||||
// Look for the "resourceGroups" section and return the section after this, hence
|
||||
// always stop before idParts.Length - 1
|
||||
for (int i = 0; i < idParts.Length - 1; i++)
|
||||
{
|
||||
if (string.Compare(idParts[i], ResourceGroupsPart, StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
return idParts[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resource Location
|
||||
|
||||
@@ -17,9 +17,10 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
/// <summary>
|
||||
/// Default constructor to initialize the subscription identifier
|
||||
/// </summary>
|
||||
public AzureSubscriptionIdentifier(IAzureUserAccount userAccount, string subscriptionId, Uri serviceManagementEndpoint)
|
||||
public AzureSubscriptionIdentifier(IAzureUserAccount userAccount, string tenantId, string subscriptionId, Uri serviceManagementEndpoint)
|
||||
{
|
||||
UserAccount = userAccount;
|
||||
TenantId = tenantId;
|
||||
SubscriptionId = subscriptionId;
|
||||
ServiceManagementEndpoint = serviceManagementEndpoint;
|
||||
}
|
||||
@@ -56,6 +57,15 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ID of the tenant this subscription comes from
|
||||
/// </summary>
|
||||
public string TenantId
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
|
||||
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation for <see cref="IAzureTenant" /> using VS services
|
||||
/// Contains information about an Azure account
|
||||
/// </summary>
|
||||
public class AzureTenant : IAzureTenant
|
||||
{
|
||||
public string TenantId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string AccountDisplayableId
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// URI defining the root for resource lookup
|
||||
/// </summary>
|
||||
public string Resource { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Access token for use in login scenarios. Note that we could consider implementing this better in the
|
||||
/// </summary>
|
||||
public string AccessToken
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional token type defining whether this is a Bearer token or other type of token
|
||||
/// </summary>
|
||||
public string TokenType
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
|
||||
@@ -36,7 +37,9 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
this.DisplayInfo = new AzureUserAccountDisplayInfo(azureUserAccount.DisplayInfo);
|
||||
this.NeedsReauthentication = azureUserAccount.NeedsReauthentication;
|
||||
this.TenantId = azureUserAccount.TenantId;
|
||||
this.AllTenants = azureUserAccount.AllTenants;
|
||||
this.UniqueId = azureUserAccount.UniqueId;
|
||||
AzureUserAccount account = azureUserAccount as AzureUserAccount;
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns true if given user account equals this class
|
||||
@@ -46,6 +49,7 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
return other != null &&
|
||||
CommonUtil.SameString(other.UniqueId, UniqueId) &&
|
||||
CommonUtil.SameString(other.TenantId, TenantId);
|
||||
// TODO probably should check the AllTenants field
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -88,6 +92,12 @@ namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public IList<IAzureTenant> AllTenants
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
215
src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/Localization/sr.cs
Normal file → Executable file
215
src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/Localization/sr.cs
Normal file → Executable file
@@ -1,105 +1,160 @@
|
||||
// WARNING:
|
||||
// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0
|
||||
// from information in sr.strings
|
||||
// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN
|
||||
//
|
||||
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Globalization;
|
||||
// WARNING:
|
||||
// This file was generated by the Microsoft DataWarehouse String Resource Tool 1.37.0.0
|
||||
// from information in sr.strings
|
||||
// DO NOT MODIFY THIS FILE'S CONTENTS, THEY WILL BE OVERWRITTEN
|
||||
//
|
||||
namespace Microsoft.SqlTools.ResourceProvider.DefaultImpl
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Globalization;
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SR
|
||||
{
|
||||
protected SR()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.Culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
Keys.Culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SR
|
||||
{
|
||||
protected SR()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.Culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
Keys.Culture = value;
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureDatabasesErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureDatabasesErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static string FailedToGetAzureDatabasesErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureDatabasesErrorMessage);
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureSubscriptionsErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureSubscriptionsErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureResourceGroupsErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureResourceGroupsErrorMessage);
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureResourceGroupsErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureResourceGroupsErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureSqlServersErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureSqlServersErrorMessage);
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureSqlServersErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureSqlServersErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FirewallRuleCreationFailed
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||
}
|
||||
|
||||
public static string FailedToGetAzureSqlServersWithError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FailedToGetAzureSqlServersWithError);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
{
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.DefaultImpl.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
public static string FirewallRuleCreationFailed
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailed);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FirewallRuleCreationFailedWithError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.FirewallRuleCreationFailedWithError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string AzureSubscriptionFailedErrorMessage
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.AzureSubscriptionFailedErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string UnsupportedAuthType
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.UnsupportedAuthType);
|
||||
}
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
{
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ResourceProvider.DefaultImpl.Localization.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
|
||||
public const string FailedToGetAzureDatabasesErrorMessage = "FailedToGetAzureDatabasesErrorMessage";
|
||||
|
||||
|
||||
public const string FailedToGetAzureSubscriptionsErrorMessage = "FailedToGetAzureSubscriptionsErrorMessage";
|
||||
|
||||
|
||||
public const string FailedToGetAzureResourceGroupsErrorMessage = "FailedToGetAzureResourceGroupsErrorMessage";
|
||||
|
||||
|
||||
public const string FailedToGetAzureSqlServersErrorMessage = "FailedToGetAzureSqlServersErrorMessage";
|
||||
|
||||
|
||||
public const string FailedToGetAzureSqlServersWithError = "FailedToGetAzureSqlServersWithError";
|
||||
|
||||
|
||||
public const string FirewallRuleCreationFailed = "FirewallRuleCreationFailed";
|
||||
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
public const string FirewallRuleCreationFailedWithError = "FirewallRuleCreationFailedWithError";
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetString(string key)
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
public const string AzureSubscriptionFailedErrorMessage = "AzureSubscriptionFailedErrorMessage";
|
||||
|
||||
|
||||
public const string UnsupportedAuthType = "UnsupportedAuthType";
|
||||
|
||||
|
||||
private Keys()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return _culture;
|
||||
}
|
||||
set
|
||||
{
|
||||
_culture = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetString(string key)
|
||||
{
|
||||
return resourceManager.GetString(key, _culture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
282
src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/Localization/sr.resx
Normal file → Executable file
282
src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/Localization/sr.resx
Normal file → Executable file
@@ -1,136 +1,156 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype=">text/microsoft-resx</resheader>
|
||||
<resheader name="version=">2.0</resheader>
|
||||
<resheader name="reader=">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer=">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1="><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing=">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64=">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64=">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata=">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true=">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded=">
|
||||
<xsd:element name="metadata=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly=">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="FailedToGetAzureDatabasesErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure databases</value>
|
||||
<comment></comment>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype=">text/microsoft-resx</resheader>
|
||||
<resheader name="version=">2.0</resheader>
|
||||
<resheader name="reader=">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer=">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1="><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing=">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64=">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64=">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata=">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true=">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded=">
|
||||
<xsd:element name="metadata=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly=">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader=">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="FailedToGetAzureDatabasesErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure databases</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FailedToGetAzureResourceGroupsErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure resource groups</value>
|
||||
<comment></comment>
|
||||
<data name="FailedToGetAzureSubscriptionsErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure subscriptions: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FailedToGetAzureSqlServersErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure Sql Servers</value>
|
||||
<comment></comment>
|
||||
<data name="FailedToGetAzureResourceGroupsErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure resource groups: {0}</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule.</value>
|
||||
<comment></comment>
|
||||
<data name="FailedToGetAzureSqlServersErrorMessage" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure Sql Servers</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FailedToGetAzureSqlServersWithError" xml:space="preserve">
|
||||
<value>An error occurred while getting Azure Sql Servers: '{0}'</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FirewallRuleCreationFailed" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="FirewallRuleCreationFailedWithError" xml:space="preserve">
|
||||
<value>An error occurred while creating a new firewall rule: '{0}'</value>
|
||||
<comment></comment>
|
||||
</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">
|
||||
<value>Unsupported account type '{0}' for this provider</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
############################################################################
|
||||
# Azure Core DLL
|
||||
FailedToGetAzureDatabasesErrorMessage = An error occurred while getting Azure databases
|
||||
FailedToGetAzureResourceGroupsErrorMessage = An error occurred while getting Azure resource groups
|
||||
FailedToGetAzureSubscriptionsErrorMessage = An error occurred while getting Azure subscriptions: {0}
|
||||
FailedToGetAzureResourceGroupsErrorMessage = An error occurred while getting Azure resource groups: {0}
|
||||
FailedToGetAzureSqlServersErrorMessage = An error occurred while getting Azure Sql Servers
|
||||
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
||||
FailedToGetAzureSqlServersWithError = An error occurred while getting Azure Sql Servers: '{0}'
|
||||
FirewallRuleCreationFailed = An error occurred while creating a new firewall rule.
|
||||
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
|
||||
@@ -8,7 +8,7 @@
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FailedToGetAzureResourceGroupsErrorMessage">
|
||||
<source>An error occurred while getting Azure resource groups</source>
|
||||
<source>An error occurred while getting Azure resource groups: {0}</source>
|
||||
<target state="new">An error occurred while getting Azure resource groups</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
@@ -22,6 +22,31 @@
|
||||
<target state="new">An error occurred while creating a new firewall rule.</target>
|
||||
<note></note>
|
||||
</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">
|
||||
<source>Unsupported account type '{0}' for this provider</source>
|
||||
<target state="new">Unsupported account type '{0}' for this provider</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FailedToGetAzureSqlServersWithError">
|
||||
<source>An error occurred while getting Azure Sql Servers: '{0}'</source>
|
||||
<target state="new">An error occurred while getting Azure Sql Servers: '{0}'</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FirewallRuleCreationFailedWithError">
|
||||
<source>An error occurred while creating a new firewall rule: '{0}'</source>
|
||||
<target state="new">An error occurred while creating a new firewall rule: '{0}'</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
<trans-unit id="FailedToGetAzureSubscriptionsErrorMessage">
|
||||
<source>An error occurred while getting Azure subscriptions: {0}</source>
|
||||
<target state="new">An error occurred while getting Azure subscriptions: {0}</target>
|
||||
<note></note>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
@@ -3,12 +3,12 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageId>Microsoft.SqlTools.ResourceProvider.DefaultImpl</PackageId>
|
||||
<AssemblyName>Microsoft.SqlTools.ResourceProvider.DefaultImpl</AssemblyName>
|
||||
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
|
||||
<ApplicationIcon />
|
||||
<OutputType>Library</OutputType>
|
||||
<StartupObject />
|
||||
<Description>Provides the default for SqlTools applications.</Description>
|
||||
<Copyright><EFBFBD> Microsoft Corporation. All rights reserved.</Copyright>
|
||||
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
|
||||
<ApplicationIcon />
|
||||
<OutputType>Library</OutputType>
|
||||
<StartupObject />
|
||||
<Description>Provides the default for SqlTools applications.</Description>
|
||||
<Copyright><EFBFBD> Microsoft Corporation. All rights reserved.</Copyright>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.Management.ResourceManager" Version="1.6.0-preview" />
|
||||
@@ -18,7 +18,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.0.0" />
|
||||
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||
<PackageReference Include="System.Composition" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.Azure.Management.Sql" Version="1.6.0-preview" />
|
||||
<PackageReference Include="Microsoft.Azure.Management.Sql" Version="1.7.0-preview" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj" />
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj" />
|
||||
<!-- Note: must reference the resource provider projects in order for them to be bundled into the app. Otherwise will not have any of the required DLLs and
|
||||
dependencies included when the project is shipped. If adding new DLLs, add them here or find another solution to keep them bundled
|
||||
-->
|
||||
<ProjectReference Include="..\Microsoft.SqlTools.ResourceProvider.Core\Microsoft.SqlTools.ResourceProvider.Core.csproj" />
|
||||
<ProjectReference Include="..\Microsoft.SqlTools.ResourceProvider.DefaultImpl\Microsoft.SqlTools.ResourceProvider.DefaultImpl.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Localization\sr.resx" />
|
||||
|
||||
@@ -11,11 +11,11 @@ using Microsoft.SqlTools.Utility;
|
||||
namespace Microsoft.SqlTools.ResourceProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Main application class for Credentials Service Host executable
|
||||
/// Main application class for the executable that supports the resource provider and identity services
|
||||
/// </summary>
|
||||
internal class Program
|
||||
{
|
||||
private const string ServiceName = "SqlToolsAzure.exe";
|
||||
private const string ServiceName = "SqlToolsResourceProviderService.exe";
|
||||
|
||||
/// <summary>
|
||||
/// Main entry point into the Credentials Service Host
|
||||
@@ -31,7 +31,7 @@ namespace Microsoft.SqlTools.ResourceProvider
|
||||
return;
|
||||
}
|
||||
|
||||
string logFilePath = "sqltoolsazure";
|
||||
string logFilePath = "SqlToolsResourceProviderService";
|
||||
if (!string.IsNullOrWhiteSpace(commandOptions.LoggingDirectory))
|
||||
{
|
||||
logFilePath = Path.Combine(commandOptions.LoggingDirectory, logFilePath);
|
||||
@@ -40,11 +40,11 @@ namespace Microsoft.SqlTools.ResourceProvider
|
||||
// turn on Verbose logging during early development
|
||||
// we need to switch to Normal when preparing for public preview
|
||||
Logger.Initialize(logFilePath: logFilePath, minimumLogLevel: LogLevel.Verbose, isEnabled: commandOptions.EnableLogging);
|
||||
Logger.Write(LogLevel.Normal, "Starting SqlTools Azure Provider");
|
||||
Logger.Write(LogLevel.Normal, "Starting SqlTools Resource Provider");
|
||||
|
||||
// set up the host details and profile paths
|
||||
var hostDetails = new HostDetails(
|
||||
name: "SqlTools Azure Provider",
|
||||
name: "SqlTools Resource Provider",
|
||||
profileId: "Microsoft.SqlTools.ResourceProvider",
|
||||
version: new Version(1, 0));
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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 System.Reflection;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.Hosting;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
@@ -45,18 +47,25 @@ namespace Microsoft.SqlTools.ResourceProvider
|
||||
{
|
||||
// Load extension provider, which currently finds all exports in current DLL. Can be changed to find based
|
||||
// on directory or assembly list quite easily in the future
|
||||
ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider();
|
||||
ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.CreateFromAssembliesInDirectory(GetResourceProviderExtensionDlls());
|
||||
|
||||
serviceProvider.RegisterSingleService(sqlToolsContext);
|
||||
serviceProvider.RegisterSingleService(serviceHost);
|
||||
|
||||
// CredentialService.Instance.InitializeService(serviceHost);
|
||||
// serviceProvider.RegisterSingleService(CredentialService.Instance);
|
||||
|
||||
|
||||
InitializeHostedServices(serviceProvider, serviceHost);
|
||||
|
||||
serviceHost.InitializeRequestHandlers();
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetResourceProviderExtensionDlls()
|
||||
{
|
||||
return new string[] {
|
||||
"SqlToolsResourceProviderService.dll",
|
||||
"Microsoft.SqlTools.ResourceProvider.Core.dll",
|
||||
"Microsoft.SqlTools.ResourceProvider.DefaultImpl.dll"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal to support testing. Initializes <see cref="IHostedService"/> instances in the service,
|
||||
/// and registers them for their preferred service type
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.SqlTools.ServiceLayer.TaskServices;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Profiler.Contracts
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using Microsoft.SqlTools.ServiceLayer.DisasterRecovery;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.DisasterRecovery
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.ServiceLayer/Microsoft.SqlTools.ServiceLayer.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.ResourceProvider/Microsoft.SqlTools.ResourceProvider.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.ResourceProvider.Core/Microsoft.SqlTools.ResourceProvider.Core.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.ResourceProvider.DefaultImpl/Microsoft.SqlTools.ResourceProvider.DefaultImpl.csproj" />
|
||||
<ProjectReference Include="../../test/Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj" />
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
||||
public void SubscriptionNameShouldReturnCorrectValueGivenValidSubscription()
|
||||
{
|
||||
string name = Guid.NewGuid().ToString();
|
||||
|
||||
AzureSubscriptionContext subscriptionContext = new AzureSubscriptionContext(new AzureSubscriptionIdentifier(null, name, null));
|
||||
string tenantId = Guid.NewGuid().ToString();
|
||||
AzureSubscriptionContext subscriptionContext = new AzureSubscriptionContext(new AzureSubscriptionIdentifier(null, null, name, null));
|
||||
Assert.True(subscriptionContext.SubscriptionName == name);
|
||||
Assert.True(subscriptionContext.Subscription != null);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
|
||||
foreach (string subscriptionName in subscriptionToDatabaseMap.Keys)
|
||||
{
|
||||
var azureAccount = new AzureUserAccount();
|
||||
AzureSubscriptionIdentifier subId = new AzureSubscriptionIdentifier(azureAccount, subscriptionName, null);
|
||||
string tenantId = Guid.NewGuid().ToString();
|
||||
AzureSubscriptionIdentifier subId = new AzureSubscriptionIdentifier(azureAccount, tenantId, subscriptionName, null);
|
||||
var subscription = new AzureUserAccountSubscriptionContext(subId, new TokenCredentials("dummy"));
|
||||
accountSubscriptions.Add(subscription);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.FirewallRule;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider
|
||||
|
||||
@@ -8,7 +8,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.FirewallRule;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Firewall;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.Extensibility;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core;
|
||||
using Moq;
|
||||
using Microsoft.SqlTools.ResourceProvider;
|
||||
using Microsoft.SqlTools.ResourceProvider.Core.Authentication;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Formatter
|
||||
{
|
||||
public class ResourceProviderServiceTests
|
||||
{
|
||||
public ResourceProviderServiceTests()
|
||||
{
|
||||
HostMock = new Mock<IProtocolEndpoint>();
|
||||
AuthenticationManagerMock = new Mock<IAzureAuthenticationManager>();
|
||||
ResourceManagerMock = new Mock<IAzureResourceManager>();
|
||||
ServiceProvider = ExtensionServiceProvider.CreateFromAssembliesInDirectory(ResourceProviderHostLoader.GetResourceProviderExtensionDlls());
|
||||
ServiceProvider.RegisterSingleService<IAzureAuthenticationManager>(AuthenticationManagerMock.Object);
|
||||
ServiceProvider.RegisterSingleService<IAzureResourceManager>(ResourceManagerMock.Object);
|
||||
HostLoader.InitializeHostedServices(ServiceProvider, HostMock.Object);
|
||||
ResourceProviderService = ServiceProvider.GetService<ResourceProviderService>();
|
||||
}
|
||||
|
||||
protected RegisteredServiceProvider ServiceProvider { get; private set; }
|
||||
protected Mock<IProtocolEndpoint> HostMock { get; private set; }
|
||||
|
||||
protected Mock<IAzureAuthenticationManager> AuthenticationManagerMock { get; set; }
|
||||
protected Mock<IAzureResourceManager> ResourceManagerMock { get; set; }
|
||||
|
||||
protected ResourceProviderService ResourceProviderService { get; private set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user