Skip to content

Commit 2ff897d

Browse files
committed
Compute.ServerMetadata
1 parent ff97d1a commit 2ff897d

11 files changed

Lines changed: 453 additions & 1 deletion

File tree

src/corelib/Compute/v2_1/ComputeService.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,30 @@ public ComputeService(IAuthenticationProvider authenticationProvider, string reg
3636
return _computeApi.GetServerAsync<Server>(serverId, cancellationToken);
3737
}
3838

39+
/// <inheritdoc cref="ComputeApi.GetServerMetadataAsync{T}" />
40+
public Task<ServerMetadata> GetServerMetadataAsync(Identifier serverId, CancellationToken cancellationToken = default(CancellationToken))
41+
{
42+
return _computeApi.GetServerMetadataAsync<ServerMetadata>(serverId, cancellationToken);
43+
}
44+
45+
/// <inheritdoc cref="ComputeApi.GetServerMetadataItemAsync" />
46+
public Task<string> GetServerMetadataItemAsync(Identifier serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
47+
{
48+
return _computeApi.GetServerMetadataItemAsync(serverId, key, cancellationToken);
49+
}
50+
3951
/// <inheritdoc cref="ComputeApi.CreateServerAsync{T}" />
4052
public Task<Server> CreateServerAsync(ServerCreateDefinition server, CancellationToken cancellationToken = default(CancellationToken))
4153
{
4254
return _computeApi.CreateServerAsync<Server>(server, cancellationToken);
4355
}
4456

57+
/// <inheritdoc cref="ComputeApi.CreateServerMetadataAsync" />
58+
public Task CreateServerMetadataAsync(Identifier serverId, string key, string value, CancellationToken cancellationToken = default(CancellationToken))
59+
{
60+
return _computeApi.CreateServerMetadataAsync(serverId, key, value, cancellationToken);
61+
}
62+
4563
/// <inheritdoc cref="ComputeApi.WaitForServerStatusAsync{TServer,TStatus}(string,TStatus,TimeSpan?,TimeSpan?,IProgress{bool},CancellationToken)" />
4664
public Task<Server> WaitForServerStatusAsync(Identifier serverId, ServerStatus status, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null, CancellationToken cancellationToken = default(CancellationToken))
4765
{
@@ -72,12 +90,25 @@ public ComputeService(IAuthenticationProvider authenticationProvider, string reg
7290
return _computeApi.UpdateServerAsync<Server>(serverid, server, cancellationToken);
7391
}
7492

93+
/// <inheritdoc cref="ComputeApi.UpdateServerMetadataAsync{T}" />
94+
public Task<ServerMetadata> UpdateServerMetadataAsync(Identifier serverId, ServerMetadata metadata, bool overwrite = false, CancellationToken cancellationToken = default(CancellationToken))
95+
{
96+
return _computeApi.UpdateServerMetadataAsync<ServerMetadata>(serverId, metadata, overwrite, cancellationToken);
97+
}
98+
7599
/// <inheritdoc cref="ComputeApi.DeleteServerAsync" />
76100
public Task DeleteServerAsync(Identifier serverId, CancellationToken cancellationToken = default(CancellationToken))
77101
{
78102
return _computeApi.DeleteServerAsync(serverId, cancellationToken);
79103
}
80104

105+
/// <inheritdoc cref="ComputeApi.DeleteServerMetadataAsync" />
106+
public Task DeleteServerMetadataAsync(Identifier serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
107+
{
108+
return _computeApi.DeleteServerMetadataAsync(serverId, key, cancellationToken);
109+
}
110+
111+
81112
/// <inheritdoc cref="ComputeApi.WaitUntilServerIsDeletedAsync{TServer,TStatus}" />
82113
public Task WaitUntilServerIsDeletedAsync(Identifier serverId, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null, CancellationToken cancellationToken = default(CancellationToken))
83114
{

src/corelib/Compute/v2_1/ComputeServiceExtensions.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,30 @@ public static Server GetServer(this ComputeService service, Identifier serverId)
1818
return service.GetServerAsync(serverId).ForceSynchronous();
1919
}
2020

21+
/// <inheritdoc cref="ComputeService.GetServerAsync" />
22+
public static ServerMetadata GetServerMetadata(this ComputeService service, Identifier serverId)
23+
{
24+
return service.GetServerMetadataAsync(serverId).ForceSynchronous();
25+
}
26+
27+
/// <inheritdoc cref="ComputeService.GetServerMetadataItemAsync" />
28+
public static string GetServerMetadataItem(this ComputeService service, Identifier serverId, string key)
29+
{
30+
return service.GetServerMetadataItemAsync(serverId, key).ForceSynchronous();
31+
}
32+
2133
/// <inheritdoc cref="ComputeService.CreateServerAsync" />
2234
public static Server CreateServer(this ComputeService service, ServerCreateDefinition server)
2335
{
2436
return service.CreateServerAsync(server).ForceSynchronous();
2537
}
2638

39+
/// <inheritdoc cref="ComputeService.CreateServerMetadataAsync" />
40+
public static void CreateServerMetadata(this ComputeService service, Identifier serverId, string key, string value)
41+
{
42+
service.CreateServerMetadataAsync(serverId, key, value).ForceSynchronous();
43+
}
44+
2745
/// <inheritdoc cref="ComputeService.WaitForServerStatusAsync(Identifier,ServerStatus,TimeSpan?,TimeSpan?,IProgress{bool},System.Threading.CancellationToken)" />
2846
public static Server WaitForServerStatus(this ComputeService service, Identifier serverId, ServerStatus status, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null)
2947
{
@@ -54,12 +72,24 @@ public static Server UpdateServer(this ComputeService service, Identifier server
5472
return service.UpdateServerAsync(serverid, server).ForceSynchronous();
5573
}
5674

75+
/// <inheritdoc cref="ComputeService.UpdateServerMetadataAsync" />
76+
public static ServerMetadata UpdateServerMetadata(this ComputeService service, Identifier serverId, ServerMetadata metadata, bool overwrite = false)
77+
{
78+
return service.UpdateServerMetadataAsync(serverId, metadata, overwrite).ForceSynchronous();
79+
}
80+
5781
/// <inheritdoc cref="ComputeService.DeleteServerAsync" />
5882
public static void DeleteServer(this ComputeService service, Identifier serverId)
5983
{
6084
service.DeleteServerAsync(serverId).ForceSynchronous();
6185
}
6286

87+
/// <inheritdoc cref="ComputeService.DeleteServerMetadataAsync" />
88+
public static void DeleteServerMetadata(this ComputeService service, Identifier serverId, string key)
89+
{
90+
service.DeleteServerMetadataAsync(serverId, key).ForceSynchronous();
91+
}
92+
6393
/// <inheritdoc cref="ComputeService.WaitUntilServerIsDeletedAsync" />
6494
public static void WaitUntilServerIsDeleted(this ComputeService service, Identifier serverId, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null)
6595
{

src/corelib/Compute/v2_1/Serialization/ComputeApi.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,40 @@ protected ComputeApi(IServiceType serviceType, IAuthenticationProvider authentic
8282
return Endpoint.PrepareGetResourceRequest($"servers/{serverId}", cancellationToken);
8383
}
8484

85+
/// <summary />
86+
public virtual async Task<T> GetServerMetadataAsync<T>(string serverId, CancellationToken cancellationToken = default(CancellationToken))
87+
where T : IChildResource
88+
{
89+
return await BuildGetServerMetadataRequest(serverId, cancellationToken)
90+
.SendAsync()
91+
.ReceiveJson<T>()
92+
.PropogateOwner(this)
93+
.SetParent(serverId);
94+
}
95+
96+
/// <summary />
97+
public virtual Task<PreparedRequest> BuildGetServerMetadataRequest(string serverId, CancellationToken cancellationToken = default(CancellationToken))
98+
{
99+
return Endpoint.PrepareGetResourceRequest($"servers/{serverId}/metadata", cancellationToken);
100+
}
101+
102+
/// <summary />
103+
public virtual async Task<string> GetServerMetadataItemAsync(string serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
104+
{
105+
dynamic result = await BuildGetServerMetadataItemRequest(serverId, key, cancellationToken)
106+
.SendAsync()
107+
.ReceiveJson();
108+
109+
var meta = (IDictionary<string, object>)result.meta;
110+
return meta[key]?.ToString();
111+
}
112+
113+
/// <summary />
114+
public virtual Task<PreparedRequest> BuildGetServerMetadataItemRequest(string serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
115+
{
116+
return Endpoint.PrepareGetResourceRequest($"servers/{serverId}/metadata/{key}", cancellationToken);
117+
}
118+
85119
/// <summary />
86120
public virtual Task<PreparedRequest> BuildCreateServerRequest(object server, CancellationToken cancellationToken = default(CancellationToken))
87121
{
@@ -98,6 +132,27 @@ protected ComputeApi(IServiceType serviceType, IAuthenticationProvider authentic
98132
.PropogateOwner(this);
99133
}
100134

135+
/// <summary />
136+
public virtual Task CreateServerMetadataAsync(string serverId, string key, string value, CancellationToken cancellationToken = default(CancellationToken))
137+
{
138+
return BuildCreateServerMetadataRequest(serverId, key, value, cancellationToken).SendAsync();
139+
}
140+
141+
/// <summary />
142+
public virtual async Task<PreparedRequest> BuildCreateServerMetadataRequest(string serverId, string key, string value, CancellationToken cancellationToken = default(CancellationToken))
143+
{
144+
var serverMetadata = new
145+
{
146+
meta = new Dictionary<string, string>
147+
{
148+
[key] = value
149+
}
150+
};
151+
152+
PreparedRequest request = await Endpoint.PrepareRequest($"servers/{serverId}/metadata/{key}", cancellationToken);
153+
return request.PreparePutJson(serverMetadata, cancellationToken);
154+
}
155+
101156
/// <summary>
102157
/// Waits for the server to reach the specified status.
103158
/// </summary>
@@ -213,6 +268,27 @@ protected ComputeApi(IServiceType serviceType, IAuthenticationProvider authentic
213268
.PropogateOwner(this);
214269
}
215270

271+
/// <summary /> // this keeps existing, but omitted values
272+
public virtual async Task<T> UpdateServerMetadataAsync<T>(string serverId, object metadata, bool overwrite = false, CancellationToken cancellationToken = default(CancellationToken))
273+
where T : IServiceResource
274+
{
275+
return await BuildUpdateServerMetadataRequest(serverId, metadata, overwrite, cancellationToken)
276+
.SendAsync()
277+
.ReceiveJson<T>()
278+
.PropogateOwner(this);
279+
}
280+
281+
/// <summary />
282+
public virtual async Task<PreparedRequest> BuildUpdateServerMetadataRequest(string serverId, object metadata, bool overwrite = false, CancellationToken cancellationToken = default(CancellationToken))
283+
{
284+
PreparedRequest request = await Endpoint.PrepareRequest($"servers/{serverId}/metadata", cancellationToken);
285+
286+
if (overwrite)
287+
return request.PreparePutJson(metadata, cancellationToken);
288+
289+
return request.PreparePostJson(metadata, cancellationToken);
290+
}
291+
216292
/// <summary />
217293
public virtual Task DeleteServerAsync(string serverId, CancellationToken cancellationToken = default(CancellationToken))
218294
{
@@ -225,6 +301,24 @@ protected ComputeApi(IServiceType serviceType, IAuthenticationProvider authentic
225301
return Endpoint.PrepareDeleteResourceRequest($"servers/{serverId}", cancellationToken);
226302
}
227303

304+
/// <summary />
305+
public virtual Task DeleteServerMetadataAsync(string serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
306+
{
307+
return BuildDeleteServerMetadataRequest(serverId, key, cancellationToken).SendAsync();
308+
}
309+
310+
/// <summary />
311+
public virtual Task<PreparedRequest> BuildDeleteServerMetadataRequest(string serverId, string key, CancellationToken cancellationToken = default(CancellationToken))
312+
{
313+
if (serverId == null)
314+
throw new ArgumentNullException("serverId");
315+
316+
if (key == null)
317+
throw new ArgumentNullException("key");
318+
319+
return Endpoint.PrepareDeleteResourceRequest($"servers/{serverId}/metadata/{key}", cancellationToken);
320+
}
321+
228322
/// <summary>
229323
/// Waits for an image to reach the specified state.
230324
/// </summary>

src/corelib/Compute/v2_1/Server.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public Server()
1919
{
2020
Addresses = new Dictionary<string, IList<ServerAddress>>();
2121
AttachedVolumes = new List<ServerVolumeReference>();
22+
Metadata = new ServerMetadata();
2223
SecurityGroups = new List<SecurityGroupReference>();
2324
}
2425

@@ -58,7 +59,7 @@ public string AdminPassword
5859

5960
/// <summary />
6061
[JsonProperty("metadata")]
61-
public IDictionary<string, string> Metadata { get; set; }
62+
public ServerMetadata Metadata { get; set; }
6263

6364
/// <summary />
6465
[JsonProperty("accessIPv4")]
@@ -191,6 +192,7 @@ public string AdminPassword
191192
[OnDeserialized]
192193
private void OnDeserializedMethod(StreamingContext context)
193194
{
195+
Metadata.SetParent(this);
194196
foreach (var volume in AttachedVolumes)
195197
{
196198
volume.SetParent(this);

src/corelib/Compute/v2_1/ServerExtensions.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ public static IList<ServerAddress> GetAddress(this ServerReference server, strin
2121
return server.GetAddressAsync(key).ForceSynchronous();
2222
}
2323

24+
/// <inheritdoc cref="ServerReference.GetMetadataAsync"/>
25+
public static ServerMetadata GetMetadata(this ServerReference server)
26+
{
27+
return server.GetMetadataAsync().ForceSynchronous();
28+
}
29+
30+
/// <inheritdoc cref="ServerReference.GetMetadataItemAsync"/>
31+
public static string GetMetadataItem(this ServerReference server, string key)
32+
{
33+
return server.GetMetadataItemAsync(key).ForceSynchronous();
34+
}
35+
2436
/// <inheritdoc cref="ServerReference.GetServerAsync"/>
2537
public static IDictionary<string, IList<ServerAddress>> ListAddresses(this ServerReference server)
2638
{
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Linq;
8+
using OpenStack.Compute.v2_1.Serialization;
9+
using OpenStack.Serialization;
10+
11+
namespace OpenStack.Compute.v2_1
12+
{
13+
/// <summary />
14+
[JsonConverterWithConstructor(typeof (RootWrapperConverter), "metadata")]
15+
public class ServerMetadata : Dictionary<string, string>, IHaveExtraData, IChildResource
16+
{
17+
/// <summary />
18+
[JsonIgnore]
19+
protected ServerReference Server { get; set; }
20+
21+
/// <summary />
22+
[JsonExtensionData]
23+
IDictionary<string, JToken> IHaveExtraData.Data { get; set; } = new Dictionary<string, JToken>();
24+
25+
object IServiceResource.Owner { get; set; }
26+
27+
/// <summary />
28+
protected internal void SetParent(ServerReference parent)
29+
{
30+
Server = parent;
31+
}
32+
33+
void IChildResource.SetParent(string parentId)
34+
{
35+
SetParent(new ServerReference {Id = parentId});
36+
}
37+
38+
void IChildResource.SetParent(object parent)
39+
{
40+
SetParent((ServerReference)parent);
41+
}
42+
43+
/// <summary />
44+
protected void AssertParentIsSet([CallerMemberName]string callerName = "")
45+
{
46+
if (Server != null)
47+
return;
48+
49+
throw new InvalidOperationException(string.Format($"{callerName} can only be used on instances which were constructed by the ComputeService. Use ComputeService.{callerName} instead."));
50+
}
51+
52+
/// <summary />
53+
public async Task CreateAsync(string key, string value, CancellationToken cancellationToken = default(CancellationToken))
54+
{
55+
AssertParentIsSet();
56+
var compute = this.GetOwnerOrThrow<ComputeApi>();
57+
await compute.CreateServerMetadataAsync(Server.Id, key, value, cancellationToken);
58+
this[key] = value;
59+
}
60+
61+
/// <summary />
62+
public async Task UpdateAsync(bool overwrite = false, CancellationToken cancellationToken = default(CancellationToken))
63+
{
64+
AssertParentIsSet();
65+
var compute = this.GetOwnerOrThrow<ComputeApi>();
66+
var results = await compute.UpdateServerMetadataAsync<ServerMetadata>(Server.Id, this, overwrite, cancellationToken);
67+
Clear();
68+
foreach (var result in results)
69+
{
70+
Add(result.Key, result.Value);
71+
}
72+
}
73+
74+
/// <summary />
75+
public async Task DeleteAsync(string key, CancellationToken cancellationToken = default(CancellationToken))
76+
{
77+
if (!ContainsKey(key))
78+
return;
79+
80+
AssertParentIsSet();
81+
var compute = this.GetOwnerOrThrow<ComputeApi>();
82+
await compute.DeleteServerMetadataAsync(Server.Id, key, cancellationToken);
83+
Remove(key);
84+
}
85+
}
86+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using OpenStack.Compute.v2_1;
2+
using OpenStack.Synchronous.Extensions;
3+
4+
// ReSharper disable once CheckNamespace
5+
namespace OpenStack.Synchronous
6+
{
7+
/// <summary />
8+
public static class ServerMetadataExtensions_v2_1
9+
{
10+
/// <inheritdoc cref="ServerMetadata.CreateAsync"/>
11+
public static void Create(this ServerMetadata metadata, string key, string value)
12+
{
13+
metadata.CreateAsync(key, value).ForceSynchronous();
14+
}
15+
16+
/// <inheritdoc cref="ServerMetadata.UpdateAsync"/>
17+
public static void Update(this ServerMetadata metadata, bool overwrite = false)
18+
{
19+
metadata.UpdateAsync(overwrite).ForceSynchronous();
20+
}
21+
22+
/// <inheritdoc cref="ServerMetadata.DeleteAsync"/>
23+
public static void Delete(this ServerMetadata metadata, string key)
24+
{
25+
metadata.DeleteAsync(key).ForceSynchronous();
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)