Skip to content

Commit 9fd7319

Browse files
committed
Implement support and tests for listing load balancer usage records
1 parent 549647d commit 9fd7319

5 files changed

Lines changed: 213 additions & 10 deletions

File tree

src/corelib/Providers/Rackspace/CloudLoadBalancerProvider.cs

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,19 +981,83 @@ public Task<IEnumerable<LoadBalancer>> ListBillableLoadBalancersAsync(DateTimeOf
981981
/// <inheritdoc/>
982982
public Task<IEnumerable<LoadBalancerUsage>> ListAccountLevelUsageAsync(DateTimeOffset? startTime, DateTimeOffset? endTime, CancellationToken cancellationToken)
983983
{
984-
throw new NotImplementedException();
984+
if (endTime < startTime)
985+
throw new ArgumentOutOfRangeException("endTime");
986+
987+
UriTemplate template = new UriTemplate("/loadbalancers/usage?startTime={startTime}&endTime={endTime}");
988+
var parameters = new Dictionary<string, string>();
989+
if (startTime != null)
990+
parameters.Add("startTime", startTime.Value.ToString("yyyy-MM-dd"));
991+
if (endTime != null)
992+
parameters.Add("endTime", endTime.Value.ToString("yyyy-MM-dd"));
993+
994+
Func<Task<Tuple<IdentityToken, Uri>>, HttpWebRequest> prepareRequest =
995+
PrepareRequestAsyncFunc(HttpMethod.GET, template, parameters);
996+
997+
Func<Task<HttpWebRequest>, Task<ListLoadBalancerUsageResponse>> requestResource =
998+
GetResponseAsyncFunc<ListLoadBalancerUsageResponse>(cancellationToken);
999+
1000+
Func<Task<ListLoadBalancerUsageResponse>, IEnumerable<LoadBalancerUsage>> resultSelector =
1001+
task => (task.Result != null ? task.Result.UsageRecords : null) ?? Enumerable.Empty<LoadBalancerUsage>();
1002+
1003+
return AuthenticateServiceAsync(cancellationToken)
1004+
.ContinueWith(prepareRequest)
1005+
.ContinueWith(requestResource).Unwrap()
1006+
.ContinueWith(resultSelector);
9851007
}
9861008

9871009
/// <inheritdoc/>
988-
public Task<IEnumerable<LoadBalancerUsage>> ListHistoricalUsageAsync(LoadBalancerId loadBalancerId, DateTimeOffset? startTime, DateTimeOffset? endTime, CancellationToken cancellationToken1)
1010+
public Task<IEnumerable<LoadBalancerUsage>> ListHistoricalUsageAsync(LoadBalancerId loadBalancerId, DateTimeOffset? startTime, DateTimeOffset? endTime, CancellationToken cancellationToken)
9891011
{
990-
throw new NotImplementedException();
1012+
if (loadBalancerId == null)
1013+
throw new ArgumentNullException("loadBalancerId");
1014+
if (endTime < startTime)
1015+
throw new ArgumentOutOfRangeException("endTime");
1016+
1017+
UriTemplate template = new UriTemplate("/loadbalancers/{loadBalancerId}/usage?startTime={startTime}&endTime={endTime}");
1018+
var parameters = new Dictionary<string, string> { { "loadBalancerId", loadBalancerId.Value } };
1019+
if (startTime != null)
1020+
parameters.Add("startTime", startTime.Value.ToString("yyyy-MM-dd"));
1021+
if (endTime != null)
1022+
parameters.Add("endTime", endTime.Value.ToString("yyyy-MM-dd"));
1023+
1024+
Func<Task<Tuple<IdentityToken, Uri>>, HttpWebRequest> prepareRequest =
1025+
PrepareRequestAsyncFunc(HttpMethod.GET, template, parameters);
1026+
1027+
Func<Task<HttpWebRequest>, Task<ListLoadBalancerUsageResponse>> requestResource =
1028+
GetResponseAsyncFunc<ListLoadBalancerUsageResponse>(cancellationToken);
1029+
1030+
Func<Task<ListLoadBalancerUsageResponse>, IEnumerable<LoadBalancerUsage>> resultSelector =
1031+
task => (task.Result != null ? task.Result.UsageRecords : null) ?? Enumerable.Empty<LoadBalancerUsage>();
1032+
1033+
return AuthenticateServiceAsync(cancellationToken)
1034+
.ContinueWith(prepareRequest)
1035+
.ContinueWith(requestResource).Unwrap()
1036+
.ContinueWith(resultSelector);
9911037
}
9921038

9931039
/// <inheritdoc/>
9941040
public Task<IEnumerable<LoadBalancerUsage>> ListCurrentUsageAsync(LoadBalancerId loadBalancerId, CancellationToken cancellationToken)
9951041
{
996-
throw new NotImplementedException();
1042+
if (loadBalancerId == null)
1043+
throw new ArgumentNullException("loadBalancerId");
1044+
1045+
UriTemplate template = new UriTemplate("/loadbalancers/{loadBalancerId}/usage/current");
1046+
var parameters = new Dictionary<string, string> { { "loadBalancerId", loadBalancerId.Value } };
1047+
1048+
Func<Task<Tuple<IdentityToken, Uri>>, HttpWebRequest> prepareRequest =
1049+
PrepareRequestAsyncFunc(HttpMethod.GET, template, parameters);
1050+
1051+
Func<Task<HttpWebRequest>, Task<ListLoadBalancerUsageResponse>> requestResource =
1052+
GetResponseAsyncFunc<ListLoadBalancerUsageResponse>(cancellationToken);
1053+
1054+
Func<Task<ListLoadBalancerUsageResponse>, IEnumerable<LoadBalancerUsage>> resultSelector =
1055+
task => (task.Result != null ? task.Result.UsageRecords : null) ?? Enumerable.Empty<LoadBalancerUsage>();
1056+
1057+
return AuthenticateServiceAsync(cancellationToken)
1058+
.ContinueWith(prepareRequest)
1059+
.ContinueWith(requestResource).Unwrap()
1060+
.ContinueWith(resultSelector);
9971061
}
9981062

9991063
/// <inheritdoc/>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace net.openstack.Providers.Rackspace.Objects.LoadBalancers.Response
2+
{
3+
using System.Collections.ObjectModel;
4+
using Newtonsoft.Json;
5+
6+
/// <summary>
7+
/// This models the JSON response used for the List Usage request.
8+
/// </summary>
9+
/// <seealso href="http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/List_Usage-d1e3014.html">List Usage (Rackspace Cloud Load Balancers Developer Guide - API v1.0)</seealso>
10+
/// <threadsafety static="true" instance="false"/>
11+
/// <preliminary/>
12+
[JsonObject(MemberSerialization.OptIn)]
13+
internal class ListLoadBalancerUsageResponse
14+
{
15+
#pragma warning disable 649 // Field 'fieldName' is never assigned to, and will always have its default value
16+
/// <summary>
17+
/// This is the backing field for the <see cref="UsageRecords"/> property.
18+
/// </summary>
19+
[JsonProperty("loadBalancerUsageRecords")]
20+
private LoadBalancerUsage[] _loadBalancerUsage;
21+
#pragma warning restore 649
22+
23+
/// <summary>
24+
/// Initializes a new instance of the <see cref="ListLoadBalancerUsageResponse"/> class
25+
/// during JSON deserialization.
26+
/// </summary>
27+
[JsonConstructor]
28+
protected ListLoadBalancerUsageResponse()
29+
{
30+
}
31+
32+
/// <summary>
33+
/// Gets a collection of <see cref="LoadBalancerUsage"/> objects describing the load
34+
/// balancer usage resources in a load balancer service provider.
35+
/// </summary>
36+
public ReadOnlyCollection<LoadBalancerUsage> UsageRecords
37+
{
38+
get
39+
{
40+
if (_loadBalancerUsage == null)
41+
return null;
42+
43+
return new ReadOnlyCollection<LoadBalancerUsage>(_loadBalancerUsage);
44+
}
45+
}
46+
}
47+
}

src/corelib/corelib.v3.5.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@
273273
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\NodeType.cs" />
274274
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\NodeUpdate.cs" />
275275
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Request\NamespaceDoc.cs" />
276+
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancerUsageResponse.cs" />
276277
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\NamespaceDoc.cs" />
277278
<Compile Include="Providers\Rackspace\Objects\Queues\NamespaceDoc.cs" />
278279
<Compile Include="Providers\Rackspace\Objects\Queues\Request\ClaimMessagesRequest.cs" />

src/corelib/corelib.v4.0.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@
287287
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancerNodesResponse.cs" />
288288
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancersResponse.cs" />
289289
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancerThrottlesResponse.cs" />
290+
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancerUsageResponse.cs" />
290291
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancingAlgorithmsResponse.cs" />
291292
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListLoadBalancingProtocolsResponse.cs" />
292293
<Compile Include="Providers\Rackspace\Objects\LoadBalancers\Response\ListNodeServiceEventsResponse.cs" />

src/testing/integration/Providers/Rackspace/UserLoadBalancerTests.cs

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -730,25 +730,115 @@ public async Task TestListBillableLoadBalancers()
730730
[TestMethod]
731731
[TestCategory(TestCategories.User)]
732732
[TestCategory(TestCategories.LoadBalancers)]
733-
public void TestListAccountLevelUsage()
733+
public async Task TestListAccountLevelUsage()
734734
{
735-
Assert.Inconclusive("Not yet implemented.");
735+
ILoadBalancerService provider = CreateProvider();
736+
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TestTimeout(TimeSpan.FromSeconds(60))))
737+
{
738+
IEnumerable<LoadBalancingProtocol> protocols = await provider.ListProtocolsAsync(cancellationTokenSource.Token);
739+
LoadBalancingProtocol httpProtocol = protocols.First(i => i.Name.Equals("HTTP", StringComparison.OrdinalIgnoreCase));
740+
741+
string loadBalancerName = CreateRandomLoadBalancerName();
742+
743+
LoadBalancerConfiguration configuration = new LoadBalancerConfiguration(
744+
name: loadBalancerName,
745+
nodes: null,
746+
protocol: httpProtocol,
747+
virtualAddresses: new[] { new LoadBalancerVirtualAddress(LoadBalancerVirtualAddressType.Public) },
748+
algorithm: LoadBalancingAlgorithm.RoundRobin);
749+
LoadBalancer tempLoadBalancer = await provider.CreateLoadBalancerAsync(configuration, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
750+
751+
IEnumerable<LoadBalancerUsage> usage = await provider.ListAccountLevelUsageAsync(DateTimeOffset.Now.Date.AddDays(-60), DateTimeOffset.Now.Date.AddDays(1), cancellationTokenSource.Token);
752+
Assert.IsNotNull(usage);
753+
LoadBalancerUsage[] usageRecords = usage.ToArray();
754+
if (usageRecords.Length == 0)
755+
Assert.Inconclusive("No account level usage was reported.");
756+
757+
Console.WriteLine("Account Level Usage ({0} records)", usageRecords.Length);
758+
foreach (LoadBalancerUsage usageRecord in usageRecords)
759+
Console.WriteLine(JsonConvert.SerializeObject(usageRecord, Formatting.Indented));
760+
761+
/* Cleanup
762+
*/
763+
764+
await provider.RemoveLoadBalancerAsync(tempLoadBalancer.Id, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
765+
}
736766
}
737767

738768
[TestMethod]
739769
[TestCategory(TestCategories.User)]
740770
[TestCategory(TestCategories.LoadBalancers)]
741-
public void TestListHistoricalUsage()
771+
public async Task TestListHistoricalUsage()
742772
{
743-
Assert.Inconclusive("Not yet implemented.");
773+
ILoadBalancerService provider = CreateProvider();
774+
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TestTimeout(TimeSpan.FromSeconds(60))))
775+
{
776+
IEnumerable<LoadBalancingProtocol> protocols = await provider.ListProtocolsAsync(cancellationTokenSource.Token);
777+
LoadBalancingProtocol httpProtocol = protocols.First(i => i.Name.Equals("HTTP", StringComparison.OrdinalIgnoreCase));
778+
779+
string loadBalancerName = CreateRandomLoadBalancerName();
780+
781+
LoadBalancerConfiguration configuration = new LoadBalancerConfiguration(
782+
name: loadBalancerName,
783+
nodes: null,
784+
protocol: httpProtocol,
785+
virtualAddresses: new[] { new LoadBalancerVirtualAddress(LoadBalancerVirtualAddressType.Public) },
786+
algorithm: LoadBalancingAlgorithm.RoundRobin);
787+
LoadBalancer tempLoadBalancer = await provider.CreateLoadBalancerAsync(configuration, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
788+
789+
IEnumerable<LoadBalancerUsage> usage = await provider.ListHistoricalUsageAsync(tempLoadBalancer.Id, DateTimeOffset.Now.Date.AddDays(-60), DateTimeOffset.Now.Date.AddDays(1), cancellationTokenSource.Token);
790+
Assert.IsNotNull(usage);
791+
LoadBalancerUsage[] usageRecords = usage.ToArray();
792+
if (usageRecords.Length == 0)
793+
Assert.Inconclusive("No historical usage was reported for load balancer: {0}", tempLoadBalancer.Id);
794+
795+
Console.WriteLine("Historical Load Balancer Usage ({0} records)", usageRecords.Length);
796+
foreach (LoadBalancerUsage usageRecord in usageRecords)
797+
Console.WriteLine(JsonConvert.SerializeObject(usageRecord, Formatting.Indented));
798+
799+
/* Cleanup
800+
*/
801+
802+
await provider.RemoveLoadBalancerAsync(tempLoadBalancer.Id, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
803+
}
744804
}
745805

746806
[TestMethod]
747807
[TestCategory(TestCategories.User)]
748808
[TestCategory(TestCategories.LoadBalancers)]
749-
public void TestListCurrentUsage()
809+
public async Task TestListCurrentUsage()
750810
{
751-
Assert.Inconclusive("Not yet implemented.");
811+
ILoadBalancerService provider = CreateProvider();
812+
using (CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(TestTimeout(TimeSpan.FromSeconds(60))))
813+
{
814+
IEnumerable<LoadBalancingProtocol> protocols = await provider.ListProtocolsAsync(cancellationTokenSource.Token);
815+
LoadBalancingProtocol httpProtocol = protocols.First(i => i.Name.Equals("HTTP", StringComparison.OrdinalIgnoreCase));
816+
817+
string loadBalancerName = CreateRandomLoadBalancerName();
818+
819+
LoadBalancerConfiguration configuration = new LoadBalancerConfiguration(
820+
name: loadBalancerName,
821+
nodes: null,
822+
protocol: httpProtocol,
823+
virtualAddresses: new[] { new LoadBalancerVirtualAddress(LoadBalancerVirtualAddressType.Public) },
824+
algorithm: LoadBalancingAlgorithm.RoundRobin);
825+
LoadBalancer tempLoadBalancer = await provider.CreateLoadBalancerAsync(configuration, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
826+
827+
IEnumerable<LoadBalancerUsage> usage = await provider.ListCurrentUsageAsync(tempLoadBalancer.Id, cancellationTokenSource.Token);
828+
Assert.IsNotNull(usage);
829+
LoadBalancerUsage[] usageRecords = usage.ToArray();
830+
if (usageRecords.Length == 0)
831+
Assert.Inconclusive("No current usage was reported for load balancer: {0}", tempLoadBalancer.Id);
832+
833+
Console.WriteLine("Current Load Balancer Usage ({0} records)", usageRecords.Length);
834+
foreach (LoadBalancerUsage usageRecord in usageRecords)
835+
Console.WriteLine(JsonConvert.SerializeObject(usageRecord, Formatting.Indented));
836+
837+
/* Cleanup
838+
*/
839+
840+
await provider.RemoveLoadBalancerAsync(tempLoadBalancer.Id, AsyncCompletionOption.RequestCompleted, cancellationTokenSource.Token, null);
841+
}
752842
}
753843

754844
[TestMethod]

0 commit comments

Comments
 (0)