Adding the initial code base for this repo
Change-Id: Ie3c70c76e0a96978383d2524e8af9a0cc04bd6a2
This commit is contained in:
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
################################################################################
|
||||
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
|
||||
################################################################################
|
||||
|
||||
/Openstack/Openstack/obj
|
||||
/Openstack/Openstack.Common/obj
|
||||
/Openstack/Openstack.Test/obj
|
||||
/Openstack/Bin
|
||||
*.user
|
||||
*.suo
|
||||
/Openstack/packages
|
||||
/Openstack/Openstack/obj
|
||||
/Openstack/Openstack.Common/obj
|
||||
/Openstack/Openstack.Test/obj
|
1
Openstack/Build/readme.txt
Normal file
1
Openstack/Build/readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
This is where we would put things like fixcop and stylcop related stuff or any custom build targets that we would want to bring in... basically anything that is related to building the solution.
|
1
Openstack/Externals/readme.txt
vendored
Normal file
1
Openstack/Externals/readme.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
This is a folder to bring in any non-NuGet external dependencies...
|
51
Openstack/Openstack.Common/Http/DisposableClass.cs
Normal file
51
Openstack/Openstack.Common/Http/DisposableClass.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public class DisposableClass : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~DisposableClass()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//if (disposing)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
192
Openstack/Openstack.Common/Http/HttpAbstractionClient.cs
Normal file
192
Openstack/Openstack.Common/Http/HttpAbstractionClient.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Handlers;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public class HttpAbstractionClient : DisposableClass, IHttpAbstractionClient
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private readonly ProgressMessageHandler _handler;
|
||||
private CancellationToken _cancellationToken = CancellationToken.None;
|
||||
private static readonly TimeSpan _defaultTimeout = new TimeSpan(0, 5, 0);
|
||||
|
||||
internal HttpAbstractionClient(TimeSpan timeout, CancellationToken cancellationToken)
|
||||
{
|
||||
this._handler = new ProgressMessageHandler(new HttpClientHandler());
|
||||
this._client = new HttpClient(_handler) { Timeout = timeout };
|
||||
|
||||
this._cancellationToken = cancellationToken;
|
||||
this.Method = HttpMethod.Get;
|
||||
this.Headers = new Dictionary<string, string>();
|
||||
this.ContentType = string.Empty;
|
||||
}
|
||||
|
||||
public static IHttpAbstractionClient Create()
|
||||
{
|
||||
return new HttpAbstractionClient(_defaultTimeout, CancellationToken.None );
|
||||
}
|
||||
|
||||
public static IHttpAbstractionClient Create(TimeSpan timeout)
|
||||
{
|
||||
return new HttpAbstractionClient(timeout, CancellationToken.None);
|
||||
}
|
||||
|
||||
public static IHttpAbstractionClient Create(CancellationToken cancellationToken)
|
||||
{
|
||||
return new HttpAbstractionClient(_defaultTimeout, cancellationToken);
|
||||
}
|
||||
|
||||
public static IHttpAbstractionClient Create(CancellationToken cancellationToken, TimeSpan timeout)
|
||||
{
|
||||
return new HttpAbstractionClient(timeout, cancellationToken);
|
||||
}
|
||||
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpReceiveProgress
|
||||
//{
|
||||
// add { this._handler.HttpReceiveProgress += value; }
|
||||
// remove { this._handler.HttpReceiveProgress -= value; }
|
||||
//}
|
||||
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpSendProgress
|
||||
//{
|
||||
// add { this._handler.HttpSendProgress += value; }
|
||||
// remove { this._handler.HttpSendProgress -= value; }
|
||||
//}
|
||||
|
||||
public HttpMethod Method { get; set; }
|
||||
|
||||
public Uri Uri { get; set; }
|
||||
|
||||
public Stream Content { get; set; }
|
||||
|
||||
public IDictionary<string, string> Headers { get; private set; }
|
||||
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public TimeSpan Timeout { get; set; }
|
||||
|
||||
public async Task<IHttpResponseAbstraction> SendAsync()
|
||||
{
|
||||
var requestMessage = new HttpRequestMessage { Method = this.Method, RequestUri = this.Uri };
|
||||
|
||||
if (this.Method == HttpMethod.Post || this.Method == HttpMethod.Put)
|
||||
{
|
||||
requestMessage.Content = new StreamContent(this.Content);
|
||||
if (this.ContentType != string.Empty)
|
||||
{
|
||||
requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(this.ContentType);
|
||||
}
|
||||
}
|
||||
|
||||
requestMessage.Headers.Clear();
|
||||
foreach (var header in this.Headers)
|
||||
{
|
||||
requestMessage.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
var result = await this._client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, this._cancellationToken);
|
||||
|
||||
var headers = new HttpHeadersAbstraction(result.Headers);
|
||||
|
||||
Stream content = null;
|
||||
if (result.Content != null )
|
||||
{
|
||||
headers.AddRange(result.Content.Headers);
|
||||
content = this.WaitForResult(result.Content.ReadAsStreamAsync(), new TimeSpan(0,0,0,0,int.MaxValue) );
|
||||
}
|
||||
|
||||
var retval = new HttpResponseAbstraction(content, headers, result.StatusCode);
|
||||
|
||||
//TODO: Add logging code
|
||||
|
||||
return retval;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//TODO: Add logging code
|
||||
|
||||
var tcex = ex as TaskCanceledException;
|
||||
if (tcex == null)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
if (this._cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw new OperationCanceledException("The operation was canceled by user request.", tcex, this._cancellationToken);
|
||||
}
|
||||
|
||||
if (DateTime.Now - startTime > this.Timeout)
|
||||
{
|
||||
throw new TimeoutException(string.Format(CultureInfo.InvariantCulture, "The task failed to complete in the given timeout period ({0}).", this.Timeout));
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
internal T WaitForResult<T>(Task<T> task, TimeSpan timeout)
|
||||
{
|
||||
if (task == null )
|
||||
{
|
||||
throw new ArgumentNullException("task");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
task.Wait(timeout);
|
||||
}
|
||||
catch (AggregateException aggregateException)
|
||||
{
|
||||
throw GetInnerException(aggregateException);
|
||||
}
|
||||
|
||||
if (task.Status != TaskStatus.RanToCompletion && task.Status != TaskStatus.Faulted && task.Status != TaskStatus.Canceled)
|
||||
{
|
||||
throw new TimeoutException(string.Format(CultureInfo.InvariantCulture, "The task failed to complete in the given timeout period ({0}).", timeout));
|
||||
}
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
internal Exception GetInnerException(AggregateException aggregateException)
|
||||
{
|
||||
//helper function to spool off the layers of aggregate exceptions and get the underlying exception...
|
||||
Exception innerExcception = aggregateException;
|
||||
while (aggregateException != null)
|
||||
{
|
||||
innerExcception = aggregateException.InnerExceptions[0];
|
||||
aggregateException = innerExcception as AggregateException;
|
||||
}
|
||||
return innerExcception;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public class HttpAbstractionClientFactory : IHttpAbstractionClientFactory
|
||||
{
|
||||
public IHttpAbstractionClient Create()
|
||||
{
|
||||
return HttpAbstractionClient.Create();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout)
|
||||
{
|
||||
return HttpAbstractionClient.Create(timeout);
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(CancellationToken token)
|
||||
{
|
||||
return HttpAbstractionClient.Create(token);
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout, CancellationToken token)
|
||||
{
|
||||
return HttpAbstractionClient.Create(token, timeout);
|
||||
}
|
||||
}
|
||||
}
|
106
Openstack/Openstack.Common/Http/HttpHeadersAbstraction.cs
Normal file
106
Openstack/Openstack.Common/Http/HttpHeadersAbstraction.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public class HttpHeadersAbstraction : IHttpHeadersAbstraction
|
||||
{
|
||||
private readonly Dictionary<string, IEnumerable<string>> _headers = new Dictionary<string, IEnumerable<string>>();
|
||||
|
||||
public HttpHeadersAbstraction()
|
||||
{
|
||||
}
|
||||
|
||||
public HttpHeadersAbstraction(HttpResponseHeaders headers)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
this._headers.Add(header.Key,header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator()
|
||||
{
|
||||
return this._headers.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this._headers.GetEnumerator();
|
||||
}
|
||||
|
||||
public void Add(string name, IEnumerable<string> values)
|
||||
{
|
||||
this._headers.Add(name,values);
|
||||
}
|
||||
|
||||
public void AddRange(HttpResponseHeaders headers)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
this._headers.Add(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRange(HttpContentHeaders headers)
|
||||
{
|
||||
foreach (var header in headers)
|
||||
{
|
||||
this._headers.Add(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string name, string value)
|
||||
{
|
||||
this._headers.Add(name, new List<string>() { value });
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
this._headers.Clear();
|
||||
}
|
||||
|
||||
public bool Contains(string name)
|
||||
{
|
||||
return this._headers.ContainsKey(name);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetValues(string name)
|
||||
{
|
||||
return this._headers[name];
|
||||
}
|
||||
|
||||
public void Remove(string name)
|
||||
{
|
||||
this._headers.Remove(name);
|
||||
}
|
||||
|
||||
public bool TryGetValue(string name, out IEnumerable<string> values)
|
||||
{
|
||||
return this._headers.TryGetValue(name, out values);
|
||||
}
|
||||
|
||||
public IEnumerable<string> this[string name]
|
||||
{
|
||||
get { return this._headers[name]; }
|
||||
set { this._headers[name] = value; }
|
||||
}
|
||||
}
|
||||
}
|
46
Openstack/Openstack.Common/Http/HttpResponseAbstraction.cs
Normal file
46
Openstack/Openstack.Common/Http/HttpResponseAbstraction.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public class HttpResponseAbstraction : IHttpResponseAbstraction
|
||||
{
|
||||
public HttpResponseAbstraction(Stream content, IHttpHeadersAbstraction headers, HttpStatusCode status)
|
||||
{
|
||||
this.Headers = headers ?? new HttpHeadersAbstraction();
|
||||
this.StatusCode = status;
|
||||
this.Content = content;
|
||||
}
|
||||
|
||||
public Stream Content { get; private set; }
|
||||
|
||||
public IHttpHeadersAbstraction Headers { get; private set; }
|
||||
|
||||
public HttpStatusCode StatusCode { get; private set; }
|
||||
|
||||
public async Task<string> ReadContentAsStringAsync()
|
||||
{
|
||||
using (var sr = new StreamReader(this.Content))
|
||||
{
|
||||
return await sr.ReadToEndAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
Openstack/Openstack.Common/Http/IHttpAbstractionClient.cs
Normal file
45
Openstack/Openstack.Common/Http/IHttpAbstractionClient.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public interface IHttpAbstractionClient : IDisposable
|
||||
{
|
||||
HttpMethod Method { get; set; }
|
||||
|
||||
Uri Uri { get; set; }
|
||||
|
||||
Stream Content { get; set; }
|
||||
|
||||
IDictionary<string, string> Headers { get; }
|
||||
|
||||
string ContentType { get; set; }
|
||||
|
||||
TimeSpan Timeout { get; set; }
|
||||
|
||||
|
||||
//event EventHandler<HttpProgressEventArgs> HttpReceiveProgress;
|
||||
//event EventHandler<HttpProgressEventArgs> HttpSendProgress;
|
||||
|
||||
Task<IHttpResponseAbstraction> SendAsync();
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public interface IHttpAbstractionClientFactory
|
||||
{
|
||||
IHttpAbstractionClient Create();
|
||||
|
||||
IHttpAbstractionClient Create(CancellationToken token);
|
||||
|
||||
IHttpAbstractionClient Create(TimeSpan timeout);
|
||||
|
||||
IHttpAbstractionClient Create(TimeSpan timeout, CancellationToken token);
|
||||
}
|
||||
}
|
39
Openstack/Openstack.Common/Http/IHttpHeadersAbstraction.cs
Normal file
39
Openstack/Openstack.Common/Http/IHttpHeadersAbstraction.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public interface IHttpHeadersAbstraction : IEnumerable<KeyValuePair<string, IEnumerable<string>>>
|
||||
{
|
||||
void Add(string name, IEnumerable<string> values);
|
||||
|
||||
void Add(string name, string value);
|
||||
|
||||
void Clear();
|
||||
|
||||
bool Contains(string name);
|
||||
|
||||
IEnumerable<string> GetValues(string name);
|
||||
|
||||
void Remove(string name);
|
||||
|
||||
bool TryGetValue(string name, out IEnumerable<string> values);
|
||||
|
||||
IEnumerable<string> this[string name] { get; set; }
|
||||
}
|
||||
}
|
33
Openstack/Openstack.Common/Http/IHttpResponseAbstraction.cs
Normal file
33
Openstack/Openstack.Common/Http/IHttpResponseAbstraction.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public interface IHttpResponseAbstraction
|
||||
{
|
||||
Stream Content { get; }
|
||||
|
||||
IHttpHeadersAbstraction Headers { get; }
|
||||
|
||||
HttpStatusCode StatusCode { get; }
|
||||
|
||||
Task<string> ReadContentAsStringAsync();
|
||||
}
|
||||
}
|
29
Openstack/Openstack.Common/Http/IOpenStackAccessToken.cs
Normal file
29
Openstack/Openstack.Common/Http/IOpenStackAccessToken.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
|
||||
namespace Openstack.Common.Http
|
||||
{
|
||||
public interface IOpenStackAccessToken
|
||||
{
|
||||
string Id { get; }
|
||||
|
||||
Uri Endpoint { get; }
|
||||
|
||||
DateTime Expiration { get; }
|
||||
}
|
||||
}
|
151
Openstack/Openstack.Common/ObjectExtentions.cs
Normal file
151
Openstack/Openstack.Common/ObjectExtentions.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
|
||||
namespace Openstack.Common
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
/// <summary>
|
||||
/// Holds extension methods for common objects and tasks.
|
||||
/// </summary>
|
||||
public static class ObjectExtentions
|
||||
{
|
||||
/// <summary>
|
||||
/// Throws an argument exception if the given object is null.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Given Type of the object.</typeparam>
|
||||
/// <param name="input">The object.</param>
|
||||
/// <param name="paramName">A string that represents a name for the object.</param>
|
||||
public static void AssertIsNotNull<T>(this T input, string paramName)
|
||||
{
|
||||
if (ReferenceEquals(input, null))
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an argument exception if the given object is null.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Given Type of the object.</typeparam>
|
||||
/// <param name="input">The object.</param>
|
||||
/// <param name="paramName">A string that represents a name for the object.</param>
|
||||
/// <param name="message">A message to include in the thrown exception.</param>
|
||||
public static void AssertIsNotNull<T>(this T input, string paramName, string message)
|
||||
{
|
||||
if (ReferenceEquals(input, null))
|
||||
{
|
||||
throw new ArgumentNullException(paramName, message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an argument exception if the given string is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="input">The given string.</param>
|
||||
/// <param name="paramName">A string that represents a name for the object.</param>
|
||||
public static void AssertIsNotNullOrEmpty(this string input, string paramName)
|
||||
{
|
||||
if (ReferenceEquals(input, null))
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
throw new ArgumentException(string.Empty, paramName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an argument exception if the given string is null or empty.
|
||||
/// </summary>
|
||||
/// <param name="input">The given string.</param>
|
||||
/// <param name="paramName">A string that represents a name for the object.</param>
|
||||
/// <param name="message">A message to include in the thrown exception.</param>
|
||||
public static void AssertIsNotNullOrEmpty(this string input, string paramName, string message)
|
||||
{
|
||||
if (ReferenceEquals(input, null))
|
||||
{
|
||||
throw new ArgumentNullException(paramName, message);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
throw new ArgumentException(message, paramName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given string to a stream.
|
||||
/// </summary>
|
||||
/// <param name="content">The string to convert.</param>
|
||||
/// <returns>A stream that includes the given string.</returns>
|
||||
public static Stream ConvertToStream(this string content)
|
||||
{
|
||||
var byteArray = Encoding.ASCII.GetBytes(content);
|
||||
return new MemoryStream(byteArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to a SecureString.
|
||||
/// </summary>
|
||||
/// <param name="password">The string to convert.</param>
|
||||
/// <returns>The converted SecureString object.</returns>
|
||||
public static SecureString ConvertToSecureString(this string password)
|
||||
{
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
|
||||
var securePassword = new SecureString();
|
||||
password.ToCharArray().ToList().ForEach(securePassword.AppendChar);
|
||||
securePassword.MakeReadOnly();
|
||||
return securePassword;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a SecureString object to a plain-text string.
|
||||
/// </summary>
|
||||
/// <param name="securePassword">The SecureString object.</param>
|
||||
/// <returns>The plain-text version of the given SecureString.</returns>
|
||||
public static string ConvertToUnsecureString(this SecureString securePassword)
|
||||
{
|
||||
if (securePassword == null)
|
||||
{
|
||||
throw new ArgumentNullException("securePassword");
|
||||
}
|
||||
|
||||
var unmanagedString = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
|
||||
return Marshal.PtrToStringUni(unmanagedString);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
80
Openstack/Openstack.Common/Openstack.Common.csproj
Normal file
80
Openstack/Openstack.Common/Openstack.Common.csproj
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" 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>{C53D669C-CDF1-4157-AEC1-BD167F655B2B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Openstack.Common</RootNamespace>
|
||||
<AssemblyName>Openstack.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<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' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Http\DisposableClass.cs" />
|
||||
<Compile Include="Http\HttpAbstractionClient.cs" />
|
||||
<Compile Include="Http\HttpAbstractionClientFactory.cs" />
|
||||
<Compile Include="Http\HttpHeadersAbstraction.cs" />
|
||||
<Compile Include="Http\HttpResponseAbstraction.cs" />
|
||||
<Compile Include="Http\IHttpAbstractionClient.cs" />
|
||||
<Compile Include="Http\IHttpAbstractionClientFactory.cs" />
|
||||
<Compile Include="Http\IHttpHeadersAbstraction.cs" />
|
||||
<Compile Include="Http\IHttpResponseAbstraction.cs" />
|
||||
<Compile Include="Http\IOpenStackAccessToken.cs" />
|
||||
<Compile Include="ObjectExtentions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceLocation\AssemblyNameComparer.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationAssemblyScanner.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationManager.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationOverrideManager.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationRegistrar.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationRegistrarFactory.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocationRuntimeManager.cs" />
|
||||
<Compile Include="ServiceLocation\IServiceLocator.cs" />
|
||||
<Compile Include="ServiceLocation\RuntimeRegistrationManager.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocationAssemblyScanner.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocationManager.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocationRegistrarFactory.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocator.cs" />
|
||||
<Compile Include="ServiceRegistrar.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
53
Openstack/Openstack.Common/Properties/AssemblyInfo.cs
Normal file
53
Openstack/Openstack.Common/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Openstack.Common")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Openstack.org")]
|
||||
[assembly: AssemblyProduct("Openstack.Common")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("0ed0b3bc-5dcd-488c-a9bd-0940e43afc4a")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: InternalsVisibleTo("Openstack.Test")]
|
@@ -0,0 +1,62 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for comparing assembly names.
|
||||
/// </summary>
|
||||
internal class AssemblyNameEqualityComparer : IEqualityComparer<AssemblyName>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool Equals(AssemblyName x, AssemblyName y)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (x == null || y == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (x.Name.Equals(y.Name, StringComparison.Ordinal) &&
|
||||
x.Version.Equals(y.Version) &&
|
||||
x.CultureInfo.Equals(y.CultureInfo) &&
|
||||
(ReferenceEquals(x.KeyPair, y.KeyPair) ||
|
||||
(x.KeyPair != null && y.KeyPair!= null &&
|
||||
x.KeyPair.PublicKey.SequenceEqual(y.KeyPair.PublicKey))))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int GetHashCode(AssemblyName obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
return obj.GetHashCode();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for scanning an assembly for service location registrars.
|
||||
/// </summary>
|
||||
internal interface IServiceLocationAssemblyScanner
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the scanner has detected assemblies that have not been scanned.
|
||||
/// </summary>
|
||||
/// <returns>A value indicating if new assemblies are present.</returns>
|
||||
bool HasNewAssemblies();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerable collection of service location registrars.
|
||||
/// </summary>
|
||||
/// <returns>enumerable collection of service location registrars</returns>
|
||||
IEnumerable<IServiceLocationRegistrar> GetRegistrars();
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an object that can manage service location registration.
|
||||
/// </summary>
|
||||
public interface IServiceLocationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers an instance of a service with the service locator.
|
||||
/// </summary>
|
||||
/// <typeparam name="TService">The interface of the service to be registered.</typeparam>
|
||||
/// <param name="instance">An instance of the service to be returned by the service locator.</param>
|
||||
void RegisterServiceInstance<TService>(TService instance);
|
||||
|
||||
/// <summary>
|
||||
/// Registers an instance of a service with the service locator.
|
||||
/// </summary>
|
||||
/// <param name="type">The interface of the service to be registered.</param>
|
||||
/// <param name="instance">An instance of the service to be returned by the service locator.</param>
|
||||
void RegisterServiceInstance(Type type, object instance);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a type of a service with the service locator.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The interface of the service to be registered.</typeparam>
|
||||
/// <param name="type">A concrete type of the service to be returned by the service locator.</param>
|
||||
void RegisterServiceType<T>(Type type);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a type of a service with the service locator.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInterface">The interface of the service to be registered.</typeparam>
|
||||
/// <typeparam name="TConcretion">A concrete type of the service to be returned by the service locator.</typeparam>
|
||||
void RegisterServiceType<TInterface, TConcretion>() where TConcretion : class, TInterface;
|
||||
|
||||
/// <summary>
|
||||
/// Registers a type of a service with the service locator.
|
||||
/// </summary>
|
||||
/// <param name="type">The interface of the service to be registered.</param>
|
||||
/// <param name="registrationValue">A concrete type of the service to be returned by the service locator.</param>
|
||||
void RegisterServiceType(Type type, Type registrationValue);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an object that can manage overriding service location registrations.
|
||||
/// </summary>
|
||||
interface IServiceLocationOverrideManager : IServiceLocationManager
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an object that will register services for location.
|
||||
/// </summary>
|
||||
public interface IServiceLocationRegistrar
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers services for location.
|
||||
/// </summary>
|
||||
/// <param name="manager">A service location manager to use for registering services.</param>
|
||||
/// <param name="locator">A reference to the service locator.</param>
|
||||
void Register(IServiceLocationManager manager, IServiceLocator locator);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for an object that knows how to create service registrars.
|
||||
/// </summary>
|
||||
interface IServiceLocationRegistrarFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a service registrar.
|
||||
/// </summary>
|
||||
/// <param name="type">The type of the service registrar to create.</param>
|
||||
/// <returns>An instance of the given registrar type.</returns>
|
||||
IServiceLocationRegistrar Create(Type type);
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an object that can manage service location registrations at runtime.
|
||||
/// </summary>
|
||||
interface IServiceLocationRuntimeManager : IServiceLocationManager
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an object that can locate services.
|
||||
/// </summary>
|
||||
public interface IServiceLocator
|
||||
{
|
||||
/// <summary>
|
||||
/// Locates an instance of the requested service.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the service to locate.</typeparam>
|
||||
/// <returns>An instance of the service.</returns>
|
||||
T Locate<T>();
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class RuntimeRegistrationManager : ServiceLocationManager
|
||||
{
|
||||
private IServiceLocator locator;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the RuntimeRegistrationManager class.
|
||||
/// </summary>
|
||||
/// <param name="locator">A reference to a service locator.</param>
|
||||
public RuntimeRegistrationManager(IServiceLocator locator)
|
||||
{
|
||||
this.locator = locator;
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, object> _discovered = new Dictionary<Type, object>();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void RegisterServiceInstance(Type serviceType, object instance)
|
||||
{
|
||||
var registering = instance as IServiceLocationRegistrar;
|
||||
object discoveredInstance;
|
||||
if (this._discovered.TryGetValue(serviceType,
|
||||
out discoveredInstance))
|
||||
{
|
||||
if (!ReferenceEquals(discoveredInstance,
|
||||
instance) && !ReferenceEquals(registering,
|
||||
null))
|
||||
{
|
||||
this._discovered[serviceType] = instance;
|
||||
registering.Register(this, this.locator);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._discovered[serviceType] = instance;
|
||||
if (!ReferenceEquals(registering,
|
||||
null))
|
||||
{
|
||||
registering.Register(this, this.locator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of types and objects that have been discovered/registered.
|
||||
/// </summary>
|
||||
/// <returns>An enumerable list of types and instances.</returns>
|
||||
public IEnumerable<KeyValuePair<Type, object>> GetDiscovered()
|
||||
{
|
||||
return this._discovered;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class ServiceLocationAssemblyScanner : IServiceLocationAssemblyScanner
|
||||
{
|
||||
private IServiceLocationRegistrarFactory ServiceRegistrarFactory { get; set; }
|
||||
private readonly List<Type> _registrars = new List<Type>();
|
||||
private readonly List<Assembly> _assemblies = new List<Assembly>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets a list of assemblies that have been scanned.
|
||||
/// </summary>
|
||||
internal Func<IEnumerable<Assembly>> GetAllAssemblies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the ServiceLocationAssemblyScanner class.
|
||||
/// </summary>
|
||||
public ServiceLocationAssemblyScanner()
|
||||
{
|
||||
this.GetAllAssemblies = this.InternalGetAllAssemblies;
|
||||
this.ServiceRegistrarFactory = new ServiceLocationRegistrarFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all assemblies in the current application domain.
|
||||
/// </summary>
|
||||
/// <returns>A list of assembly objects.</returns>
|
||||
internal IEnumerable<Assembly> InternalGetAllAssemblies()
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool HasNewAssemblies()
|
||||
{
|
||||
var assemblies = this.GetAllAssemblies().ToList();
|
||||
this._assemblies.All(assemblies.Remove);
|
||||
this._assemblies.AddRange(assemblies);
|
||||
return assemblies.Any();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<IServiceLocationRegistrar> GetRegistrars()
|
||||
{
|
||||
var newRegistrars = new List<Type>();
|
||||
if (this.HasNewAssemblies())
|
||||
{
|
||||
newRegistrars = this.GetRegistrarTypes().ToList();
|
||||
}
|
||||
|
||||
this._registrars.All(newRegistrars.Remove);
|
||||
this._registrars.AddRange(newRegistrars);
|
||||
|
||||
var objects = (from t in this._registrars
|
||||
select ServiceRegistrarFactory.Create(t)).ToList();
|
||||
return objects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of types for any services registrars in the current application domain.
|
||||
/// </summary>
|
||||
/// <returns>A list of types.</returns>
|
||||
internal IEnumerable<Type> GetRegistrarTypes()
|
||||
{
|
||||
var comparer = new AssemblyNameEqualityComparer();
|
||||
var rawTypes = new List<Type>();
|
||||
|
||||
var scansedAssemblies = this.GetAllAssemblies();
|
||||
var workingAssemblies = (from s in scansedAssemblies
|
||||
where s.GetReferencedAssemblies().Contains(typeof(IServiceLocationRegistrar).Assembly.GetName(), comparer)
|
||||
select s).ToList();
|
||||
workingAssemblies.Add(this.GetType().Assembly);
|
||||
|
||||
foreach (var assembly in workingAssemblies)
|
||||
{
|
||||
try
|
||||
{
|
||||
rawTypes.AddRange(assembly.GetTypes());
|
||||
}
|
||||
catch (ReflectionTypeLoadException loadEx)
|
||||
{
|
||||
var foundTypes = (from t in loadEx.Types where t != null select t).ToList();
|
||||
rawTypes.AddRange(foundTypes);
|
||||
}
|
||||
}
|
||||
|
||||
var unorderedTypes = new Queue<Type>();
|
||||
foreach (var type in rawTypes)
|
||||
{
|
||||
if (type.IsInterface)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof(IServiceLocationRegistrar).IsAssignableFrom(type) && !ReferenceEquals(type.GetConstructor(new Type[0]), null))
|
||||
{
|
||||
unorderedTypes.Enqueue(type);
|
||||
}
|
||||
}
|
||||
|
||||
var registrarTypes = new List<Type>();
|
||||
while (unorderedTypes.Count > 0)
|
||||
{
|
||||
var type = unorderedTypes.Dequeue();
|
||||
var addToTypesList = true;
|
||||
foreach (var stackType in unorderedTypes)
|
||||
{
|
||||
if (!type.Assembly.GetReferencedAssemblies().Contains(stackType.Assembly.GetName(), comparer))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
addToTypesList = false;
|
||||
unorderedTypes.Enqueue(type);
|
||||
break;
|
||||
}
|
||||
if (addToTypesList)
|
||||
{
|
||||
registrarTypes.Add(type);
|
||||
}
|
||||
}
|
||||
|
||||
return registrarTypes;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal abstract class ServiceLocationManager : IServiceLocationManager
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public void RegisterServiceInstance<TService>(TService instance)
|
||||
{
|
||||
this.RegisterServiceInstance(typeof(TService),
|
||||
instance);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public abstract void RegisterServiceInstance(Type type, object instance);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RegisterServiceType<T>(Type registrationValue)
|
||||
{
|
||||
this.RegisterServiceType(typeof(T),
|
||||
registrationValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RegisterServiceType<TInterface, TConcreate>() where TConcreate : class, TInterface
|
||||
{
|
||||
this.RegisterServiceType(typeof(TInterface), typeof(TConcreate));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void RegisterServiceType(Type type, Type registrationValue)
|
||||
{
|
||||
ThrowIfInvalidRegistration(type, registrationValue);
|
||||
|
||||
var obj = Activator.CreateInstance(registrationValue);
|
||||
|
||||
this.RegisterServiceInstance(type, obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if the type or implementation are null.
|
||||
/// </summary>
|
||||
/// <param name="type">A Type object.</param>
|
||||
/// <param name="implementation">The implementation of the given Type.</param>
|
||||
internal static void ThrowIfNullInstance(Type type, object implementation)
|
||||
{
|
||||
if (ReferenceEquals(type, null))
|
||||
{
|
||||
var msg = string.Format(CultureInfo.InvariantCulture,
|
||||
"Cannot register a null service.");
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
|
||||
if (ReferenceEquals(implementation, null))
|
||||
{
|
||||
var msg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"A service cannot have a null implementation '{0}'",
|
||||
type.FullName);
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if the given Type and implementation represent an invalid registration.
|
||||
/// An invalid registration is one where the given Type is of a restricted type, is not an interface, or the given implementation does not inherit from the given Type.
|
||||
/// </summary>
|
||||
/// <param name="type">A Type object.</param>
|
||||
/// <param name="implementation">The implementation of the given Type.</param>
|
||||
internal static void ThrowIfInvalidRegistration(Type type, Type implementation)
|
||||
{
|
||||
ThrowIfNullInstance(type,
|
||||
implementation);
|
||||
if (type == typeof(IServiceLocationRuntimeManager) ||
|
||||
type == typeof(IServiceLocationOverrideManager) ||
|
||||
type == typeof(IServiceLocationManager) ||
|
||||
type == typeof(IServiceLocator))
|
||||
{
|
||||
var msg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Service location services cannot be registered or overriden: '{0}'",
|
||||
type.FullName);
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
if (!type.IsInterface)
|
||||
{
|
||||
var msg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"The following type: '{0}' is not an interface",
|
||||
type.FullName);
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
if (!type.IsAssignableFrom(implementation))
|
||||
{
|
||||
var msg = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"Cannot register or ovverride the service '{0}' for the type '{1}' which is not derived from the service",
|
||||
implementation.FullName,
|
||||
type.FullName);
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <inheritdoc/>
|
||||
class ServiceLocationRegistrarFactory : IServiceLocationRegistrarFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public IServiceLocationRegistrar Create(Type type)
|
||||
{
|
||||
return (IServiceLocationRegistrar)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
173
Openstack/Openstack.Common/ServiceLocation/ServiceLocator.cs
Normal file
173
Openstack/Openstack.Common/ServiceLocation/ServiceLocator.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common.ServiceLocation
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ServiceLocator : IServiceLocator
|
||||
{
|
||||
private static IServiceLocator _instance = new ServiceLocator();
|
||||
private readonly ServiceLocationManager _runtimeManager;
|
||||
private readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
|
||||
private readonly Dictionary<Type, object> _overrideServices = new Dictionary<Type, object>();
|
||||
private readonly IServiceLocationAssemblyScanner _scanner = new ServiceLocationAssemblyScanner();
|
||||
|
||||
|
||||
public static IServiceLocator Instance
|
||||
{
|
||||
get { return _instance; }
|
||||
}
|
||||
|
||||
internal static void Reset()
|
||||
{
|
||||
_instance = new ServiceLocator();
|
||||
}
|
||||
|
||||
private ServiceLocator()
|
||||
{
|
||||
this._runtimeManager = new ServiceLocationRuntimeManager(this);
|
||||
this._services.Add(typeof(IServiceLocationRuntimeManager), this._runtimeManager);
|
||||
this._services.Add(typeof(IServiceLocationOverrideManager), new ServiceLocationOverrideManager(this));
|
||||
this.RegisterServices();
|
||||
}
|
||||
|
||||
private void RegisterServices()
|
||||
{
|
||||
var registrars = this._scanner.GetRegistrars().ToList();
|
||||
foreach (var serviceLocationRegistrar in registrars)
|
||||
{
|
||||
serviceLocationRegistrar.Register(this._runtimeManager, this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public T Locate<T>()
|
||||
{
|
||||
return (T)this.Locate(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates an implementation of the given Type.
|
||||
/// </summary>
|
||||
/// <param name="type">The Type to locate.</param>
|
||||
/// <returns>The implementation of the given type that has been located.</returns>
|
||||
internal object Locate(Type type)
|
||||
{
|
||||
var retval = this.InternalLocate(type);
|
||||
if (retval != null)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (this._scanner.HasNewAssemblies())
|
||||
{
|
||||
this.RegisterServices();
|
||||
retval = this.InternalLocate(type);
|
||||
}
|
||||
|
||||
if (retval != null)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
var message = string.Format(CultureInfo.InvariantCulture,
|
||||
"Service '{0}' has not been registered",
|
||||
type.FullName);
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locates an implementation of the given Type.
|
||||
/// </summary>
|
||||
/// <param name="type">The Type to locate.</param>
|
||||
/// <returns>The implementation of the given type that has been located.</returns>
|
||||
private object InternalLocate(Type type)
|
||||
{
|
||||
if (ReferenceEquals(type,
|
||||
null))
|
||||
{
|
||||
throw new ArgumentNullException("type");
|
||||
}
|
||||
object runtimeVersion = null;
|
||||
object overrideVersion = null;
|
||||
|
||||
// First try to get a an override
|
||||
if (!this._overrideServices.TryGetValue(type, out overrideVersion))
|
||||
{
|
||||
//if no override, then try to get the actual service.
|
||||
this._services.TryGetValue(type, out runtimeVersion);
|
||||
}
|
||||
|
||||
return overrideVersion ?? runtimeVersion;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
private class ServiceLocationRuntimeManager : ServiceLocationManager, IServiceLocationRuntimeManager
|
||||
{
|
||||
private readonly ServiceLocator _locator;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ServiceLocationRuntimeManager(ServiceLocator locator)
|
||||
{
|
||||
this._locator = locator;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void RegisterServiceInstance(Type type, object instance)
|
||||
{
|
||||
ThrowIfNullInstance(type,
|
||||
instance);
|
||||
ThrowIfInvalidRegistration(type,
|
||||
instance.GetType());
|
||||
var internalManager = new RuntimeRegistrationManager(this._locator);
|
||||
internalManager.RegisterServiceInstance(type,
|
||||
instance);
|
||||
foreach (KeyValuePair<Type, object> keyValuePair in internalManager.GetDiscovered())
|
||||
{
|
||||
this._locator._services[keyValuePair.Key] = keyValuePair.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
private class ServiceLocationOverrideManager : ServiceLocationManager, IServiceLocationOverrideManager
|
||||
{
|
||||
private readonly ServiceLocator _locator;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ServiceLocationOverrideManager(ServiceLocator locator)
|
||||
{
|
||||
this._locator = locator;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void RegisterServiceInstance(Type type, object instance)
|
||||
{
|
||||
ThrowIfNullInstance(type,
|
||||
instance);
|
||||
ThrowIfInvalidRegistration(type,
|
||||
instance.GetType());
|
||||
|
||||
this._locator._overrideServices[type] = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
Openstack/Openstack.Common/ServiceRegistrar.cs
Normal file
35
Openstack/Openstack.Common/ServiceRegistrar.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Common
|
||||
{
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class ServiceRegistrar : IServiceLocationRegistrar
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers relevant services for the Openstack.Common namespace.
|
||||
/// </summary>
|
||||
/// <param name="manager">The service manager to use when registering the services.</param>
|
||||
/// <param name="locator">A reference to the service locator.</param>
|
||||
public void Register(IServiceLocationManager manager, IServiceLocator locator)
|
||||
{
|
||||
manager.RegisterServiceInstance(typeof(IHttpAbstractionClientFactory), new HttpAbstractionClientFactory());
|
||||
}
|
||||
}
|
||||
}
|
73
Openstack/Openstack.Test/Helper.cs
Normal file
73
Openstack/Openstack.Test/Helper.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
public static class TestHelper
|
||||
{
|
||||
public static MemoryStream CreateStream(string input)
|
||||
{
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes(input);
|
||||
return new MemoryStream(byteArray);
|
||||
}
|
||||
|
||||
public static string GetStringFromStream(Stream input)
|
||||
{
|
||||
var reader = new StreamReader(input);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
public static IHttpResponseAbstraction CreateErrorResponse()
|
||||
{
|
||||
return new HttpResponseAbstraction(null, new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
}
|
||||
|
||||
public static IHttpResponseAbstraction CreateResponse(HttpStatusCode code)
|
||||
{
|
||||
return new HttpResponseAbstraction(null, new HttpHeadersAbstraction(), code);
|
||||
}
|
||||
|
||||
public static IHttpResponseAbstraction CreateResponse(HttpStatusCode code, IEnumerable<KeyValuePair<string, string>> headers)
|
||||
{
|
||||
var abstractionHeaders = new HttpHeadersAbstraction();
|
||||
foreach (var header in headers)
|
||||
{
|
||||
abstractionHeaders.Add(header.Key, header.Value);
|
||||
}
|
||||
return new HttpResponseAbstraction(null, abstractionHeaders, code);
|
||||
}
|
||||
|
||||
public static IHttpResponseAbstraction CreateResponse(HttpStatusCode code, IEnumerable<KeyValuePair<string, string>> headers, Stream content)
|
||||
{
|
||||
var abstractionHeaders = new HttpHeadersAbstraction();
|
||||
foreach (var header in headers)
|
||||
{
|
||||
abstractionHeaders.Add(header.Key, header.Value);
|
||||
}
|
||||
return new HttpResponseAbstraction(content, abstractionHeaders, code);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,278 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
namespace Openstack.Test.HttpAbstraction
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpAbstractionClientTests
|
||||
{
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void CanMakeGetRequest()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/get");
|
||||
client.Method = HttpMethod.Get;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
Assert.IsNotNull(response.Content);
|
||||
var content = TestHelper.GetStringFromStream(response.Content);
|
||||
Assert.AreNotEqual(0, content.Length);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void ResponsesIncludeContentHeaders()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create(new TimeSpan(0, 5, 0), CancellationToken.None))
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/get");
|
||||
client.Method = HttpMethod.Get;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
Assert.IsTrue(response.Headers.Contains("Content-Length"));
|
||||
Assert.IsTrue(response.Headers.Contains("Content-Type"));
|
||||
|
||||
Assert.AreEqual("214", response.Headers["Content-Length"].First());
|
||||
Assert.AreEqual("application/json", response.Headers["Content-Type"].First());
|
||||
|
||||
Assert.IsNotNull(response.Content);
|
||||
var content = TestHelper.GetStringFromStream(response.Content);
|
||||
Assert.AreNotEqual(0, content.Length);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void CanMakePutRequest()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
using (var content = TestHelper.CreateStream("Test Text"))
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/put");
|
||||
client.Method = HttpMethod.Put;
|
||||
client.Content = content;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
Assert.IsNotNull(response.Content);
|
||||
|
||||
var stringContent = TestHelper.GetStringFromStream(response.Content);
|
||||
Assert.AreNotEqual(0, stringContent.Length);
|
||||
Assert.IsTrue(stringContent.Contains("\"data\": \"Test Text\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void CanMakePostRequest()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
using (var content = TestHelper.CreateStream("Test Text"))
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/post");
|
||||
client.Method = HttpMethod.Post;
|
||||
client.Content = content;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var stringContent = TestHelper.GetStringFromStream(response.Content);
|
||||
|
||||
Assert.IsTrue(stringContent.Contains("\"data\": \"Test Text\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void CanMakeDeleteRequest()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
|
||||
client.Uri = new Uri("http://httpbin.org/delete");
|
||||
client.Method = HttpMethod.Delete;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
Assert.IsNotNull(response.Content);
|
||||
var content = TestHelper.GetStringFromStream(response.Content);
|
||||
Assert.AreNotEqual(0, content.Length);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void CanMakeMultipleGetRequestsWithSameClient()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
|
||||
client.Uri = new Uri("http://httpbin.org/get");
|
||||
client.Method = HttpMethod.Get;
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
|
||||
responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void RequestsHonorsClientSideTimeout()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create(TimeSpan.FromMilliseconds(100)))
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/delay/30000");
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
}
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
var inner = ex.InnerException;
|
||||
Assert.IsInstanceOfType(inner,typeof(TimeoutException));
|
||||
Assert.IsTrue(inner.Message.Contains("failed to complete in the given timeout period"));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void RequestsHonorsCancelationToken()
|
||||
{
|
||||
var token = new CancellationToken(true);
|
||||
var startTime = DateTime.Now;
|
||||
|
||||
try
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create(token))
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/delay/30000");
|
||||
client.Timeout = TimeSpan.FromSeconds(31);
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
}
|
||||
}
|
||||
catch (AggregateException ex)
|
||||
{
|
||||
var inner = ex.InnerException;
|
||||
Assert.IsTrue(DateTime.Now - startTime < TimeSpan.FromSeconds(30));
|
||||
Assert.IsTrue(inner.Message.Contains("A task was canceled"));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void RequestsHandlesHttpErrors()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/status/404");
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
|
||||
|
||||
var stringContent = TestHelper.GetStringFromStream(response.Content);
|
||||
|
||||
Assert.AreEqual(string.Empty, stringContent);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Integration")]
|
||||
[TestCategory("LongRunning")]
|
||||
public void RequestsCanSendHeaders()
|
||||
{
|
||||
using (var client = new HttpAbstractionClientFactory().Create())
|
||||
{
|
||||
client.Uri = new Uri("http://httpbin.org/get");
|
||||
client.Headers.Add("X-Test-Header","TEST");
|
||||
|
||||
var responseTask = client.SendAsync();
|
||||
responseTask.Wait();
|
||||
var response = responseTask.Result;
|
||||
|
||||
Assert.IsNotNull(response);
|
||||
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
Assert.IsNotNull(response.Content);
|
||||
var content = TestHelper.GetStringFromStream(response.Content);
|
||||
Assert.AreNotEqual(0, content.Length);
|
||||
|
||||
Assert.IsTrue(content.Contains("\"X-Test-Header\": \"TEST\""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
namespace Openstack.Test.HttpAbstraction
|
||||
{
|
||||
[TestClass]
|
||||
public class HttpHeadersAbstractionTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanAddHeaders()
|
||||
{
|
||||
var headers = new HttpHeadersAbstraction();
|
||||
headers.Add("Test","Value");
|
||||
Assert.IsTrue(headers.Contains("Test"));
|
||||
Assert.AreEqual("Value",headers["Test"].First());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanAddRangeHeaders()
|
||||
{
|
||||
var headers = new HttpHeadersAbstraction();
|
||||
|
||||
var rspMsg = new HttpResponseMessage();
|
||||
rspMsg.Headers.Add("Test", "Value");
|
||||
|
||||
headers.AddRange(rspMsg.Headers);
|
||||
Assert.IsTrue(headers.Contains("Test"));
|
||||
Assert.AreEqual("Value", headers["Test"].First());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanClearHeaders()
|
||||
{
|
||||
var headers = new HttpHeadersAbstraction();
|
||||
headers.Add("Test", "Value");
|
||||
Assert.IsTrue(headers.Contains("Test"));
|
||||
|
||||
headers.Clear();
|
||||
Assert.AreEqual(0,headers.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetValuesHeaders()
|
||||
{
|
||||
var headers = new HttpHeadersAbstraction();
|
||||
var values = new List<string>() {"value1", "value2"};
|
||||
headers.Add("Test", values);
|
||||
Assert.IsTrue(headers.Contains("Test"));
|
||||
Assert.AreEqual(values, headers.GetValues("Test"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanTryGetValuesHeaders()
|
||||
{
|
||||
var headers = new HttpHeadersAbstraction();
|
||||
var values = new List<string>() { "value1", "value2" };
|
||||
headers.Add("Test", values);
|
||||
|
||||
IEnumerable<string> resValues = new List<string>();
|
||||
Assert.IsTrue(headers.TryGetValue("Test", out resValues));
|
||||
|
||||
Assert.AreEqual(2,resValues.Count());
|
||||
Assert.AreEqual(values, resValues);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class AccessTokenPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayload()
|
||||
{
|
||||
var AuthJsonResponseFixture = @"{
|
||||
""access"": {
|
||||
""token"": {
|
||||
""expires"": ""2014-03-18T10:59:46.355Z"",
|
||||
""id"": ""HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb"",
|
||||
""tenant"": {
|
||||
""id"": ""10244656540440"",
|
||||
""name"": ""10255892528404-Project""
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
var expectedToken = "HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb";
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
var token = converter.Convert(AuthJsonResponseFixture);
|
||||
Assert.IsNotNull(token);
|
||||
Assert.AreEqual(expectedToken, token);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadMissingTokenId()
|
||||
{
|
||||
var missingTokenIdFixture = @"{
|
||||
""access"": {
|
||||
""token"": {
|
||||
""expires"": ""2014-03-18T10:59:46.355Z"",
|
||||
""tenant"": {
|
||||
""id"": ""10244656540440"",
|
||||
""name"": ""10255892528404-Project""
|
||||
}
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
converter.Convert(missingTokenIdFixture);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadMissingToken()
|
||||
{
|
||||
var missingTokenFixture = @"{
|
||||
""access"": { }
|
||||
}";
|
||||
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
converter.Convert(missingTokenFixture);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadEmptyObject()
|
||||
{
|
||||
var emptyObjectFixture = @"{ }";
|
||||
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
converter.Convert(emptyObjectFixture);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertInvalidJson()
|
||||
{
|
||||
var badJsonFixture = @"{ NOT JSON";
|
||||
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
converter.Convert(badJsonFixture);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertNonObjectJson()
|
||||
{
|
||||
var nonObjectJson = @"[]";
|
||||
|
||||
var converter = new AccessTokenPayloadConverter();
|
||||
converter.Convert(nonObjectJson);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,210 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
public class IdentityRestServiceSimulator : DisposableClass, IHttpAbstractionClient
|
||||
{
|
||||
#region Authentication Json Response Fixture
|
||||
|
||||
internal string AuthJsonResponseFixture = @"{
|
||||
""access"": {
|
||||
""token"": {
|
||||
""expires"": ""2014-03-18T10:59:46.355Z"",
|
||||
""id"": ""HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb"",
|
||||
""tenant"": {
|
||||
""id"": ""10244656540440"",
|
||||
""name"": ""10255892528404-Project""
|
||||
}
|
||||
},
|
||||
""user"": {
|
||||
""id"": ""10391119133001"",
|
||||
""name"": ""wayne.foley"",
|
||||
""otherAttributes"": {
|
||||
""domainStatus"": ""enabled"",
|
||||
""domainStatusCode"": ""00""
|
||||
},
|
||||
""roles"": [ ]
|
||||
},
|
||||
""serviceCatalog"": [
|
||||
{
|
||||
""name"": ""Networking"",
|
||||
""type"": ""network"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.network.hpcloudsvc.com"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""2.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.network.hpcloudsvc.com"",
|
||||
""versionList"": ""https://region-a.geo-1.network.hpcloudsvc.com""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
""name"": ""Identity"",
|
||||
""type"": ""identity"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""publicURL"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""2.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357/v2.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357""
|
||||
},
|
||||
{
|
||||
""publicURL"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357/v3/"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""3.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357/v3/"",
|
||||
""versionList"": ""https://region-a.geo-1.identity.hpcloudsvc.com:35357""
|
||||
},
|
||||
{
|
||||
""publicURL"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""2.0"",
|
||||
""versionInfo"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/"",
|
||||
""versionList"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357""
|
||||
},
|
||||
{
|
||||
""publicURL"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357/v3/"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""3.0"",
|
||||
""versionInfo"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357/v3/"",
|
||||
""versionList"": ""https://region-b.geo-1.identity.hpcloudsvc.com:35357""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
""name"": ""Compute"",
|
||||
""type"": ""compute"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.compute.hpcloudsvc.com/v2/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""2"",
|
||||
""versionInfo"": ""https://region-a.geo-1.compute.hpcloudsvc.com/v2/"",
|
||||
""versionList"": ""https://region-a.geo-1.compute.hpcloudsvc.com""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}";
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public HttpMethod Method { get; set; }
|
||||
public Uri Uri { get; set; }
|
||||
public Stream Content { get; set; }
|
||||
public IDictionary<string, string> Headers { get; private set; }
|
||||
public string ContentType { get; set; }
|
||||
public TimeSpan Timeout { get; set; }
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpReceiveProgress;
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpSendProgress;
|
||||
|
||||
public IdentityRestServiceSimulator()
|
||||
{
|
||||
this.Headers = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> SendAsync()
|
||||
{
|
||||
var resp = TestHelper.CreateResponse(HttpStatusCode.OK, new List<KeyValuePair<string, string>>(),
|
||||
this.AuthJsonResponseFixture.ConvertToStream());
|
||||
return Task.Factory.StartNew(() => resp);
|
||||
}
|
||||
}
|
||||
|
||||
public class IdentityRestServiceSimulatorFactory : IHttpAbstractionClientFactory
|
||||
{
|
||||
internal IdentityRestServiceSimulator Simulator;
|
||||
|
||||
public IdentityRestServiceSimulatorFactory(IdentityRestServiceSimulator simulator)
|
||||
{
|
||||
this.Simulator = simulator;
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(CancellationToken token)
|
||||
{
|
||||
if (this.Simulator != null)
|
||||
{
|
||||
this.Simulator.Headers.Clear();
|
||||
}
|
||||
return this.Simulator ?? new IdentityRestServiceSimulator();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(IOpenStackAccessToken credentials, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(IOpenStackAccessToken credentials, TimeSpan timeout, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Identity;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class IdentityServiceClientDefinitionTests
|
||||
{
|
||||
public IOpenstackCredential GetValidCredentials()
|
||||
{
|
||||
var endpoint = new Uri("https://someidentityendpoint:35357/v2.0/tokens");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
return new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSupportVersion2()
|
||||
{
|
||||
var client = new IdentityServiceClientDefinition();
|
||||
|
||||
Assert.IsTrue(client.IsSupported(GetValidCredentials()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CannotSupportVersion1()
|
||||
{
|
||||
var endpoint = new Uri("https://someidentityendpoint:35357/v1.0/tokens");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var creds = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
|
||||
var client = new IdentityServiceClientDefinition();
|
||||
|
||||
Assert.IsFalse(client.IsSupported(creds));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Version2Supported()
|
||||
{
|
||||
var client = new IdentityServiceClientDefinition();
|
||||
Assert.IsTrue(client.ListSupportedVersions().Contains("2.0.0.0"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class IdentityServiceClientTests
|
||||
{
|
||||
internal TestIdentityServicePocoClient pocoClient;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
this.pocoClient = new TestIdentityServicePocoClient();
|
||||
|
||||
ServiceLocator.Reset();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
manager.RegisterServiceInstance(typeof(IIdentityServicePocoClientFactory), new TestIdentityServicePocoClientFactory(pocoClient));
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.pocoClient = new TestIdentityServicePocoClient();
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
public IOpenstackCredential GetValidCredentials()
|
||||
{
|
||||
var endpoint = new Uri("https://someidentityendpoint:35357/v2.0/tokens");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
return new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanAuthenticate()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
var token = "someToken";
|
||||
|
||||
this.pocoClient.AuthenticationDelegate = () =>
|
||||
{
|
||||
creds.SetAccessTokenId(token);
|
||||
return Task.Factory.StartNew(() => creds);
|
||||
};
|
||||
|
||||
var client = new IdentityServiceClientDefinition().Create(GetValidCredentials(),CancellationToken.None) as IdentityServiceClient;
|
||||
var resp = await client.Authenticate();
|
||||
|
||||
Assert.AreEqual(creds, resp);
|
||||
Assert.AreEqual(creds,client.Credential);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,286 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class IdentityServicePocoClientTests
|
||||
{
|
||||
internal TestIdentityServiceRestClient RestClient;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
this.RestClient = new TestIdentityServiceRestClient();
|
||||
|
||||
ServiceLocator.Reset();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
manager.RegisterServiceInstance(typeof(IIdentityServiceRestClientFactory), new TestIdentityServiceRestClientFactory(RestClient));
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.RestClient = new TestIdentityServiceRestClient();
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
public IOpenstackCredential GetValidCredentials()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
return new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanAuthenticateWithOkResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var expectedToken = "HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb";
|
||||
|
||||
var payload = @"{
|
||||
""access"": {
|
||||
""token"": {
|
||||
""expires"": ""2014-03-18T10:59:46.355Z"",
|
||||
""id"": ""HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb"",
|
||||
""tenant"": {
|
||||
""id"": ""10244656540440"",
|
||||
""name"": ""10255892528404-Project""
|
||||
}
|
||||
},
|
||||
""serviceCatalog"":[{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, new HttpHeadersAbstraction(), HttpStatusCode.OK);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client =
|
||||
new IdentityServicePocoClientFactory().Create(creds, CancellationToken.None) as
|
||||
IdentityServicePocoClient;
|
||||
var result = await client.Authenticate();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(creds.UserName, result.UserName);
|
||||
Assert.AreEqual(creds.Password.ConvertToUnsecureString(), result.Password.ConvertToUnsecureString());
|
||||
Assert.AreEqual(creds.TenantId, result.TenantId);
|
||||
Assert.AreEqual(expectedToken, result.AccessTokenId);
|
||||
Assert.AreEqual(1,result.ServiceCatalog.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanAuthenticateWithNonAuthoritativeInfoResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var expectedToken = "HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb";
|
||||
|
||||
var payload = @"{
|
||||
""access"": {
|
||||
""token"": {
|
||||
""expires"": ""2014-03-18T10:59:46.355Z"",
|
||||
""id"": ""HPAuth10_af3d1bfe456d18e8d4793e54922f839fa051d9f60f115aca52c9a44f9e3d96fb"",
|
||||
""tenant"": {
|
||||
""id"": ""10244656540440"",
|
||||
""name"": ""10255892528404-Project""
|
||||
}
|
||||
},
|
||||
""serviceCatalog"":[{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, new HttpHeadersAbstraction(), HttpStatusCode.NonAuthoritativeInformation);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
var result = await client.Authenticate();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(creds.UserName, result.UserName);
|
||||
Assert.AreEqual(creds.Password.ConvertToUnsecureString(), result.Password.ConvertToUnsecureString());
|
||||
Assert.AreEqual(creds.TenantId, result.TenantId);
|
||||
Assert.AreEqual(expectedToken, result.AccessTokenId);
|
||||
Assert.AreEqual(1, result.ServiceCatalog.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithUnauthorizedResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithBadRequestResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.BadRequest);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithInternalServerErrorResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithForbiddenResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Forbidden);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithBadMethodResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.MethodNotAllowed);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithOverLimitResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.RequestEntityTooLarge);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithServiceUnavailableResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.ServiceUnavailable);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task CannotAuthenticateWithNotFoundResponse()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NotFound);
|
||||
this.RestClient.Response = restResp;
|
||||
|
||||
var client = new IdentityServicePocoClient(creds, CancellationToken.None);
|
||||
await client.Authenticate();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class IdentityServiceRestClientTests
|
||||
{
|
||||
internal IdentityRestServiceSimulator simulator;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
//this is here to force the Object assembly to get loaded. This is a bug in the test runner.
|
||||
//var binder = typeof (Openstack.ServiceRegistrar);
|
||||
|
||||
this.simulator = new IdentityRestServiceSimulator();
|
||||
|
||||
ServiceLocator.Reset();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
manager.RegisterServiceInstance(typeof(IHttpAbstractionClientFactory), new IdentityRestServiceSimulatorFactory(simulator));
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.simulator = new IdentityRestServiceSimulator();
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
public IOpenstackCredential GetValidCredentials()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
return new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AuthenticationMethodAndUriAreValid()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
var client = new IdentityServiceRestClientFactory().Create(creds,CancellationToken.None);
|
||||
|
||||
await client.Authenticate();
|
||||
|
||||
Assert.AreEqual(creds.AuthenticationEndpoint, this.simulator.Uri);
|
||||
Assert.AreEqual(HttpMethod.Post, this.simulator.Method);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AuthenticateIncludesCorrectHeaders()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
var client = new IdentityServiceRestClient(creds, CancellationToken.None);
|
||||
|
||||
await client.Authenticate();
|
||||
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("Accept"));
|
||||
Assert.AreEqual("application/json", this.simulator.Headers["Accept"]);
|
||||
Assert.AreEqual("application/json", this.simulator.ContentType);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task AuthenticateIncludesPayload()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
var client = new IdentityServiceRestClient(creds, CancellationToken.None);
|
||||
|
||||
await client.Authenticate();
|
||||
|
||||
Assert.IsNotNull(this.simulator.Content);
|
||||
|
||||
var content = TestHelper.GetStringFromStream(this.simulator.Content);
|
||||
Assert.IsTrue(content.Length > 0);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AuthenticationPayloadIsGeneratedCorrectly()
|
||||
{
|
||||
var creds = GetValidCredentials();
|
||||
var payload = IdentityServiceRestClient.CreateAuthenticationJsonPayload(creds);
|
||||
|
||||
var obj = JObject.Parse(payload);
|
||||
var userName = obj["auth"]["passwordCredentials"]["username"];
|
||||
var password = obj["auth"]["passwordCredentials"]["password"];
|
||||
var tenantId = obj["auth"]["tenantName"];
|
||||
|
||||
Assert.AreEqual(creds.UserName, userName);
|
||||
Assert.AreEqual(creds.Password.ConvertToUnsecureString(), password);
|
||||
Assert.AreEqual(creds.TenantId, tenantId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
180
Openstack/Openstack.Test/Identity/OpenstackCredentialTests.cs
Normal file
180
Openstack/Openstack.Test/Identity/OpenstackCredentialTests.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackCredentialTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanCreateAnOpenstackCredential()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
|
||||
Assert.IsNotNull(cred);
|
||||
Assert.AreEqual(userName, cred.UserName);
|
||||
Assert.AreEqual(endpoint, cred.AuthenticationEndpoint);
|
||||
Assert.IsNotNull(cred.Password);
|
||||
Assert.AreEqual(tenantId, cred.TenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSetAcessTokenId()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
var token = "someToken";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
cred.SetAccessTokenId(token);
|
||||
|
||||
Assert.AreEqual(token, cred.AccessTokenId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotSetAcessTokenIdWithNullToken()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
cred.SetAccessTokenId(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSetServiceCatalog()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
cred.SetServiceCatalog(catalog);
|
||||
|
||||
Assert.AreEqual(catalog, cred.ServiceCatalog);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotSetServiceCatalogWithNullToken()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
cred.SetServiceCatalog(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void CannotSetAcessTokenIdWithEmptyToken()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, tenantId);
|
||||
cred.SetAccessTokenId(string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithNullEndpoint()
|
||||
{
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(null, userName, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithNullUserName()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, null, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithEmptyUserName()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, string.Empty, password, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithNullPassword()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var tenantId = "12345";
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, null, tenantId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithNullTenantId()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void CannotCreateAnOpenstackCredentialWithEmptyTenantId()
|
||||
{
|
||||
var endpoint = new Uri("https://auth.someplace.com/authme");
|
||||
var userName = "TestUser";
|
||||
var password = "RandomPassword".ConvertToSecureString();
|
||||
|
||||
var cred = new OpenstackCredential(endpoint, userName, password, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,190 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackServiceCatalogPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayload()
|
||||
{
|
||||
var expectedName = "Object Storage";
|
||||
var expectedType = "object-store";
|
||||
|
||||
var serviceCatalogPayload = @"{
|
||||
""access"": {
|
||||
|
||||
""serviceCatalog"":[{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}]}}";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
var serviceDefs = converter.Convert(serviceCatalogPayload).ToList();
|
||||
|
||||
Assert.AreEqual(1, serviceDefs.Count());
|
||||
|
||||
var service = serviceDefs.First(i => i.Name == expectedName);
|
||||
Assert.IsNotNull(service);
|
||||
Assert.AreEqual(expectedName, service.Name);
|
||||
Assert.AreEqual(expectedType, service.Type);
|
||||
Assert.AreEqual(2, service.Endpoints.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayloadWithMultipleServiceDefs()
|
||||
{
|
||||
var expectedName1 = "Object Storage";
|
||||
var expectedType1 = "object-store";
|
||||
|
||||
var expectedName2 = "Some Other Service";
|
||||
var expectedType2 = "other-service";
|
||||
|
||||
var serviceCatalogPayload = @"{
|
||||
""access"": {
|
||||
|
||||
""serviceCatalog"":[{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
""name"": ""Some Other Service"",
|
||||
""type"": ""other-service"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
}
|
||||
]
|
||||
}]}}";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
var serviceDefs = converter.Convert(serviceCatalogPayload).ToList();
|
||||
|
||||
Assert.AreEqual(2, serviceDefs.Count());
|
||||
|
||||
var service1 = serviceDefs.First(i => i.Name == expectedName1);
|
||||
Assert.IsNotNull(service1);
|
||||
Assert.AreEqual(expectedName1, service1.Name);
|
||||
Assert.AreEqual(expectedType1, service1.Type);
|
||||
Assert.AreEqual(2, service1.Endpoints.Count());
|
||||
|
||||
var service2 = serviceDefs.First(i => i.Name == expectedName2);
|
||||
Assert.IsNotNull(service1);
|
||||
Assert.AreEqual(expectedName2, service2.Name);
|
||||
Assert.AreEqual(expectedType2, service2.Type);
|
||||
Assert.AreEqual(1, service2.Endpoints.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingCatalog()
|
||||
{
|
||||
var serviceCatalogPayload = @"{
|
||||
""access"": {
|
||||
|
||||
}}";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
converter.Convert(serviceCatalogPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithEmptyObject()
|
||||
{
|
||||
var serviceDefPayload = @" { }";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotConvertWithNullJsonPayload()
|
||||
{
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
converter.Convert(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertInvalidJsonPayload()
|
||||
{
|
||||
var serviceDefPayload = @" { NOT JSON";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertNonObjectJsonPayload()
|
||||
{
|
||||
var serviceDefPayload = @"[]";
|
||||
|
||||
var converter = new OpenstackServiceCatalogPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,224 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackServiceCatalogTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanGetPublicEndpointForService()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog {serviceDef};
|
||||
var endpoint = catalog.GetPublicEndpoint("Test Service", "some region");
|
||||
Assert.AreEqual(expectedEndpoint,endpoint);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetPublicEndpointForServiceWithMultipleServicesInCatalog()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
catalog.Add(new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
catalog.Add(new OpenstackServiceDefinition("Other Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://other.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
var endpoint = catalog.GetPublicEndpoint("Test Service", "some region");
|
||||
Assert.AreEqual(expectedEndpoint, endpoint);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotGetPublicEndpointWithNoMatchingService()
|
||||
{
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
catalog.Add(new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://some.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
catalog.Add(new OpenstackServiceDefinition("Other Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://other.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
catalog.GetPublicEndpoint("Missing Service", "some region");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotGetPublicEndpointWithServiceAndNoEndpoints()
|
||||
{
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
catalog.Add(new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()));
|
||||
|
||||
catalog.Add(new OpenstackServiceDefinition("Other Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://other.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
catalog.GetPublicEndpoint("Test Service", "some region");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetPublicEndpointWithServiceAndMultipleEndpoints()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
catalog.Add(new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://public.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com")),
|
||||
|
||||
new OpenstackServiceEndpoint("http://other.endpoint.org", "some other region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
var endpoint = catalog.GetPublicEndpoint("Test Service", "some region");
|
||||
Assert.AreEqual(expectedEndpoint, endpoint);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IfAServiceExistsCatalogReturnsTrue()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog { serviceDef };
|
||||
Assert.IsTrue(catalog.Exists("Test Service"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void IfAServiceDoesNotExistsCatalogReturnsFalse()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog { serviceDef };
|
||||
Assert.IsFalse(catalog.Exists("NOT IN CATALOG"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetServicesInRegion()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog { serviceDef };
|
||||
var services = catalog.GetServicesInAvailabilityZone("some region").ToList();
|
||||
Assert.AreEqual(1,services.Count());
|
||||
Assert.AreEqual("Test Service",services.First().Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetServicesInRegionWithMultipleServices()
|
||||
{
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
catalog.Add(new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://some.endpoint.com", "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
catalog.Add(new OpenstackServiceDefinition("Other Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://other.endpoint.org", "some region", "1.0",
|
||||
new Uri("http://www.someotherplace.com"), new Uri("http://www.someplace.com"))
|
||||
}));
|
||||
|
||||
var services = catalog.GetServicesInAvailabilityZone("some region").ToList();
|
||||
Assert.AreEqual(2, services.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GettingServicesInRegionWhenNonExistReturnsAnEmptyCollection()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog { serviceDef };
|
||||
var services = catalog.GetServicesInAvailabilityZone("some other region").ToList();
|
||||
Assert.AreEqual(0, services.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetServicesForRegionWithMultipleEndpoints()
|
||||
{
|
||||
var expectedEndpoint = new Uri("http://public.endpoint.org");
|
||||
var serviceDef = new OpenstackServiceDefinition("Test Service", "Test-Service",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com")),
|
||||
new OpenstackServiceEndpoint(expectedEndpoint.ToString(), "some other region", "1.0",
|
||||
new Uri("http://www.someplace.com"), new Uri("http://www.someplace.com"))
|
||||
});
|
||||
var catalog = new OpenstackServiceCatalog { serviceDef };
|
||||
var services = catalog.GetServicesInAvailabilityZone("some other region").ToList();
|
||||
Assert.AreEqual(1, services.Count());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,177 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackServiceDefinitionPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayload()
|
||||
{
|
||||
var expectedName = "Object Storage";
|
||||
var expectedType = "object-store";
|
||||
|
||||
var serviceDefPayload = @" {
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
var service = converter.Convert(serviceDefPayload);
|
||||
|
||||
Assert.IsNotNull(service);
|
||||
Assert.AreEqual(expectedName, service.Name);
|
||||
Assert.AreEqual(expectedType, service.Type);
|
||||
Assert.AreEqual(2, service.Endpoints.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingName()
|
||||
{
|
||||
var serviceDefPayload = @"{
|
||||
""type"": ""object-store"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingType()
|
||||
{
|
||||
var serviceDefPayload = @"{
|
||||
""name"": ""Object Storage"",
|
||||
""endpoints"": [
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1/10244656540440"",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.objects.hpcloudsvc.com/v1.0/"",
|
||||
""versionList"": ""https://region-a.geo-1.objects.hpcloudsvc.com""
|
||||
},
|
||||
{
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/10244656540440"",
|
||||
""region"": ""region-b.geo-1"",
|
||||
""versionId"": ""1"",
|
||||
""versionInfo"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443/v1/"",
|
||||
""versionList"": ""https://region-b.geo-1.objects.hpcloudsvc.com:443""
|
||||
}
|
||||
]
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof (HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingEndpoints()
|
||||
{
|
||||
var serviceDefPayload = @"{
|
||||
""name"": ""Object Storage"",
|
||||
""type"": ""object-store"",
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithEmptyObject()
|
||||
{
|
||||
var serviceDefPayload = @" { }";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotConvertWithNullJsonPayload()
|
||||
{
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertInvalidJsonPayload()
|
||||
{
|
||||
var serviceDefPayload = @" { NOT JSON";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertNonObjectJsonPayload()
|
||||
{
|
||||
var serviceDefPayload = @"[]";
|
||||
|
||||
var converter = new OpenstackServiceDefinitionPayloadConverter();
|
||||
converter.Convert(serviceDefPayload);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,223 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackServiceEndpointPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayload()
|
||||
{
|
||||
var expectedPublicUri = "https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440";
|
||||
var expectedRegion = "region-a.geo-1";
|
||||
var expectedVersion = "1.0";
|
||||
var expectedVersionList = "https://region-a.geo-1.block.hpcloudsvc.com/";
|
||||
var expectedVersionInfo = "https://region-a.geo-1.block.hpcloudsvc.com/v1";
|
||||
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
var endpoint = converter.Convert(endpointPayload);
|
||||
|
||||
Assert.IsNotNull(endpoint);
|
||||
Assert.AreEqual(expectedPublicUri, endpoint.PublicUri.ToString());
|
||||
Assert.AreEqual(expectedRegion, endpoint.Region);
|
||||
Assert.AreEqual(expectedVersion, endpoint.Version);
|
||||
Assert.AreEqual(expectedVersionInfo, endpoint.VersionInformation.ToString());
|
||||
Assert.AreEqual(expectedVersionList, endpoint.VersionList.ToString());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotConvertWithNullJsonPayload()
|
||||
{
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingPublicUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingRegion()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingVersion()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingVersionInfoUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithMissingVersionListUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertJsonPayloadWithBadPublicUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""httpsBAD://reg&VERYBAD&ion-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithBadVersionInfoUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""htBADtps://region&BAD&-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""https://region-a.geo-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertJsonPayloadWithBadVersionListcUri()
|
||||
{
|
||||
var endpointPayload = @" {
|
||||
""tenantId"": ""10244656540440"",
|
||||
""publicURL"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1/10244656540440"",
|
||||
""publicURL2"": """",
|
||||
""region"": ""region-a.geo-1"",
|
||||
""versionId"": ""1.0"",
|
||||
""versionInfo"": ""https://region-a.geo-1.block.hpcloudsvc.com/v1"",
|
||||
""versionList"": ""htBADtps://region-a.ge&BAD&o-1.block.hpcloudsvc.com""
|
||||
}";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertInvalidJsonPayload()
|
||||
{
|
||||
var endpointPayload = @" { NOT JSON";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotConvertNonObjectJsonPayload()
|
||||
{
|
||||
var endpointPayload = @" [] ";
|
||||
|
||||
var converter = new OpenstackServiceEndpointPayloadConverter();
|
||||
converter.Convert(endpointPayload);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
public class TestIdentityServicePocoClient : IIdentityServicePocoClient
|
||||
{
|
||||
public Func<Task<IOpenstackCredential>> AuthenticationDelegate { get; set; }
|
||||
|
||||
public Task<IOpenstackCredential> Authenticate()
|
||||
{
|
||||
return AuthenticationDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
public class TestIdentityServicePocoClientFactory : IIdentityServicePocoClientFactory
|
||||
{
|
||||
internal IIdentityServicePocoClient client;
|
||||
|
||||
public TestIdentityServicePocoClientFactory(IIdentityServicePocoClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public IIdentityServicePocoClient Create(IOpenstackCredential credentials, CancellationToken token)
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test.Identity
|
||||
{
|
||||
public class TestIdentityServiceRestClient : IIdentityServiceRestClient
|
||||
{
|
||||
public IHttpResponseAbstraction Response { get; set; }
|
||||
|
||||
public Task<IHttpResponseAbstraction> Authenticate()
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestIdentityServiceRestClientFactory : IIdentityServiceRestClientFactory
|
||||
{
|
||||
internal IIdentityServiceRestClient Client;
|
||||
|
||||
public TestIdentityServiceRestClientFactory(IIdentityServiceRestClient client)
|
||||
{
|
||||
this.Client = client;
|
||||
}
|
||||
|
||||
public IIdentityServiceRestClient Create(IOpenstackCredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
return Client;
|
||||
}
|
||||
}
|
||||
}
|
41
Openstack/Openstack.Test/ObjectExtentionsTests.cs
Normal file
41
Openstack/Openstack.Test/ObjectExtentionsTests.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Security;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class ObjectExtentionsTests
|
||||
{
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ConvertingNullToSecureStringThrows()
|
||||
{
|
||||
((string) null).ConvertToSecureString();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void ConvertingNullToUnSecureStringThrows()
|
||||
{
|
||||
((SecureString)null).ConvertToUnsecureString();
|
||||
}
|
||||
}
|
||||
}
|
135
Openstack/Openstack.Test/Openstack.Test.csproj
Normal file
135
Openstack/Openstack.Test/Openstack.Test.csproj
Normal file
@@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7AF6DEC5-2257-4A29-BB55-66711DE3055D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Openstack.Test</RootNamespace>
|
||||
<AssemblyName>Openstack.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<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' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\packages\Newtonsoft.Json.4.5.7\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
<Reference Include="System.Web" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="Helper.cs" />
|
||||
<Compile Include="HttpAbstraction\HttpAbstractionClientTests.cs" />
|
||||
<Compile Include="HttpAbstraction\HttpHeadersAbstractionTests.cs" />
|
||||
<Compile Include="Identity\IdentityRestServiceSimulator.cs" />
|
||||
<Compile Include="Identity\IdentityServiceRestClientTests.cs" />
|
||||
<Compile Include="Identity\AccessTokenPayloadConverterTests.cs" />
|
||||
<Compile Include="Identity\IdentityServicePocoClientTests.cs" />
|
||||
<Compile Include="Identity\TestIdentityServicePocoClient.cs" />
|
||||
<Compile Include="Identity\TestIdentityServiceRestClient.cs" />
|
||||
<Compile Include="Identity\IdentityServiceClientTests.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceEndpointPayloadConverterTests.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceDefinitionPayloadConverterTests.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceCatalogPayloadConverterTests.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceCatalogTests.cs" />
|
||||
<Compile Include="Identity\IdentityServiceClientDefinitionTests.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocationAssemblyScannerTests.cs" />
|
||||
<Compile Include="ServiceLocation\ServiceLocatorTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Storage\StorageAccountPayloadConverterTests.cs" />
|
||||
<Compile Include="Storage\StorageContainerPayloadConverterTests.cs" />
|
||||
<Compile Include="Storage\StorageObjectPayloadConverterTests.cs" />
|
||||
<Compile Include="Storage\StorageServicePocoClientTests.cs" />
|
||||
<Compile Include="Storage\StorageServiceRestClientTests.cs" />
|
||||
<Compile Include="Storage\StorageRestSimulator.cs" />
|
||||
<Compile Include="Storage\TestStorageServicePocoClient.cs" />
|
||||
<Compile Include="Storage\TestStorageServiceRestClient.cs" />
|
||||
<Compile Include="Storage\StorageServiceClientTests.cs" />
|
||||
<Compile Include="Identity\OpenstackCredentialTests.cs" />
|
||||
<Compile Include="OpenstackClientManagerTests.cs" />
|
||||
<Compile Include="OpenstackServiceClientManagerTests.cs" />
|
||||
<Compile Include="Storage\StorageServiceClientDefinitionTests.cs" />
|
||||
<Compile Include="TestOpenstackServiceEndpointResolver.cs" />
|
||||
<Compile Include="ObjectExtentionsTests.cs" />
|
||||
<Compile Include="OpenstackClientTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Openstack.Common\Openstack.Common.csproj">
|
||||
<Project>{c53d669c-cdf1-4157-aec1-bd167f655b2b}</Project>
|
||||
<Name>Openstack.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Openstack\Openstack.csproj">
|
||||
<Project>{b2c92371-b62b-45a2-adeb-edebefa3a75c}</Project>
|
||||
<Name>Openstack</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
301
Openstack/Openstack.Test/OpenstackClientManagerTests.cs
Normal file
301
Openstack/Openstack.Test/OpenstackClientManagerTests.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackClientManagerTests
|
||||
{
|
||||
internal class TestCredential : ICredential
|
||||
{
|
||||
public Uri AuthenticationEndpoint { get; private set; }
|
||||
public string AccessTokenId { get; private set; }
|
||||
|
||||
public OpenstackServiceCatalog ServiceCatalog
|
||||
{
|
||||
get
|
||||
{
|
||||
var catalog =
|
||||
new OpenstackServiceCatalog
|
||||
{
|
||||
new OpenstackServiceDefinition("Test", "Test",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://someplace.com", "somewhere", "2.0.0.0",
|
||||
new Uri("http://someplace.com"), new Uri("http://someplace.com"))
|
||||
})
|
||||
};
|
||||
return catalog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestOpenstackClient : IOpenstackClient
|
||||
{
|
||||
#region Test Client Impl
|
||||
|
||||
public IOpenstackCredential Credential { get; private set; }
|
||||
|
||||
public Task Connect()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>() where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>(string version) where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential, string version)
|
||||
{
|
||||
return credential is TestCredential;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class OtherTestOpenstackClient : IOpenstackClient
|
||||
{
|
||||
#region Test Client Impl
|
||||
|
||||
public IOpenstackCredential Credential { get; private set; }
|
||||
|
||||
public Task Connect()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>() where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>(string version) where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential, string version)
|
||||
{
|
||||
return credential is OpenstackCredential;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class NonDefaultTestOpenstackClient : IOpenstackClient
|
||||
{
|
||||
public NonDefaultTestOpenstackClient(string parameter)
|
||||
{
|
||||
//forces a non-default ctor
|
||||
}
|
||||
|
||||
#region Test Client Impl
|
||||
|
||||
public IOpenstackCredential Credential { get; private set; }
|
||||
|
||||
public Task Connect()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>() where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public T CreateServiceClient<T>(string version) where T : IOpenstackServiceClient
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential, string version)
|
||||
{
|
||||
return credential is OpenstackCredential;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanRegisterANewClient()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.RegisterClient<TestOpenstackClient>();
|
||||
|
||||
Assert.AreEqual(1, manager.clients.Count);
|
||||
Assert.AreEqual(typeof(TestOpenstackClient), manager.clients.First());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterTheSameClientTwice()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.RegisterClient<TestOpenstackClient>();
|
||||
manager.RegisterClient<TestOpenstackClient>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanRegisterMultipleClients()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.RegisterClient<TestOpenstackClient>();
|
||||
manager.RegisterClient<OtherTestOpenstackClient>();
|
||||
|
||||
Assert.AreEqual(2, manager.clients.Count);
|
||||
Assert.IsTrue(manager.clients.Contains(typeof(TestOpenstackClient)));
|
||||
Assert.IsTrue(manager.clients.Contains(typeof(OtherTestOpenstackClient)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanListAvailableClients()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(TestOpenstackClient));
|
||||
manager.clients.Add(typeof(OtherTestOpenstackClient));
|
||||
|
||||
var clients = manager.ListAvailableClients().ToList();
|
||||
|
||||
Assert.AreEqual(2, clients.Count());
|
||||
Assert.IsTrue(clients.Contains(typeof(TestOpenstackClient)));
|
||||
Assert.IsTrue(clients.Contains(typeof(OtherTestOpenstackClient)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanCreateAClient()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(TestOpenstackClient));
|
||||
|
||||
var client = manager.CreateClient(new TestCredential());
|
||||
|
||||
Assert.IsNotNull(client);
|
||||
Assert.IsInstanceOfType(client, typeof(TestOpenstackClient));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAClientIfCredentialIsNotSupported()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(OtherTestOpenstackClient));
|
||||
|
||||
manager.CreateClient(new TestCredential());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAClientIfNoClientsAreRegistered()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.CreateClient(new TestCredential());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAClientWithNullCredential()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(TestOpenstackClient));
|
||||
|
||||
manager.CreateClient((ICredential)null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAClientWithNullCredentialAndVersion()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(TestOpenstackClient));
|
||||
|
||||
manager.CreateClient(null, "1.0.0..0");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAClientWithCredentialAndNullVersion()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.clients.Add(typeof(TestOpenstackClient));
|
||||
|
||||
manager.CreateClient(new TestCredential(), null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanCreateAnInstanceOfAClient()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
|
||||
var client = manager.CreateClient(typeof (TestOpenstackClient));
|
||||
Assert.IsNotNull(client);
|
||||
Assert.IsInstanceOfType(client, typeof(TestOpenstackClient));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CanCreateAnInstanceOfAClientWithNullType()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
|
||||
manager.CreateClient((Type)null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAnInstanceOfANonOpenstackClient()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
manager.CreateClient(typeof(Object));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAnInstanceOfAOpenstackClientWithoutADefaultCtor()
|
||||
{
|
||||
var manager = new OpenstackClientManager();
|
||||
|
||||
manager.CreateClient(typeof(NonDefaultTestOpenstackClient));
|
||||
}
|
||||
}
|
||||
}
|
133
Openstack/Openstack.Test/OpenstackClientTests.cs
Normal file
133
Openstack/Openstack.Test/OpenstackClientTests.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
[TestClass]
|
||||
public class OpenstackClientTests
|
||||
{
|
||||
internal class TestIdentityServiceClient : IIdentityServiceClient
|
||||
{
|
||||
internal IOpenstackCredential cred;
|
||||
internal CancellationToken token;
|
||||
|
||||
public TestIdentityServiceClient(IOpenstackCredential cred, CancellationToken token)
|
||||
{
|
||||
this.cred = cred;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public async Task<IOpenstackCredential> Authenticate()
|
||||
{
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
this.cred.SetAccessTokenId("12345");
|
||||
return cred;
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestIdentityServiceClientDefinition : IOpenstackServiceClientDefinition
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public IOpenstackServiceClient Create(ICredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
return new TestIdentityServiceClient((IOpenstackCredential)credential, cancellationToken);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
ServiceLocator.Reset();
|
||||
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
|
||||
var serviceManager = new OpenstackServiceClientManager();
|
||||
serviceManager.RegisterServiceClient<TestIdentityServiceClient>(new TestIdentityServiceClientDefinition());
|
||||
manager.RegisterServiceInstance(typeof(IOpenstackServiceClientManager), serviceManager);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanConnect()
|
||||
{
|
||||
var client =
|
||||
new OpenstackClient(
|
||||
new OpenstackCredential(new Uri("http://someplace.org"), "someuser", new SecureString(),
|
||||
"sometenant"), CancellationToken.None);
|
||||
await client.Connect();
|
||||
Assert.AreEqual("12345", client.Credential.AccessTokenId);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSupportAnyVersion()
|
||||
{
|
||||
var client = new OpenstackClient();
|
||||
var versions = client.GetSupportedVersions();
|
||||
Assert.IsTrue(versions.Contains("Any"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSupportOpenstackCredential()
|
||||
{
|
||||
var cred = new OpenstackCredential(new Uri("http://someplace.org"), "someuser", new SecureString(), "sometenant");
|
||||
var client = new OpenstackClient();
|
||||
Assert.IsTrue(client.IsSupported(cred,string.Empty));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CannotSupportNullCredential()
|
||||
{
|
||||
var client = new OpenstackClient();
|
||||
Assert.IsFalse(client.IsSupported(null, string.Empty));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSupportNullVersion()
|
||||
{
|
||||
var cred = new OpenstackCredential(new Uri("http://someplace.org"), "someuser", new SecureString(), "sometenant");
|
||||
var client = new OpenstackClient();
|
||||
Assert.IsTrue(client.IsSupported(cred, null));
|
||||
}
|
||||
}
|
||||
}
|
236
Openstack/Openstack.Test/OpenstackServiceClientManagerTests.cs
Normal file
236
Openstack/Openstack.Test/OpenstackServiceClientManagerTests.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Identity;
|
||||
|
||||
[TestClass]
|
||||
public class OpenstackServiceClientManagerTests
|
||||
{
|
||||
internal class TestOpenstackServiceClient : IOpenstackServiceClient
|
||||
{
|
||||
public TestOpenstackServiceClient(ICredential credential, CancellationToken token)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestOpenstackServiceClientDefinition : IOpenstackServiceClientDefinition
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public IOpenstackServiceClient Create(ICredential credential, CancellationToken token)
|
||||
{
|
||||
return new TestOpenstackServiceClient(credential, token);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal class OtherTestOpenstackServiceClient : IOpenstackServiceClient
|
||||
{
|
||||
public OtherTestOpenstackServiceClient(ICredential credential, CancellationToken token)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static IOpenstackServiceClient Create(ICredential credential, CancellationToken token)
|
||||
{
|
||||
return new OtherTestOpenstackServiceClient(credential, token);
|
||||
}
|
||||
}
|
||||
|
||||
internal class OtherTestOpenstackServiceClientDefinition : IOpenstackServiceClientDefinition
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public IOpenstackServiceClient Create(ICredential credential, CancellationToken token)
|
||||
{
|
||||
return new OtherTestOpenstackServiceClient(credential, token);
|
||||
}
|
||||
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported(ICredential credential)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoValidCtroTestOpenstackServiceClient : IOpenstackServiceClient
|
||||
{
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsSupported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanRegisterANewService()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.RegisterServiceClient<TestOpenstackServiceClient>(new TestOpenstackServiceClientDefinition());
|
||||
|
||||
Assert.AreEqual(1, manager.serviceClientDefinitions.Count);
|
||||
Assert.IsTrue(manager.serviceClientDefinitions.ContainsKey(typeof(TestOpenstackServiceClient)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterTheSameServiceTwice()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.RegisterServiceClient<TestOpenstackServiceClient>(new TestOpenstackServiceClientDefinition());
|
||||
manager.RegisterServiceClient<TestOpenstackServiceClient>(new TestOpenstackServiceClientDefinition());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanRegisterMultipleServices()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.RegisterServiceClient<TestOpenstackServiceClient>(new TestOpenstackServiceClientDefinition());
|
||||
manager.RegisterServiceClient<OtherTestOpenstackServiceClient>(new OtherTestOpenstackServiceClientDefinition());
|
||||
|
||||
Assert.AreEqual(2, manager.serviceClientDefinitions.Count);
|
||||
Assert.IsTrue(manager.serviceClientDefinitions.ContainsKey(typeof(TestOpenstackServiceClient)));
|
||||
Assert.IsTrue(manager.serviceClientDefinitions.ContainsKey(typeof(OtherTestOpenstackServiceClient)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanListAvailableClients()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(TestOpenstackServiceClient), new TestOpenstackServiceClientDefinition());
|
||||
manager.serviceClientDefinitions.Add(typeof(OtherTestOpenstackServiceClient), new OtherTestOpenstackServiceClientDefinition());
|
||||
|
||||
var services = manager.ListAvailableServiceClients().ToList();
|
||||
|
||||
Assert.AreEqual(2, services.Count());
|
||||
Assert.IsTrue(services.Contains(typeof(TestOpenstackServiceClient)));
|
||||
Assert.IsTrue(services.Contains(typeof(OtherTestOpenstackServiceClient)));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanCreateAClient()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(TestOpenstackServiceClient), new TestOpenstackServiceClientDefinition());
|
||||
|
||||
var service = manager.CreateServiceClient<TestOpenstackServiceClient>(new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
|
||||
Assert.IsNotNull(service);
|
||||
Assert.IsInstanceOfType(service, typeof(TestOpenstackServiceClient));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAServiceIfVersionIsNotSupported()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(OtherTestOpenstackServiceClient), new OtherTestOpenstackServiceClientDefinition());
|
||||
|
||||
manager.CreateServiceClient<OtherTestOpenstackServiceClient>(new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAClientIfNoServicesAreRegistered()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.CreateServiceClient<OtherTestOpenstackServiceClient>(new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAServiceWithNullCredential()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(TestOpenstackServiceClient), new TestOpenstackServiceClientDefinition());
|
||||
|
||||
manager.CreateServiceClient<TestOpenstackServiceClient>((ICredential)null, CancellationToken.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotCreateAServiceWithNullCredentialAndVersion()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(TestOpenstackServiceClient), new TestOpenstackServiceClientDefinition());
|
||||
|
||||
manager.CreateServiceClient<TestOpenstackServiceClient>((ICredential)null, CancellationToken.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotCreateAServiceWithCredentialAndNullFactory()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.serviceClientDefinitions.Add(typeof(TestOpenstackServiceClient), null);
|
||||
|
||||
manager.CreateServiceClient<TestOpenstackServiceClient>(new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanCreateAnInstanceOfAService()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
|
||||
var service = manager.CreateServiceClientInstance(new TestOpenstackServiceClientDefinition(), new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
Assert.IsNotNull(service);
|
||||
Assert.IsInstanceOfType(service, typeof(TestOpenstackServiceClient));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CanCreateAnInstanceOfAServiceWithNullFactory()
|
||||
{
|
||||
var manager = new OpenstackServiceClientManager();
|
||||
manager.CreateServiceClientInstance(null, new OpenstackClientManagerTests.TestCredential(), CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
51
Openstack/Openstack.Test/Properties/AssemblyInfo.cs
Normal file
51
Openstack/Openstack.Test/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Openstack.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Openstack.org")]
|
||||
[assembly: AssemblyProduct("Openstack.Test")]
|
||||
[assembly: AssemblyCopyright("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("47bc2198-4d59-47a0-9b5f-a3985ff6ab5a")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -0,0 +1,142 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
namespace Openstack.Objects.Test.ServiceLocation
|
||||
{
|
||||
[TestClass]
|
||||
public class ServiceLocationAssemblyScannerTests
|
||||
{
|
||||
internal class TestRegistrar : IServiceLocationRegistrar
|
||||
{
|
||||
public void Register(IServiceLocationManager manager, IServiceLocator locator)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class OtherTestRegistrar : IServiceLocationRegistrar
|
||||
{
|
||||
public void Register(IServiceLocationManager manager, IServiceLocator locator)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class NonDefaultTestRegistrar : IServiceLocationRegistrar
|
||||
{
|
||||
public NonDefaultTestRegistrar(string beans)
|
||||
{
|
||||
//this is here to force a non-default constructor, this should not be loaded as a registrar.
|
||||
}
|
||||
|
||||
public void Register(IServiceLocationManager manager, IServiceLocator locator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void HasNewAssembliesWithNewAssemblies()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
|
||||
var temp = assemblies.First();
|
||||
assemblies.Remove(temp);
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
|
||||
Assert.IsTrue(sweeper.HasNewAssemblies());
|
||||
Assert.IsFalse(sweeper.HasNewAssemblies());
|
||||
assemblies.Add(temp);
|
||||
|
||||
Assert.IsTrue(sweeper.HasNewAssemblies());
|
||||
Assert.IsFalse(sweeper.HasNewAssemblies());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetOnlyRegistrarTypes()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = new List<Assembly>() {this.GetType().Assembly};
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
var types = sweeper.GetRegistrarTypes();
|
||||
Assert.AreEqual(3, types.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OnlyRegistrarTypesAreReturned()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
|
||||
assemblies.Remove(this.GetType().Assembly);
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
var types = sweeper.GetRegistrarTypes();
|
||||
Assert.AreEqual(2, types.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetOnlyRegistrars()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
|
||||
assemblies.Remove(this.GetType().Assembly);
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
var registrars = sweeper.GetRegistrars();
|
||||
Assert.AreEqual(2, registrars.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetNewRegistrars()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
|
||||
assemblies.RemoveAll( a => true);
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
|
||||
var registrars = sweeper.GetRegistrars();
|
||||
Assert.AreEqual(0, registrars.Count());
|
||||
|
||||
assemblies = new List<Assembly>() { this.GetType().Assembly };
|
||||
|
||||
registrars = sweeper.GetRegistrars();
|
||||
Assert.AreEqual(3, registrars.Count());
|
||||
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
public void CanGetOnlyRegistrar()
|
||||
{
|
||||
var sweeper = new ServiceLocationAssemblyScanner();
|
||||
var assemblies = new List<Assembly>() { this.GetType().Assembly };
|
||||
|
||||
sweeper.GetAllAssemblies = () => assemblies;
|
||||
var registrars = sweeper.GetRegistrars();
|
||||
Assert.AreEqual(3, registrars.Count());
|
||||
}
|
||||
}
|
||||
}
|
223
Openstack/Openstack.Test/ServiceLocation/ServiceLocatorTests.cs
Normal file
223
Openstack/Openstack.Test/ServiceLocation/ServiceLocatorTests.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
namespace Openstack.Test.ServiceLocation
|
||||
{
|
||||
|
||||
[TestClass]
|
||||
public class ServiceLocatorTests
|
||||
{
|
||||
public interface ITestEchoService
|
||||
{
|
||||
string Echo(string msg);
|
||||
}
|
||||
|
||||
public class TestEchoService : ITestEchoService
|
||||
{
|
||||
public string Echo(string msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
public class TestReverseEchoService : ITestEchoService
|
||||
{
|
||||
public string Echo(string msg)
|
||||
{
|
||||
return new string(msg.Reverse().ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServiceLocator : IServiceLocator
|
||||
{
|
||||
public T Locate<T>()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServiceManager : IServiceLocationRuntimeManager
|
||||
{
|
||||
public void RegisterServiceInstance<TService>(TService instance)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceInstance(Type type, object instance)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType<T>(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType<TInterface, TConcretion>() where TConcretion : class, TInterface
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType(Type type, Type registrationValue)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServiceOverrideManager : IServiceLocationOverrideManager
|
||||
{
|
||||
public void RegisterServiceInstance<TService>(TService instance)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceInstance(Type type, object instance)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType<T>(Type type)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType<TInterface, TConcretion>() where TConcretion : class, TInterface
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void RegisterServiceType(Type type, Type registrationValue)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanRegisterAndLocateAService()
|
||||
{
|
||||
var myServiceInstance = new TestEchoService();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
Assert.IsNotNull(manager);
|
||||
manager.RegisterServiceInstance<ITestEchoService>(myServiceInstance);
|
||||
|
||||
var service = ServiceLocator.Instance.Locate<ITestEchoService>();
|
||||
|
||||
Assert.IsNotNull(service);
|
||||
Assert.AreEqual("Works", service.Echo("Works"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotLocateAServiceThatHasNotBeenRegistered()
|
||||
{
|
||||
ServiceLocator.Instance.Locate<ITestEchoService>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanOverrideAndLocateAService()
|
||||
{
|
||||
var echoServiceInstance = new TestEchoService();
|
||||
var reverseEchoServiceInstance = new TestReverseEchoService();
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
var overrrideManager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
|
||||
Assert.IsNotNull(runtimeManager);
|
||||
Assert.IsNotNull(overrrideManager);
|
||||
|
||||
runtimeManager.RegisterServiceInstance<ITestEchoService>(echoServiceInstance);
|
||||
overrrideManager.RegisterServiceInstance<ITestEchoService>(reverseEchoServiceInstance);
|
||||
|
||||
|
||||
var service = ServiceLocator.Instance.Locate<ITestEchoService>();
|
||||
|
||||
Assert.IsNotNull(service);
|
||||
Assert.IsInstanceOfType(service, typeof(TestReverseEchoService));
|
||||
Assert.AreEqual("skroW", service.Echo("Works"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterNullService()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance<ITestEchoService>(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterNullType()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance(null,new TestEchoService());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterNonInterface()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance<string>("Hello!");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterAServiceLocator()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance<IServiceLocator>(new TestServiceLocator());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterAServiceManager()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance<IServiceLocationRuntimeManager>(new TestServiceManager());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void CannotRegisterAnOverrideManager()
|
||||
{
|
||||
var runtimeManager = ServiceLocator.Instance.Locate<IServiceLocationRuntimeManager>();
|
||||
|
||||
runtimeManager.RegisterServiceInstance<IServiceLocationOverrideManager>(new TestServiceOverrideManager());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,270 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageAccountPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanParseAccountWithValidJsonPayloadAndHeaders()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
var account = converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
|
||||
Assert.IsNotNull(account);
|
||||
Assert.AreEqual(accountName, account.Name);
|
||||
Assert.AreEqual(12345, account.TotalBytesUsed);
|
||||
Assert.AreEqual(1, account.TotalObjectCount);
|
||||
Assert.AreEqual(1, account.TotalContainerCount);
|
||||
Assert.AreEqual(1, account.Containers.ToList().Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithMissingBytesUsedHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithMissingObjectCountHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithMissingContainerCountHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithBadBytesUsedHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "NOT A NUMBER"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithBadObjectCountHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "NOT A NUMBER"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithBadContainerCountHeader()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "NOT A NUMBER"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseAccountWithBadPayload()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var invalidSingleContainerJson = @"[
|
||||
{
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, invalidSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseAccountWithNullName()
|
||||
{
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(null, headers, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseAccountWithNullHeaders()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, null, validSingleContainerJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseAccountWithNullPayload()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var converter = new StorageAccountPayloadConverter();
|
||||
converter.Convert(accountName, headers, null);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,425 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageContainerPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanParseValidJsonPayloadWithMultipleObjects()
|
||||
{
|
||||
var validMultipleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
},
|
||||
{
|
||||
""count"": 5,
|
||||
""bytes"": 2000,
|
||||
""name"": ""OtherTestContainer""
|
||||
}
|
||||
]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var containers = converter.Convert(validMultipleContainerJson).ToList();
|
||||
|
||||
Assert.AreEqual(2, containers.Count());
|
||||
var obj1 =
|
||||
containers.First(o => string.Compare(o.Name, "TestContainer", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
var obj2 =
|
||||
containers.First(o => string.Compare(o.Name, "OtherTestContainer", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
Assert.IsNotNull(obj1);
|
||||
Assert.IsNotNull(obj2);
|
||||
|
||||
Assert.AreEqual(7, obj1.TotalBytesUsed);
|
||||
Assert.AreEqual("TestContainer", obj1.Name);
|
||||
Assert.AreEqual(1, obj1.TotalObjectCount);
|
||||
|
||||
Assert.AreEqual(2000, obj2.TotalBytesUsed);
|
||||
Assert.AreEqual("OtherTestContainer", obj2.Name);
|
||||
Assert.AreEqual(5, obj2.TotalObjectCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseValidJsonPayloadWithSingleObject()
|
||||
{
|
||||
var validSingleContainerJson = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var containers = converter.Convert(validSingleContainerJson).ToList();
|
||||
|
||||
Assert.AreEqual(1, containers.Count());
|
||||
var obj1 =
|
||||
containers.First(o => string.Compare(o.Name, "TestContainer", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
Assert.IsNotNull(obj1);
|
||||
|
||||
Assert.AreEqual(7, obj1.TotalBytesUsed);
|
||||
Assert.AreEqual("TestContainer", obj1.Name);
|
||||
Assert.AreEqual(1, obj1.TotalObjectCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseValidEmptyJsonArrayPayload()
|
||||
{
|
||||
var emptyJsonArray = @"[]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var containers = converter.Convert(emptyJsonArray).ToList();
|
||||
|
||||
Assert.AreEqual(0, containers.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseAnEmptyPayload()
|
||||
{
|
||||
var payload = string.Empty;
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var containers = converter.Convert(payload).ToList();
|
||||
|
||||
Assert.AreEqual(0, containers.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseANullPayload()
|
||||
{
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseInvalidJsonPayload()
|
||||
{
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert("[ { \"SomeAtrib\" }]");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseInvalidPayload()
|
||||
{
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert("NOT JSON");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingBytesProperty()
|
||||
{
|
||||
var InvalidJsonWithoutBytes = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(InvalidJsonWithoutBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingCountProperty()
|
||||
{
|
||||
string InvalidJsonWithoutCount = @"[
|
||||
{
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(InvalidJsonWithoutCount);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingNameProperty()
|
||||
{
|
||||
string InvalidJsonWithoutName = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(InvalidJsonWithoutName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseExceptionIncludesNameWhenPossible()
|
||||
{
|
||||
string InvalidJsonWithoutBytes = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
try
|
||||
{
|
||||
converter.Convert(InvalidJsonWithoutBytes);
|
||||
Assert.Fail("Parsing did not fail as expected.");
|
||||
}
|
||||
catch (HttpParseException ex)
|
||||
{
|
||||
Assert.IsTrue(ex.Message.StartsWith("Storage Container 'TestContainer'"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithBadBytesValue()
|
||||
{
|
||||
string InvalidJsonWithBadBytesValue = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": ""NOT A NUMBER"",
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(InvalidJsonWithBadBytesValue);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithBadCountValue()
|
||||
{
|
||||
string InvalidJsonWithBadCountValue = @"[
|
||||
{
|
||||
""count"": ""NOT A NUMBER"",
|
||||
""bytes"": 12345,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
converter.Convert(InvalidJsonWithBadCountValue);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseContainerWithValidJsonPayloadAndHeaders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var container = converter.Convert(containerName, headers, validObjectJson);
|
||||
Assert.IsNotNull(container);
|
||||
Assert.AreEqual(containerName,container.Name);
|
||||
Assert.AreEqual(12345, container.TotalBytesUsed);
|
||||
Assert.AreEqual(1, container.TotalObjectCount);
|
||||
Assert.AreEqual(1, container.Objects.ToList().Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseContainerWithMissingBytesUsedHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
converter.Convert(containerName, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseContainerWithMissingObjectCountHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"}
|
||||
};
|
||||
|
||||
converter.Convert(containerName, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseContainerWithBadBytesUsedHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "This is not a number"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
converter.Convert(containerName, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseContainerWithBadObjectCountHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "This is not a number"}
|
||||
};
|
||||
|
||||
converter.Convert(containerName, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseContainerWithBadPayload()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"":";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
converter.Convert(containerName, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseContainerWithNullName()
|
||||
{
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
converter.Convert(null, headers, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseContainerWithNullHeaders()
|
||||
{
|
||||
var validObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
|
||||
converter.Convert("Name", null, validObjectJson);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseContainerWithNullPayload()
|
||||
{
|
||||
var converter = new StorageContainerPayloadConverter();
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
converter.Convert("Name", headers, null);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,548 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageObjectPayloadConverterTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void CanParseValidJsonPayloadWithMultipleObjects()
|
||||
{
|
||||
var validMultipleObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""hash"": ""97cdd4bb45c3d5d652c0079901fb4eec"",
|
||||
""last_modified"": ""2014-03-05T01:10:22.786140"",
|
||||
""bytes"": 2147483649,
|
||||
""name"": ""LargeFile.bin"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}
|
||||
]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var objects = converter.Convert("TestContainer", validMultipleObjectJson).ToList();
|
||||
|
||||
Assert.AreEqual(2,objects.Count());
|
||||
var obj1 =
|
||||
objects.First(o => string.Compare(o.Name, "BLAH", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
var obj2 =
|
||||
objects.First(o => string.Compare(o.Name, "LargeFile.bin", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
Assert.IsNotNull(obj1);
|
||||
Assert.IsNotNull(obj2);
|
||||
|
||||
Assert.AreEqual(0,obj1.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj1.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj1.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("2014-03-07T21:31:31.588170"), obj1.LastModified);
|
||||
Assert.AreEqual("BLAH", obj1.Name);
|
||||
Assert.AreEqual("TestContainer", obj1.ContainerName);
|
||||
|
||||
Assert.AreEqual(2147483649, obj2.Length);
|
||||
Assert.AreEqual("97cdd4bb45c3d5d652c0079901fb4eec", obj2.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj2.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("2014-03-05T01:10:22.786140"), obj2.LastModified);
|
||||
Assert.AreEqual("LargeFile.bin", obj2.Name);
|
||||
Assert.AreEqual("TestContainer", obj2.ContainerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseValidJsonPayloadWithSingleObject()
|
||||
{
|
||||
var validSingleObjectJson = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var objects = converter.Convert("TestContainer", validSingleObjectJson).ToList();
|
||||
|
||||
Assert.AreEqual(1, objects.Count());
|
||||
var obj1 =
|
||||
objects.First(o => string.Compare(o.Name, "BLAH", StringComparison.InvariantCultureIgnoreCase) == 0);
|
||||
Assert.IsNotNull(obj1);
|
||||
|
||||
Assert.AreEqual(0, obj1.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj1.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj1.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("2014-03-07T21:31:31.588170"), obj1.LastModified);
|
||||
Assert.AreEqual("BLAH", obj1.Name);
|
||||
Assert.AreEqual("TestContainer", obj1.ContainerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseValidEmptyJsonArrayPayload()
|
||||
{
|
||||
var emptyJsonArray = @"[]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var objects = converter.Convert("TestContainer", emptyJsonArray).ToList();
|
||||
|
||||
Assert.AreEqual(0, objects.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseAnEmptyPayload()
|
||||
{
|
||||
var payload = string.Empty;
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var objects = converter.Convert("TestContainer", payload).ToList();
|
||||
|
||||
Assert.AreEqual(0, objects.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseANullPayload()
|
||||
{
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseInvalidJsonPayload()
|
||||
{
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", "[ { \"SomeAtrib\" }]");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseInvalidPayload()
|
||||
{
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", "NOT JSON");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingBytesProperty()
|
||||
{
|
||||
string InvalidJsonWithoutBytes = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}
|
||||
]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutBytes);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingHashProperty()
|
||||
{
|
||||
string InvalidJsonWithoutHash = @"[
|
||||
{
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutHash);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingModifiedProperty()
|
||||
{
|
||||
string InvalidJsonWithoutLastModified = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutLastModified);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CannotParseJsonPayloadWithMissingNameProperty()
|
||||
{
|
||||
string InvalidJsonWithoutName = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
|
||||
try
|
||||
{
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutName);
|
||||
Assert.Fail("Parsing did not fail as expected.");
|
||||
}
|
||||
catch (HttpParseException ex)
|
||||
{
|
||||
Assert.IsTrue(ex.Message.StartsWith("Storage Object payload could not be parsed."));
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void ParseExceptionIncludesNameWhenPossible()
|
||||
{
|
||||
string InvalidJsonWithoutHash = @"[
|
||||
{
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
try
|
||||
{
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutHash);
|
||||
Assert.Fail("Parsing did not fail as expected.");
|
||||
}
|
||||
catch (HttpParseException ex)
|
||||
{
|
||||
Assert.IsTrue(ex.Message.StartsWith("Storage Object 'BLAH'"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithMissingContentTypeProperty()
|
||||
{
|
||||
string InvalidJsonWithoutContentType = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithoutContentType);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithBadModifiedDate()
|
||||
{
|
||||
string InvalidJsonWithBadDateType = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""This is not a date"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithBadDateType);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseJsonPayloadWithBadBytesValue()
|
||||
{
|
||||
string InvalidJsonWithBadBytesValue = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": ""This is not a number"",
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert("TestContainer", InvalidJsonWithBadBytesValue);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseFromHeaders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseFromHeadersWithMetadata()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseWithANullObjectName()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, null, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void CannotParseWithAnEmptyConatinerName()
|
||||
{
|
||||
var containerName = string.Empty;
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseWithNullHeaders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void CannotParseWithAnEmptyObjectName()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName =string.Empty;
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotParseWithNullConatinerName()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(null, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithMissingContentLengthHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithMissingETagHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithMissingModifiedHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithMissingContentTypeHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithBadModifiedDateHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "This is not a date"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(HttpParseException))]
|
||||
public void CannotParseWithBadBytesHeader()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "This is not a number"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"Etag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
}
|
||||
}
|
536
Openstack/Openstack.Test/Storage/StorageRestSimulator.cs
Normal file
536
Openstack/Openstack.Test/Storage/StorageRestSimulator.cs
Normal file
@@ -0,0 +1,536 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
public class StorageRestSimulator : DisposableClass, IHttpAbstractionClient
|
||||
{
|
||||
internal class StorageItem
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public IDictionary<string,string> MetaData { get; set; }
|
||||
|
||||
public Stream Content { get; set; }
|
||||
|
||||
public StorageItem()
|
||||
{
|
||||
this.MetaData = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public StorageItem(string name) : this()
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
public void ProcessMetaDataFromHeaders(IDictionary<string, string> headers)
|
||||
{
|
||||
headers.Keys.Where(k => k.ToLowerInvariant().StartsWith("x-object-meta-")).ToList().ForEach(i => this.MetaData.Add(i, headers[i]));
|
||||
}
|
||||
|
||||
public void LoadContent(Stream content)
|
||||
{
|
||||
var memStream = new MemoryStream();
|
||||
if (content != null)
|
||||
{
|
||||
content.CopyTo(memStream);
|
||||
memStream.Position = 0;
|
||||
}
|
||||
this.Content = memStream;
|
||||
}
|
||||
}
|
||||
|
||||
public StorageRestSimulator()
|
||||
{
|
||||
this.Headers = new Dictionary<string, string>();
|
||||
this.Containers = new Dictionary<string, StorageItem>();
|
||||
this.Objects = new Dictionary<string, StorageItem>();
|
||||
this.Delay = TimeSpan.FromMilliseconds(0);
|
||||
this.IsContainerEmpty = true;
|
||||
}
|
||||
|
||||
public StorageRestSimulator(CancellationToken token) : this()
|
||||
{
|
||||
}
|
||||
|
||||
internal Dictionary<string, StorageItem> Containers { get; set; }
|
||||
|
||||
internal Dictionary<string, StorageItem> Objects { get; set; }
|
||||
|
||||
public HttpMethod Method { get; set; }
|
||||
|
||||
public Uri Uri { get; set; }
|
||||
|
||||
public Stream Content { get; set; }
|
||||
|
||||
public IDictionary<string, string> Headers { get; private set; }
|
||||
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public TimeSpan Timeout { get; set; }
|
||||
|
||||
public TimeSpan Delay { get; set; }
|
||||
|
||||
public bool IsContainerEmpty { get; set; }
|
||||
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpReceiveProgress;
|
||||
//public event EventHandler<HttpProgressEventArgs> HttpSendProgress;
|
||||
|
||||
public Task<IHttpResponseAbstraction> SendAsync()
|
||||
{
|
||||
if (!this.Headers.ContainsKey("X-Auth-Token") || this.Headers["X-Auth-Token"] != "12345")
|
||||
{
|
||||
return Task.Factory.StartNew(() => TestHelper.CreateResponse(HttpStatusCode.Unauthorized));
|
||||
}
|
||||
IHttpResponseAbstraction retVal;
|
||||
switch (this.Method.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "get":
|
||||
retVal = HandleGet();
|
||||
break;
|
||||
case "post":
|
||||
retVal = HandlePost();
|
||||
break;
|
||||
case "put":
|
||||
retVal = HandlePut();
|
||||
break;
|
||||
case "delete":
|
||||
retVal = HandleDelete();
|
||||
break;
|
||||
case "head":
|
||||
retVal = HandleHead();
|
||||
break;
|
||||
case "copy":
|
||||
retVal = HandleCopy();
|
||||
break;
|
||||
default:
|
||||
retVal = TestHelper.CreateErrorResponse();
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(Delay);
|
||||
return Task.Factory.StartNew(() => retVal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private IHttpResponseAbstraction HandleCopy()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
//cannot copy a container
|
||||
if (objectName == null)
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
if (!this.Headers.ContainsKey("Destination"))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.PreconditionFailed);
|
||||
}
|
||||
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var destination = this.Headers["Destination"];
|
||||
var destinationSegs = destination.Split('/');
|
||||
if (destinationSegs.Count() < 2)
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.PreconditionFailed);
|
||||
}
|
||||
|
||||
if (destinationSegs[1] == string.Empty)
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
if (!this.Containers.ContainsKey(destinationSegs[0]))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var destObjectName = string.Join("", destinationSegs.Skip(1));
|
||||
var srcObj = this.Objects[objectName];
|
||||
|
||||
var obj = new StorageItem(destObjectName);
|
||||
obj.MetaData = srcObj.MetaData;
|
||||
obj.ProcessMetaDataFromHeaders(this.Headers);
|
||||
var content = new MemoryStream();
|
||||
srcObj.Content.CopyTo(content);
|
||||
srcObj.Content.Position = 0;
|
||||
content.Position = 0;
|
||||
obj.Content = content;
|
||||
|
||||
this.Objects[obj.Name] = obj;
|
||||
|
||||
var headers = GenerateObjectResponseHeaders(obj);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.Created, headers);
|
||||
|
||||
}
|
||||
|
||||
private IHttpResponseAbstraction HandleHead()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
var headers = new Dictionary<string, string>();
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
headers = GenerateObjectResponseHeaders(this.Objects[objectName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
headers = GenerateContainerResponseHeaders(this.Containers[containerName]);
|
||||
}
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NoContent, headers);
|
||||
}
|
||||
|
||||
private IHttpResponseAbstraction HandleDelete()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
this.Objects.Remove(objectName);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NoContent, GenerateDeleteHeaders());
|
||||
}
|
||||
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var statusCode = HttpStatusCode.NoContent;
|
||||
|
||||
if (!this.IsContainerEmpty)
|
||||
{
|
||||
statusCode = HttpStatusCode.Conflict;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Containers.Remove(containerName);
|
||||
}
|
||||
|
||||
return TestHelper.CreateResponse(statusCode, GenerateDeleteHeaders());
|
||||
}
|
||||
|
||||
private IHttpResponseAbstraction HandlePut()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
var obj = new StorageItem(objectName);
|
||||
obj.ProcessMetaDataFromHeaders(this.Headers);
|
||||
obj.LoadContent(this.Content);
|
||||
this.Objects[obj.Name] = obj;
|
||||
|
||||
var headers = GenerateObjectResponseHeaders(obj);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.Created, headers);
|
||||
}
|
||||
else
|
||||
{
|
||||
var container = new StorageItem(containerName);
|
||||
container.ProcessMetaDataFromHeaders(this.Headers);
|
||||
|
||||
var containerUpdated = this.Containers.Keys.Any(k => String.Equals(k, container.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||
|
||||
this.Containers[container.Name] = container;
|
||||
|
||||
return TestHelper.CreateResponse(containerUpdated ? HttpStatusCode.Accepted : HttpStatusCode.Created);
|
||||
}
|
||||
}
|
||||
|
||||
private IHttpResponseAbstraction HandlePost()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
StorageItem storageItem;
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
storageItem = this.Objects[objectName];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
storageItem = this.Containers[containerName];
|
||||
}
|
||||
|
||||
storageItem.MetaData.Clear();
|
||||
storageItem.ProcessMetaDataFromHeaders(this.Headers);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.Accepted);
|
||||
}
|
||||
|
||||
private IHttpResponseAbstraction HandleGet()
|
||||
{
|
||||
var containerName = GetContainerName(this.Uri.Segments);
|
||||
var objectName = GetObjectName(this.Uri.Segments);
|
||||
var accountName = GetAccountName(this.Uri.Segments);
|
||||
|
||||
if (containerName == null && objectName == null)
|
||||
{
|
||||
if (accountName == null)
|
||||
{
|
||||
return TestHelper.CreateErrorResponse();
|
||||
}
|
||||
|
||||
var accountHeaders = GenerateAccountResponseHeaders();
|
||||
var accountContent = TestHelper.CreateStream(GenerateAccountPayload());
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.OK, accountHeaders, accountContent);
|
||||
|
||||
}
|
||||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var obj = this.Objects[objectName];
|
||||
var objectHeaders = GenerateObjectResponseHeaders(obj);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.OK, objectHeaders, obj.Content);
|
||||
}
|
||||
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var container = this.Containers[containerName];
|
||||
var headers = GenerateContainerResponseHeaders(container);
|
||||
var content = TestHelper.CreateStream("[]");
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.OK, headers, content);
|
||||
}
|
||||
|
||||
public string GetContainerName(string[] uriSegments)
|
||||
{
|
||||
return uriSegments.Count() < 4 ? null : uriSegments[3].TrimEnd('/');
|
||||
}
|
||||
|
||||
public string GetAccountName(string[] uriSegments)
|
||||
{
|
||||
return uriSegments.Count() < 3 ? null : uriSegments[2].TrimEnd('/');
|
||||
}
|
||||
|
||||
public string GetObjectName(string[] uriSegments)
|
||||
{
|
||||
if (uriSegments.Count() < 5)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return string.Join("", uriSegments.Skip(4));
|
||||
}
|
||||
|
||||
private string GenerateAccountPayload()
|
||||
{
|
||||
var payload = new StringBuilder();
|
||||
payload.Append("[");
|
||||
var first = true;
|
||||
foreach (var container in this.Containers)
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
payload.Append(",");
|
||||
first = false;
|
||||
}
|
||||
|
||||
payload.Append("{");
|
||||
payload.Append("\"count\": 42,");
|
||||
payload.Append("\"bytes\": 12345,");
|
||||
payload.Append(string.Format("\"name\": \"{0}\"",container.Value.Name));
|
||||
payload.Append("}");
|
||||
}
|
||||
payload.Append("]");
|
||||
return payload.ToString();
|
||||
}
|
||||
|
||||
private IEnumerable<KeyValuePair<string, string>> GenerateAccountResponseHeaders()
|
||||
{
|
||||
return new Dictionary<string, string>()
|
||||
{
|
||||
{"X-Account-Bytes-Used", "12345"},
|
||||
{"X-Account-Container-Count", this.Containers.Count.ToString()},
|
||||
{"X-Account-Object-Count", this.Objects.Count.ToString()},
|
||||
{"Content-Type", this.ContentType},
|
||||
{"X-Trans-Id", "12345"},
|
||||
{"Date", DateTime.UtcNow.ToShortTimeString()},
|
||||
{"X-Timestamp", "1234567890.98765"}
|
||||
};
|
||||
}
|
||||
|
||||
internal Dictionary<string, string> GenerateObjectResponseHeaders(StorageItem obj)
|
||||
{
|
||||
var etag = Convert.ToBase64String(MD5.Create().ComputeHash(obj.Content));
|
||||
obj.Content.Position = 0;
|
||||
|
||||
return new Dictionary<string, string>(obj.MetaData)
|
||||
{
|
||||
{"ETag", etag},
|
||||
{"Content-Type", this.ContentType},
|
||||
{"X-Trans-Id", "12345"},
|
||||
{"Date", DateTime.UtcNow.ToShortTimeString()},
|
||||
{"X-Timestamp", "1234567890.98765"}
|
||||
};
|
||||
}
|
||||
|
||||
internal Dictionary<string, string> GenerateContainerResponseHeaders(StorageItem obj)
|
||||
{
|
||||
return new Dictionary<string, string>(obj.MetaData)
|
||||
{
|
||||
{"X-Container-Bytes-Used", "0"},
|
||||
{"Content-Type", this.ContentType},
|
||||
{"X-Container-Object-Count", "0"},
|
||||
{"Date", DateTime.UtcNow.ToShortTimeString()},
|
||||
{"X-Container-Read", ".r.*,.rlistings"},
|
||||
{"X-Trans-Id", "12345"},
|
||||
{"X-Timestamp", "1234567890.98765"}
|
||||
};
|
||||
}
|
||||
|
||||
internal Dictionary<string, string> GenerateDeleteHeaders()
|
||||
{
|
||||
return new Dictionary<string, string>()
|
||||
{
|
||||
{"X-Trans-Id", "12345"},
|
||||
{"Date", DateTime.UtcNow.ToShortTimeString()}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageRestSimulatorFactory : IHttpAbstractionClientFactory
|
||||
{
|
||||
internal StorageRestSimulator Simulator = null;
|
||||
public StorageRestSimulatorFactory(StorageRestSimulator simulator)
|
||||
{
|
||||
this.Simulator = simulator;
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(CancellationToken token)
|
||||
{
|
||||
if (this.Simulator != null)
|
||||
{
|
||||
this.Simulator.Headers.Clear();
|
||||
}
|
||||
return this.Simulator ?? new StorageRestSimulator(token);
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(TimeSpan timeout, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(IOpenStackAccessToken credentials, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IHttpAbstractionClient Create(IOpenStackAccessToken credentials, TimeSpan timeout, CancellationToken token)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Identity;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageServiceClientDefinitionTests
|
||||
{
|
||||
IOpenstackCredential GetValidCreds()
|
||||
{
|
||||
var authId = "12345";
|
||||
var endpoint = "http://teststorageendpoint.com/v1/1234567890";
|
||||
|
||||
var creds = new OpenstackCredential(new Uri(endpoint), "SomeUser", "Password".ConvertToSecureString(), "SomeTenant");
|
||||
creds.SetAccessTokenId(authId);
|
||||
return creds;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanSupportVersion1()
|
||||
{
|
||||
var client = new StorageServiceClientDefinition();
|
||||
var creds = GetValidCreds();
|
||||
var catalog =
|
||||
new OpenstackServiceCatalog
|
||||
{
|
||||
new OpenstackServiceDefinition("Object Storage", "Test",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://someplace.com", "somewhere", "1.0",
|
||||
new Uri("http://someplace.com"), new Uri("http://someplace.com"))
|
||||
})
|
||||
};
|
||||
creds.SetServiceCatalog(catalog);
|
||||
Assert.IsTrue(client.IsSupported(creds));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CannotSupportVersion2()
|
||||
{
|
||||
var client = new StorageServiceClientDefinition();
|
||||
var creds = GetValidCreds();
|
||||
var catalog =
|
||||
new OpenstackServiceCatalog
|
||||
{
|
||||
new OpenstackServiceDefinition("Object Storage", "Test",
|
||||
new List<OpenstackServiceEndpoint>()
|
||||
{
|
||||
new OpenstackServiceEndpoint("http://someplace.com", "somewhere", "2.0.0.0",
|
||||
new Uri("http://someplace.com"), new Uri("http://someplace.com"))
|
||||
})
|
||||
};
|
||||
creds.SetServiceCatalog(catalog);
|
||||
Assert.IsFalse(client.IsSupported(creds));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Version1Supported()
|
||||
{
|
||||
var client = new StorageServiceClientDefinition();
|
||||
Assert.IsTrue(client.ListSupportedVersions().Contains("1.0"));
|
||||
Assert.IsTrue(client.ListSupportedVersions().Contains("1"));
|
||||
}
|
||||
}
|
||||
}
|
589
Openstack/Openstack.Test/Storage/StorageServiceClientTests.cs
Normal file
589
Openstack/Openstack.Test/Storage/StorageServiceClientTests.cs
Normal file
@@ -0,0 +1,589 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageServiceClientTests
|
||||
{
|
||||
internal TestStorageServicePocoClient ServicePocoClient;
|
||||
internal string authId = "12345";
|
||||
internal string endpoint = "http://teststorageendpoint.com/v1/1234567890";
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
this.ServicePocoClient = new TestStorageServicePocoClient();
|
||||
|
||||
ServiceLocator.Reset();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
manager.RegisterServiceInstance(typeof(IStorageServicePocoClientFactory), new TestStorageServicePocoClientFactory(ServicePocoClient));
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.ServicePocoClient = new TestStorageServicePocoClient();
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
IOpenstackCredential GetValidCreds()
|
||||
{
|
||||
var creds = new OpenstackCredential(new Uri(this.endpoint), "SomeUser", "Password".ConvertToSecureString(), "SomeTenant");
|
||||
creds.SetAccessTokenId(this.authId);
|
||||
return creds;
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanListStorageObjects()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var numberObjCalls = 0;
|
||||
var obj = new StorageObject("TestObj", containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var container = new StorageContainer(containerName, 100, 1, new Dictionary<string, string>(),
|
||||
new List<StorageObject>() {obj});
|
||||
this.ServicePocoClient.GetStorageContainerDelegate = s =>
|
||||
{
|
||||
Assert.AreEqual(container.Name, s);
|
||||
return Task.Factory.StartNew(() => container);
|
||||
};
|
||||
this.ServicePocoClient.GetStorageObjectDelegate = (s, s1) =>
|
||||
{
|
||||
numberObjCalls++;
|
||||
Assert.AreEqual(s, obj.ContainerName);
|
||||
Assert.AreEqual(s1, obj.Name);
|
||||
return Task.Factory.StartNew(() => obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.ListStorageObjects(containerName);
|
||||
|
||||
Assert.AreEqual(1,numberObjCalls);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task ListingStorageObjectsWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.ListStorageObjects(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanListStorageContainers()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var numberContainerCalls = 0;
|
||||
|
||||
var container = new StorageContainer(containerName, 100, 1, new Dictionary<string, string>(),
|
||||
new List<StorageObject>());
|
||||
|
||||
var account = new StorageAccount("1234567890", 100, 1, 1, new List<StorageContainer>() { container });
|
||||
|
||||
this.ServicePocoClient.GetStorageContainerDelegate = s =>
|
||||
{
|
||||
numberContainerCalls++;
|
||||
Assert.AreEqual(container.Name, s);
|
||||
return Task.Factory.StartNew(() => container);
|
||||
};
|
||||
|
||||
this.ServicePocoClient.GetStorageAccountDelegate = () => Task.Factory.StartNew(() => account);
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.ListStorageContainers();
|
||||
var containers = resp.ToList();
|
||||
|
||||
Assert.AreEqual(1, containers.Count);
|
||||
Assert.AreEqual(1, numberContainerCalls);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageAccount()
|
||||
{
|
||||
var account = new StorageAccount("1234567890", 100, 10, 1, new List<StorageContainer>());
|
||||
|
||||
this.ServicePocoClient.GetStorageAccountDelegate = () =>
|
||||
{
|
||||
Assert.AreEqual("1234567890", account.Name);
|
||||
return Task.Factory.StartNew(() => account);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.GetStorageAccount();
|
||||
|
||||
Assert.AreEqual(account, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageObjects()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.GetStorageObjectDelegate = (s, s1) =>
|
||||
{
|
||||
Assert.AreEqual(s, obj.ContainerName);
|
||||
Assert.AreEqual(s1, obj.Name);
|
||||
return Task.Factory.StartNew(() => obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.GetStorageObject(containerName, objectName);
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task GettingStorageObjectsWithNullContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageObject(null, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task GettingStorageObjectsWithEmptyContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageObject(string.Empty, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task GettingStorageObjectsWithNullObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageObject(containerName, null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task GettingStorageObjectsWithEmptyObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageObject(containerName, string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageObjects()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
var content = TestHelper.CreateStream("Some Data");
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.CreateStorageObjectDelegate = async (s, stream) =>
|
||||
{
|
||||
Assert.AreEqual(s.ContainerName, obj.ContainerName);
|
||||
Assert.AreEqual(s.Name, obj.Name);
|
||||
Assert.AreEqual(stream, content);
|
||||
return await Task.Run(()=>obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.CreateStorageObject(containerName, objectName, new Dictionary<string,string>(), content);
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageObjectsWithNullContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(null, objectName, new Dictionary<string, string>(), new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageObjectsWithEmptyContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(string.Empty, objectName, new Dictionary<string, string>(), new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageObjectsWithNullObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(containerName, null, new Dictionary<string, string>(), new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageObjectsWithEmptyObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(containerName, string.Empty, new Dictionary<string, string>(), new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageObjectsWithNullStreamThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(containerName, objectName, new Dictionary<string, string>(), null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageObjectsWithNullMetadataThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageObject(containerName, objectName, null, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageContainers()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var obj = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.CreateStorageContainerDelegate = async (s) =>
|
||||
{
|
||||
Assert.AreEqual(s.Name, obj.Name);
|
||||
return await Task.Run(()=>obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageContainer(containerName, new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageContainersWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageContainer(null, new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageContainersWithEmptyContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageContainer(string.Empty, new Dictionary<string, string>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageContainersWithNullMetadataThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageContainer("TestContainer", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageContainer()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var obj = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.GetStorageContainerDelegate = (s) =>
|
||||
{
|
||||
Assert.AreEqual(s, obj.Name);
|
||||
return Task.Factory.StartNew(() => obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.GetStorageContainer(containerName);
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task GettingStorageContainersWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageContainer(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof (ArgumentException))]
|
||||
public async Task GettingStorageContainersWithEmptyContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageContainer(string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanUpdateStorageContainer()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var obj = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.UpdateStorageContainerDelegate = async (s) =>
|
||||
{
|
||||
await Task.Run(() => Assert.AreEqual(s.Name, obj.Name));
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.UpdateStorageContainer(obj);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task UpdatingStorageContainersWithNullContainerThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.UpdateStorageContainer(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageContainer()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var obj = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.DeleteStorageConainerDelegate = async (s) =>
|
||||
{
|
||||
await Task.Run(()=>Assert.AreEqual(s, obj.Name));
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageContainer(obj.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DeletingStorageContainersWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageContainer(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DeletingStorageContainersWithEmptyContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageContainer(string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageObject()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.DeleteStorageObjectDelegate = async (s, s1) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s, obj.ContainerName);
|
||||
Assert.AreEqual(s1, obj.Name);
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageObject(obj.ContainerName,obj.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DeletingStorageObjectWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageObject(null,"TestObject");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DeletingStorageObjectsWithEmptyContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageObject(string.Empty, "TestObject");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DeletingStorageObjectWithNullObjectNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageObject("TestContainer", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DeletingStorageObjectsWithEmptyObjectNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageObject("TestContainer", string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanUpdateStorageObject()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.UpdateStorageObjectDelegate = async (s) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s.ContainerName, obj.ContainerName);
|
||||
Assert.AreEqual(s.Name, obj.Name);
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.UpdateStorageObject(obj);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task UpdatingStorageObjectWithNullContainerThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.UpdateStorageObject(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDownloadStorageObjects()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
var data = "some data";
|
||||
var content = TestHelper.CreateStream(data);
|
||||
var respStream = new MemoryStream();
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.DownloadStorageObjectDelegate = async (s, s1, stream) =>
|
||||
{
|
||||
Assert.AreEqual(s, obj.ContainerName);
|
||||
Assert.AreEqual(s1, obj.Name);
|
||||
|
||||
await content.CopyToAsync(stream);
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.DownloadStorageObject(containerName, objectName, respStream);
|
||||
respStream.Position = 0;
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
Assert.AreEqual(data,TestHelper.GetStringFromStream(respStream));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DownloadingStorageObjectsWithNullContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DownloadStorageObject(null, objectName, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DownloadingStorageObjectsWithEmptyContainerNameThrows()
|
||||
{
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DownloadStorageObject(string.Empty, objectName, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DownloadingStorageObjectsWithNullObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DownloadStorageObject(containerName, null, new MemoryStream() );
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DownloadingStorageObjectsWithEmptyObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DownloadStorageObject(containerName, string.Empty, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DownloadingStorageObjectsWithNullStreamThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DownloadStorageObject(containerName, objectName, null);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,980 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
using Openstack.Identity;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
[TestClass]
|
||||
public class StorageServicePocoClientTests
|
||||
{
|
||||
internal TestOpenstackServiceEndpointResolver resolver;
|
||||
internal TestStorageServiceRestClient StorageServiceRestClient;
|
||||
internal string authId = "12345";
|
||||
internal Uri endpoint = new Uri("http://teststorageendpoint.com/v1/1234567890");
|
||||
|
||||
[TestInitialize]
|
||||
public void TestSetup()
|
||||
{
|
||||
this.StorageServiceRestClient = new TestStorageServiceRestClient();
|
||||
this.resolver = new TestOpenstackServiceEndpointResolver() { Endpoint = endpoint };
|
||||
|
||||
ServiceLocator.Reset();
|
||||
var manager = ServiceLocator.Instance.Locate<IServiceLocationOverrideManager>();
|
||||
manager.RegisterServiceInstance(typeof(IStorageServiceRestClientFactory), new TestStorageServiceRestClientFactory(StorageServiceRestClient));
|
||||
manager.RegisterServiceInstance(typeof(IOpenstackServiceEndpointResolver), this.resolver);
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void TestCleanup()
|
||||
{
|
||||
this.resolver = new TestOpenstackServiceEndpointResolver() { Endpoint = endpoint };
|
||||
this.StorageServiceRestClient = new TestStorageServiceRestClient();
|
||||
ServiceLocator.Reset();
|
||||
}
|
||||
|
||||
StorageServiceClientContext GetValidContext()
|
||||
{
|
||||
var creds = new OpenstackCredential(this.endpoint, "SomeUser", "Password".ConvertToSecureString(), "SomeTenant");
|
||||
creds.SetAccessTokenId(this.authId);
|
||||
|
||||
return new StorageServiceClientContext(creds, CancellationToken.None, "Object Storage", "region-a.geo-1");
|
||||
}
|
||||
|
||||
#region Get Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageContainerWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
var result = await client.GetStorageContainer(containerName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(containerName, result.Name);
|
||||
Assert.AreEqual(1234, result.TotalBytesUsed);
|
||||
Assert.AreEqual(1, result.TotalObjectCount);
|
||||
Assert.IsNotNull(result.Objects);
|
||||
Assert.AreEqual(1, result.Objects.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageContainerWithNoContent()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "0"},
|
||||
{"X-Container-Object-Count", "0"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageContainer(containerName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(containerName, result.Name);
|
||||
Assert.AreEqual(0, result.TotalBytesUsed);
|
||||
Assert.AreEqual(0, result.TotalObjectCount);
|
||||
Assert.IsNotNull(result.Objects);
|
||||
Assert.AreEqual(0, result.Objects.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageContainerThatDoesNotExist()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NotFound);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageContainerAndNotAuthed()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageContainerAndServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotGetStorageContainerWithNullName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageContainer(null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Storage Account Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageAccountWithOkResponse()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Account-Bytes-Used", "1234"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[
|
||||
{
|
||||
""count"": 1,
|
||||
""bytes"": 7,
|
||||
""name"": ""TestContainer""
|
||||
}]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageAccount();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(accountName, result.Name);
|
||||
Assert.AreEqual(1234, result.TotalBytesUsed);
|
||||
Assert.AreEqual(1, result.TotalObjectCount);
|
||||
Assert.AreEqual(1, result.TotalContainerCount);
|
||||
Assert.IsNotNull(result.Containers);
|
||||
Assert.AreEqual(1, result.Containers.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageAccontWithNoContent()
|
||||
{
|
||||
var accountName = "1234567890";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Account-Bytes-Used", "1234"},
|
||||
{"X-Account-Object-Count", "1"},
|
||||
{"X-Account-Container-Count", "1"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageAccount();
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(accountName, result.Name);
|
||||
Assert.AreEqual(1234, result.TotalBytesUsed);
|
||||
Assert.AreEqual(1, result.TotalObjectCount);
|
||||
Assert.AreEqual(1, result.TotalContainerCount);
|
||||
Assert.IsNotNull(result.Containers);
|
||||
Assert.AreEqual(0, result.Containers.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageAccountAndNotAuthed()
|
||||
{
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageAccount();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageAccountAndServerError()
|
||||
{
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageAccount();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Download Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDownloadStorageObjectWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var data = "some data";
|
||||
var content = TestHelper.CreateStream(data);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
|
||||
var respContent = new MemoryStream();
|
||||
var result = await client.DownloadStorageObject(containerName, objectName, respContent);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(objectName, result.Name);
|
||||
Assert.AreEqual(containerName, result.ContainerName);
|
||||
Assert.AreEqual(1234, result.Length);
|
||||
Assert.AreEqual("application/octet-stream", result.ContentType);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
|
||||
Assert.AreEqual(data,TestHelper.GetStringFromStream(respContent));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenDownloadingAStorageObjectThatDoesNotExist()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NotFound);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject(containerName, objectName, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenDownloadingAStorageObjectAndNotAuthed()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject(containerName, objectName, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenDownloadingAStorageObjectAndServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject(containerName, objectName, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotDownloadStorageObjectWithNullContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject(null, "object", new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotDownloadStorageObjectWithNullObjectName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject("container", null, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotDownloadStorageObjectWithEmptyContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject(string.Empty, "object", new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotDownloadStorageObjectWithEmptyObjectName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject("container", string.Empty, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotDownloadStorageObjectWithnullOutputStream()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DownloadStorageObject("container", "object", null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageObjectWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageObject(containerName, objectName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(objectName, result.Name);
|
||||
Assert.AreEqual(containerName, result.ContainerName);
|
||||
Assert.AreEqual(1234, result.Length);
|
||||
Assert.AreEqual("application/octet-stream", result.ContentType);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageObjectWithNoContent()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageObject(containerName, objectName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(objectName, result.Name);
|
||||
Assert.AreEqual(containerName, result.ContainerName);
|
||||
Assert.AreEqual(1234, result.Length);
|
||||
Assert.AreEqual("application/octet-stream", result.ContentType);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageObjectWithHeaders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.GetStorageObject(containerName, objectName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(objectName, result.Name);
|
||||
Assert.AreEqual(containerName, result.ContainerName);
|
||||
Assert.AreEqual(1234, result.Length);
|
||||
Assert.AreEqual("application/octet-stream", result.ContentType);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
|
||||
Assert.AreEqual(1, result.Metadata.Count());
|
||||
Assert.IsTrue(result.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", result.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageObjectThatDoesNotExist()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NotFound);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageObjectAndNotAuthed()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageObjectAndServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotGetStorageObjectWithNullContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject(null,"object");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotGetStorageObjectWithNullObjectName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject("container", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotGetStorageObjectWithEmptyContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject(string.Empty, "object");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotGetStorageObjectWithEmptyObjectName()
|
||||
{
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageObject("container", string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageObjectWithCreatedResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.Created);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
var result = await client.CreateStorageObject(objRequest, content);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual(objectName, result.Name);
|
||||
Assert.AreEqual(containerName, result.ContainerName);
|
||||
Assert.AreEqual(1234, result.Length);
|
||||
Assert.AreEqual("application/octet-stream", result.ContentType);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", result.ETag);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), result.LastModified);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageObjectMissingLength()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.LengthRequired);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageObject(objRequest, content);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageObjectWithBadETag()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), (HttpStatusCode)422);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageObject(objRequest, content);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageObjectWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageObject(objRequest, content);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageObjectHasInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageObject(objRequest, content);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageObjectTimesOut()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objRequest = new StorageObject(objectName, containerName);
|
||||
var content = TestHelper.CreateStream("Some Content");
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.RequestTimeout);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageObject(objRequest, content);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageContainerWithCreatedResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.Created);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageContainer(containerReq);
|
||||
|
||||
//Assert.IsNotNull(container);
|
||||
//Assert.AreEqual(containerName, container.Name);
|
||||
//Assert.AreEqual(12345, container.TotalBytesUsed);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageContainerWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var headers = new HttpHeadersAbstraction
|
||||
{
|
||||
{"X-Container-Bytes-Used", "12345"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageContainer(containerReq);
|
||||
|
||||
//Assert.IsNotNull(container);
|
||||
//Assert.AreEqual(containerName, container.Name);
|
||||
//Assert.AreEqual(12345, container.TotalBytesUsed);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageContainerWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageContainer(containerReq);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageContainerHasInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageContainer(containerReq);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageContainerWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageContainerWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageContainerWithObjects()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Conflict);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageContainerWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageContainer(containerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageContainerWithInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageContainer(containerName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageObjectWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageObjectWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageObjectWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageObjectWithInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageObject(containerName, objectName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanUpdateAStorageContainerWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageContainer(containerReq);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenUpdatingAStorageContainerWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageContainer(containerReq);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenUpdatingAStorageContainerWithInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var containerReq = new StorageContainer(containerName, new Dictionary<string, string>());
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageContainer(containerReq);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanUpdateAStorageObjectWithAcceptedResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objectReq = new StorageObject(containerName, objectName);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Accepted);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageObject(objectReq);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenUpdatingAStorageObjectWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objectReq = new StorageObject(containerName, objectName);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageObject(objectReq);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenUpdatingAStorageObjectWithInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var objectReq = new StorageObject(containerName, objectName);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.UpdateStorageObject(objectReq);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
1293
Openstack/Openstack.Test/Storage/StorageServiceRestClientTests.cs
Normal file
1293
Openstack/Openstack.Test/Storage/StorageServiceRestClientTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
111
Openstack/Openstack.Test/Storage/TestStorageServicePocoClient.cs
Normal file
111
Openstack/Openstack.Test/Storage/TestStorageServicePocoClient.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
public class TestStorageServicePocoClient : IStorageServicePocoClient
|
||||
{
|
||||
public Func<StorageObject, Stream, Task<StorageObject>> CreateStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<StorageContainer, Task<StorageContainer>> CreateStorageContainerDelegate { get; set; }
|
||||
|
||||
public Func<string, Task<StorageContainer>> GetStorageContainerDelegate { get; set; }
|
||||
|
||||
public Func<Task<StorageAccount>> GetStorageAccountDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task<StorageObject>> GetStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Stream, Task<StorageObject>> DownloadStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task> DeleteStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<StorageObject, Task> UpdateStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, Task> DeleteStorageConainerDelegate { get; set; }
|
||||
|
||||
public Func<StorageContainer, Task> UpdateStorageContainerDelegate { get; set; }
|
||||
|
||||
public async Task<StorageObject> CreateStorageObject(StorageObject obj, Stream content)
|
||||
{
|
||||
return await this.CreateStorageObjectDelegate(obj, content);
|
||||
}
|
||||
|
||||
public async Task CreateStorageContainer(StorageContainer container)
|
||||
{
|
||||
await this.CreateStorageContainerDelegate(container);
|
||||
}
|
||||
|
||||
public async Task<StorageAccount> GetStorageAccount()
|
||||
{
|
||||
return await this.GetStorageAccountDelegate();
|
||||
}
|
||||
|
||||
public async Task<StorageContainer> GetStorageContainer(string containerName)
|
||||
{
|
||||
return await this.GetStorageContainerDelegate(containerName);
|
||||
}
|
||||
|
||||
public async Task<StorageObject> GetStorageObject(string containerName, string objectName)
|
||||
{
|
||||
return await this.GetStorageObjectDelegate(containerName, objectName);
|
||||
}
|
||||
|
||||
public async Task<StorageObject> DownloadStorageObject(string containerName, string objectName, Stream outputStream)
|
||||
{
|
||||
return await this.DownloadStorageObjectDelegate(containerName, objectName, outputStream);
|
||||
}
|
||||
|
||||
public async Task DeleteStorageObject(string containerName, string objectName)
|
||||
{
|
||||
await this.DeleteStorageObjectDelegate(containerName, objectName);
|
||||
}
|
||||
|
||||
public async Task DeleteStorageContainer(string containerName)
|
||||
{
|
||||
await this.DeleteStorageConainerDelegate(containerName);
|
||||
}
|
||||
|
||||
public async Task UpdateStorageContainer(StorageContainer container)
|
||||
{
|
||||
await this.UpdateStorageContainerDelegate(container);
|
||||
}
|
||||
|
||||
public async Task UpdateStorageObject(StorageObject obj)
|
||||
{
|
||||
await this.UpdateStorageObjectDelegate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestStorageServicePocoClientFactory : IStorageServicePocoClientFactory
|
||||
{
|
||||
internal IStorageServicePocoClient client;
|
||||
|
||||
public TestStorageServicePocoClientFactory(IStorageServicePocoClient client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public IStorageServicePocoClient Create(StorageServiceClientContext context)
|
||||
{
|
||||
return client;
|
||||
}
|
||||
}
|
||||
}
|
104
Openstack/Openstack.Test/Storage/TestStorageServiceRestClient.cs
Normal file
104
Openstack/Openstack.Test/Storage/TestStorageServiceRestClient.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Storage;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
public class TestStorageServiceRestClient : IStorageServiceRestClient
|
||||
{
|
||||
public IHttpResponseAbstraction Response { get; set; }
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateObject(string containerName, string objectName, IDictionary<string, string> metadata, Stream content)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateContainer(string containerName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetObject(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetContainer(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> DeleteObject(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> DeleteContainer(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> UpdateObject(string containerName, string objectName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> UpdateContainer(string containerName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetContainerMetadata(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetObjectMetadata(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CopyObject(string sourceContainerName, string sourceObjectName, string targetContainerName,
|
||||
string targetObjectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetAccount()
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestStorageServiceRestClientFactory : IStorageServiceRestClientFactory
|
||||
{
|
||||
internal IStorageServiceRestClient Client;
|
||||
public TestStorageServiceRestClientFactory(IStorageServiceRestClient client)
|
||||
{
|
||||
this.Client = client;
|
||||
}
|
||||
|
||||
public IStorageServiceRestClient Create(StorageServiceClientContext context)
|
||||
{
|
||||
return Client;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack.Test
|
||||
{
|
||||
public class TestOpenstackServiceEndpointResolver : IOpenstackServiceEndpointResolver
|
||||
{
|
||||
internal Uri Endpoint { get; set; }
|
||||
|
||||
public string ResolveEndpoint(ICollection<OpenstackServiceDefinition> catalog, string serviceName, string region)
|
||||
{
|
||||
return Endpoint.ToString();
|
||||
}
|
||||
}
|
||||
}
|
4
Openstack/Openstack.Test/packages.config
Normal file
4
Openstack/Openstack.Test/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="4.5.7" targetFramework="net45" />
|
||||
</packages>
|
34
Openstack/Openstack.sln
Normal file
34
Openstack/Openstack.sln
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Openstack.Common", "Openstack.Common\Openstack.Common.csproj", "{C53D669C-CDF1-4157-AEC1-BD167F655B2B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Openstack", "Openstack\Openstack.csproj", "{B2C92371-B62B-45A2-ADEB-EDEBEFA3A75C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Openstack.Test", "Openstack.Test\Openstack.Test.csproj", "{7AF6DEC5-2257-4A29-BB55-66711DE3055D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C53D669C-CDF1-4157-AEC1-BD167F655B2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C53D669C-CDF1-4157-AEC1-BD167F655B2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C53D669C-CDF1-4157-AEC1-BD167F655B2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C53D669C-CDF1-4157-AEC1-BD167F655B2B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B2C92371-B62B-45A2-ADEB-EDEBEFA3A75C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B2C92371-B62B-45A2-ADEB-EDEBEFA3A75C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B2C92371-B62B-45A2-ADEB-EDEBEFA3A75C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B2C92371-B62B-45A2-ADEB-EDEBEFA3A75C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7AF6DEC5-2257-4A29-BB55-66711DE3055D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7AF6DEC5-2257-4A29-BB55-66711DE3055D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7AF6DEC5-2257-4A29-BB55-66711DE3055D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7AF6DEC5-2257-4A29-BB55-66711DE3055D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
68
Openstack/Openstack/IOpenstackClient.cs
Normal file
68
Openstack/Openstack/IOpenstackClient.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// Top level Openstack client used to connect and interact with an instance of Openstack.
|
||||
/// </summary>
|
||||
public interface IOpenstackClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a reference to the credential currently being used.
|
||||
/// </summary>
|
||||
IOpenstackCredential Credential { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Connects the client to the remote instance of Openstack.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task Connect();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a client for a given Openstack service.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of client to create.</typeparam>
|
||||
/// <returns>An implementation of the requested client.</returns>
|
||||
T CreateServiceClient<T>() where T : IOpenstackServiceClient;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a client for a given Openstack service that supports the given version.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of client to create.</typeparam>
|
||||
/// <param name="version">The version that must be supported.</param>
|
||||
/// <returns>An implementation of the requested client.</returns>
|
||||
T CreateServiceClient<T>(string version) where T : IOpenstackServiceClient;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of supported Openstack versions for this client.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IEnumerable<string> GetSupportedVersions();
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the client can support the given credential and version.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential that must be supported.</param>
|
||||
/// <param name="version">The version that must be supported.</param>
|
||||
/// <returns>A value indicating if the given credential and version are supported.</returns>
|
||||
bool IsSupported(ICredential credential, string version);
|
||||
}
|
||||
}
|
54
Openstack/Openstack/IOpenstackClientManager.cs
Normal file
54
Openstack/Openstack/IOpenstackClientManager.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Identity;
|
||||
/// <summary>
|
||||
/// Manages the creation and registration of Openstack clients.
|
||||
/// </summary>
|
||||
public interface IOpenstackClientManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates an instance of a client that can support the given credential.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential that must be supported.</param>
|
||||
/// <returns>An instance of an Openstack client.</returns>
|
||||
IOpenstackClient CreateClient(ICredential credential);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of a client that can support the given credential and version.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential that must be supported.</param>
|
||||
/// <param name="version">The version that must be supported.</param>
|
||||
/// <returns>An instance of an Openstack client.</returns>
|
||||
IOpenstackClient CreateClient(ICredential credential, string version);
|
||||
|
||||
/// <summary>
|
||||
/// Registers a client for use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the client to be registered.</typeparam>
|
||||
void RegisterClient<T>() where T : IOpenstackClient;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of available clients that are being managed by this object.
|
||||
/// </summary>
|
||||
/// <returns>A list of Openstack clients.</returns>
|
||||
IEnumerable<Type> ListAvailableClients();
|
||||
}
|
||||
}
|
30
Openstack/Openstack/IOpenstackServiceClient.cs
Normal file
30
Openstack/Openstack/IOpenstackServiceClient.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using Openstack.Identity;
|
||||
|
||||
namespace Openstack
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// A client that can be used to interact with an Openstack service.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceClient
|
||||
{
|
||||
|
||||
}
|
||||
}
|
51
Openstack/Openstack/IOpenstackServiceClientDefinition.cs
Normal file
51
Openstack/Openstack/IOpenstackServiceClientDefinition.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Openstack.Identity;
|
||||
|
||||
public interface IOpenstackServiceClientDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the service client.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the service client being defined.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential that the client will use.</param>
|
||||
/// <param name="cancellationToken">The cancellation token that the client will use.</param>
|
||||
/// <returns></returns>
|
||||
IOpenstackServiceClient Create(ICredential credential, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of supported versions.
|
||||
/// </summary>
|
||||
/// <returns>A list of versions.</returns>
|
||||
IEnumerable<string> ListSupportedVersions();
|
||||
|
||||
/// <summary>
|
||||
/// Determines if this client is currently supported.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential for the service to use.</param>
|
||||
/// <returns>A value indicating if the client is supported.</returns>
|
||||
bool IsSupported(ICredential credential);
|
||||
}
|
||||
}
|
51
Openstack/Openstack/IOpenstackServiceClientManager.cs
Normal file
51
Openstack/Openstack/IOpenstackServiceClientManager.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Openstack.Identity;
|
||||
|
||||
/// <summary>
|
||||
/// Creates and registers clients that can be used to interact with Openstack services.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceClientManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a client that can interact with the requested Openstack service.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of client to be created.</typeparam>
|
||||
/// <param name="credential">The credential to be used by the client.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to be used by the client.</param>
|
||||
/// <returns>An instance of the requested client.</returns>
|
||||
T CreateServiceClient<T>(ICredential credential, CancellationToken cancellationToken) where T : IOpenstackServiceClient;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all available clients that can be used to interact with Openstack services.
|
||||
/// </summary>
|
||||
/// <returns>A list of types of clients.</returns>
|
||||
IEnumerable<Type> ListAvailableServiceClients();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a client for use.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the client to register.</typeparam>
|
||||
/// <param name="serviceClientDefinition">An object that can be used to validate support and construct the given client.</param>
|
||||
void RegisterServiceClient<T>(IOpenstackServiceClientDefinition serviceClientDefinition) where T : IOpenstackServiceClient;
|
||||
}
|
||||
}
|
55
Openstack/Openstack/Identity/AccessTokenPayloadConverter.cs
Normal file
55
Openstack/Openstack/Identity/AccessTokenPayloadConverter.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class AccessTokenPayloadConverter : IAccessTokenPayloadConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Convert(string payload)
|
||||
{
|
||||
payload.AssertIsNotNull("payload", "A null Storage Container payload cannot be converted.");
|
||||
|
||||
if (String.IsNullOrEmpty(payload))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var obj = JObject.Parse(payload);
|
||||
var token = (string)obj["access"]["token"]["id"];
|
||||
|
||||
if (token == null)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Access token payload could not be parsed. Token is null. Payload: '{0}'", payload));
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Access token payload could not be parsed. Payload: '{0}'", payload), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
Openstack/Openstack/Identity/IAccessTokenPayloadConverter.cs
Normal file
31
Openstack/Openstack/Identity/IAccessTokenPayloadConverter.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into an access token Id.
|
||||
/// </summary>
|
||||
interface IAccessTokenPayloadConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into an access token Id.
|
||||
/// </summary>
|
||||
/// <param name="payload">The Json payload to convert.</param>
|
||||
/// <returns>The converted access token Id.</returns>
|
||||
string Convert(string payload);
|
||||
}
|
||||
}
|
41
Openstack/Openstack/Identity/ICredential.cs
Normal file
41
Openstack/Openstack/Identity/ICredential.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// A credential to be used when communicating with an instance of Openstack.
|
||||
/// </summary>
|
||||
public interface ICredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the authentication endpoint to be used for the current instance of Openstack.
|
||||
/// </summary>
|
||||
Uri AuthenticationEndpoint { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the access token to be used for the current instance of Openstack.
|
||||
/// </summary>
|
||||
string AccessTokenId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the service catalog for the current instance of Openstack.
|
||||
/// </summary>
|
||||
OpenstackServiceCatalog ServiceCatalog { get; }
|
||||
}
|
||||
}
|
32
Openstack/Openstack/Identity/IIdentityServiceClient.cs
Normal file
32
Openstack/Openstack/Identity/IIdentityServiceClient.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// A client that can be used to communicate with an Openstack identity service.
|
||||
/// </summary>
|
||||
public interface IIdentityServiceClient : IOpenstackServiceClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Authenticates against an instance of Openstack.
|
||||
/// </summary>
|
||||
/// <returns>An authentication credential that can be used to communicate with Openstack.</returns>
|
||||
Task<IOpenstackCredential> Authenticate();
|
||||
}
|
||||
}
|
32
Openstack/Openstack/Identity/IIdentityServicePocoClient.cs
Normal file
32
Openstack/Openstack/Identity/IIdentityServicePocoClient.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// A client that can be used to create and interact with POCO objects related to the Openstack identity service.
|
||||
/// </summary>
|
||||
public interface IIdentityServicePocoClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Authenticates against a remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <returns>A credential that can be used to interact with the remote instance of Openstack.</returns>
|
||||
Task<IOpenstackCredential> Authenticate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs clients that can be used to interact with POCO object related to the Openstack identity service.
|
||||
/// </summary>
|
||||
public interface IIdentityServicePocoClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a client that can be used to interact with the remote Openstack service.
|
||||
/// </summary>
|
||||
/// <param name="credentials">The credential to be used when interacting with Openstack.</param>
|
||||
/// <param name="token">The cancellation token to be used when interacting with Openstack.</param>
|
||||
/// <returns>An instance of the client.</returns>
|
||||
IIdentityServicePocoClient Create(IOpenstackCredential credentials, CancellationToken token);
|
||||
}
|
||||
}
|
33
Openstack/Openstack/Identity/IIdentityServiceRestClient.cs
Normal file
33
Openstack/Openstack/Identity/IIdentityServiceRestClient.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common.Http;
|
||||
|
||||
/// <summary>
|
||||
/// A client that can be used to create and interact with REST interfaces related to the Openstack identity service.
|
||||
/// </summary>
|
||||
public interface IIdentityServiceRestClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Authenticates against a remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <returns>A credential that can be used to interact with the remote instance of Openstack.</returns>
|
||||
Task<IHttpResponseAbstraction> Authenticate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs clients that can be used to interact with REST interfaces related to the Openstack identity service.
|
||||
/// </summary>
|
||||
public interface IIdentityServiceRestClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a client that can be used to interact with the remote Openstack service.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential to be used when interacting with Openstack.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to be used when interacting with Openstack.</param>
|
||||
/// <returns>An instance of the client.</returns>
|
||||
IIdentityServiceRestClient Create(IOpenstackCredential credential, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
52
Openstack/Openstack/Identity/IOpenstackCredential.cs
Normal file
52
Openstack/Openstack/Identity/IOpenstackCredential.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Security;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public interface IOpenstackCredential : ICredential
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the user to use for the current instance of Openstack
|
||||
/// </summary>
|
||||
string UserName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the password to use for the current instance of Openstack
|
||||
/// </summary>
|
||||
SecureString Password { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Id of the tenant to use for the current instance of Openstack
|
||||
/// </summary>
|
||||
string TenantId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the access token to be used for the current instance of Openstack.
|
||||
/// </summary>
|
||||
/// <param name="accessTokenId">The access token id.</param>
|
||||
void SetAccessTokenId(string accessTokenId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets the service catalog to be used for the current instance of Openstack.
|
||||
/// </summary>
|
||||
/// <param name="catalog">The service catalog.</param>
|
||||
void SetServiceCatalog(OpenstackServiceCatalog catalog);
|
||||
}
|
||||
}
|
49
Openstack/Openstack/Identity/IOpenstackServiceCatalog.cs
Normal file
49
Openstack/Openstack/Identity/IOpenstackServiceCatalog.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// A listing of services offered by a remote instance of Openstack.
|
||||
/// </summary>
|
||||
internal interface IOpenstackServiceCatalog : IEnumerable<OpenstackServiceDefinition>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the public endpoint for the given service and region.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">The name of the service.</param>
|
||||
/// <param name="region">The region of the endpoint.</param>
|
||||
/// <returns>A Uri that represents the public endpoint for the given service in the given region.</returns>
|
||||
Uri GetPublicEndpoint(string serviceName, string region);
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given service exists in the catalog.
|
||||
/// </summary>
|
||||
/// <param name="serviceName">The name of the service to check for.</param>
|
||||
/// <returns>A value indicating if the service could be found in the catalog.</returns>
|
||||
bool Exists(string serviceName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of services available in the given region/availability zone.
|
||||
/// </summary>
|
||||
/// <param name="availabilityZoneName">The name of the region/availability zone.</param>
|
||||
/// <returns>A list of available services.</returns>
|
||||
IEnumerable<OpenstackServiceDefinition> GetServicesInAvailabilityZone(string availabilityZoneName);
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into an object that represents a service catalog.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceCatalogPayloadConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into a service catalog.
|
||||
/// </summary>
|
||||
/// <param name="payload">The Json payload to convert.</param>
|
||||
/// <returns>The converted service catalog.</returns>
|
||||
OpenstackServiceCatalog Convert(string payload);
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into an object that represents a service definition.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceDefinitionPayloadConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into a service definition.
|
||||
/// </summary>
|
||||
/// <param name="payload">The Json payload to convert.</param>
|
||||
/// <returns>The converted service definition.</returns>
|
||||
OpenstackServiceDefinition Convert(string payload);
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into an object that represents a service endpoint.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceEndpointPayloadConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a Json payload into a service endpoint.
|
||||
/// </summary>
|
||||
/// <param name="payload">The Json payload to convert.</param>
|
||||
/// <returns>The converted service endpoint.</returns>
|
||||
OpenstackServiceEndpoint Convert(string payload);
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Resolves services endpoints from a service catalog.
|
||||
/// </summary>
|
||||
public interface IOpenstackServiceEndpointResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Resolves a service endpoint from the supplied service catalog using the given service and region.
|
||||
/// </summary>
|
||||
/// <param name="catalog">The service catalog.</param>
|
||||
/// <param name="serviceName">The name of the service.</param>
|
||||
/// <param name="region">The region of the endpoint.</param>
|
||||
/// <returns>a string that represents the resolved endpoint.</returns>
|
||||
string ResolveEndpoint(ICollection<OpenstackServiceDefinition> catalog, string serviceName, string region);
|
||||
}
|
||||
}
|
51
Openstack/Openstack/Identity/IdentityServiceClient.cs
Normal file
51
Openstack/Openstack/Identity/IdentityServiceClient.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServiceClient : IIdentityServiceClient
|
||||
{
|
||||
internal IOpenstackCredential Credential;
|
||||
internal CancellationToken CancellationToken;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IdentityServiceClient class.
|
||||
/// </summary>
|
||||
/// <param name="credential"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
internal IdentityServiceClient(IOpenstackCredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
this.Credential = credential;
|
||||
this.CancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IOpenstackCredential> Authenticate()
|
||||
{
|
||||
var client = ServiceLocator.Instance.Locate<IIdentityServicePocoClientFactory>().Create(this.Credential, this.CancellationToken);
|
||||
this.Credential = await client.Authenticate();
|
||||
return this.Credential;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Openstack.Identity;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServiceClientDefinition : IOpenstackServiceClientDefinition
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IdentityServiceClientDefinition class.
|
||||
/// </summary>
|
||||
public IdentityServiceClientDefinition()
|
||||
{
|
||||
this.Name = typeof(IdentityServiceClient).Name;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IOpenstackServiceClient Create(ICredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
return new IdentityServiceClient((IOpenstackCredential)credential, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> ListSupportedVersions()
|
||||
{
|
||||
return new List<string>() { "2.0.0.0" };
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool IsSupported(ICredential credential)
|
||||
{
|
||||
if (credential != null && credential.AuthenticationEndpoint != null)
|
||||
{
|
||||
//https://someidentityendpoint:35357/v2.0/tokens
|
||||
var endpointSegs = credential.AuthenticationEndpoint.Segments;
|
||||
if (endpointSegs.Count() == 3 && string.Compare(endpointSegs[1].Trim('/'), "v2.0", StringComparison.InvariantCultureIgnoreCase) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
72
Openstack/Openstack/Identity/IdentityServicePocoClient.cs
Normal file
72
Openstack/Openstack/Identity/IdentityServicePocoClient.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServicePocoClient : IIdentityServicePocoClient
|
||||
{
|
||||
internal IOpenstackCredential credential;
|
||||
internal CancellationToken cancellationToken;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IdentityServicePocoClient class.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential to be used when interacting with Openstack.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to be used when interacting with Openstack.</param>
|
||||
public IdentityServicePocoClient(IOpenstackCredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
credential.AssertIsNotNull("credential");
|
||||
cancellationToken.AssertIsNotNull("cancellationToken");
|
||||
|
||||
this.credential = credential;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IOpenstackCredential> Authenticate()
|
||||
{
|
||||
var client = ServiceLocator.Instance.Locate<IIdentityServiceRestClientFactory>().Create(this.credential, this.cancellationToken);
|
||||
|
||||
var resp = await client.Authenticate();
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.NonAuthoritativeInformation)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to authenticate. The remote server returned the following status code: '{0}'.", resp.StatusCode));
|
||||
}
|
||||
|
||||
var payload = await resp.ReadContentAsStringAsync();
|
||||
|
||||
var tokenConverter = ServiceLocator.Instance.Locate<IAccessTokenPayloadConverter>();
|
||||
var accessToken = tokenConverter.Convert(payload);
|
||||
|
||||
var scConverter = ServiceLocator.Instance.Locate<IOpenstackServiceCatalogPayloadConverter>();
|
||||
var serviceCatalog = scConverter.Convert(payload);
|
||||
|
||||
this.credential.SetAccessTokenId(accessToken);
|
||||
this.credential.SetServiceCatalog(serviceCatalog);
|
||||
|
||||
return this.credential;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServicePocoClientFactory :IIdentityServicePocoClientFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public IIdentityServicePocoClient Create(IOpenstackCredential credentials, CancellationToken token)
|
||||
{
|
||||
return new IdentityServicePocoClient(credentials, token);
|
||||
}
|
||||
}
|
||||
}
|
79
Openstack/Openstack/Identity/IdentityServiceRestClient.cs
Normal file
79
Openstack/Openstack/Identity/IdentityServiceRestClient.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServiceRestClient : IIdentityServiceRestClient
|
||||
{
|
||||
internal IOpenstackCredential credential;
|
||||
internal CancellationToken cancellationToken;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the IdentityServiceRestClient class.
|
||||
/// </summary>
|
||||
/// <param name="credential">The credential to be used by this client.</param>
|
||||
/// <param name="cancellationToken">The cancellation token to be used by this client.</param>
|
||||
public IdentityServiceRestClient(IOpenstackCredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
credential.AssertIsNotNull("credential");
|
||||
cancellationToken.AssertIsNotNull("cancellationToken");
|
||||
|
||||
this.credential = credential;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> Authenticate()
|
||||
{
|
||||
var client = ServiceLocator.Instance.Locate<IHttpAbstractionClientFactory>().Create(this.cancellationToken);
|
||||
client.Headers.Add("Accept", "application/json");
|
||||
client.ContentType = "application/json";
|
||||
|
||||
client.Uri = this.credential.AuthenticationEndpoint;
|
||||
client.Method = HttpMethod.Post;
|
||||
client.Content = CreateAuthenticationJsonPayload(this.credential).ConvertToStream();
|
||||
|
||||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Json payload that will be sent to the remote instance to authenticate.
|
||||
/// </summary>
|
||||
/// <param name="creds">The credentials used to authenticate.</param>
|
||||
/// <returns>A string that represents a Json payload.</returns>
|
||||
internal static string CreateAuthenticationJsonPayload(IOpenstackCredential creds)
|
||||
{
|
||||
var authPayload = new StringBuilder();
|
||||
authPayload.Append("{\"auth\":{\"passwordCredentials\":{\"username\":\"");
|
||||
authPayload.Append(creds.UserName);
|
||||
authPayload.Append("\",\"password\":\"");
|
||||
authPayload.Append(creds.Password.ConvertToUnsecureString());
|
||||
authPayload.Append("\"},\"tenantName\":\"");
|
||||
authPayload.Append(creds.TenantId);
|
||||
authPayload.Append("\"}}");
|
||||
return authPayload.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Threading;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class IdentityServiceRestClientFactory : IIdentityServiceRestClientFactory
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public IIdentityServiceRestClient Create(IOpenstackCredential credential, CancellationToken cancellationToken)
|
||||
{
|
||||
return new IdentityServiceRestClient(credential, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
80
Openstack/Openstack/Identity/OpenstackCredential.cs
Normal file
80
Openstack/Openstack/Identity/OpenstackCredential.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Security;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class OpenstackCredential : IOpenstackCredential
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public Uri AuthenticationEndpoint { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string AccessTokenId { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string UserName { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public SecureString Password { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string TenantId { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public OpenstackServiceCatalog ServiceCatalog { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the OpenstackCredential class.
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The endpoint to be used for authentication.</param>
|
||||
/// <param name="userName">the user name to be used for authentication.</param>
|
||||
/// <param name="password">The password to be used for authentication.</param>
|
||||
/// <param name="tenantId">The tenant id to be used for the authentication.</param>
|
||||
public OpenstackCredential(Uri endpoint, string userName, SecureString password, string tenantId)
|
||||
{
|
||||
endpoint.AssertIsNotNull("endpoint","An Openstack credential cannot be created with a null endpoint.");
|
||||
userName.AssertIsNotNullOrEmpty("userName", "An Openstack credential cannot be created with a null or empty user name.");
|
||||
password.AssertIsNotNull("password", "An Openstack credential cannot be created with a null password.");
|
||||
tenantId.AssertIsNotNullOrEmpty("tenantId", "An Openstack credential cannot be created with a null or empty tenant id.");
|
||||
|
||||
this.AuthenticationEndpoint = endpoint;
|
||||
this.UserName = userName;
|
||||
this.Password = password;
|
||||
this.TenantId = tenantId;
|
||||
|
||||
this.ServiceCatalog = new OpenstackServiceCatalog();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetAccessTokenId(string accessTokenId)
|
||||
{
|
||||
accessTokenId.AssertIsNotNullOrEmpty("accessTokenId","Access token cannot be null or empty.");
|
||||
this.AccessTokenId = accessTokenId;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void SetServiceCatalog(OpenstackServiceCatalog catalog)
|
||||
{
|
||||
catalog.AssertIsNotNull("catalog", "Service catalog cannot be null or empty.");
|
||||
this.ServiceCatalog = catalog;
|
||||
}
|
||||
}
|
||||
}
|
46
Openstack/Openstack/Identity/OpenstackServiceCatalog.cs
Normal file
46
Openstack/Openstack/Identity/OpenstackServiceCatalog.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public class OpenstackServiceCatalog : List<OpenstackServiceDefinition>, IOpenstackServiceCatalog
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public Uri GetPublicEndpoint(string serviceName, string region)
|
||||
{
|
||||
var resolver = ServiceLocator.Instance.Locate<IOpenstackServiceEndpointResolver>();
|
||||
return new Uri(resolver.ResolveEndpoint(this, serviceName, region));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Exists(string serviceName)
|
||||
{
|
||||
return this.Any(s => string.Compare(s.Name, serviceName, StringComparison.InvariantCulture) == 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<OpenstackServiceDefinition> GetServicesInAvailabilityZone(string availabilityZoneName)
|
||||
{
|
||||
return this.Where(s => s.Endpoints.Any(e => e.Region.Contains(availabilityZoneName)));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class OpenstackServiceCatalogPayloadConverter : IOpenstackServiceCatalogPayloadConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public OpenstackServiceCatalog Convert(string payload)
|
||||
{
|
||||
payload.AssertIsNotNull("payload", "A null service catalog payload cannot be converted.");
|
||||
|
||||
var catalog = new OpenstackServiceCatalog();
|
||||
|
||||
if (String.IsNullOrEmpty(payload))
|
||||
{
|
||||
return catalog;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var obj = JObject.Parse(payload);
|
||||
var defArray = obj["access"]["serviceCatalog"];
|
||||
catalog.AddRange(defArray.Select(ConvertServiceDefinition));
|
||||
}
|
||||
catch (HttpParseException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Service catalog payload could not be parsed. Payload: '{0}'", payload), ex);
|
||||
}
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json token that represents a service definition into a POCO object.
|
||||
/// </summary>
|
||||
/// <param name="serviceDef">The token.</param>
|
||||
/// <returns>The service definition.</returns>
|
||||
internal OpenstackServiceDefinition ConvertServiceDefinition(JToken serviceDef)
|
||||
{
|
||||
var converter = ServiceLocator.Instance.Locate<IOpenstackServiceDefinitionPayloadConverter>();
|
||||
return converter.Convert(serviceDef.ToString());
|
||||
}
|
||||
}
|
||||
}
|
59
Openstack/Openstack/Identity/OpenstackServiceDefinition.cs
Normal file
59
Openstack/Openstack/Identity/OpenstackServiceDefinition.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the definition of an Openstack service.
|
||||
/// </summary>
|
||||
public class OpenstackServiceDefinition
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the service.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the service.
|
||||
/// </summary>
|
||||
public string Type { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of endpoints for the service.
|
||||
/// </summary>
|
||||
public IEnumerable<OpenstackServiceEndpoint> Endpoints { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the OpenstackServiceDefinition class.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="endpoints"></param>
|
||||
internal OpenstackServiceDefinition(string name, string type, IEnumerable<OpenstackServiceEndpoint> endpoints)
|
||||
{
|
||||
name.AssertIsNotNullOrEmpty("name","Cannot create a service definition with a name that is null or empty.");
|
||||
type.AssertIsNotNullOrEmpty("type", "Cannot create a service definition with a type that is null or empty.");
|
||||
endpoints.AssertIsNotNull("endpoints", "Cannot create a service definition with a null endpoint collection.");
|
||||
|
||||
this.Name = name;
|
||||
this.Type = type;
|
||||
this.Endpoints = endpoints;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class OpenstackServiceDefinitionPayloadConverter : IOpenstackServiceDefinitionPayloadConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public OpenstackServiceDefinition Convert(string payload)
|
||||
{
|
||||
payload.AssertIsNotNull("payload", "A null service catalog payload cannot be converted.");
|
||||
|
||||
try
|
||||
{
|
||||
var serviceDefinition = JObject.Parse(payload);
|
||||
var name = (string)serviceDefinition["name"];
|
||||
var type = (string)serviceDefinition["type"];
|
||||
|
||||
var endpoints = new List<OpenstackServiceEndpoint>();
|
||||
endpoints.AddRange(serviceDefinition["endpoints"].Select(ConvertEndpoint));
|
||||
|
||||
return new OpenstackServiceDefinition(name, type, endpoints);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Service definition payload could not be parsed. Payload: '{0}'", payload), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json token that represents a service endpoint into a POCO object.
|
||||
/// </summary>
|
||||
/// <param name="endpoint">The token.</param>
|
||||
/// <returns>A service endpoint.</returns>
|
||||
internal OpenstackServiceEndpoint ConvertEndpoint(JToken endpoint)
|
||||
{
|
||||
var converter = ServiceLocator.Instance.Locate<IOpenstackServiceEndpointPayloadConverter>();
|
||||
return converter.Convert(endpoint.ToString());
|
||||
}
|
||||
}
|
||||
}
|
75
Openstack/Openstack/Identity/OpenstackServiceEndpoint.cs
Normal file
75
Openstack/Openstack/Identity/OpenstackServiceEndpoint.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an endpoint of an Openstack service.
|
||||
/// </summary>
|
||||
public class OpenstackServiceEndpoint
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the public Uri of the endpoint.
|
||||
/// </summary>
|
||||
public string PublicUri { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the region of the endpoint.
|
||||
/// </summary>
|
||||
public string Region { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the version of the endpoint.
|
||||
/// </summary>
|
||||
public string Version { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Uri for the endpoints version information.
|
||||
/// </summary>
|
||||
public Uri VersionInformation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Uri for the endpoints list of versions.
|
||||
/// </summary>
|
||||
public Uri VersionList { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the OpenstackServiceEndpoint class.
|
||||
/// </summary>
|
||||
/// <param name="publicUri">The public Uri of the endpoint.</param>
|
||||
/// <param name="region">The region of the endpoint.</param>
|
||||
/// <param name="version">The version of the endpoint.</param>
|
||||
/// <param name="versionInfo">The link to version information.</param>
|
||||
/// <param name="versionList">The link to a list of versions.</param>
|
||||
internal OpenstackServiceEndpoint(string publicUri, string region, string version, Uri versionInfo, Uri versionList)
|
||||
{
|
||||
publicUri.AssertIsNotNull("publicUri", "Cannot create a service endpoint with a null public URI.");
|
||||
region.AssertIsNotNull("region", "Cannot create a service endpoint with a null public URI.");
|
||||
version.AssertIsNotNull("version", "Cannot create a service endpoint with a null version.");
|
||||
versionInfo.AssertIsNotNull("versionInfo", "Cannot create a service endpoint with a null version information URI.");
|
||||
versionList.AssertIsNotNull("versionList", "Cannot create a service endpoint with a null version list URI.");
|
||||
|
||||
this.PublicUri = publicUri;
|
||||
this.Region = region;
|
||||
this.Version = version;
|
||||
this.VersionInformation = versionInfo;
|
||||
this.VersionList = versionList;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Web;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class OpenstackServiceEndpointPayloadConverter : IOpenstackServiceEndpointPayloadConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public OpenstackServiceEndpoint Convert(string payload)
|
||||
{
|
||||
payload.AssertIsNotNullOrEmpty("payload", "A null or empty service endpoint payload cannot be converted.");
|
||||
|
||||
try
|
||||
{
|
||||
var endpoint = JObject.Parse(payload);
|
||||
var publicUri = (string) endpoint["publicURL"];
|
||||
var region = (string)endpoint["region"];
|
||||
var version = (string)endpoint["versionId"];
|
||||
var versionInfo = new Uri((string)endpoint["versionInfo"]);
|
||||
var versionList = new Uri((string)endpoint["versionList"]);
|
||||
|
||||
return new OpenstackServiceEndpoint(publicUri, region, version, versionInfo, versionList);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Service endpoint payload could not be parsed. Payload: '{0}'", payload), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Identity
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class OpenstackServiceEndpointResolver : IOpenstackServiceEndpointResolver
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string ResolveEndpoint(ICollection<OpenstackServiceDefinition> catalog, string serviceName, string region)
|
||||
{
|
||||
catalog.AssertIsNotNull("catalog","Cannot resolve the public endpoint of a service with a null catalog.");
|
||||
serviceName.AssertIsNotNullOrEmpty("serviceName", "Cannot resolve the public endpoint of a service with a null or empty service name.");
|
||||
serviceName.AssertIsNotNullOrEmpty("region", "Cannot resolve the public endpoint of a service with a null or empty region.");
|
||||
|
||||
if (catalog.All(s => string.Compare(s.Name, serviceName, StringComparison.OrdinalIgnoreCase) != 0))
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Service catalog does not contain an entry for the '{0}' service. The request could not be completed.", serviceName));
|
||||
}
|
||||
|
||||
var service = catalog.First(s => string.Compare(s.Name, serviceName, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
|
||||
if (service.Endpoints.All(e => string.Compare(e.Region, region, StringComparison.OrdinalIgnoreCase) != 0))
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Service catalog does not contain an endpoint for the '{0}' service in the requested region. Region: '{1}'", serviceName, region));
|
||||
}
|
||||
|
||||
var endpoint = service.Endpoints.First(e => string.Compare(e.Region, region, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
|
||||
return endpoint.PublicUri;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user