/// <summary> List repositories in this registry. </summary> /// <param name="cancellationToken"> The cancellation token to use. </param> /// <exception cref="RequestFailedException">Thrown when a failure is returned by the Container Registry service.</exception> public virtual AsyncPageable <string> GetRepositoryNamesAsync(CancellationToken cancellationToken = default) { async Task <Page <string> > FirstPageFunc(int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryClient)}.{nameof(GetRepositoryNames)}"); scope.Start(); try { ResponseWithHeaders <Repositories, ContainerRegistryGetRepositoriesHeaders> response = await _restClient.GetRepositoriesAsync(last : null, n : pageSizeHint, cancellationToken).ConfigureAwait(false); return(Page.FromValues(response.Value.RepositoriesValue, response.Headers.Link, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } async Task <Page <string> > NextPageFunc(string continuationToken, int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryClient)}.{nameof(GetRepositoryNames)}"); scope.Start(); try { string uriReference = ParseUriReferenceFromLinkHeader(continuationToken); ResponseWithHeaders <Repositories, ContainerRegistryGetRepositoriesHeaders> response = await _restClient.GetRepositoriesNextPageAsync(uriReference, last : null, n : null, cancellationToken).ConfigureAwait(false); return(Page.FromValues(response.Value.RepositoriesValue, response.Headers.Link, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } return(PageableHelpers.CreateAsyncEnumerable(FirstPageFunc, NextPageFunc)); }
/// <summary> /// Upload an artifact blob. /// </summary> /// <param name="stream">The stream containing the blob data.</param> /// <param name="cancellationToken"> The cancellation token to use. </param> /// <returns></returns> public virtual async Task <Response <UploadBlobResult> > UploadBlobAsync(Stream stream, CancellationToken cancellationToken = default) { Argument.AssertNotNull(stream, nameof(stream)); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(UploadBlob)}"); scope.Start(); try { string digest = OciBlobDescriptor.ComputeDigest(stream); ResponseWithHeaders <ContainerRegistryBlobStartUploadHeaders> startUploadResult = await _blobRestClient.StartUploadAsync(_repositoryName, cancellationToken).ConfigureAwait(false); ResponseWithHeaders <ContainerRegistryBlobUploadChunkHeaders> uploadChunkResult = await _blobRestClient.UploadChunkAsync(startUploadResult.Headers.Location, stream, cancellationToken).ConfigureAwait(false); ResponseWithHeaders <ContainerRegistryBlobCompleteUploadHeaders> completeUploadResult = await _blobRestClient.CompleteUploadAsync(digest, uploadChunkResult.Headers.Location, null, cancellationToken).ConfigureAwait(false); return(Response.FromValue(new UploadBlobResult(completeUploadResult.Headers.DockerContentDigest), completeUploadResult.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } }
/// <summary> /// Download a blob that is part of an artifact. /// </summary> /// <param name="digest">The digest of the blob to download.</param> /// <param name="cancellationToken"> The cancellation token to use. </param> /// <returns></returns> public virtual async Task <Response <DownloadBlobResult> > DownloadBlobAsync(string digest, CancellationToken cancellationToken = default) { Argument.AssertNotNull(digest, nameof(digest)); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(DownloadBlob)}"); scope.Start(); try { ResponseWithHeaders <Stream, ContainerRegistryBlobGetBlobHeaders> blobResult = await _blobRestClient.GetBlobAsync(_repositoryName, digest, cancellationToken).ConfigureAwait(false); if (!ValidateDigest(blobResult.Value, digest)) { throw _clientDiagnostics.CreateRequestFailedException(blobResult, new ResponseError(null, "The requested digest does not match the digest of the received manifest.")); } return(Response.FromValue(new DownloadBlobResult(digest, blobResult.Value), blobResult.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } }
/// <summary> /// Uploads a manifest for an OCI Artifact. /// </summary> /// <param name="manifest">The manifest to upload.</param> /// <param name="options">Options for configuring the upload operation.</param> /// <param name="cancellationToken"> The cancellation token to use. </param> /// <returns></returns> public virtual Response <UploadManifestResult> UploadManifest(OciManifest manifest, UploadManifestOptions options = default, CancellationToken cancellationToken = default) { Argument.AssertNotNull(manifest, nameof(manifest)); options ??= new UploadManifestOptions(); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(UploadManifest)}"); scope.Start(); try { Stream manifestStream = SerializeManifest(manifest); string manifestDigest = OciBlobDescriptor.ComputeDigest(manifestStream); string tagOrDigest = options.Tag ?? manifestDigest; ResponseWithHeaders <ContainerRegistryCreateManifestHeaders> response = _restClient.CreateManifest(_repositoryName, tagOrDigest, manifestStream, ManifestMediaType.OciManifest.ToString(), cancellationToken); if (!manifestDigest.Equals(response.Headers.DockerContentDigest, StringComparison.Ordinal)) { throw _clientDiagnostics.CreateRequestFailedException(response, new ResponseError(null, "The digest in the response does not match the digest of the uploaded manifest.")); } return(Response.FromValue(new UploadManifestResult(response.Headers.DockerContentDigest), response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } }
/// <summary> /// Uploads a manifest for an OCI artifact. /// </summary> /// <param name="manifestStream">The <see cref="Stream"/> manifest to upload.</param> /// <param name="options">Options for configuring the upload operation.</param> /// <param name="cancellationToken"> The cancellation token to use. </param> /// <returns></returns> public virtual async Task <Response <UploadManifestResult> > UploadManifestAsync(Stream manifestStream, UploadManifestOptions options = default, CancellationToken cancellationToken = default) { Argument.AssertNotNull(manifestStream, nameof(manifestStream)); options ??= new UploadManifestOptions(); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryBlobClient)}.{nameof(UploadManifest)}"); scope.Start(); try { using Stream stream = new MemoryStream(); await manifestStream.CopyToAsync(stream).ConfigureAwait(false); manifestStream.Position = 0; stream.Position = 0; string tagOrDigest = options.Tag ?? OciBlobDescriptor.ComputeDigest(manifestStream); ResponseWithHeaders <ContainerRegistryCreateManifestHeaders> response = await _restClient.CreateManifestAsync(_repositoryName, tagOrDigest, manifestStream, ManifestMediaType.OciManifest.ToString(), cancellationToken).ConfigureAwait(false); if (!ValidateDigest(stream, response.Headers.DockerContentDigest)) { throw _clientDiagnostics.CreateRequestFailedException(response, new ResponseError(null, "The digest in the response does not match the digest of the uploaded manifest.")); } return(Response.FromValue(new UploadManifestResult(response.Headers.DockerContentDigest), response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } }
/// <summary> /// Get the status results for all submitted translation operations. /// </summary> /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> public virtual AsyncPageable <TranslationStatusResult> GetTranslationsAsync(CancellationToken cancellationToken = default) { async Task <Page <TranslationStatusResult> > FirstPageFunc(int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(DocumentTranslationClient)}.{nameof(GetTranslations)}"); scope.Start(); try { ResponseWithHeaders <TranslationsStatus, DocumentTranslationGetTranslationsStatusHeaders> response = await _serviceRestClient.GetTranslationsStatusAsync(cancellationToken : cancellationToken).ConfigureAwait(false); return(Page.FromValues(response.Value.Value, response.Value.NextLink, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } async Task <Page <TranslationStatusResult> > NextPageFunc(string nextLink, int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(DocumentTranslationClient)}.{nameof(GetTranslations)}"); scope.Start(); try { ResponseWithHeaders <TranslationsStatus, DocumentTranslationGetTranslationsStatusHeaders> response = await _serviceRestClient.GetTranslationsStatusNextPageAsync(nextLink, cancellationToken : cancellationToken).ConfigureAwait(false); return(Page.FromValues(response.Value.Value, response.Value.NextLink, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } return(PageableHelpers.CreateAsyncEnumerable(FirstPageFunc, NextPageFunc)); }
/// <summary> /// Retrieve a token from the STS service for the specified account identifier asynchronously. /// </summary> /// <param name="cancellationToken">The cancellation token.</param> /// <returns><see cref="Response{AccessToken}"/>.</returns> public virtual async Task <Response <AccessToken> > GetTokenAsync(CancellationToken cancellationToken = default) { MixedRealityTokenRequestOptions headerOptions = MixedRealityTokenRequestOptions.GenerateNew(); using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(MixedRealityStsClient)}.{nameof(GetToken)}"); scope.AddAttribute(nameof(headerOptions.ClientRequestId), headerOptions.ClientRequestId); scope.Start(); try { ResponseWithHeaders <StsTokenResponseMessage, MixedRealityStsGetTokenHeaders> response = await _restClient.GetTokenAsync(AccountId, headerOptions, cancellationToken).ConfigureAwait(false); return(ResponseWithHeaders.FromValue(response.Value.ToAccessToken(), response.Headers, response.GetRawResponse())); } catch (Exception ex) { scope.Failed(ex); throw; } }
/// <summary> /// Get the status results for all submitted translation operations. /// </summary> /// <param name="cancellationToken">A <see cref="CancellationToken"/> controlling the request lifetime.</param> public virtual Pageable <TranslationStatusResult> GetTranslations(CancellationToken cancellationToken = default) { Page <TranslationStatusResult> FirstPageFunc(int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(DocumentTranslationClient)}.{nameof(GetTranslations)}"); scope.Start(); try { ResponseWithHeaders <BatchStatusResponse, DocumentTranslationGetOperationsHeaders> response = _serviceRestClient.GetOperations(cancellationToken: cancellationToken); return(Page.FromValues(response.Value.Value, response.Value.NextLink, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } Page <TranslationStatusResult> NextPageFunc(string nextLink, int?pageSizeHint) { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(DocumentTranslationClient)}.{nameof(GetTranslations)}"); scope.Start(); try { Response <BatchStatusResponse> response = _serviceRestClient.GetOperationsNextPage(nextLink, cancellationToken: cancellationToken); return(Page.FromValues(response.Value.Value, response.Value.NextLink, response.GetRawResponse())); } catch (Exception e) { scope.Failed(e); throw; } } return(PageableHelpers.CreateEnumerable(FirstPageFunc, NextPageFunc)); }
/// <summary> List repositories. </summary> /// <param name="cancellationToken"> The cancellation token to use. </param> public virtual Pageable <string> GetRepositories(CancellationToken cancellationToken = default) { return(PageResponseEnumerator.CreateEnumerable((continuationToken, pageSizeHint) => { using DiagnosticScope scope = _clientDiagnostics.CreateScope($"{nameof(ContainerRegistryClient)}.{nameof(GetRepositories)}"); scope.Start(); try { ResponseWithHeaders <Repositories, RepositoryGetListHeaders> response = _restClient.GetList( continuationToken, pageSizeHint, cancellationToken); string lastRepository = null; if (!string.IsNullOrEmpty(response.Headers.Link)) { Uri nextLink = new Uri(response.Headers.Link); NameValueCollection queryParams = HttpUtility.ParseQueryString(nextLink.Query); lastRepository = queryParams["last"]; } return Page <string> .FromValues(response.Value.Names, lastRepository, response.GetRawResponse()); } catch (Exception ex) { scope.Failed(ex); throw; } })); }
public virtual async Task <Response <DownloadBlobResult> > DownloadBlobAsync(string digest, DownloadBlobOptions options = default, CancellationToken cancellationToken = default) { options ??= new DownloadBlobOptions(); ResponseWithHeaders <Stream, ContainerRegistryBlobGetBlobHeaders> blobResult = await _blobRestClient.GetBlobAsync(_repositoryName, digest, cancellationToken).ConfigureAwait(false); return(Response.FromValue(new DownloadBlobResult(digest, blobResult.Value), blobResult.GetRawResponse())); }