Azure-webjobs-sdk: Using blob only storage account in webjobs 3.x

Created on 10 Jan 2018  路  7Comments  路  Source: Azure/azure-webjobs-sdk

When using another storage account which is blob only for binding, the operation fail with a Service Unavailable exception.

Repro steps

Have two storage account :

  • account1 which is a general purpose account used as AzureWebJobsStorage account
  • account2 which is a blob only account

``` [FunctionName("MyFunc")]
public static async Task MyFuncAsync(
[ServiceBusTrigger("myqueue", Connection = "servicebus")]Message queueMessage,
Binder binder,
TraceWriter traceWriter)
{
try
{
var stream = await binder.BindAsync(new Attribute[]
{
new StorageAccountAttribute("account2"),
new BlobAttribute($"test/{queueMessage.MessageId}", FileAccess.Write)
});
/* ... */
}
catch(Exception e)
{ traceWriter.Error(e.ToString(), e); }
}


#### Expected behavior
I expect to have a valid stream to the blob

#### Actual behavior

I end up with an exception in BindAsync :

> [10/01/2018 15:12:35] A ScriptHost error has occurred
[10/01/2018 15:12:35] Exception while executing function: SendMailFunction. Microsoft.WindowsAzure.Storage: Service Unavailable.
[10/01/2018 15:12:35] Exception while executing function: SendMailFunction
[10/01/2018 15:12:35] Exception while executing function: SendMailFunction. Microsoft.WindowsAzure.Storage: Service Unavailable.
[10/01/2018 15:12:35] Function completed (Failure, Id=1081697d-7b44-4675-92b7-c7e7281e0d07, Duration=26473ms)
[10/01/2018 15:12:35]
[10/01/2018 15:12:35] Executed 'SendMailFunction' (Failed, Id=1081697d-7b44-4675-92b7-c7e7281e0d07)
[10/01/2018 15:12:35] System.Private.CoreLib: Exception while executing function: SendMailFunction. Microsoft.WindowsAzure.Storage: Service Unavailable.
[10/01/2018 15:12:35]   Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '1081697d-7b44-4675-92b7-c7e7281e0d07'
[10/01/2018 15:12:35] System.Private.CoreLib: Exception while executing function: SendMailFunction. Microsoft.WindowsAzure.Storage: Service Unavailable.

The exception come from this line :
https://github.com/Azure/azure-webjobs-sdk/blob/4ce0982d0a48219e5300cdfdf4567654ade6da07/src/Microsoft.Azure.WebJobs.Host/Executors/DefaultStorageCredentialsValidator.cs#L72
As it is a blob only, it can't create a queue or check if it exists.

Full stack :

Microsoft.WindowsAzure.Storage.StorageException: Service Unavailable
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.d__41.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.WindowsAzure.Storage.Queue.CloudQueue.<>c__DisplayClass63_0.<<ExistsAsync>b__0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.Azure.WebJobs.Host.Executors.DefaultStorageCredentialsValidator.d__1.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultStorageCredentialsValidator.cs:line 88
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.WebJobs.Host.Executors.DefaultStorageCredentialsValidator.d__0.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultStorageCredentialsValidator.cs:line 27
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.WebJobs.Host.Executors.DefaultStorageAccountProvider.d__24.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultStorageAccountProvider.cs:line 180
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.Azure.WebJobs.Host.Executors.DefaultStorageAccountProvider.<TryGetAccountAsync>d__25.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultStorageAccountProvider.cs:line 197 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.Azure.WebJobs.Host.Executors.StorageAccountProviderExtensions.d__2.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\StorageAccountProviderExtensions.cs:line 52
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.Azure.WebJobs.Host.Executors.StorageAccountProviderExtensions.<GetStorageAccountAsync>d__3.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\StorageAccountProviderExtensions.cs:line 59 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.Azure.WebJobs.Host.Blobs.Bindings.BlobAttributeBindingProvider.d__5.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Blobs\Bindings\BlobAttributeBindingProvider.cs:line 63
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at Microsoft.Azure.WebJobs.Host.Bindings.CompositeBindingProvider.<TryCreateAsync>d__2.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingProviders\CompositeBindingProvider.cs:line 25 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.Azure.WebJobs.Binder.d__131.MoveNext() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\Runtime\Binder.cs:line 97 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Tools.Messenger.MessengerFunctions.Functions.d__0.MoveNext() in C:\dev\Messenger\Src\Tools.Messenger.MessengerFunctions\Functions.cs:line 28
Request Information
RequestID:
RequestDate:Wed, 10 Jan 2018 16:23:20 GMT
StatusMessage:Service Unavailable

Please note that e.GetBaseException() as WebException is null, therefore the exception rethrown in the catch of ValidateCredentialsAsyncCore

#### Known workarounds

No known workaround (except changing second account to general purpose)

#### Related information 
Package used :
<PackageReference Include="Microsoft.Azure.WebJobs.ServiceBus" Version="3.0.0-beta4-11131" />
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.0-beta4-11131" />
<PackageReference Include="Microsoft.Azure.ServiceBus" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.7" />

```

3.x bug

All 7 comments

Yeah it looks like the code in ValidateCredentialsAsyncCore to detect a blob only account doesn't work correctly against Azure Storage v8.x. So this is a regression.

I'd be glad to fix the bug, can I ? Do you have any particular guidance or things I need to follow ?

Ok, I've pinpointed the issue. In fact it's not a problem of the version of WindowsAzure.Storage, it's a problem with the .net framework.
I've run this simple console app as net461 and netcoreapp2.0 :

var account = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=foo;AccountKey=bar;EndpointSuffix=core.windows.net");
var blobClient = account.CreateCloudBlobClient();
await blobClient.GetServicePropertiesAsync();

var queueClient = account.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("name");
try
{
    Console.WriteLine(await queue.ExistsAsync());
}
catch (StorageException e)
{
    Console.WriteLine(e.GetBaseException());
    Console.WriteLine(e.InnerException);
    Console.WriteLine(e);
}

On net461 it works well and the GetBaseException/InnerException is really a WebException and therefore we can use it.
Unfortunately, with netcoreapp2.0, it uses the netstandard1.3 of Microsoft.Azure.Storage.dll and in netstandard1.3 WebException is not part of the .net API that's why e.InnerException is null and GetBaseException is not WebException.

My conclusion is that under .netstandard, the catch should be different.

Hi @NatMarchand, we would gladly accept a PR that fixes this. The docs for getting a working development environment are here. The PR would need to target our dev branch. Keep in mind that the fix needs to work on both full framework and .NET core. To get an idea of what tests you might want to be touching, take a look at the commit that added this blob-only check in the first place: https://github.com/Azure/azure-webjobs-sdk/commit/663a508e8a851629c26a51e7de3af36629dfd120.

Is there any issue preventing the PR from being accepted ? :)

@NatMarchand Sorry, looks like nobody picked this up for review. I'll move it along. Thanks for the ping.

@NatMarchand closing this as your PR was merged. Thanks for helping us out with this!

Was this page helpful?
0 / 5 - 0 ratings