Merge branch 'ChristianWolf42-geodr'
This commit is contained in:
Коммит
a85589e81b
|
@ -0,0 +1,74 @@
|
|||
# Azure Service Bus Geo-disaster recovery
|
||||
|
||||
To learn more about Azure Service Bus, please visit our [marketing page](https://azure.microsoft.com/en-us/services/service-bus/).
|
||||
|
||||
To learn more about our Geo-DR feature in general please follow [this](https://docs.microsoft.com/azure/service-bus-messaging/service-bus-geo-dr) link.
|
||||
|
||||
This sample shows how to:
|
||||
|
||||
1. Achieve Geo-DR for an Service Bus namespace.
|
||||
2. Create a namespace with live metadata replication between two customer chosen regions
|
||||
|
||||
This sample consists of three parts:
|
||||
|
||||
1. The main scenario showing management (Setup, failover, remove pairing) of new or existing namespaces sample can be found [here](https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/GeoDR/SBGeoDR2/SBGeoDR2)
|
||||
2. The scenario in which you want to use an existing namespace name as alias can be found [here](https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/GeoDR/SBGeoDR2/SBGeoDR_existing_namespace_name). Make sure to thoroughly look through the comments as this diverges slightly from the main scenario. Examine both, App.config and Program.cs. ***Note:*** If you do not failover but just do break pairing, there is no need to execute delete alias as namespace name and alias are the same. If you do failover you would need to delete the alias if you would want to use the namespace outside of a DR setup.
|
||||
3. A sample on how to access the alias connection string which can be found [here](https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/GeoDR/TestGeoDR).
|
||||
|
||||
## Getting Started
|
||||
### Prerequisites
|
||||
|
||||
In order to get started using the sample (as it uses the Service Bus management libraries), you must authenticate with Azure Active Directory (AAD). This requires you to authenticate as a Service Principal, which provides access to your Azure resources.
|
||||
To obtain a service principal please do the following steps:
|
||||
|
||||
1. Go to the Azure Portal and select Azure Active Directory in the left menu.
|
||||
2. Create a new Application under App registrations / + New application registration.
|
||||
1. The application should be of type Web app / API.
|
||||
2. You can provide any URL for your application as sign on URL.
|
||||
3. Navigate to your newly created application
|
||||
3. Application or AppId is the client Id. Note it down as you will need it for the sample.
|
||||
4. Select keys and create a new key. Note down the Value as you won't be able to access it later.
|
||||
5. Go back to the root Azure Active Directory and select properties.
|
||||
1. Note down the Directory ID as this is your TenantId.
|
||||
6. You must have ‘Owner’ permissions under Role for the resource group that you wish to run the sample on. Regardless if you want to use an existing namespace or create a new one, make sure to add the newly created application as owner under Access Control (IAM).
|
||||
|
||||
For more information on creating a Service Principal, refer to the following articles:
|
||||
|
||||
* [Use the Azure Portal to create Active Directory application and service principal that can access resources](https://docs.microsoft.com/azure/azure-resource-manager/resource-group-create-service-principal-portal)
|
||||
* [Use Azure PowerShell to create a service principal to access resources](https://docs.microsoft.com/azure/azure-resource-manager/resource-group-authenticate-service-principal)
|
||||
* [Use Azure CLI to create a service principal to access resources](https://docs.microsoft.com/azure/azure-resource-manager/resource-group-authenticate-service-principal-cli)
|
||||
|
||||
<!-- The above articles helps you to obtain an AppId (ClientId), TenantId, and ClientSecret (Authentication Key), all of which are required to authenticate the management libraries. Finally, when creating your Active Directory application, if you do not have a sign-on URL to input in the create step, simply input any URL format string e.g. https://contoso.org/exampleapp -->
|
||||
|
||||
### Required NuGet packages
|
||||
|
||||
1. Microsoft.Azure.Management.ServiceBus
|
||||
2. Microsoft.IdentityModel.Clients.ActiveDirectory - used to authenticate with AAD
|
||||
|
||||
### Running the sample
|
||||
|
||||
1. Please use Visual Studio 2017
|
||||
2. Make sure all assemblies are in place.
|
||||
2. Populate the regarding values in the App.config.
|
||||
3. Build the solution.
|
||||
4. Make sure to execute on Screen option A before any other option.
|
||||
|
||||
The Geo DR actions could be
|
||||
|
||||
* CreatePairing
|
||||
For creating a paired region. After this, you should see metadata (i.e. Queues, Topics and Subscriptions replicated to the secondary namespace).
|
||||
|
||||
* FailOver
|
||||
Simulating a failover. After this action, the secondary namespace becomes the primary
|
||||
|
||||
* BreakPairing
|
||||
For breaking the pairing between a primary and secondary namespace
|
||||
|
||||
* DeleteAlias
|
||||
For deleting an alias, that contains information about the primary-secondary pairing
|
||||
|
||||
* GetConnectionStrings
|
||||
In a Geo DR enabled namespace, the Service Bus should be accessed only via the alias. This is because, the alias can point to either the primary Service Bus or the failed over Service Bus. This way, the user does not have to adjust the connection strings in his/her apps to point to a different Service Bus in the case of a failover.
|
||||
The way to get the alias connection string is shown in a seperate console app which you can also use to test your newly geo paired namespaces. It can be found [here](https://github.com/Azure/azure-service-bus/tree/master/samples/DotNet/Microsoft.ServiceBus.Messaging/GeoDR/TestGeoDR).
|
||||
|
||||
***Note:*** The AAD access data for the GeoDR sample must also be used for the Test sample.
|
|
@ -3,4 +3,31 @@
|
|||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
<appSettings>
|
||||
|
||||
<!-- Use the following link to learn how to setup an client app in access Active Directory
|
||||
and grant that app rights to your azure subscription
|
||||
https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
Respectively follow this: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
|
||||
To get the below three values. Make sure to add the application as owner in your resource group via "Access control (IAM)". -->
|
||||
|
||||
<add key="tenantId" value="" /> <!-- Directory ID in portal -->
|
||||
<add key="clientId" value="" /> <!-- Application ID in portal -->
|
||||
<add key="subscriptionId" value="" /> <!-- Pick existing subscription -->
|
||||
<add key="resourceGroupName" value="" /> <!-- Pick existing resource group, make sure your aad app is added as owner of the resource group. -->
|
||||
<add key="activeDirectoryAuthority" value="https://login.microsoftonline.com" />
|
||||
<add key="resourceManagerUrl" value="https://management.azure.com/" />
|
||||
<add key="clientSecret" value="" /> <!-- Key in portal -->
|
||||
<add key="geoDRPrimaryNS" value="" />
|
||||
<add key="geoDRSecondaryNS" value="" />
|
||||
<add key="alias" value="" />
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Configuration;
|
||||
using Microsoft.Azure.Management.ServiceBus;
|
||||
using Microsoft.Azure.Management.ServiceBus.Models;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
|
@ -8,43 +9,68 @@ using Microsoft.Rest;
|
|||
|
||||
namespace SBGeoDR2
|
||||
{
|
||||
static class Program
|
||||
class Program
|
||||
{
|
||||
static string subscriptionId = "your subscription id"; // Pick existing subscription
|
||||
static string resourceGroupName = "your resource group name"; // Pick existing resource group
|
||||
|
||||
static string activeDirectoryAuthority = "https://login.microsoftonline.com";
|
||||
static string resourceManagerUrl = "https://management.azure.com/";
|
||||
|
||||
// Use the following link to learn how to setup an client app in access Active Directory
|
||||
// and grant that app rights to your azure subscription
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
// Respectively follow this: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
|
||||
// To get the below three values. Make sure to add the application as owner in your resource group via "Access control (IAM)".
|
||||
|
||||
static string tenantId = "your tenant / directory id"; // Directory ID in portal
|
||||
static string clientId = "your client / application id"; //Application ID in portal
|
||||
static string clientSecret = "your clientSecret / key"; // Key in portal
|
||||
|
||||
static readonly string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
|
||||
static readonly string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
|
||||
static readonly string activeDirectoryAuthority = ConfigurationManager.AppSettings["activeDirectoryAuthority"];
|
||||
static readonly string resourceManagerUrl = ConfigurationManager.AppSettings["resourceManagerUrl"];
|
||||
static readonly string tenantId = ConfigurationManager.AppSettings["tenantId"];
|
||||
static readonly string clientId = ConfigurationManager.AppSettings["clientId"];
|
||||
static readonly string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
|
||||
|
||||
static string geoDRPrimaryNS = "your primary ns";
|
||||
static string geoDRSecondaryNS = "your secondary ns";
|
||||
static string alias = "your alias";
|
||||
static readonly string geoDRPrimaryNS = ConfigurationManager.AppSettings["geoDRPrimaryNS"];
|
||||
static readonly string geoDRSecondaryNS = ConfigurationManager.AppSettings["geoDRSecondaryNS"];
|
||||
static readonly string alias = ConfigurationManager.AppSettings["alias"];
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
MainAsync().GetAwaiter().GetResult();
|
||||
//MainAsync().GetAwaiter().GetResult();
|
||||
|
||||
Console.WriteLine ("Choose an action:");
|
||||
Console.WriteLine ("[A] Create or update namespaces, pair them and create a few entities");
|
||||
Console.WriteLine ("[B] Failover");
|
||||
Console.WriteLine ("[C] Break pairing");
|
||||
Console.WriteLine ("[D] Delete Alias in case of break pairing was executed and no failover happened.");
|
||||
Console.WriteLine ("[E] Delete Alias after Failover.");
|
||||
|
||||
Char key = Console.ReadKey(true).KeyChar;
|
||||
String keyPressed = key.ToString().ToUpper();
|
||||
|
||||
switch (keyPressed)
|
||||
{
|
||||
case "A":
|
||||
CreatePairing().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "B":
|
||||
ExecuteFailover().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "C":
|
||||
BreakPairing().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "D":
|
||||
DeleteAliasPrim().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "E":
|
||||
DeleteAliasSec().GetAwaiter().GetResult();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Unknown command, press enter to exit");
|
||||
Console.ReadLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static async Task MainAsync()
|
||||
{
|
||||
static async Task CreatePairing()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
//// 1. Create Primary Namespace (optional)
|
||||
// 1. Create Primary Namespace (optional)
|
||||
Console.WriteLine("Create or update namespace 1");
|
||||
var namespaceParams = new SBNamespace
|
||||
{
|
||||
Location = "South Central US",
|
||||
|
@ -57,7 +83,8 @@ namespace SBGeoDR2
|
|||
var namespace1 = await client.Namespaces.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, namespaceParams)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
//// 2. Create Secondary Namespace (optional if you already have an empty namespace available)
|
||||
// 2. Create Secondary Namespace (optional if you already have an empty namespace available)
|
||||
Console.WriteLine("Create or update namespace 2");
|
||||
var namespaceParams2 = new SBNamespace
|
||||
{
|
||||
Location = "North Central US",
|
||||
|
@ -68,17 +95,18 @@ namespace SBGeoDR2
|
|||
}
|
||||
};
|
||||
|
||||
//// If you re-run this program while namespaces are still paired this operation will fail with a bad request.
|
||||
//// this is because we block all updates on secondary namespaces once it is paired
|
||||
// If you re-run this program while namespaces are still paired this operation will fail with a bad request.
|
||||
// this is because we block all updates on secondary namespaces once it is paired
|
||||
var namespace2 = await client.Namespaces.CreateOrUpdateAsync(resourceGroupName, geoDRSecondaryNS, namespaceParams2)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// 3. Pair the namespaces to enable DR.
|
||||
// 3. Pair the namespaces to enable DR.
|
||||
Console.WriteLine("Starting Pairing");
|
||||
ArmDisasterRecovery drStatus = await client.DisasterRecoveryConfigs.CreateOrUpdateAsync(
|
||||
resourceGroupName,
|
||||
geoDRPrimaryNS,
|
||||
alias,
|
||||
new ArmDisasterRecovery { PartnerNamespace = geoDRSecondaryNS })
|
||||
new ArmDisasterRecovery { PartnerNamespace = namespace2.Id })
|
||||
.ConfigureAwait(false);
|
||||
|
||||
while (drStatus.ProvisioningState != ProvisioningStateDR.Succeeded)
|
||||
|
@ -91,27 +119,93 @@ namespace SBGeoDR2
|
|||
alias);
|
||||
|
||||
Thread.CurrentThread.Join(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Creating test entities to show pairing.");
|
||||
await client.Topics.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, "myTopic", new SBTopic())
|
||||
.ConfigureAwait(false);
|
||||
await client.Subscriptions.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, "myTopic", "myTopic-Sub1", new SBSubscription())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// sleeping to allow metadata to sync across primary and secondary
|
||||
// Sleeping to allow metadata to sync across primary and secondary
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
|
||||
// 6. Failover. Note that this Failover operations is ALWAYS run against the secondary ( because primary might be down at time of failover )
|
||||
// client.DisasterRecoveryConfigs.FailOver(resourceGroupName, geoDRSecondaryNS, alias);
|
||||
|
||||
// other possible DR operations
|
||||
Console.WriteLine("Initial setup complete. Please see in the portal if all resources have been created as expected.");
|
||||
Console.WriteLine("Try creating a few additional entities in the primary in the portal.");
|
||||
Console.WriteLine("Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
// 7. Break Pairing
|
||||
// client.DisasterRecoveryConfigs.BreakPairing(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
static async Task ExecuteFailover()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
// 8. Delete DR config (alias)
|
||||
// note that this operation needs to run against the namespace that the alias is currently pointing to
|
||||
// client.DisasterRecoveryConfigs.Delete(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// Failover. Note that this Failover operations is ALWAYS run against the secondary ( because primary might be down at time of failover )
|
||||
Console.WriteLine("Initiating failover. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.FailOver(resourceGroupName, geoDRSecondaryNS, alias);
|
||||
|
||||
// Sleeping to allow the break pairing to happen
|
||||
Console.WriteLine("Waiting for failover to complete.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Failover Complete, press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task BreakPairing()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// Break Pairing
|
||||
Console.WriteLine("Disabling pairing. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.BreakPairing(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
|
||||
// sleeping to allow the break pairing to happen
|
||||
Console.WriteLine("Waiting for break pairing to complete.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Break pairing complete. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task DeleteAliasPrim()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
Console.WriteLine("Deleting the alias. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.Delete(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
|
||||
Console.WriteLine("Wait for the alias to be deleted.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Alias deleted. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task DeleteAliasSec()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
Console.WriteLine("Deleting the alias. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.Delete(resourceGroupName, geoDRSecondaryNS, alias);
|
||||
|
||||
Console.WriteLine("Wait for the alias to be deleted.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Alias deleted. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
private static async Task<string> GetAuthorizationHeaderAsync()
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -33,21 +33,25 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Azure.Management.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Azure.Management.ServiceBus.1.0.2\lib\net452\Microsoft.Azure.Management.ServiceBus.dll</HintPath>
|
||||
<HintPath>packages\Microsoft.Azure.Management.ServiceBus.1.0.2\lib\net452\Microsoft.Azure.Management.ServiceBus.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.0.27603, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.0\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.10\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.Azure.3.3.10\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
@ -57,12 +61,17 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SBGeoDR2", "SBGeoDR2.csproj", "{563A166C-792E-4C38-AEC7-ADA6F583F83F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1952A059-429C-4545-8836-86472B4698FE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Azure.Management.ServiceBus" version="1.0.2" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.0" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.2" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime" version="2.3.10" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.10" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
</packages>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
<appSettings>
|
||||
|
||||
<!-- Use the following link to learn how to setup an client app in access Active Directory
|
||||
and grant that app rights to your azure subscription
|
||||
https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
Respectively follow this: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
|
||||
To get the below three values. Make sure to add the application as owner in your resource group via "Access control (IAM)". -->
|
||||
|
||||
<add key="tenantId" value="" /> <!-- Directory ID in portal -->
|
||||
<add key="clientId" value="" /> <!-- Application ID in portal -->
|
||||
<add key="subscriptionId" value="" /> <!-- Pick existing subscription -->
|
||||
<add key="resourceGroupName" value="" /> <!-- Pick existing resource group, make sure your aad app is added as owner of the resource group. -->
|
||||
<add key="activeDirectoryAuthority" value="https://login.microsoftonline.com" />
|
||||
<add key="resourceManagerUrl" value="https://management.azure.com/" />
|
||||
<add key="clientSecret" value="" /> <!-- Key in portal -->
|
||||
<add key="geoDRPrimaryNS" value="" />
|
||||
<add key="geoDRSecondaryNS" value="" />
|
||||
<add key="alias" value="" />
|
||||
<!-- This field should be your primary namespace name or can be empty as your primary namespace name will be your alias. -->
|
||||
<add key="alternatePrimaryName" value="" /> <!-- This represents your new namespace name. -->
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -0,0 +1,226 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Configuration;
|
||||
using Microsoft.Azure.Management.ServiceBus;
|
||||
using Microsoft.Azure.Management.ServiceBus.Models;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using Microsoft.Rest;
|
||||
|
||||
namespace SBGeoDR2
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static readonly string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
|
||||
static readonly string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
|
||||
static readonly string activeDirectoryAuthority = ConfigurationManager.AppSettings["activeDirectoryAuthority"];
|
||||
static readonly string resourceManagerUrl = ConfigurationManager.AppSettings["resourceManagerUrl"];
|
||||
static readonly string tenantId = ConfigurationManager.AppSettings["tenantId"];
|
||||
static readonly string clientId = ConfigurationManager.AppSettings["clientId"];
|
||||
static readonly string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
|
||||
|
||||
static readonly string geoDRPrimaryNS = ConfigurationManager.AppSettings["geoDRPrimaryNS"];
|
||||
static readonly string geoDRSecondaryNS = ConfigurationManager.AppSettings["geoDRSecondaryNS"];
|
||||
static readonly string alias = ConfigurationManager.AppSettings["alias"];
|
||||
static readonly string alternateName = ConfigurationManager.AppSettings["alternatePrimaryName"];
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
//MainAsync().GetAwaiter().GetResult();
|
||||
|
||||
Console.WriteLine ("Choose an action:");
|
||||
Console.WriteLine ("[A] Create or update namespaces, pair them and create a few entities");
|
||||
Console.WriteLine ("[B] Failover");
|
||||
Console.WriteLine ("[C] Break pairing");
|
||||
Console.WriteLine ("[D] Delete Alias after Failover.");
|
||||
|
||||
Char key = Console.ReadKey(true).KeyChar;
|
||||
String keyPressed = key.ToString().ToUpper();
|
||||
|
||||
switch (keyPressed)
|
||||
{
|
||||
case "A":
|
||||
CreatePairing().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "B":
|
||||
ExecuteFailover().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "C":
|
||||
BreakPairing().GetAwaiter().GetResult();
|
||||
break;
|
||||
case "D":
|
||||
DeleteAliasSec().GetAwaiter().GetResult();
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Unknown command, press enter to exit");
|
||||
Console.ReadLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static async Task CreatePairing()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// 1. Create Primary Namespace (optional)
|
||||
Console.WriteLine("Create or update namespace 1");
|
||||
var namespaceParams = new SBNamespace
|
||||
{
|
||||
Location = "South Central US",
|
||||
Sku = new SBSku
|
||||
{
|
||||
Name = SkuName.Premium,
|
||||
Capacity = 1
|
||||
}
|
||||
};
|
||||
var namespace1 = await client.Namespaces.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, namespaceParams)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// 2. Create Secondary Namespace (optional if you already have an empty namespace available)
|
||||
Console.WriteLine("Create or update namespace 2");
|
||||
var namespaceParams2 = new SBNamespace
|
||||
{
|
||||
Location = "North Central US",
|
||||
Sku = new SBSku
|
||||
{
|
||||
Name = SkuName.Premium,
|
||||
Capacity = 1
|
||||
}
|
||||
};
|
||||
|
||||
// If you re-run this program while namespaces are still paired this operation will fail with a bad request.
|
||||
// this is because we block all updates on secondary namespaces once it is paired
|
||||
var namespace2 = await client.Namespaces.CreateOrUpdateAsync(resourceGroupName, geoDRSecondaryNS, namespaceParams2)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// 3. Pair the namespaces to enable DR.
|
||||
Console.WriteLine("Starting Pairing");
|
||||
ArmDisasterRecovery drStatus = await client.DisasterRecoveryConfigs.CreateOrUpdateAsync(
|
||||
resourceGroupName,
|
||||
geoDRPrimaryNS,
|
||||
alias,
|
||||
new ArmDisasterRecovery { PartnerNamespace = namespace2.Id, AlternateName = alternateName })
|
||||
// Note: The additional, optional parameter AlternateName is resposible for using the namespace name as alias and renaming the primary namespace.
|
||||
.ConfigureAwait(false);
|
||||
|
||||
while (drStatus.ProvisioningState != ProvisioningStateDR.Succeeded)
|
||||
{
|
||||
Console.WriteLine("Waiting for DR to be setup. Current State: " + drStatus.ProvisioningState);
|
||||
|
||||
drStatus = client.DisasterRecoveryConfigs.Get(
|
||||
resourceGroupName,
|
||||
geoDRPrimaryNS,
|
||||
alias);
|
||||
|
||||
Thread.CurrentThread.Join(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
Console.WriteLine("Creating test entities to show pairing.");
|
||||
await client.Topics.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, "myTopic", new SBTopic())
|
||||
.ConfigureAwait(false);
|
||||
await client.Subscriptions.CreateOrUpdateAsync(resourceGroupName, geoDRPrimaryNS, "myTopic", "myTopic-Sub1", new SBSubscription())
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Sleeping to allow metadata to sync across primary and secondary
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
|
||||
Console.WriteLine("Initial setup complete. Please see in the portal if all resources have been created as expected.");
|
||||
Console.WriteLine("Try creating a few additional entities in the primary in the portal.");
|
||||
Console.WriteLine("Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task ExecuteFailover()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// Failover. Note that this Failover operations is ALWAYS run against the secondary ( because primary might be down at time of failover )
|
||||
Console.WriteLine("Initiating failover. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.FailOver(resourceGroupName, geoDRSecondaryNS, alias);
|
||||
|
||||
// Sleeping to allow the break pairing to happen
|
||||
Console.WriteLine("Waiting for failover to complete.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Failover Complete, press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task BreakPairing()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// Break Pairing
|
||||
Console.WriteLine("Disabling pairing. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.BreakPairing(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
|
||||
// sleeping to allow the break pairing to happen
|
||||
Console.WriteLine("Waiting for break pairing to complete.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Break pairing complete. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task DeleteAliasPrim()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
Console.WriteLine("Deleting the alias. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.Delete(resourceGroupName, geoDRPrimaryNS, alias);
|
||||
|
||||
Console.WriteLine("Wait for the alias to be deleted.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Alias deleted. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
static async Task DeleteAliasSec()
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
string token = await GetAuthorizationHeaderAsync().ConfigureAwait(false);
|
||||
|
||||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
Console.WriteLine("Deleting the alias. Management operations can take 1-2 minutes to take effect.");
|
||||
client.DisasterRecoveryConfigs.Delete(resourceGroupName, geoDRSecondaryNS, alias);
|
||||
|
||||
Console.WriteLine("Wait for the alias to be deleted.");
|
||||
await Task.Delay(TimeSpan.FromSeconds(60));
|
||||
Console.WriteLine("Alias deleted. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
private static async Task<string> GetAuthorizationHeaderAsync()
|
||||
{
|
||||
var context = new AuthenticationContext($"{activeDirectoryAuthority}/{tenantId}");
|
||||
|
||||
var result = await context.AcquireTokenAsync(
|
||||
resourceManagerUrl,
|
||||
new ClientCredential(clientId, clientSecret))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to obtain the JWT token.");
|
||||
}
|
||||
|
||||
return result.AccessToken;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{563A166C-792E-4C38-AEC7-ADA6F583F83F}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SBGeoDR2</RootNamespace>
|
||||
<AssemblyName>SBGeoDR2</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Azure.Management.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Azure.Management.ServiceBus.1.0.3\lib\net452\Microsoft.Azure.Management.ServiceBus.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.Azure.3.3.10\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SBGeoDR2_existing_namespace_name", "SBGeoDR2_existing_namespace_name.csproj", "{563A166C-792E-4C38-AEC7-ADA6F583F83F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{563A166C-792E-4C38-AEC7-ADA6F583F83F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1952A059-429C-4545-8836-86472B4698FE}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Azure.Management.ServiceBus" version="1.0.3" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.2" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime" version="2.3.10" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.10" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
</packages>
|
|
@ -3,4 +3,40 @@
|
|||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
<appSettings>
|
||||
|
||||
<!-- Use the following link to learn how to setup an client app in access Active Directory
|
||||
and grant that app rights to your azure subscription
|
||||
https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
Respectively follow this: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
|
||||
To get the below three values. Make sure to add the application as owner in your resource group via "Access control (IAM)". -->
|
||||
|
||||
<add key="tenantId" value="" />
|
||||
<!-- Directory ID in portal -->
|
||||
<add key="clientId" value="" />
|
||||
<!-- Application ID in portal -->
|
||||
<add key="subscriptionId" value="" />
|
||||
<!-- Pick existing subscription -->
|
||||
<add key="resourceGroupName" value="" />
|
||||
<!-- Pick existing resource group, make sure your aad app is added as owner of the resource group. -->
|
||||
<add key="activeDirectoryAuthority" value="https://login.microsoftonline.com" />
|
||||
<add key="resourceManagerUrl" value="https://management.azure.com/" />
|
||||
<add key="clientSecret" value="" />
|
||||
<!-- Key in portal -->
|
||||
<add key="geoDRPrimaryNS" value="" />
|
||||
<add key="geoDRSecondaryNS" value="" />
|
||||
<add key="alias" value="" />
|
||||
</appSettings>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Runtime.Serialization.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -1,35 +1,28 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.ServiceBus.Messaging;
|
||||
using System.Text;
|
||||
using System.Configuration;
|
||||
using Microsoft.Azure.ServiceBus;
|
||||
using Microsoft.Azure.Management.ServiceBus;
|
||||
using Microsoft.IdentityModel.Clients.ActiveDirectory;
|
||||
using Microsoft.Rest;
|
||||
|
||||
|
||||
namespace ConsoleApp1
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
static string subscriptionId = "your subscription id"; // Pick existing subscription
|
||||
static string resourceGroupName = "your resource group name"; // Pick existing resource group
|
||||
static readonly string subscriptionId = ConfigurationManager.AppSettings["subscriptionId"];
|
||||
static readonly string resourceGroupName = ConfigurationManager.AppSettings["resourceGroupName"];
|
||||
static readonly string activeDirectoryAuthority = ConfigurationManager.AppSettings["activeDirectoryAuthority"];
|
||||
static readonly string resourceManagerUrl = ConfigurationManager.AppSettings["resourceManagerUrl"];
|
||||
static readonly string tenantId = ConfigurationManager.AppSettings["tenantId"];
|
||||
static readonly string clientId = ConfigurationManager.AppSettings["clientId"];
|
||||
static readonly string clientSecret = ConfigurationManager.AppSettings["clientSecret"];
|
||||
|
||||
static string activeDirectoryAuthority = "https://login.microsoftonline.com";
|
||||
static string resourceManagerUrl = "https://management.azure.com/";
|
||||
|
||||
// Use the following link to learn how to setup an client app in access Active Directory
|
||||
// and grant that app rights to your azure subscription
|
||||
// https://msdn.microsoft.com/en-us/library/azure/dn790557.aspx#bk_portal
|
||||
// Respectively follow this: https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-service-principal-portal
|
||||
// To get the below three values. Make sure to add the application as owner in your resource group via "Access control (IAM)".
|
||||
|
||||
static string tenantId = "your tenant / directory id"; // Directory ID in portal
|
||||
static string clientId = "your client / application id"; //Application ID in portal
|
||||
static string clientSecret = "your clientSecret / key"; // Key in portal
|
||||
|
||||
|
||||
static string geoDRPrimaryNS = "your primary ns";
|
||||
static string geoDRSecondaryNS = "your secondary ns";
|
||||
static string alias = "your alias";
|
||||
static readonly string geoDRPrimaryNS = ConfigurationManager.AppSettings["geoDRPrimaryNS"];
|
||||
static readonly string geoDRSecondaryNS = ConfigurationManager.AppSettings["geoDRSecondaryNS"];
|
||||
static readonly string alias = ConfigurationManager.AppSettings["alias"];
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
|
@ -44,30 +37,50 @@ namespace ConsoleApp1
|
|||
TokenCredentials creds = new TokenCredentials(token);
|
||||
ServiceBusManagementClient client = new ServiceBusManagementClient(creds) { SubscriptionId = subscriptionId };
|
||||
|
||||
// Get alias connstring and Create Service and Consumer Groups
|
||||
var accessKeys = client.Namespaces.ListKeys(resourceGroupName, geoDRPrimaryNS, "RootManageSharedAccessKey");
|
||||
var aliasPrimaryConnectionString = accessKeys.AliasPrimaryConnectionString;
|
||||
var aliasSecondaryConnectionString = accessKeys.AliasSecondaryConnectionString;
|
||||
// Get alias connstring and Create Service and Consumer Groups.
|
||||
// Note: In a real world scenario you would do this operations outside of your client and then add the Alias connection strings to your client.
|
||||
String aliasPrimaryConnectionString;
|
||||
String aliasSecondaryConnectionString;
|
||||
|
||||
if(aliasPrimaryConnectionString == null)
|
||||
try
|
||||
{
|
||||
accessKeys = client.Namespaces.ListKeys(resourceGroupName, geoDRSecondaryNS, "RootManageSharedAccessKey");
|
||||
var accessKeys = client.DisasterRecoveryConfigs.ListKeys(resourceGroupName, geoDRPrimaryNS, alias, "RootManageSharedAccessKey");
|
||||
aliasPrimaryConnectionString = accessKeys.AliasPrimaryConnectionString;
|
||||
aliasSecondaryConnectionString = accessKeys.AliasSecondaryConnectionString;
|
||||
|
||||
}
|
||||
catch
|
||||
{
|
||||
var accessKeys = client.DisasterRecoveryConfigs.ListKeys(resourceGroupName, geoDRSecondaryNS, alias, "RootManageSharedAccessKey");
|
||||
aliasPrimaryConnectionString = accessKeys.AliasPrimaryConnectionString;
|
||||
aliasSecondaryConnectionString = accessKeys.AliasSecondaryConnectionString;
|
||||
}
|
||||
|
||||
var connectionString = aliasPrimaryConnectionString;
|
||||
}
|
||||
|
||||
var ServiceBusConnectionString = aliasPrimaryConnectionString;
|
||||
var topicName = "mytopic";
|
||||
|
||||
var clientSR = TopicClient.CreateFromConnectionString(connectionString, topicName);
|
||||
var message = new BrokeredMessage("This is a test message!");
|
||||
var topicClient = new TopicClient(ServiceBusConnectionString,topicName);
|
||||
try
|
||||
{
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
// Create a new message to send to the queue
|
||||
string messageBody = $"Message {i}";
|
||||
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
|
||||
|
||||
Console.WriteLine($"Message id: {message.MessageId}");
|
||||
// Write the body of the message to the console
|
||||
Console.WriteLine($"Sending message: {messageBody}");
|
||||
|
||||
await clientSR.SendAsync(message)
|
||||
.ConfigureAwait(false);
|
||||
// Send the message to the queue
|
||||
await topicClient.SendAsync(message);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Console.WriteLine($"{DateTime.Now} :: Exception: {exception.Message}");
|
||||
}
|
||||
|
||||
Console.WriteLine("Message successfully sent! Press ENTER to exit program");
|
||||
Console.WriteLine("Sending done. Press enter to exit.");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
|
@ -32,29 +32,64 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Azure.Management.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Azure.Management.ServiceBus.1.0.2\lib\net452\Microsoft.Azure.Management.ServiceBus.dll</HintPath>
|
||||
<Reference Include="Microsoft.Azure.Amqp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Azure.Amqp.2.1.2\lib\net45\Microsoft.Azure.Amqp.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.0.27603, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.0\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
<Reference Include="Microsoft.Azure.Management.ServiceBus, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Azure.Management.ServiceBus.1.0.3\lib\net452\Microsoft.Azure.Management.ServiceBus.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Azure.ServiceBus, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7e34167dcc6d6d8c, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.Azure.ServiceBus.2.0.0\lib\net461\Microsoft.Azure.ServiceBus.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.17.2.31801, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.17.2\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Rest.ClientRuntime.Azure, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Rest.ClientRuntime.Azure.3.3.10\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.ServiceBus, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WindowsAzure.ServiceBus.4.1.3\lib\net45\Microsoft.ServiceBus.dll</HintPath>
|
||||
<HintPath>packages\Microsoft.Rest.ClientRuntime.Azure.3.3.10\lib\net452\Microsoft.Rest.ClientRuntime.Azure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
<HintPath>packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.WebSockets, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Net.WebSockets.4.0.0\lib\net46\System.Net.WebSockets.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.WebSockets.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Net.WebSockets.Client.4.0.0\lib\net46\System.Net.WebSockets.Client.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Runtime.Serialization.Primitives, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.Serialization.Primitives.4.3.0\lib\net46\System.Runtime.Serialization.Primitives.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization.Xml, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Runtime.Serialization.Xml.4.3.0\lib\net46\System.Runtime.Serialization.Xml.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Algorithms.4.2.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Encoding.4.0.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.Primitives.4.0.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>packages\System.Security.Cryptography.X509Certificates.4.1.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
|
@ -66,7 +101,9 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="App.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2006
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestGeoDR", "TestGeoDR.csproj", "{382CAB58-435E-4EE6-97CD-CCD8AC09C21B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{382CAB58-435E-4EE6-97CD-CCD8AC09C21B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{382CAB58-435E-4EE6-97CD-CCD8AC09C21B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{382CAB58-435E-4EE6-97CD-CCD8AC09C21B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{382CAB58-435E-4EE6-97CD-CCD8AC09C21B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E192456B-47B8-4887-B6B1-6C694D83B491}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -1,9 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Azure.Management.ServiceBus" version="1.0.2" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.0" targetFramework="net461" />
|
||||
<package id="Microsoft.Azure.Amqp" version="2.1.2" targetFramework="net461" />
|
||||
<package id="Microsoft.Azure.Management.ServiceBus" version="1.0.3" targetFramework="net461" />
|
||||
<package id="Microsoft.Azure.ServiceBus" version="2.0.0" targetFramework="net461" />
|
||||
<package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.17.2" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime" version="2.3.10" targetFramework="net461" />
|
||||
<package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.10" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net461" />
|
||||
<package id="WindowsAzure.ServiceBus" version="4.1.3" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
|
||||
<package id="System.Net.WebSockets" version="4.0.0" targetFramework="net461" />
|
||||
<package id="System.Net.WebSockets.Client" version="4.0.0" targetFramework="net461" />
|
||||
<package id="System.Runtime.Serialization.Primitives" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Runtime.Serialization.Xml" version="4.3.0" targetFramework="net461" />
|
||||
<package id="System.Security.Cryptography.Algorithms" version="4.2.0" targetFramework="net461" />
|
||||
<package id="System.Security.Cryptography.Encoding" version="4.0.0" targetFramework="net461" />
|
||||
<package id="System.Security.Cryptography.Primitives" version="4.0.0" targetFramework="net461" />
|
||||
<package id="System.Security.Cryptography.X509Certificates" version="4.1.0" targetFramework="net461" />
|
||||
</packages>
|
Загрузка…
Ссылка в новой задаче