From fe4c9f4e57863c3ba154251877a20d3d4f2a76f1 Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Thu, 11 Jun 2020 13:00:42 -0700 Subject: [PATCH 1/7] refactor jobStorageHelper --- .../Exceptions/StorageClientException.cs | 7 +- .../JobManagement/Workspace.cs | 50 ++++----- .../Storage/IStorageHelper.cs | 27 +++-- .../Storage/JobStorageHelper.cs | 93 ++++++++-------- .../Storage/JobStorageHelperBase.cs | 97 +++++++++++++++++ .../Storage/LinkedStorageJobHelper.cs | 100 ++++++++++++++++++ .../Storage/StorageHelper.cs | 93 ++++++---------- 7 files changed, 319 insertions(+), 148 deletions(-) create mode 100644 src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs create mode 100644 src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs diff --git a/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs b/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs index 9e3bbc53d4a..5bef01d9787 100644 --- a/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs +++ b/src/Azure/Azure.Quantum.Client/Exceptions/StorageClientException.cs @@ -1,10 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; - namespace Microsoft.Azure.Quantum.Exceptions { + using System; + /// /// The exception that is thrown when an error related to the Azure storage client occurs. /// @@ -46,19 +46,16 @@ public StorageClientException( /// Initializes a new instance of the class with a specified error message, a reference to another exception that caused this one and more detailes that are specific to the storage client. /// /// Error message that explains the reason for the exception. - /// Connection string used by the storage client. /// Name of the container involved in the operation that caused the exception. /// Name of the BLOB involved in the operation that caused the exception. /// Exception that is the cause of the current one. public StorageClientException( string message, - string connectionString, string containerName, string blobName, Exception inner) : base( $"{BaseMessage}: {message}{Environment.NewLine}" + - $"ConnectionString: {connectionString}{Environment.NewLine}" + $"ContainerName: {containerName}{Environment.NewLine}" + $"BlobName: {blobName}", inner) diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs index 856b9dc6dca..5f9261aaa75 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs @@ -1,30 +1,30 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Azure.Core; -using Microsoft.Azure.Quantum.Authentication; -using Microsoft.Azure.Quantum.Client; -using Microsoft.Azure.Quantum.Client.Models; -using Microsoft.Azure.Quantum.Exceptions; -using Microsoft.Azure.Quantum.Utility; - namespace Microsoft.Azure.Quantum { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using global::Azure.Core; + using Microsoft.Azure.Quantum.Authentication; + using Microsoft.Azure.Quantum.Client; + using Microsoft.Azure.Quantum.Client.Models; + using Microsoft.Azure.Quantum.Exceptions; + using Microsoft.Azure.Quantum.Utility; + /// /// Workspace class. /// /// public class Workspace : IWorkspace { - private readonly Uri BaseUri; - private readonly string ResourceGroupName; - private readonly string SubscriptionId; - private readonly string WorkspaceName; + private readonly Uri baseUri; + private readonly string resourceGroupName; + private readonly string subscriptionId; + private readonly string workspaceName; /// /// Initializes a new instance of the class. @@ -79,13 +79,13 @@ private Workspace( IAccessTokenProvider accessTokenProvider, Uri baseUri = null) { - BaseUri = baseUri ?? new Uri(Constants.DefaultBaseUri); + this.baseUri = baseUri ?? new Uri(Constants.DefaultBaseUri); Ensure.NotNullOrWhiteSpace(subscriptionId, nameof(subscriptionId)); - SubscriptionId = subscriptionId; + this.subscriptionId = subscriptionId; Ensure.NotNullOrWhiteSpace(resourceGroupName, nameof(resourceGroupName)); - ResourceGroupName = resourceGroupName; + this.resourceGroupName = resourceGroupName; Ensure.NotNullOrWhiteSpace(workspaceName, nameof(workspaceName)); - WorkspaceName = workspaceName; + this.workspaceName = workspaceName; try { @@ -102,7 +102,7 @@ private Workspace( { this.JobsClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider)) { - BaseUri = BaseUri, + BaseUri = this.baseUri, SubscriptionId = subscriptionId, ResourceGroupName = resourceGroupName, WorkspaceName = workspaceName, @@ -233,10 +233,10 @@ private WorkspaceClientException CreateException( { return new WorkspaceClientException( message, - SubscriptionId, - ResourceGroupName, - WorkspaceName, - BaseUri, + subscriptionId, + resourceGroupName, + workspaceName, + baseUri, jobId, inner); } diff --git a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs index 6b8f937890f..d1e010f9e9e 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/IStorageHelper.cs @@ -1,27 +1,28 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Bond; -using Microsoft.WindowsAzure.Storage.Blob; - namespace Microsoft.Azure.Quantum.Storage { + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Bond; + using global::Azure.Storage.Blobs; + using Microsoft.WindowsAzure.Storage.Blob; + public interface IStorageHelper { /// /// Downloads the BLOB. /// - /// Name of the container. + /// Container client. /// Name of the BLOB. /// The destination. /// The cancellation token. /// Serialization protocol of the downloaded BLOB. Task DownloadBlobAsync( - string containerName, + BlobContainerClient containerClient, string blobName, Stream destination, CancellationToken cancellationToken = default); @@ -29,14 +30,14 @@ Task DownloadBlobAsync( /// /// Uploads the BLOB. /// - /// Name of the container. + /// Container client. /// Name of the BLOB. /// The input. /// Serialization protocol of the BLOB to upload. /// The cancellation token. /// async task. Task UploadBlobAsync( - string containerName, + BlobContainerClient containerClient, string blobName, Stream input, ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, @@ -45,12 +46,14 @@ Task UploadBlobAsync( /// /// Gets the BLOB sas URI. /// + /// Storage account connection string. /// Name of the container. /// Name of the BLOB. /// The expiry interval. /// The permissions. /// Blob uri. string GetBlobSasUri( + string connectionString, string containerName, string blobName, TimeSpan expiryInterval, @@ -59,11 +62,13 @@ string GetBlobSasUri( /// /// Gets the BLOB container sas URI. /// + /// Storage account connection string. /// Name of the container. /// The expiry interval. /// The permissions. /// Container uri. string GetBlobContainerSasUri( + string connectionString, string containerName, TimeSpan expiryInterval, SharedAccessBlobPermissions permissions); diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs index 17fc10a7103..ea7da8d8b7f 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs @@ -1,19 +1,23 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Bond; -using Microsoft.Azure.Quantum.Utility; -using Microsoft.WindowsAzure.Storage.Blob; - namespace Microsoft.Azure.Quantum.Storage { - public class JobStorageHelper : IJobStorageHelper + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Bond; + using global::Azure.Storage.Blobs; + using Microsoft.Azure.Quantum.Exceptions; + using Microsoft.Azure.Quantum.Utility; + using Microsoft.WindowsAzure.Storage; + using Microsoft.WindowsAzure.Storage.Blob; + + public abstract class JobStorageHelper : JobStorageHelperBase { - private readonly TimeSpan expiryInterval; + private readonly string connectionString; + private readonly CloudStorageAccount storageAccount; /// /// Initializes a new instance of the class. @@ -21,14 +25,19 @@ public class JobStorageHelper : IJobStorageHelper /// The connection string. public JobStorageHelper(string connectionString) { - this.StorageHelper = new StorageHelper(connectionString); - this.expiryInterval = TimeSpan.FromDays(Constants.Storage.ExpiryIntervalInDays); - } + this.connectionString = connectionString; - /// - /// Gets the underlying storage helper. - /// - public IStorageHelper StorageHelper { get; } + try + { + this.storageAccount = CloudStorageAccount.Parse(connectionString); + } + catch (Exception ex) + { + throw new StorageClientException( + "An error related to the cloud storage account occurred", + ex); + } + } /// /// Uploads the job input. @@ -40,29 +49,34 @@ public JobStorageHelper(string connectionString) /// /// Container uri + Input uri. /// - public async Task<(string containerUri, string inputUri)> UploadJobInputAsync( + public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync( string jobId, Stream input, ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, CancellationToken cancellationToken = default) { string containerName = GetContainerName(jobId); + + BlobContainerClient containerClient = await this.GetContainerClient(containerName); + await this.StorageHelper.UploadBlobAsync( - containerName, + containerClient, Constants.Storage.InputBlobName, input, protocol, cancellationToken); string containerUri = this.StorageHelper.GetBlobContainerSasUri( + this.connectionString, containerName, - this.expiryInterval, + this.ExpiryInterval, SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read); string inputUri = this.StorageHelper.GetBlobSasUri( + this.connectionString, containerName, Constants.Storage.InputBlobName, - this.expiryInterval, + this.ExpiryInterval, SharedAccessBlobPermissions.Read); return (containerUri, inputUri); @@ -76,57 +90,42 @@ await this.StorageHelper.UploadBlobAsync( /// Serialization protocol of the mapping to upload. /// The cancellation token. /// Container uri + Mapping uri. - public async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync( + public override async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync( string jobId, Stream mapping, ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, CancellationToken cancellationToken = default) { string containerName = GetContainerName(jobId); + BlobContainerClient containerClient = await this.GetContainerClient(containerName); + await this.StorageHelper.UploadBlobAsync( - containerName, + containerClient, Constants.Storage.MappingBlobName, mapping, protocol, cancellationToken); string containerUri = this.StorageHelper.GetBlobContainerSasUri( + this.connectionString, containerName, - this.expiryInterval, + this.ExpiryInterval, SharedAccessBlobPermissions.Create | SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.Read); string mappingUri = this.StorageHelper.GetBlobSasUri( + this.connectionString, containerName, Constants.Storage.MappingBlobName, - this.expiryInterval, + this.ExpiryInterval, SharedAccessBlobPermissions.Read); return (containerUri, mappingUri); } - /// - /// Downloads the job's execution output. - /// - /// The job id. - /// The destination stream. - /// The cancellation token. - /// Serialization protocol of the downloaded execution output. - public Task DownloadJobOutputAsync( - string jobId, - Stream destination, - CancellationToken cancellationToken = default) - { - string containerName = GetContainerName(jobId); - return this.StorageHelper.DownloadBlobAsync( - containerName, - "rawOutputData", // TODO: 14643 - destination, - cancellationToken); - } - - private static string GetContainerName(string jobId) + protected override Task GetContainerClient(string containerName) { - return Constants.Storage.ContainerNamePrefix + jobId.ToLowerInvariant(); + BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); + return Task.FromResult(blobServiceClient.GetBlobContainerClient(containerName)); } } } diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs new file mode 100644 index 00000000000..5c7487de208 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Azure.Quantum.Storage +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Bond; + using global::Azure.Storage.Blobs; + using Microsoft.Azure.Quantum.Utility; + + public abstract class JobStorageHelperBase : IJobStorageHelper + { + /// + /// Initializes a new instance of the class. + /// + public JobStorageHelperBase() + { + this.StorageHelper = new StorageHelper(); + this.ExpiryInterval = TimeSpan.FromDays(Constants.Storage.ExpiryIntervalInDays); + } + + /// + /// Gets the underlying storage helper. + /// + public IStorageHelper StorageHelper { get; } + + /// + /// Gets the expiry interval. + /// + protected TimeSpan ExpiryInterval { get; private set; } + + /// + /// Downloads the job's execution output. + /// + /// The job id. + /// The destination stream. + /// The cancellation token. + /// Serialization protocol of the downloaded execution output. + public async Task DownloadJobOutputAsync( + string jobId, + Stream destination, + CancellationToken cancellationToken = default) + { + string containerName = GetContainerName(jobId); + BlobContainerClient containerClient = await this.GetContainerClient(containerName); + + return await this.StorageHelper.DownloadBlobAsync( + containerClient, + "rawOutputData", // TODO: 14643 + destination, + cancellationToken); + } + + /// + /// Uploads the job input. + /// + /// The job id. + /// The input. + /// Serialization protocol of the input to upload. + /// The cancellation token. + /// Container uri + Input uri. + public abstract Task<(string containerUri, string inputUri)> UploadJobInputAsync( + string jobId, + Stream input, + ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, + CancellationToken cancellationToken = default); + + /// + /// Uploads the job program output mapping. + /// + /// The job id. + /// The job program output mapping. + /// Serialization protocol of the mapping to upload. + /// The cancellation token. + /// Container uri + Mapping uri. + public abstract Task<(string containerUri, string mappingUri)> UploadJobMappingAsync( + string jobId, + Stream mapping, + ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, + CancellationToken cancellationToken = default); + + /// + /// Gets the container client. + /// + /// Name of the container. + /// Container client. + protected abstract Task GetContainerClient(string containerName); + + protected static string GetContainerName(string jobId) + { + return Constants.Storage.ContainerNamePrefix + jobId.ToLowerInvariant(); + } + } +} diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs new file mode 100644 index 00000000000..e0838d18ec3 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Azure.Quantum.Storage +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Bond; + using global::Azure.Storage.Blobs; + using Microsoft.Azure.Quantum.Client; + using Microsoft.Azure.Quantum.Utility; + + public abstract class LinkedStorageJobHelper : JobStorageHelperBase + { + private readonly IJobsOperations jobsClient; + + /// + /// Initializes a new instance of the class. + /// + /// The jobs client. + public LinkedStorageJobHelper(IJobsOperations jobsClient) + { + this.jobsClient = jobsClient; + } + + /// + /// Uploads the job input. + /// + /// The job id. + /// The input. + /// Serialization protocol of the input to upload. + /// The cancellation token. + /// + /// Container uri + Input uri without SAS. + /// + public override async Task<(string containerUri, string inputUri)> UploadJobInputAsync( + string jobId, + Stream input, + ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, + CancellationToken cancellationToken = default) + { + string containerName = GetContainerName(jobId); + + BlobContainerClient containerClient = await this.GetContainerClient(containerName); + + await this.StorageHelper.UploadBlobAsync( + containerClient, + Constants.Storage.InputBlobName, + input, + protocol, + cancellationToken); + + Uri inputUri = containerClient + .GetBlobClient(Constants.Storage.InputBlobName) + .Uri; + + return (containerClient.Uri.ToString(), inputUri.ToString()); + } + + /// + /// Uploads the job program output mapping. + /// + /// The job id. + /// The job program output mapping. + /// Serialization protocol of the mapping to upload. + /// The cancellation token. + /// Container uri + Mapping uri without SAS. + public override async Task<(string containerUri, string mappingUri)> UploadJobMappingAsync( + string jobId, + Stream mapping, + ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, + CancellationToken cancellationToken = default) + { + string containerName = GetContainerName(jobId); + BlobContainerClient containerClient = await this.GetContainerClient(containerName); + + await this.StorageHelper.UploadBlobAsync( + containerClient, + Constants.Storage.MappingBlobName, + mapping, + protocol, + cancellationToken); + + Uri mappingUri = containerClient + .GetBlobClient(Constants.Storage.MappingBlobName) + .Uri; + + return (containerClient.Uri.ToString(), mappingUri.ToString()); + } + + protected override Task GetContainerClient(string containerName) + { + // TODO: call the new api to get container SAS + BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); + return Task.FromResult(blobServiceClient.GetBlobContainerClient(containerName)); + } + } +} diff --git a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs index ac97887a266..e3ee0787da2 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/StorageHelper.cs @@ -1,64 +1,43 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Azure.Storage.Blobs; -using Azure.Storage.Blobs.Models; -using Bond; -using Microsoft.Azure.Quantum.Exceptions; -using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Blob; - namespace Microsoft.Azure.Quantum.Storage { + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Bond; + using global::Azure.Storage.Blobs; + using global::Azure.Storage.Blobs.Models; + using Microsoft.Azure.Quantum.Exceptions; + using Microsoft.WindowsAzure.Storage; + using Microsoft.WindowsAzure.Storage.Blob; + internal class StorageHelper : IStorageHelper { - private readonly string connectionString; - private readonly CloudStorageAccount storageAccount; - - /// - /// Initializes a new instance of the class. - /// - /// The connection string. - public StorageHelper(string connectionString) - { - this.connectionString = connectionString; - - try - { - this.storageAccount = CloudStorageAccount.Parse(connectionString); - } - catch (Exception ex) - { - throw CreateException(ex, "An error related to the cloud storage account occurred"); - } - } - /// /// Downloads the BLOB. /// - /// Name of the container. + /// Container client. /// Name of the BLOB. /// The destination. /// The cancellation token. /// Serialization protocol of the downloaded BLOB. public async Task DownloadBlobAsync( - string containerName, + BlobContainerClient containerClient, string blobName, Stream destination, CancellationToken cancellationToken = default) { try { - BlobClient blob = await this.GetBlobClient(containerName, blobName, false, cancellationToken); + BlobClient blob = containerClient.GetBlobClient(blobName); await blob.DownloadToAsync(destination, cancellationToken); } catch (Exception ex) { - throw CreateException(ex, "Could not download BLOB", containerName, blobName); + throw CreateException(ex, "Could not download BLOB", containerClient.Name, blobName); } return ProtocolType.COMPACT_PROTOCOL; @@ -67,14 +46,14 @@ public async Task DownloadBlobAsync( /// /// Uploads the BLOB. /// - /// Name of the container. + /// Container client. /// Name of the BLOB. /// The input. /// Serialization protocol of the BLOB to upload. /// The cancellation token. /// Async task. public async Task UploadBlobAsync( - string containerName, + BlobContainerClient containerClient, string blobName, Stream input, ProtocolType protocol = ProtocolType.COMPACT_PROTOCOL, @@ -82,24 +61,30 @@ public async Task UploadBlobAsync( { try { - BlobClient blob = await this.GetBlobClient(containerName, blobName, true, cancellationToken); + // Ensure container is created + await containerClient.CreateIfNotExistsAsync(PublicAccessType.Blob, cancellationToken: cancellationToken); + + // Upload blob + BlobClient blob = containerClient.GetBlobClient(blobName); await blob.UploadAsync(input, overwrite: true, cancellationToken); } catch (Exception ex) { - throw CreateException(ex, "Could not upload BLOB", containerName, blobName); + throw CreateException(ex, "Could not upload BLOB", containerClient.Name, blobName); } } /// /// Gets the BLOB sas URI. /// + /// Storage account connection string. /// Name of the container. /// Name of the BLOB. /// The expiry interval. /// The permissions. /// Blob uri. public string GetBlobSasUri( + string connectionString, string containerName, string blobName, TimeSpan expiryInterval, @@ -109,7 +94,8 @@ public string GetBlobSasUri( { SharedAccessBlobPolicy adHocSAS = CreateSharedAccessBlobPolicy(expiryInterval, permissions); - CloudBlob blob = this.storageAccount + CloudBlob blob = CloudStorageAccount + .Parse(connectionString) .CreateCloudBlobClient() .GetContainerReference(containerName) .GetBlobReference(blobName); @@ -125,11 +111,13 @@ public string GetBlobSasUri( /// /// Gets the BLOB container sas URI. /// + /// Storage account connection string. /// Name of the container. /// The expiry interval. /// The permissions. /// Container uri. public string GetBlobContainerSasUri( + string connectionString, string containerName, TimeSpan expiryInterval, SharedAccessBlobPermissions permissions) @@ -139,7 +127,10 @@ public string GetBlobContainerSasUri( SharedAccessBlobPolicy adHocPolicy = CreateSharedAccessBlobPolicy(expiryInterval, permissions); // Generate the shared access signature on the container, setting the constraints directly on the signature. - CloudBlobContainer container = this.storageAccount.CreateCloudBlobClient().GetContainerReference(containerName); + CloudBlobContainer container = CloudStorageAccount + .Parse(connectionString) + .CreateCloudBlobClient().GetContainerReference(containerName); + return container.Uri + container.GetSharedAccessSignature(adHocPolicy, null); } catch (Exception ex) @@ -156,29 +147,11 @@ private StorageClientException CreateException ( { return new StorageClientException( message, - connectionString, containerName, blobName, inner); } - private async Task GetBlobClient( - string containerName, - string blobName, - bool createContainer, - CancellationToken cancellationToken) - { - BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); - BlobContainerClient blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName); - - if (createContainer) - { - await blobContainerClient.CreateIfNotExistsAsync(PublicAccessType.Blob, cancellationToken: cancellationToken); - } - - return blobContainerClient.GetBlobClient(blobName); - } - private static SharedAccessBlobPolicy CreateSharedAccessBlobPolicy( TimeSpan expiryInterval, SharedAccessBlobPermissions permissions) From 4d2321eda336417fab6b5d6289673700ca9cc730 Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Thu, 11 Jun 2020 14:08:46 -0700 Subject: [PATCH 2/7] generate new swagger client --- .../WorkspaceTest.cs | 5 +- .../JobManagement/CloudJob.cs | 14 +- .../JobManagement/Workspace.cs | 4 +- .../Storage/LinkedStorageJobHelper.cs | 20 +- .../generated/IJobsOperations.cs | 2 +- .../generated/IProvidersOperations.cs | 2 +- .../generated/IQuantumClient.cs | 7 +- .../generated/IStorageOperations.cs | 50 ++++ .../generated/JobsOperations.cs | 30 +-- .../generated/JobsOperationsExtensions.cs | 2 +- .../generated/Models/BlobDetails.cs | 59 +++++ .../generated/Models/JobDetails.cs | 28 +- .../generated/Models/Page.cs | 2 +- .../generated/Models/ProviderStatus.cs | 2 +- .../generated/Models/RestError.cs | 4 +- .../generated/Models/RestErrorException.cs | 2 +- .../generated/Models/SasUriResponse.cs | 53 ++++ .../generated/Models/TargetStatus.cs | 2 +- .../generated/ProvidersOperations.cs | 10 +- .../ProvidersOperationsExtensions.cs | 2 +- .../generated/QuantumClient.cs | 8 +- .../generated/StorageOperations.cs | 244 ++++++++++++++++++ .../generated/StorageOperationsExtensions.cs | 61 +++++ 23 files changed, 531 insertions(+), 82 deletions(-) create mode 100644 src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs create mode 100644 src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs create mode 100644 src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs create mode 100644 src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs create mode 100644 src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs index a953436ceaa..f60060eab82 100644 --- a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs +++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs @@ -6,10 +6,9 @@ using System.Linq; using System.Net; using System.Net.Http; -using Microsoft.Azure.Quantum.Client; -using Microsoft.Azure.Quantum.Client.Models; using Microsoft.Azure.Quantum.Exceptions; -using Microsoft.Rest; +using Microsoft.Quantum; +using Microsoft.Quantum.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs index 9f3c54a7be8..e37c247c2eb 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs @@ -1,15 +1,15 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Azure.Quantum.Client.Models; -using Microsoft.Azure.Quantum.Utility; -using Microsoft.Quantum.Runtime; - namespace Microsoft.Azure.Quantum { + using System; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Quantum.Utility; + using Microsoft.Quantum.Models; + using Microsoft.Quantum.Runtime; + /// /// Cloud job class. /// diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs index 5f9261aaa75..f79934fb32e 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs @@ -10,10 +10,10 @@ namespace Microsoft.Azure.Quantum using System.Threading.Tasks; using global::Azure.Core; using Microsoft.Azure.Quantum.Authentication; - using Microsoft.Azure.Quantum.Client; - using Microsoft.Azure.Quantum.Client.Models; using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Azure.Quantum.Utility; + using Microsoft.Quantum; + using Microsoft.Quantum.Models; /// /// Workspace class. diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs index e0838d18ec3..8bbbba25d09 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs @@ -9,20 +9,21 @@ namespace Microsoft.Azure.Quantum.Storage using System.Threading.Tasks; using Bond; using global::Azure.Storage.Blobs; - using Microsoft.Azure.Quantum.Client; using Microsoft.Azure.Quantum.Utility; + using Microsoft.Quantum; + using Microsoft.Quantum.Models; public abstract class LinkedStorageJobHelper : JobStorageHelperBase { - private readonly IJobsOperations jobsClient; + private readonly IStorageOperations storageOperations; /// /// Initializes a new instance of the class. /// - /// The jobs client. - public LinkedStorageJobHelper(IJobsOperations jobsClient) + /// The jobs client. + public LinkedStorageJobHelper(IStorageOperations storageOperations) { - this.jobsClient = jobsClient; + this.storageOperations = storageOperations; } /// @@ -90,11 +91,12 @@ await this.StorageHelper.UploadBlobAsync( return (containerClient.Uri.ToString(), mappingUri.ToString()); } - protected override Task GetContainerClient(string containerName) + protected override async Task GetContainerClient(string containerName) { - // TODO: call the new api to get container SAS - BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); - return Task.FromResult(blobServiceClient.GetBlobContainerClient(containerName)); + // Calls the service to get a container SAS Uri + var containerUri = await storageOperations.SasUriAsync(new BlobDetails { ContainerName = containerName }); + + return new BlobContainerClient(new Uri(containerUri.SasUri)); } } } diff --git a/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs index 74fd4d11463..f40f90609e4 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs index 2cc635ca7c8..6a403bb90a4 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs index f4ae50f1a37..c8a978c6ddc 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; @@ -85,5 +85,10 @@ public partial interface IQuantumClient : System.IDisposable /// IProvidersOperations Providers { get; } + /// + /// Gets the IStorageOperations. + /// + IStorageOperations Storage { get; } + } } diff --git a/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs new file mode 100644 index 00000000000..f43051d6119 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs @@ -0,0 +1,50 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. +// + +namespace Microsoft.Quantum +{ + using Microsoft.Rest; + using Microsoft.Rest.Azure; + using Models; + using System.Collections; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + + /// + /// StorageOperations operations. + /// + public partial interface IStorageOperations + { + /// + /// Gets a URL with SAS token for a container/blob in the storage + /// account associated with the workspace. The SAS URL can be used to + /// upload job input and/or download job output. + /// + /// + /// + /// + /// The headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// Thrown when the operation returned an invalid status code + /// + /// + /// Thrown when unable to deserialize the response + /// + /// + /// Thrown when a required parameter is null + /// + Task> SasUriWithHttpMessagesAsync(BlobDetails blobDetails, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs index 81697920294..3061217f6f3 100644 --- a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; @@ -169,7 +169,7 @@ internal JobsOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + CloudError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex = new CloudException(_errorBody.Message); @@ -211,7 +211,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -358,7 +358,7 @@ internal JobsOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; @@ -395,7 +395,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -465,10 +465,6 @@ internal JobsOperations(QuantumClient client) { throw new ValidationException(ValidationRules.CannotBeNull, "jobDefinition"); } - if (jobDefinition != null) - { - jobDefinition.Validate(); - } // Tracing bool _shouldTrace = ServiceClientTracing.IsEnabled; string _invocationId = null; @@ -529,7 +525,7 @@ internal JobsOperations(QuantumClient client) string _requestContent = null; if(jobDefinition != null) { - _requestContent = Microsoft.Rest.Serialization.SafeJsonConvert.SerializeObject(jobDefinition, Client.SerializationSettings); + _requestContent = Rest.Serialization.SafeJsonConvert.SerializeObject(jobDefinition, Client.SerializationSettings); _httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8); _httpRequest.Content.Headers.ContentType =System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); } @@ -559,7 +555,7 @@ internal JobsOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; @@ -596,7 +592,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -614,7 +610,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -761,7 +757,7 @@ internal JobsOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; @@ -798,7 +794,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -929,7 +925,7 @@ internal JobsOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - CloudError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + CloudError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex = new CloudException(_errorBody.Message); @@ -971,7 +967,7 @@ internal JobsOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs index bfec9488a12..ad1d56176e2 100644 --- a/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs +++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs new file mode 100644 index 00000000000..0cda535c859 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. +// + +namespace Microsoft.Quantum.Models +{ + using Newtonsoft.Json; + using System.Linq; + + /// + /// Blob details. + /// + public partial class BlobDetails + { + /// + /// Initializes a new instance of the BlobDetails class. + /// + public BlobDetails() + { + CustomInit(); + } + + /// + /// Initializes a new instance of the BlobDetails class. + /// + /// The container name. + /// The blob name. + public BlobDetails(string containerName, string blobName = default(string)) + { + ContainerName = containerName; + BlobName = blobName; + CustomInit(); + } + + /// + /// An initialization method that performs custom operations like setting defaults + /// + partial void CustomInit(); + + /// + /// Gets or sets the container name. + /// + [JsonProperty(PropertyName = "containerName")] + public string ContainerName { get; set; } + + /// + /// Gets or sets the blob name. + /// + [JsonProperty(PropertyName = "blobName")] + public string BlobName { get; set; } + + } +} diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs index 82627baecd0..4705cc19126 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs @@ -8,9 +8,8 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { - using Microsoft.Rest; using Newtonsoft.Json; using System.Collections; using System.Collections.Generic; @@ -204,30 +203,5 @@ public JobDetails() [JsonProperty(PropertyName = "errorData")] public RestError ErrorData { get; private set; } - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (ContainerUri == null) - { - throw new ValidationException(ValidationRules.CannotBeNull, "ContainerUri"); - } - if (InputDataFormat == null) - { - throw new ValidationException(ValidationRules.CannotBeNull, "InputDataFormat"); - } - if (ProviderId == null) - { - throw new ValidationException(ValidationRules.CannotBeNull, "ProviderId"); - } - if (Target == null) - { - throw new ValidationException(ValidationRules.CannotBeNull, "Target"); - } - } } } diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs index 7ab5d320626..4fa8892feba 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs index 43baf39b445..4b455eca7ea 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { using Newtonsoft.Json; using System.Collections; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs index 4917d841e8e..46c9f15f1df 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { using Microsoft.Rest; using Microsoft.Rest.Serialization; @@ -18,7 +18,7 @@ namespace Microsoft.Azure.Quantum.Client.Models /// /// An Error response. /// - [JsonTransformation] + [Rest.Serialization.JsonTransformation] public partial class RestError { /// diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs index cb5804185a0..d21d38cd883 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { using Microsoft.Rest; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs new file mode 100644 index 00000000000..0a809b70f45 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. +// + +namespace Microsoft.Quantum.Models +{ + using Newtonsoft.Json; + using System.Linq; + + /// + /// Get SAS URL operation response. + /// + public partial class SasUriResponse + { + /// + /// Initializes a new instance of the SasUriResponse class. + /// + public SasUriResponse() + { + CustomInit(); + } + + /// + /// Initializes a new instance of the SasUriResponse class. + /// + /// A URL with a SAS token to upload a blob for + /// execution in the given workspace. + public SasUriResponse(string sasUri = default(string)) + { + SasUri = sasUri; + CustomInit(); + } + + /// + /// An initialization method that performs custom operations like setting defaults + /// + partial void CustomInit(); + + /// + /// Gets or sets a URL with a SAS token to upload a blob for execution + /// in the given workspace. + /// + [JsonProperty(PropertyName = "sasUri")] + public string SasUri { get; set; } + + } +} diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs index 78c150b3c95..4c08c13f823 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client.Models +namespace Microsoft.Quantum.Models { using Newtonsoft.Json; using System.Linq; diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs index 625e3d0457b..33acaf34689 100644 --- a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; @@ -169,7 +169,7 @@ internal ProvidersOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; @@ -206,7 +206,7 @@ internal ProvidersOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { @@ -337,7 +337,7 @@ internal ProvidersOperations(QuantumClient client) try { _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); - RestError _errorBody = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); if (_errorBody != null) { ex.Body = _errorBody; @@ -374,7 +374,7 @@ internal ProvidersOperations(QuantumClient client) _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); try { - _result.Body = Microsoft.Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject>(_responseContent, Client.DeserializationSettings); } catch (JsonException ex) { diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs index 649d483f64a..094abad8ece 100644 --- a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs +++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs index 3d193cee37a..82e1eff5b72 100644 --- a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs +++ b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Azure.Quantum.Client +namespace Microsoft.Quantum { using Microsoft.Rest; using Microsoft.Rest.Azure; @@ -90,6 +90,11 @@ public partial class QuantumClient : ServiceClient, IQuantumClien /// public virtual IProvidersOperations Providers { get; private set; } + /// + /// Gets the IStorageOperations. + /// + public virtual IStorageOperations Storage { get; private set; } + /// /// Initializes a new instance of the QuantumClient class. /// @@ -333,6 +338,7 @@ private void Initialize() { Jobs = new JobsOperations(this); Providers = new ProvidersOperations(this); + Storage = new StorageOperations(this); BaseUri = new System.Uri("https://app-jobscheduler-prod.azurewebsites.net"); AcceptLanguage = "en-US"; LongRunningOperationRetryTimeout = 30; diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs new file mode 100644 index 00000000000..17190376029 --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs @@ -0,0 +1,244 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. +// + +namespace Microsoft.Quantum +{ + using Microsoft.Rest; + using Microsoft.Rest.Azure; + using Models; + using Newtonsoft.Json; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using System.Net; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + /// + /// StorageOperations operations. + /// + internal partial class StorageOperations : IServiceOperations, IStorageOperations + { + /// + /// Initializes a new instance of the StorageOperations class. + /// + /// + /// Reference to the service client. + /// + /// + /// Thrown when a required parameter is null + /// + internal StorageOperations(QuantumClient client) + { + if (client == null) + { + throw new System.ArgumentNullException("client"); + } + Client = client; + } + + /// + /// Gets a reference to the QuantumClient + /// + public QuantumClient Client { get; private set; } + + /// + /// Gets a URL with SAS token for a container/blob in the storage account + /// associated with the workspace. The SAS URL can be used to upload job input + /// and/or download job output. + /// + /// + /// + /// + /// Headers that will be added to request. + /// + /// + /// The cancellation token. + /// + /// + /// Thrown when the operation returned an invalid status code + /// + /// + /// Thrown when unable to deserialize the response + /// + /// + /// Thrown when a required parameter is null + /// + /// + /// Thrown when a required parameter is null + /// + /// + /// A response object containing the response body and response headers. + /// + public async Task> SasUriWithHttpMessagesAsync(BlobDetails blobDetails, Dictionary> customHeaders = null, CancellationToken cancellationToken = default(CancellationToken)) + { + if (Client.SubscriptionId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.SubscriptionId"); + } + if (Client.ResourceGroupName == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.ResourceGroupName"); + } + if (Client.WorkspaceName == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "this.Client.WorkspaceName"); + } + if (blobDetails == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "blobDetails"); + } + // Tracing + bool _shouldTrace = ServiceClientTracing.IsEnabled; + string _invocationId = null; + if (_shouldTrace) + { + _invocationId = ServiceClientTracing.NextInvocationId.ToString(); + Dictionary tracingParameters = new Dictionary(); + tracingParameters.Add("blobDetails", blobDetails); + tracingParameters.Add("cancellationToken", cancellationToken); + ServiceClientTracing.Enter(_invocationId, this, "SasUri", tracingParameters); + } + // Construct URL + var _baseUrl = Client.BaseUri.AbsoluteUri; + var _url = new System.Uri(new System.Uri(_baseUrl + (_baseUrl.EndsWith("/") ? "" : "/")), "v1.0/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Quantum/workspaces/{workspaceName}/storage/sasUri").ToString(); + _url = _url.Replace("{subscriptionId}", System.Uri.EscapeDataString(Client.SubscriptionId)); + _url = _url.Replace("{resourceGroupName}", System.Uri.EscapeDataString(Client.ResourceGroupName)); + _url = _url.Replace("{workspaceName}", System.Uri.EscapeDataString(Client.WorkspaceName)); + List _queryParameters = new List(); + if (_queryParameters.Count > 0) + { + _url += (_url.Contains("?") ? "&" : "?") + string.Join("&", _queryParameters); + } + // Create HTTP transport objects + var _httpRequest = new HttpRequestMessage(); + HttpResponseMessage _httpResponse = null; + _httpRequest.Method = new HttpMethod("POST"); + _httpRequest.RequestUri = new System.Uri(_url); + // Set Headers + if (Client.GenerateClientRequestId != null && Client.GenerateClientRequestId.Value) + { + _httpRequest.Headers.TryAddWithoutValidation("x-ms-client-request-id", System.Guid.NewGuid().ToString()); + } + if (Client.AcceptLanguage != null) + { + if (_httpRequest.Headers.Contains("accept-language")) + { + _httpRequest.Headers.Remove("accept-language"); + } + _httpRequest.Headers.TryAddWithoutValidation("accept-language", Client.AcceptLanguage); + } + + + if (customHeaders != null) + { + foreach(var _header in customHeaders) + { + if (_httpRequest.Headers.Contains(_header.Key)) + { + _httpRequest.Headers.Remove(_header.Key); + } + _httpRequest.Headers.TryAddWithoutValidation(_header.Key, _header.Value); + } + } + + // Serialize Request + string _requestContent = null; + if(blobDetails != null) + { + _requestContent = Rest.Serialization.SafeJsonConvert.SerializeObject(blobDetails, Client.SerializationSettings); + _httpRequest.Content = new StringContent(_requestContent, System.Text.Encoding.UTF8); + _httpRequest.Content.Headers.ContentType =System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json; charset=utf-8"); + } + // Set Credentials + if (Client.Credentials != null) + { + cancellationToken.ThrowIfCancellationRequested(); + await Client.Credentials.ProcessHttpRequestAsync(_httpRequest, cancellationToken).ConfigureAwait(false); + } + // Send Request + if (_shouldTrace) + { + ServiceClientTracing.SendRequest(_invocationId, _httpRequest); + } + cancellationToken.ThrowIfCancellationRequested(); + _httpResponse = await Client.HttpClient.SendAsync(_httpRequest, cancellationToken).ConfigureAwait(false); + if (_shouldTrace) + { + ServiceClientTracing.ReceiveResponse(_invocationId, _httpResponse); + } + HttpStatusCode _statusCode = _httpResponse.StatusCode; + cancellationToken.ThrowIfCancellationRequested(); + string _responseContent = null; + if ((int)_statusCode != 200) + { + var ex = new RestErrorException(string.Format("Operation returned an invalid status code '{0}'", _statusCode)); + try + { + _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + RestError _errorBody = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + if (_errorBody != null) + { + ex.Body = _errorBody; + } + } + catch (JsonException) + { + // Ignore the exception + } + ex.Request = new HttpRequestMessageWrapper(_httpRequest, _requestContent); + ex.Response = new HttpResponseMessageWrapper(_httpResponse, _responseContent); + if (_shouldTrace) + { + ServiceClientTracing.Error(_invocationId, ex); + } + _httpRequest.Dispose(); + if (_httpResponse != null) + { + _httpResponse.Dispose(); + } + throw ex; + } + // Create Result + var _result = new AzureOperationResponse(); + _result.Request = _httpRequest; + _result.Response = _httpResponse; + if (_httpResponse.Headers.Contains("x-ms-request-id")) + { + _result.RequestId = _httpResponse.Headers.GetValues("x-ms-request-id").FirstOrDefault(); + } + // Deserialize Response + if ((int)_statusCode == 200) + { + _responseContent = await _httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + _result.Body = Rest.Serialization.SafeJsonConvert.DeserializeObject(_responseContent, Client.DeserializationSettings); + } + catch (JsonException ex) + { + _httpRequest.Dispose(); + if (_httpResponse != null) + { + _httpResponse.Dispose(); + } + throw new SerializationException("Unable to deserialize the response.", _responseContent, ex); + } + } + if (_shouldTrace) + { + ServiceClientTracing.Exit(_invocationId, _result); + } + return _result; + } + + } +} diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs new file mode 100644 index 00000000000..293b65c56dd --- /dev/null +++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs @@ -0,0 +1,61 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for +// license information. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is +// regenerated. +// + +namespace Microsoft.Quantum +{ + using Microsoft.Rest; + using Microsoft.Rest.Azure; + using Models; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Extension methods for StorageOperations. + /// + public static partial class StorageOperationsExtensions + { + /// + /// Gets a URL with SAS token for a container/blob in the storage account + /// associated with the workspace. The SAS URL can be used to upload job input + /// and/or download job output. + /// + /// + /// The operations group for this extension method. + /// + /// + /// + public static SasUriResponse SasUri(this IStorageOperations operations, BlobDetails blobDetails) + { + return operations.SasUriAsync(blobDetails).GetAwaiter().GetResult(); + } + + /// + /// Gets a URL with SAS token for a container/blob in the storage account + /// associated with the workspace. The SAS URL can be used to upload job input + /// and/or download job output. + /// + /// + /// The operations group for this extension method. + /// + /// + /// + /// + /// The cancellation token. + /// + public static async Task SasUriAsync(this IStorageOperations operations, BlobDetails blobDetails, CancellationToken cancellationToken = default(CancellationToken)) + { + using (var _result = await operations.SasUriWithHttpMessagesAsync(blobDetails, null, cancellationToken).ConfigureAwait(false)) + { + return _result.Body; + } + } + + } +} From a236e8c8ef1cd3e193fe0f2023b2976fb599d026 Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Thu, 11 Jun 2020 15:52:40 -0700 Subject: [PATCH 3/7] fixes --- .../JobManagement/IWorkspace.cs | 12 +++++++ .../JobManagement/Workspace.cs | 35 +++++++++++++++---- .../Storage/JobStorageHelper.cs | 7 ++-- .../Storage/JobStorageHelperBase.cs | 3 +- .../Storage/LinkedStorageJobHelper.cs | 20 +++++------ 5 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs index 9ad313e8c8f..eaa2db3f1b2 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/IWorkspace.cs @@ -50,5 +50,17 @@ Task GetJobAsync( /// List of jobs Task> ListJobsAsync( CancellationToken cancellationToken = default); + + /// + /// Gets as SAS Uri for the storage account associated with the workspace. + /// + /// Name of the container. + /// Name of the BLOB. + /// The cancellation token. + /// Sas Uri. + Task GetSasUriAsync( + string containerName, + string blobName = null, + CancellationToken cancellationToken = default); } } diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs index f79934fb32e..32d534ef552 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs @@ -100,13 +100,13 @@ private Workspace( try { - this.JobsClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider)) + this.QuantumClient = new QuantumClient(new AuthorizationClientHandler(accessTokenProvider)) { BaseUri = this.baseUri, SubscriptionId = subscriptionId, ResourceGroupName = resourceGroupName, WorkspaceName = workspaceName, - }.Jobs; + }; } catch (Exception ex) { @@ -121,7 +121,7 @@ private Workspace( /// /// The jobs client. /// - internal IJobsOperations JobsClient { get; set; } + internal IQuantumClient QuantumClient { get; set; } /// /// Submits the job. @@ -140,7 +140,7 @@ public async Task SubmitJobAsync( try { - JobDetails jobDetails = await this.JobsClient.PutAsync( + JobDetails jobDetails = await this.QuantumClient.Jobs.PutAsync( jobId: jobDefinition.Details.Id, jobDefinition: jobDefinition.Details, cancellationToken: cancellationToken); @@ -165,7 +165,7 @@ public async Task CancelJobAsync(string jobId, CancellationToken cance try { - JobDetails jobDetails = await this.JobsClient.DeleteAsync( + JobDetails jobDetails = await this.QuantumClient.Jobs.DeleteAsync( jobId: jobId, cancellationToken: cancellationToken); @@ -191,7 +191,7 @@ public async Task GetJobAsync(string jobId, CancellationToken cancella try { - JobDetails jobDetails = await this.JobsClient.GetAsync( + JobDetails jobDetails = await this.QuantumClient.Jobs.GetAsync( jobId: jobId, cancellationToken: cancellationToken); @@ -214,7 +214,7 @@ public async Task> ListJobsAsync(CancellationToken cancell { try { - var jobs = await this.JobsClient.ListAsync( + var jobs = await this.QuantumClient.Jobs.ListAsync( cancellationToken: cancellationToken); return jobs @@ -226,6 +226,27 @@ public async Task> ListJobsAsync(CancellationToken cancell } } + /// + /// Gets as SAS Uri for the linked storage account. + /// + /// Name of the container. + /// Name of the BLOB. + /// The cancellation token. + /// + /// Sas Uri. + /// + public async Task GetSasUriAsync(string containerName, string blobName = null, CancellationToken cancellationToken = default) + { + BlobDetails details = new BlobDetails + { + ContainerName = containerName, + BlobName = blobName, + }; + + var response = await this.QuantumClient.Storage.SasUriAsync(details, cancellationToken); + return response.SasUri; + } + private WorkspaceClientException CreateException( Exception inner, string message, diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs index ea7da8d8b7f..4898e24c6db 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelper.cs @@ -14,10 +14,9 @@ namespace Microsoft.Azure.Quantum.Storage using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; - public abstract class JobStorageHelper : JobStorageHelperBase + public class JobStorageHelper : JobStorageHelperBase { private readonly string connectionString; - private readonly CloudStorageAccount storageAccount; /// /// Initializes a new instance of the class. @@ -29,7 +28,7 @@ public JobStorageHelper(string connectionString) try { - this.storageAccount = CloudStorageAccount.Parse(connectionString); + _ = CloudStorageAccount.Parse(connectionString); } catch (Exception ex) { @@ -122,7 +121,7 @@ await this.StorageHelper.UploadBlobAsync( return (containerUri, mappingUri); } - protected override Task GetContainerClient(string containerName) + protected override Task GetContainerClient(string containerName, CancellationToken cancellationToken = default) { BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString); return Task.FromResult(blobServiceClient.GetBlobContainerClient(containerName)); diff --git a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs index 5c7487de208..29f1c232016 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/JobStorageHelperBase.cs @@ -86,8 +86,9 @@ public async Task DownloadJobOutputAsync( /// Gets the container client. /// /// Name of the container. + /// Cancellation token. /// Container client. - protected abstract Task GetContainerClient(string containerName); + protected abstract Task GetContainerClient(string containerName, CancellationToken cancellationToken = default); protected static string GetContainerName(string jobId) { diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs index 8bbbba25d09..d01bb4f4c0f 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs @@ -10,20 +10,18 @@ namespace Microsoft.Azure.Quantum.Storage using Bond; using global::Azure.Storage.Blobs; using Microsoft.Azure.Quantum.Utility; - using Microsoft.Quantum; - using Microsoft.Quantum.Models; - public abstract class LinkedStorageJobHelper : JobStorageHelperBase + public class LinkedStorageJobHelper : JobStorageHelperBase { - private readonly IStorageOperations storageOperations; + private readonly IWorkspace workspace; /// /// Initializes a new instance of the class. /// - /// The jobs client. - public LinkedStorageJobHelper(IStorageOperations storageOperations) + /// The workspace. + public LinkedStorageJobHelper(IWorkspace workspace) { - this.storageOperations = storageOperations; + this.workspace = workspace; } /// @@ -91,12 +89,14 @@ await this.StorageHelper.UploadBlobAsync( return (containerClient.Uri.ToString(), mappingUri.ToString()); } - protected override async Task GetContainerClient(string containerName) + protected override async Task GetContainerClient(string containerName, CancellationToken cancellationToken = default) { // Calls the service to get a container SAS Uri - var containerUri = await storageOperations.SasUriAsync(new BlobDetails { ContainerName = containerName }); + var containerUri = await this.workspace.GetSasUriAsync( + containerName: containerName, + cancellationToken: cancellationToken); - return new BlobContainerClient(new Uri(containerUri.SasUri)); + return new BlobContainerClient(new Uri(containerUri)); } } } From 31ffaba374a4137b14ca64f5ae7b7a3131e6c633 Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Fri, 12 Jun 2020 10:04:55 -0700 Subject: [PATCH 4/7] fix unit tests --- src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs index f60060eab82..aabc515becc 100644 --- a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs +++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs @@ -183,13 +183,13 @@ private static IWorkspace GetWorkspace() workspaceName: TestConstants.WorkspaceName) { // Mock jobs client (only needed for unit tests) - JobsClient = new QuantumClient(MockHelper.GetHttpClientMock(), true) + QuantumClient = new QuantumClient(MockHelper.GetHttpClientMock(), true) { SubscriptionId = TestConstants.SubscriptionId, ResourceGroupName = TestConstants.ResourceGroupName, WorkspaceName = TestConstants.WorkspaceName, BaseUri = new Uri(TestConstants.Endpoint), - }.Jobs, + }, }; } From 52549f2ee58396d9d2fe43bf48516934b43c198a Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Fri, 12 Jun 2020 15:44:51 -0700 Subject: [PATCH 5/7] add back validation --- .../generated/JobsOperations.cs | 4 +++ .../generated/Models/BlobDetails.cs | 14 ++++++++++ .../generated/Models/JobDetails.cs | 26 +++++++++++++++++++ .../generated/StorageOperations.cs | 4 +++ 4 files changed, 48 insertions(+) diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs index 3061217f6f3..08f637fc5d2 100644 --- a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs @@ -465,6 +465,10 @@ internal JobsOperations(QuantumClient client) { throw new ValidationException(ValidationRules.CannotBeNull, "jobDefinition"); } + if (jobDefinition != null) + { + jobDefinition.Validate(); + } // Tracing bool _shouldTrace = ServiceClientTracing.IsEnabled; string _invocationId = null; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs index 0cda535c859..28c8fafdc1e 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs @@ -10,6 +10,7 @@ namespace Microsoft.Quantum.Models { + using Microsoft.Rest; using Newtonsoft.Json; using System.Linq; @@ -55,5 +56,18 @@ public BlobDetails() [JsonProperty(PropertyName = "blobName")] public string BlobName { get; set; } + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (ContainerName == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "ContainerName"); + } + } } } diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs index 4705cc19126..7ffff6d6631 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs @@ -10,6 +10,7 @@ namespace Microsoft.Quantum.Models { + using Microsoft.Rest; using Newtonsoft.Json; using System.Collections; using System.Collections.Generic; @@ -203,5 +204,30 @@ public JobDetails() [JsonProperty(PropertyName = "errorData")] public RestError ErrorData { get; private set; } + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (ContainerUri == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "ContainerUri"); + } + if (InputDataFormat == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "InputDataFormat"); + } + if (ProviderId == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "ProviderId"); + } + if (Target == null) + { + throw new ValidationException(ValidationRules.CannotBeNull, "Target"); + } + } } } diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs index 17190376029..2c9477a7253 100644 --- a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs @@ -96,6 +96,10 @@ internal StorageOperations(QuantumClient client) { throw new ValidationException(ValidationRules.CannotBeNull, "blobDetails"); } + if (blobDetails != null) + { + blobDetails.Validate(); + } // Tracing bool _shouldTrace = ServiceClientTracing.IsEnabled; string _invocationId = null; From 746ed257891ac94fcdc66ea781708104069edbb1 Mon Sep 17 00:00:00 2001 From: GeOrGe Moussa Date: Mon, 15 Jun 2020 12:32:46 -0700 Subject: [PATCH 6/7] pr comments --- src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs | 4 ++-- src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs | 2 +- .../Azure.Quantum.Client/JobManagement/Workspace.cs | 4 ++-- .../Storage/LinkedStorageJobHelper.cs | 9 +++++++-- .../Azure.Quantum.Client/generated/IJobsOperations.cs | 2 +- .../generated/IProvidersOperations.cs | 2 +- .../Azure.Quantum.Client/generated/IQuantumClient.cs | 2 +- .../Azure.Quantum.Client/generated/IStorageOperations.cs | 2 +- .../Azure.Quantum.Client/generated/JobsOperations.cs | 2 +- .../generated/JobsOperationsExtensions.cs | 2 +- .../Azure.Quantum.Client/generated/Models/BlobDetails.cs | 2 +- .../Azure.Quantum.Client/generated/Models/JobDetails.cs | 2 +- src/Azure/Azure.Quantum.Client/generated/Models/Page.cs | 2 +- .../generated/Models/ProviderStatus.cs | 2 +- .../Azure.Quantum.Client/generated/Models/RestError.cs | 2 +- .../generated/Models/RestErrorException.cs | 2 +- .../generated/Models/SasUriResponse.cs | 2 +- .../generated/Models/TargetStatus.cs | 2 +- .../generated/ProvidersOperations.cs | 2 +- .../generated/ProvidersOperationsExtensions.cs | 2 +- .../Azure.Quantum.Client/generated/QuantumClient.cs | 2 +- .../Azure.Quantum.Client/generated/StorageOperations.cs | 2 +- .../generated/StorageOperationsExtensions.cs | 2 +- 23 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs index aabc515becc..f0c9300de19 100644 --- a/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs +++ b/src/Azure/Azure.Quantum.Client.Test/WorkspaceTest.cs @@ -6,9 +6,9 @@ using System.Linq; using System.Net; using System.Net.Http; +using Microsoft.Azure.Quantum.Client; +using Microsoft.Azure.Quantum.Client.Models; using Microsoft.Azure.Quantum.Exceptions; -using Microsoft.Quantum; -using Microsoft.Quantum.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs index e37c247c2eb..746de8c57b1 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/CloudJob.cs @@ -6,8 +6,8 @@ namespace Microsoft.Azure.Quantum using System; using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Quantum.Client.Models; using Microsoft.Azure.Quantum.Utility; - using Microsoft.Quantum.Models; using Microsoft.Quantum.Runtime; /// diff --git a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs index 32d534ef552..c123010c18b 100644 --- a/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs +++ b/src/Azure/Azure.Quantum.Client/JobManagement/Workspace.cs @@ -10,10 +10,10 @@ namespace Microsoft.Azure.Quantum using System.Threading.Tasks; using global::Azure.Core; using Microsoft.Azure.Quantum.Authentication; + using Microsoft.Azure.Quantum.Client; + using Microsoft.Azure.Quantum.Client.Models; using Microsoft.Azure.Quantum.Exceptions; using Microsoft.Azure.Quantum.Utility; - using Microsoft.Quantum; - using Microsoft.Quantum.Models; /// /// Workspace class. diff --git a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs index d01bb4f4c0f..4d6dba0334c 100644 --- a/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs +++ b/src/Azure/Azure.Quantum.Client/Storage/LinkedStorageJobHelper.cs @@ -55,7 +55,7 @@ await this.StorageHelper.UploadBlobAsync( .GetBlobClient(Constants.Storage.InputBlobName) .Uri; - return (containerClient.Uri.ToString(), inputUri.ToString()); + return (GetUriPath(containerClient.Uri), GetUriPath(inputUri)); } /// @@ -86,7 +86,7 @@ await this.StorageHelper.UploadBlobAsync( .GetBlobClient(Constants.Storage.MappingBlobName) .Uri; - return (containerClient.Uri.ToString(), mappingUri.ToString()); + return (GetUriPath(containerClient.Uri), GetUriPath(mappingUri)); } protected override async Task GetContainerClient(string containerName, CancellationToken cancellationToken = default) @@ -98,5 +98,10 @@ protected override async Task GetContainerClient(string con return new BlobContainerClient(new Uri(containerUri)); } + + private string GetUriPath(Uri uri) + { + return uri.GetLeftPart(UriPartial.Path); + } } } diff --git a/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs index f40f90609e4..74fd4d11463 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IJobsOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs index 6a403bb90a4..2cc635ca7c8 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IProvidersOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs index c8a978c6ddc..db391fa0911 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IQuantumClient.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs index f43051d6119..4010389be24 100644 --- a/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/IStorageOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs index 08f637fc5d2..cf7e04ca42a 100644 --- a/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs index ad1d56176e2..bfec9488a12 100644 --- a/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs +++ b/src/Azure/Azure.Quantum.Client/generated/JobsOperationsExtensions.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs index 28c8fafdc1e..6698af8a001 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/BlobDetails.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Microsoft.Rest; using Newtonsoft.Json; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs index 7ffff6d6631..82627baecd0 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/JobDetails.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Microsoft.Rest; using Newtonsoft.Json; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs index 4fa8892feba..7ab5d320626 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/Page.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs index 4b455eca7ea..43baf39b445 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/ProviderStatus.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Newtonsoft.Json; using System.Collections; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs index 46c9f15f1df..466b3737fa8 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestError.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Microsoft.Rest; using Microsoft.Rest.Serialization; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs index d21d38cd883..cb5804185a0 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/RestErrorException.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Microsoft.Rest; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs index 0a809b70f45..b811d2e06a6 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/SasUriResponse.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Newtonsoft.Json; using System.Linq; diff --git a/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs index 4c08c13f823..78c150b3c95 100644 --- a/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs +++ b/src/Azure/Azure.Quantum.Client/generated/Models/TargetStatus.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum.Models +namespace Microsoft.Azure.Quantum.Client.Models { using Newtonsoft.Json; using System.Linq; diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs index 33acaf34689..9cf8af20c06 100644 --- a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs index 094abad8ece..649d483f64a 100644 --- a/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs +++ b/src/Azure/Azure.Quantum.Client/generated/ProvidersOperationsExtensions.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs index 82e1eff5b72..2fdcd086b3c 100644 --- a/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs +++ b/src/Azure/Azure.Quantum.Client/generated/QuantumClient.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs index 2c9477a7253..38ac48aa70f 100644 --- a/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs +++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperations.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; diff --git a/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs index 293b65c56dd..ec883e16100 100644 --- a/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs +++ b/src/Azure/Azure.Quantum.Client/generated/StorageOperationsExtensions.cs @@ -8,7 +8,7 @@ // regenerated. // -namespace Microsoft.Quantum +namespace Microsoft.Azure.Quantum.Client { using Microsoft.Rest; using Microsoft.Rest.Azure; From aade50568afbbc56cd28aa12e0ee26191c1c72f9 Mon Sep 17 00:00:00 2001 From: George Moussa Date: Tue, 16 Jun 2020 12:20:09 -0700 Subject: [PATCH 7/7] fix QuantumMachine activator --- .../Azure.Quantum.Client/Machine/QuantumMachineFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs index 94ab65f2368..fe7aa8a6184 100644 --- a/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs +++ b/src/Azure/Azure.Quantum.Client/Machine/QuantumMachineFactory.cs @@ -47,8 +47,8 @@ targetName is null : (IQuantumMachine)Activator.CreateInstance( machineType, targetName, - storageAccountConnectionString, - workspace); + workspace, + storageAccountConnectionString); } } } \ No newline at end of file