Skip to content
This repository has been archived by the owner on Oct 12, 2023. It is now read-only.

Management Operations #481

Merged
merged 106 commits into from
Jun 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
dc32047
queuedescription
makam May 15, 2018
68e4611
Added public Interfaces and methods
makam May 15, 2018
6547e6e
New changes
makam May 16, 2018
7419e34
Changing API structure.
makam May 17, 2018
b30308d
Base format for ManagementClient.
makam May 22, 2018
9df26fc
CreateQueue
makam May 30, 2018
4e5a152
topic and subscription
makam May 31, 2018
974b4d1
Merge branch 'dev' into management
makam May 31, 2018
9e539f2
Runtime no longer part of Description
makam May 31, 2018
cdd6462
Separated runtime info
makam May 31, 2018
ccc0f0e
Minor cleanup
makam May 31, 2018
1daa59d
Removing redundant overloads
makam Jun 1, 2018
df2ba4e
Test cleanup
makam Jun 1, 2018
f3ac2f0
GetEntity + Added basic error handling
makam Jun 1, 2018
c043dea
Rules and filter parsing
makam Jun 1, 2018
fc94c01
GetRule
makam Jun 1, 2018
29fd5ff
BasicQueueCrudTest
makam Jun 6, 2018
1fbfba0
Moved constants to ManagementConstants.cs
makam Jun 6, 2018
03d2e58
CRUD test for topic and subscription
makam Jun 7, 2018
fde7cc9
Q/T/S runtime info tests
makam Jun 7, 2018
218f964
GetEntity + ExistsEntity tests
makam Jun 7, 2018
8f824a9
Updated Error handling
makam Jun 8, 2018
ff226f8
MessagingEntityAlreadyExistsExceptionTest +
makam Jun 8, 2018
da02dd6
Input validation for descriptions
makam Jun 8, 2018
6bab7ef
Merge branch 'dev' into management
makam Jun 9, 2018
ba73a93
CRUD for rules
makam Jun 11, 2018
8561521
Cleanup
makam Jun 11, 2018
6e8445d
Implemented forwardTo and DLQForwardTo
makam Jun 12, 2018
aeadc08
AuthorizationRules
makam Jun 15, 2018
f58c996
Changing MaxSizeInGB to MaxSizeInMB to support finer allocation
makam Jun 15, 2018
bb84e39
Renaming ManagementConstants to ManagementClientConstants.
makam Jun 15, 2018
658921d
Wrapping operations within retry policy
makam Jun 15, 2018
69d9fd2
Passing skip and top query params
makam Jun 15, 2018
f035b1a
Performance tweaks (#491)
SeanFeldman Jun 18, 2018
b618f04
Merge branch 'dev' into management
nemakam Jun 18, 2018
b5d15ec
Add option to dispose management client
SeanFeldman Jun 15, 2018
04269fc
Extract functionality exposed by EntityClient into internal client an…
SeanFeldman Jun 15, 2018
c3d5b88
Remove entity client from ManagementClient entirely.
SeanFeldman Jun 17, 2018
80de4bc
TokenProvider should come first if the catch-all overload has it first
SeanFeldman Jun 17, 2018
ae8ea7e
Move extensions on QueueDescription to QueueDescriptionExtensions. Do…
SeanFeldman Jun 18, 2018
a433688
Move extensions on TopicDescription to TopicDescriptionExtensions. Do…
SeanFeldman Jun 18, 2018
8dc7e29
Move extensions on SubscriptionDescription to SubscriptionDescription…
SeanFeldman Jun 18, 2018
cf5e2aa
Add comment about TopicDescription equality issue
SeanFeldman Jun 18, 2018
0699dcf
Move extensions on RuleDescription to RuleDescriptionExtensions. Do n…
SeanFeldman Jun 18, 2018
0936195
Move extensions on Filter extensions to the appropreate extensions. T…
SeanFeldman Jun 18, 2018
8e5a1c9
Remove unnecessary serialization that is handled by SqlFilter.
SeanFeldman Jun 18, 2018
d2fa85c
Remove FalseFilter.Default as it's never used as a default anywhere
SeanFeldman Jun 18, 2018
a8ccbb4
Complete move of filter related extensions out of Filter
SeanFeldman Jun 18, 2018
e7baae9
Move RuleAction extentions into RuleActionExtensions
SeanFeldman Jun 18, 2018
85b3453
Make equality safe
SeanFeldman Jun 18, 2018
5621952
Decouple *-Description from ManagementClient by moving entity name va…
SeanFeldman Jun 18, 2018
6277bd3
ManagementClient.GetToken should not be public
SeanFeldman Jun 18, 2018
79c97c8
Simplify setters for null lcases
SeanFeldman Jun 18, 2018
f8293d2
Initialize retryPolicy with default if custom is not provided
SeanFeldman Jun 18, 2018
8f29918
Test should use the public contract
SeanFeldman Jun 18, 2018
92d2337
Add missing method to the contract
SeanFeldman Jun 18, 2018
0a985e6
Approve public API
SeanFeldman Jun 18, 2018
adcb9eb
Resolve conflicts
SeanFeldman Jun 18, 2018
be65410
Serialize TrueFilter and FalseFilter with their specific type, not as…
SeanFeldman Jun 18, 2018
ed23a92
Merge pull request #493 from SeanFeldman/management-client-is-not-an-…
nemakam Jun 18, 2018
edf05e1
Default rule while creating subscription
makam Jun 18, 2018
61f6d5a
Resolving merge conflict
makam Jun 18, 2018
22b9e4a
Resolving merge conflict (2)
makam Jun 18, 2018
6c0a0dd
Clarify exception message
SeanFeldman Jun 18, 2018
9dde761
Merge pull request #495 from SeanFeldman/clarify-exception-message
nemakam Jun 18, 2018
0355aaf
Adding param support for SqlFilter and CorrelationFilter
makam Jun 19, 2018
f617b33
Merge branch 'management' of https://github.com/Azure/azure-service-b…
makam Jun 19, 2018
2964089
Minor cleanup - copyrights + unused namespaces
makam Jun 19, 2018
480d51f
Move parsing outside of *-RuntimeInfo similar to *-Description
SeanFeldman Jun 19, 2018
0e588f2
Remove unused methods
SeanFeldman Jun 19, 2018
b6dce66
Resolve rebase conflict
SeanFeldman Jun 19, 2018
6d5a421
Update public API
SeanFeldman Jun 19, 2018
cbd28da
Namespace cleanups
SeanFeldman Jun 19, 2018
530d550
Merge pull request #497 from SeanFeldman/keep-runtime-infos-simple
nemakam Jun 19, 2018
dd6fa16
Cleanup
makam Jun 19, 2018
d4a497e
Few input validations and removing TODOs
makam Jun 19, 2018
316aea3
overriding GetHashCode() and Equals(object)
makam Jun 19, 2018
42aabef
overriding == and !=
makam Jun 19, 2018
05c9d01
Added logging
makam Jun 20, 2018
c496708
removing "else"
makam Jun 20, 2018
b6b54fc
Minor cleanup
makam Jun 20, 2018
b6f1159
Fixing build
SeanFeldman Jun 20, 2018
9da79c2
Approving API
SeanFeldman Jun 20, 2018
2572f76
Merge pull request #503 from SeanFeldman/fixing-build
nemakam Jun 20, 2018
0398102
Adding EnableBatchedOperations on subscriptionClient
makam Jun 21, 2018
b815626
Merge branch 'management' of https://github.com/Azure/azure-service-b…
makam Jun 21, 2018
edfa095
Adding UserMetadata property in each of the entity descriptions
makam Jun 22, 2018
c599e1f
Example
SeanFeldman Jun 20, 2018
c8073ab
Document create methods
SeanFeldman Jun 22, 2018
77f359b
Document delete methods
SeanFeldman Jun 22, 2018
700d6d1
Merge pull request #504 from SeanFeldman/xmldoco
nemakam Jun 22, 2018
3bda038
Added xml docs to ManagementClient
makam Jun 23, 2018
f486422
Xml docs for queue/topic/subscription description
makam Jun 23, 2018
afd5249
Removing IManagementClient and making all methods virtual
makam Jun 23, 2018
cc5e92d
Added xml docs to runtimeInfo classes + few other classes
makam Jun 23, 2018
87823ff
Merge branch 'dev' into management
makam Jun 23, 2018
d206610
Merge branch 'dev' into management
nemakam Jun 23, 2018
8da458c
Made default retrypolicy as None for managementClient
makam Jun 26, 2018
8fa70cf
Merge branch 'management' of https://github.com/Azure/azure-service-b…
makam Jun 26, 2018
799a0a3
Merge branch 'dev' into management
nemakam Jun 26, 2018
c2944eb
Fixing rules test
makam Jun 26, 2018
b551a5d
Removing RetryPolicy from ManagementClient
makam Jun 27, 2018
e72613a
Updating API
makam Jun 27, 2018
e92dc6d
Removing dead code
makam Jun 27, 2018
8f2f4a6
minor cleanup
makam Jun 28, 2018
6febadc
Changing default duplicate time window to 1 min
makam Jun 28, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/Microsoft.Azure.ServiceBus/Amqp/AmqpMessageConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -379,10 +379,9 @@ public static RuleDescription GetRuleDescription(AmqpRuleDescriptionCodec amqpDe
var filter = GetFilter(amqpDescription.Filter);
var ruleAction = GetRuleAction(amqpDescription.Action);

var ruleDescription = new RuleDescription(filter)
var ruleDescription = new RuleDescription(amqpDescription.RuleName, filter)
{
Action = ruleAction,
Name = amqpDescription.RuleName
Action = ruleAction
};

return ruleDescription;
Expand Down
79 changes: 77 additions & 2 deletions src/Microsoft.Azure.ServiceBus/EntityNameHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@

namespace Microsoft.Azure.ServiceBus
{
using System;
using Microsoft.Azure.ServiceBus.Management;

/// <summary>
/// This class can be used to format the path for different Service Bus entity types.
/// </summary>
public static class EntityNameHelper
{
private const string PathDelimiter = @"/";
private const string Subscriptions = "Subscriptions";
private const string SubscriptionsSubPath = "Subscriptions";
private const string RulesSubPath = "Rules";
private const string SubQueuePrefix = "$";
private const string DeadLetterQueueSuffix = "DeadLetterQueue";
private const string DeadLetterQueueName = SubQueuePrefix + DeadLetterQueueSuffix;
Expand Down Expand Up @@ -40,9 +44,25 @@ public static string FormatSubQueuePath(string entityPath, string subQueueName)
/// Formats the subscription path, based on the topic path and subscription name.
/// </summary>
/// <param name="topicPath">The name of the topic, including slashes.</param>
/// <param name="subscriptionName">The name of the subscription.</param>
public static string FormatSubscriptionPath(string topicPath, string subscriptionName)
{
return string.Concat(topicPath, PathDelimiter, Subscriptions, PathDelimiter, subscriptionName);
return string.Concat(topicPath, PathDelimiter, SubscriptionsSubPath, PathDelimiter, subscriptionName);
}

/// <summary>
/// Formats the rule path, based on the topic path and subscription name.
/// </summary>
/// <param name="topicPath">The name of the topic, including slashes.</param>
/// <param name="subscriptionName">The name of the subscription.</param>
/// <param name="ruleName">The name of the rule</param>
public static string FormatRulePath(string topicPath, string subscriptionName, string ruleName)
{
return string.Concat(
topicPath, PathDelimiter,
SubscriptionsSubPath, PathDelimiter,
subscriptionName, PathDelimiter,
RulesSubPath, PathDelimiter, ruleName);
}

/// <summary>
Expand All @@ -52,5 +72,60 @@ public static string FormatSubscriptionPath(string topicPath, string subscriptio
{
return string.Concat(entityPath, PathDelimiter, TransferDeadLetterQueueName);
}

internal static void CheckValidQueueName(string queueName, string paramName = "queuePath")
{
CheckValidEntityName(queueName, ManagementClientConstants.QueueNameMaximumLength, true, paramName);
}

internal static void CheckValidTopicName(string topicName, string paramName = "topicPath")
{
CheckValidEntityName(topicName, ManagementClientConstants.TopicNameMaximumLength, true, paramName);
}

internal static void CheckValidSubscriptionName(string subscriptionName, string paramName = "subscriptionName")
{
CheckValidEntityName(subscriptionName, ManagementClientConstants.SubscriptionNameMaximumLength, false, paramName);
}

internal static void CheckValidRuleName(string ruleName, string paramName = "ruleName")
{
CheckValidEntityName(ruleName, ManagementClientConstants.RuleNameMaximumLength, false, paramName);
}

private static void CheckValidEntityName(string entityName, int maxEntityNameLength, bool allowSeparator, string paramName)
{
if (string.IsNullOrWhiteSpace(entityName))
{
throw new ArgumentNullException(paramName);
}

// and "\" will be converted to "/" on the REST path anyway. Gateway/REST do not
// have to worry about the begin/end slash problem, so this is purely a client side check.
var tmpName = entityName.Replace(@"\", Constants.PathDelimiter);
if (tmpName.Length > maxEntityNameLength)
{
throw new ArgumentOutOfRangeException(paramName, $@"Entity path '{entityName}' exceeds the '{maxEntityNameLength}' character limit.");
}

if (tmpName.StartsWith(Constants.PathDelimiter, StringComparison.OrdinalIgnoreCase) ||
tmpName.EndsWith(Constants.PathDelimiter, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException($@"The entity name/path cannot contain '/' as prefix or suffix. The supplied value is '{entityName}'", paramName);
}

if (!allowSeparator && tmpName.Contains(Constants.PathDelimiter))
{
throw new ArgumentException($@"The entity name/path contains an invalid character '{Constants.PathDelimiter}'", paramName);
}

foreach (var uriSchemeKey in ManagementClientConstants.InvalidEntityPathCharacters)
{
if (entityName.IndexOf(uriSchemeKey) >= 0)
{
throw new ArgumentException($@"'{entityName}' contains character '{uriSchemeKey}' which is not allowed because it is reserved in the Uri scheme.", paramName);
}
}
}
}
}
82 changes: 81 additions & 1 deletion src/Microsoft.Azure.ServiceBus/Filters/CorrelationFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Microsoft.Azure.ServiceBus
{
using System;
using System.Collections.Generic;
using System.Text;
using Primitives;
Expand All @@ -29,7 +30,7 @@ namespace Microsoft.Azure.ServiceBus
/// </remarks>
public sealed class CorrelationFilter : Filter
{
private PropertyDictionary properties;
internal PropertyDictionary properties;

/// <summary>
/// Initializes a new instance of the <see cref="CorrelationFilter" /> class with default values.
Expand Down Expand Up @@ -197,5 +198,84 @@ void AppendPropertyExpression(ref bool firstExpression, StringBuilder builder, s
builder.AppendFormat("{0} = '{1}'", propertyName, value);
}
}

public override int GetHashCode()
{
int hash = 13;
unchecked
{
hash = (hash * 7) + this.CorrelationId?.GetHashCode() ?? 0;
hash = (hash * 7) + this.MessageId?.GetHashCode() ?? 0;
hash = (hash * 7) + this.SessionId?.GetHashCode() ?? 0;
}

return hash;
}

public override bool Equals(object obj)
{
var other = obj as CorrelationFilter;
return this.Equals(other);
}

public override bool Equals(Filter other)
{
if (other is CorrelationFilter correlationFilter)
{
if (string.Equals(this.CorrelationId, correlationFilter.CorrelationId, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.MessageId, correlationFilter.MessageId, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.To, correlationFilter.To, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.ReplyTo, correlationFilter.ReplyTo, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.Label, correlationFilter.Label, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.SessionId, correlationFilter.SessionId, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.ReplyToSessionId, correlationFilter.ReplyToSessionId, StringComparison.OrdinalIgnoreCase)
&& string.Equals(this.ContentType, correlationFilter.ContentType, StringComparison.OrdinalIgnoreCase)
&& (this.properties != null && correlationFilter.properties != null
|| this.properties == null && correlationFilter.properties == null))
{
if (this.properties != null)
{
if (this.properties.Count != correlationFilter.properties.Count)
{
return false;
}

foreach (var param in this.properties)
{
if (!correlationFilter.properties.TryGetValue(param.Key, out var otherParamValue) ||
(param.Value == null ^ otherParamValue == null) ||
(param.Value != null && !param.Value.Equals(otherParamValue)))
{
return false;
}
}
}

return true;
}
}

return false;
}

public static bool operator == (CorrelationFilter o1, CorrelationFilter o2)
{
if (ReferenceEquals(o1, o2))
{
return true;
}

if (ReferenceEquals(o1, null) || ReferenceEquals(o2, null))
{
return false;
}

return o1.Equals(o2);
}

public static bool operator != (CorrelationFilter p1, CorrelationFilter p2)
{
return !(p1 == p2);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.Azure.ServiceBus
{
using System.Xml.Linq;
using Microsoft.Azure.ServiceBus.Filters;
using Microsoft.Azure.ServiceBus.Management;

internal static class CorrelationFilterExtensions
{
public static Filter ParseFromXElement(XElement xElement)
{
var correlationFilter = new CorrelationFilter();
foreach (var element in xElement.Elements())
{
switch (element.Name.LocalName)
{
case "CorrelationId":
correlationFilter.CorrelationId = element.Value;
break;
case "MessageId":
correlationFilter.MessageId = element.Value;
break;
case "To":
correlationFilter.To = element.Value;
break;
case "ReplyTo":
correlationFilter.ReplyTo = element.Value;
break;
case "Label":
correlationFilter.Label = element.Value;
break;
case "SessionId":
correlationFilter.SessionId = element.Value;
break;
case "ReplyToSessionId":
correlationFilter.ReplyToSessionId = element.Value;
break;
case "ContentType":
correlationFilter.ContentType = element.Value;
break;
case "Properties":
foreach (var prop in element.Elements(XName.Get("KeyValueOfstringanyType", ManagementClientConstants.SbNs)))
{
var key = prop.Element(XName.Get("Key", ManagementClientConstants.SbNs))?.Value;
var value = XmlObjectConvertor.ParseValueObject(prop.Element(XName.Get("Value", ManagementClientConstants.SbNs)));
correlationFilter.Properties.Add(key, value);
}
break;
default:
MessagingEventSource.Log.ManagementSerializationException(
$"{nameof(CorrelationFilterExtensions)}_{nameof(ParseFromXElement)}",
element.ToString());
break;
}
}

return correlationFilter;
}

public static XElement Serialize(this CorrelationFilter filter)
{
XElement parameterElement = null;
if (filter.properties != null)
{
parameterElement = new XElement(XName.Get("Properties", ManagementClientConstants.SbNs));
foreach (var param in filter.properties)
{
parameterElement.Add(
new XElement(XName.Get("KeyValueOfstringanyType", ManagementClientConstants.SbNs),
new XElement(XName.Get("Key", ManagementClientConstants.SbNs), param.Key),
XmlObjectConvertor.SerializeObject(param.Value)));
}
}

return new XElement(
XName.Get("Filter", ManagementClientConstants.SbNs),
new XAttribute(XName.Get("type", ManagementClientConstants.XmlSchemaInstanceNs), nameof(CorrelationFilter)),
string.IsNullOrWhiteSpace(filter.CorrelationId) ? null :
new XElement(XName.Get("CorrelationId", ManagementClientConstants.SbNs), filter.CorrelationId),
string.IsNullOrWhiteSpace(filter.MessageId) ? null :
new XElement(XName.Get("MessageId", ManagementClientConstants.SbNs), filter.MessageId),
string.IsNullOrWhiteSpace(filter.To) ? null :
new XElement(XName.Get("To", ManagementClientConstants.SbNs), filter.To),
string.IsNullOrWhiteSpace(filter.ReplyTo) ? null :
new XElement(XName.Get("ReplyTo", ManagementClientConstants.SbNs), filter.ReplyTo),
string.IsNullOrWhiteSpace(filter.Label) ? null :
new XElement(XName.Get("Label", ManagementClientConstants.SbNs), filter.Label),
string.IsNullOrWhiteSpace(filter.SessionId) ? null :
new XElement(XName.Get("SessionId", ManagementClientConstants.SbNs), filter.SessionId),
string.IsNullOrWhiteSpace(filter.ReplyToSessionId) ? null :
new XElement(XName.Get("ReplyToSessionId", ManagementClientConstants.SbNs), filter.ReplyToSessionId),
string.IsNullOrWhiteSpace(filter.ContentType) ? null :
new XElement(XName.Get("ContentType", ManagementClientConstants.SbNs), filter.ContentType),
parameterElement);
}
}
}
37 changes: 35 additions & 2 deletions src/Microsoft.Azure.ServiceBus/Filters/FalseFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ namespace Microsoft.Azure.ServiceBus
/// </summary>
public sealed class FalseFilter : SqlFilter
{
internal static readonly FalseFilter Default = new FalseFilter();

/// <summary>
/// Initializes a new instance of the <see cref="FalseFilter" /> class.
/// </summary>
Expand All @@ -26,5 +24,40 @@ public override string ToString()
{
return "FalseFilter";
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object obj)
{
return obj is FalseFilter;
}

public override bool Equals(Filter other)
{
return other is FalseFilter;
}

public static bool operator ==(FalseFilter o1, FalseFilter o2)
{
if (ReferenceEquals(o1, o2))
{
return true;
}

if (ReferenceEquals(o1, null) || ReferenceEquals(o2, null))
{
return false;
}

return o1.Equals(o2);
}

public static bool operator !=(FalseFilter o1, FalseFilter o2)
{
return !(o1 == o2);
}
}
}
Loading