PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/redistributable/openstack.net/src/corelib/ContentDeliveryNetworks/v1/ContentDeliveryNetworkService.cs

https://gitlab.com/rekby-archive/onlyoffice-CommunityServer
C# | 304 lines | 229 code | 49 blank | 26 comment | 33 complexity | af63c7ee6b01f344ce90f1e6e835020d MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Flurl;
  8. using Flurl.Extensions;
  9. using Flurl.Http;
  10. using Marvin.JsonPatch;
  11. using OpenStack.Authentication;
  12. using OpenStack.Serialization;
  13. namespace OpenStack.ContentDeliveryNetworks.v1
  14. {
  15. /// <summary>
  16. /// The default provider for the OpenStack (Poppy) Content Delivery Network Service.
  17. /// </summary>
  18. /// <preliminary/>
  19. /// <seealso href="http://docs.cloudcdn.apiary.io/">OpenStack (Poppy) Content Delivery Network Service API v1 Reference</seealso>
  20. public class ContentDeliveryNetworkService : IContentDeliveryNetworkService
  21. {
  22. private readonly IAuthenticationProvider _authenticationProvider;
  23. private readonly ServiceEndpoint _endpoint;
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="ContentDeliveryNetworkService"/> class.
  26. /// </summary>
  27. /// <param name="authenticationProvider">The authentication provider.</param>
  28. /// <param name="region">The cloud region.</param>
  29. /// <param name="useInternalUrl">if set to <c>true</c> uses the internal URLs specified in the ServiceCatalog, otherwise the public URLs are used.</param>
  30. /// <exception cref="ArgumentNullException">If the <paramref name="authenticationProvider"/> is <see langword="null"/>.</exception>
  31. /// <exception cref="ArgumentException">If the <paramref name="region"/> is <see langword="null"/> or empty.</exception>
  32. public ContentDeliveryNetworkService(IAuthenticationProvider authenticationProvider, string region, bool useInternalUrl = false)
  33. {
  34. if (authenticationProvider == null)
  35. throw new ArgumentNullException("authenticationProvider");
  36. if (string.IsNullOrEmpty(region))
  37. throw new ArgumentException("region cannot be null or empty", "region");
  38. _authenticationProvider = authenticationProvider;
  39. _endpoint = new ServiceEndpoint(ServiceType.ContentDeliveryNetwork, authenticationProvider, region, useInternalUrl);
  40. }
  41. /// <inheritdoc />
  42. public async Task<Flavor> GetFlavorAsync(string flavorId, CancellationToken cancellationToken = default(CancellationToken))
  43. {
  44. if (string.IsNullOrEmpty(flavorId))
  45. throw new ArgumentNullException("flavorId");
  46. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  47. return await endpoint
  48. .AppendPathSegments("flavors", flavorId)
  49. .Authenticate(_authenticationProvider)
  50. .GetJsonAsync<Flavor>(cancellationToken)
  51. .ConfigureAwait(false);
  52. }
  53. /// <inheritdoc />
  54. public async Task<IEnumerable<Flavor>> ListFlavorsAsync(CancellationToken cancellationToken = default(CancellationToken))
  55. {
  56. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  57. return await endpoint
  58. .AppendPathSegments("flavors")
  59. .Authenticate(_authenticationProvider)
  60. .GetJsonAsync<FlavorCollection>(cancellationToken)
  61. .ConfigureAwait(false);
  62. }
  63. /// <inheritdoc />
  64. public async Task PingAsync(CancellationToken cancellationToken = default(CancellationToken))
  65. {
  66. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  67. await endpoint
  68. .AppendPathSegments("ping")
  69. .Authenticate(_authenticationProvider)
  70. .GetAsync(cancellationToken)
  71. .ConfigureAwait(false);
  72. }
  73. /// <inheritdoc />
  74. public async Task<IPage<Service>> ListServicesAsync(string startServiceId = null, int? pageSize = null, CancellationToken cancellationToken = default(CancellationToken))
  75. {
  76. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  77. string url = endpoint
  78. .AppendPathSegments("services")
  79. .SetQueryParams(new
  80. {
  81. marker = startServiceId,
  82. limit = pageSize
  83. });
  84. return await ListServicesAsync(url, cancellationToken).ConfigureAwait(false);
  85. }
  86. // TODO: move into a class that we can use via composition so that we aren't implementing this for everything that is paged?
  87. private async Task<ServiceCollection> ListServicesAsync(Url url, CancellationToken cancellationToken)
  88. {
  89. ServiceCollection result = await url
  90. .Authenticate(_authenticationProvider)
  91. .GetJsonAsync<ServiceCollection>(cancellationToken)
  92. .ConfigureAwait(false);
  93. ((IPageBuilder<ServiceCollection>)result).SetNextPageHandler(ListServicesAsync);
  94. return result;
  95. }
  96. /// <inheritdoc />
  97. public async Task<Service> GetServiceAsync(string serviceId, CancellationToken cancellationToken = default(CancellationToken))
  98. {
  99. if (string.IsNullOrEmpty(serviceId))
  100. throw new ArgumentNullException("serviceId");
  101. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  102. return await endpoint
  103. .AppendPathSegments("services", serviceId)
  104. .Authenticate(_authenticationProvider)
  105. .GetJsonAsync<Service>(cancellationToken)
  106. .ConfigureAwait(false);
  107. }
  108. /// <inheritdoc />
  109. public async Task<string> CreateServiceAsync(ServiceDefinition service, CancellationToken cancellationToken = default(CancellationToken))
  110. {
  111. if (service == null)
  112. throw new ArgumentNullException("service");
  113. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  114. var response = await endpoint
  115. .AppendPathSegments("services")
  116. .Authenticate(_authenticationProvider)
  117. .PostJsonAsync(service, cancellationToken)
  118. .ConfigureAwait(false);
  119. response.Headers.TryGetFirst("Location", out var location);
  120. return new Uri(location).Segments.Last();
  121. }
  122. /// <inheritdoc />
  123. public async Task DeleteServiceAsync(string serviceId, CancellationToken cancellationToken = default(CancellationToken))
  124. {
  125. if (string.IsNullOrEmpty(serviceId))
  126. throw new ArgumentNullException("serviceId");
  127. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  128. await endpoint
  129. .AppendPathSegments("services", serviceId)
  130. .Authenticate(_authenticationProvider)
  131. .AllowHttpStatus(HttpStatusCode.NotFound)
  132. .DeleteAsync(cancellationToken)
  133. .ConfigureAwait(false);
  134. }
  135. /// <inheritdoc />
  136. public async Task UpdateServiceAsync(string serviceId, JsonPatchDocument<ServiceDefinition> patch, CancellationToken cancellationToken = default(CancellationToken))
  137. {
  138. if (string.IsNullOrEmpty(serviceId))
  139. throw new ArgumentNullException("serviceId");
  140. if (patch == null)
  141. throw new ArgumentNullException("patch");
  142. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  143. await endpoint
  144. .AppendPathSegments("services", serviceId)
  145. .Authenticate(_authenticationProvider)
  146. .PatchJsonAsync(patch, cancellationToken)
  147. .ConfigureAwait(false);
  148. }
  149. /// <inheritdoc />
  150. public async Task PurgeCachedAssetAsync(string serviceId, string url, CancellationToken cancellationToken = default(CancellationToken))
  151. {
  152. if (string.IsNullOrEmpty(serviceId))
  153. throw new ArgumentNullException("serviceId");
  154. if (string.IsNullOrEmpty(url))
  155. throw new ArgumentNullException("url");
  156. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  157. await endpoint
  158. .AppendPathSegments("services", serviceId, "assets")
  159. .SetQueryParam("url", url)
  160. .Authenticate(_authenticationProvider)
  161. .AllowHttpStatus(HttpStatusCode.NotFound)
  162. .DeleteAsync(cancellationToken)
  163. .ConfigureAwait(false);
  164. }
  165. /// <inheritdoc />
  166. public async Task PurgeCachedAssetsAsync(string serviceId, CancellationToken cancellationToken = default(CancellationToken))
  167. {
  168. if (string.IsNullOrEmpty(serviceId))
  169. throw new ArgumentNullException("serviceId");
  170. string endpoint = await _endpoint.GetEndpoint(cancellationToken).ConfigureAwait(false);
  171. await endpoint
  172. .AppendPathSegments("services", serviceId, "assets")
  173. .SetQueryParam("all", true)
  174. .Authenticate(_authenticationProvider)
  175. .DeleteAsync(cancellationToken)
  176. .ConfigureAwait(false);
  177. }
  178. /// <inheritdoc />
  179. public async Task<Service> WaitForServiceDeployedAsync(string serviceId, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null, CancellationToken cancellationToken = default(CancellationToken))
  180. {
  181. if (string.IsNullOrEmpty(serviceId))
  182. throw new ArgumentNullException("serviceId");
  183. refreshDelay = refreshDelay ?? TimeSpan.FromSeconds(5);
  184. timeout = timeout ?? TimeSpan.FromMinutes(5);
  185. using (var timeoutSource = new CancellationTokenSource(timeout.Value))
  186. using (var rootCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutSource.Token))
  187. {
  188. while (true)
  189. {
  190. var service = await GetServiceAsync(serviceId, cancellationToken).ConfigureAwait(false);
  191. if (service.Status == ServiceStatus.Failed)
  192. throw new ServiceOperationFailedException(service.Errors);
  193. bool complete = service.Status == ServiceStatus.Deployed;
  194. if (progress != null)
  195. progress.Report(complete);
  196. if (complete)
  197. return service;
  198. try
  199. {
  200. await Task.Delay(refreshDelay.Value, rootCancellationToken.Token).ConfigureAwait(false);
  201. }
  202. catch (OperationCanceledException ex)
  203. {
  204. if (timeoutSource.IsCancellationRequested)
  205. throw new TimeoutException(string.Format("The requested timeout of {0} seconds has been reached while waiting for the service ({1}) to be deployed.", timeout.Value.TotalSeconds, serviceId), ex);
  206. throw;
  207. }
  208. }
  209. }
  210. }
  211. /// <inheritdoc />
  212. public async Task WaitForServiceDeletedAsync(string serviceId, TimeSpan? refreshDelay = null, TimeSpan? timeout = null, IProgress<bool> progress = null, CancellationToken cancellationToken = default(CancellationToken))
  213. {
  214. if (string.IsNullOrEmpty(serviceId))
  215. throw new ArgumentNullException("serviceId");
  216. refreshDelay = refreshDelay ?? TimeSpan.FromSeconds(5);
  217. timeout = timeout ?? TimeSpan.FromMinutes(5);
  218. using (var timeoutSource = new CancellationTokenSource(timeout.Value))
  219. using (var rootCancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutSource.Token))
  220. {
  221. while (true)
  222. {
  223. bool complete = false;
  224. try
  225. {
  226. var service = await GetServiceAsync(serviceId, cancellationToken).ConfigureAwait(false);
  227. if (service.Status == ServiceStatus.Failed)
  228. throw new ServiceOperationFailedException(service.Errors);
  229. }
  230. catch (FlurlHttpException httpError)
  231. {
  232. if (httpError.Call.Response.StatusCode == (int)HttpStatusCode.NotFound)
  233. complete = true;
  234. else
  235. throw;
  236. }
  237. if (progress != null)
  238. progress.Report(complete);
  239. if (complete)
  240. return;
  241. try
  242. {
  243. await Task.Delay(refreshDelay.Value, rootCancellationToken.Token).ConfigureAwait(false);
  244. }
  245. catch (OperationCanceledException ex)
  246. {
  247. if (timeoutSource.IsCancellationRequested)
  248. throw new TimeoutException(string.Format("The requested timeout of {0} seconds has been reached while waiting for the service ({1}) to be deleted.", timeout.Value.TotalSeconds, serviceId), ex);
  249. throw;
  250. }
  251. }
  252. }
  253. }
  254. }
  255. }