Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Storage][Webjobs] Samples #16081

Merged
merged 17 commits into from
Oct 21, 2020
137 changes: 131 additions & 6 deletions sdk/storage/Azure.Storage.Webjobs.Extensions.Blobs/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,159 @@
# Azure WebJobs Storage Blobs client library for .NET

TODO
This extension provides functionality for accessing Azure Storage Blobs in Azure Functions.

## Getting started

### Install the package

Install the Storage Blobs extension with [NuGet][nuget]:

```Powershell
dotnet add package Azure.WebJobs.Extensions.Storage.Blobs
```

### Prerequisites

You need an [Azure subscription][azure_sub] and a
[Storage Account][storage_account_docs] to use this package.

To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal],
[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli].
Here's an example using the Azure CLI:

```Powershell
az storage account create --name <your-resource-name> --resource-group <your-resource-group-name> --location westus --sku Standard_LRS
```

### Authenticate the client

In order for the extension to access Blobs, you will need the connection string which can be found in the [Azure Portal](https://portal.azure.com/) or by using the [Azure CLI](https://docs.microsoft.com/cli/azure) snippet below.

```bash
az storage account show-connection-string -g <your-resource-group-name> -n <your-resource-name>
```

The connection string can be supplied through [AzureWebJobsStorage app setting](https://docs.microsoft.com/azure/azure-functions/functions-app-settings).

## Key concepts

TODO
### Using Blob binding

Please follow the [input binding tutorial](https://docs.microsoft.com/azure/azure-functions/functions-bindings-storage-blob-input?tabs=csharp) and [output binding tutorial](https://docs.microsoft.com/azure/azure-functions/functions-bindings-storage-blob-output?tabs=csharp) to learn about using this extension for accessing Blobs.

### Using Blob trigger

Please follow the [tutorial](https://docs.microsoft.com/azure/azure-functions/functions-bindings-storage-blob-trigger?tabs=csharp) to learn about triggering an Azure Function when a blob is modified.

## Examples

TODO
### Binding to string

```C# Snippet:BlobFunction_String
public static class BlobFunction_String
{
[FunctionName("BlobFunction")]
public static void Run(
[BlobTrigger("sample-container/sample-blob-1")] string blobTriggerContent,
[Blob("sample-container/sample-blob-2")] string blobContent,
ILogger logger)
{
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated with content: {content}", blobTriggerContent);
logger.LogInformation("Blob sample-container/sample-blob-2 has content: {content}", blobContent);
}
}
```

### Reading from stream

```C# Snippet:BlobFunction_ReadStream
public static class BlobFunction_ReadStream
{
[FunctionName("BlobFunction")]
public static void Run(
[BlobTrigger("sample-container/sample-blob-1")] Stream blobTriggerStream,
[Blob("sample-container/sample-blob-2", FileAccess.Read)] Stream blobStream,
ILogger logger)
{
using var blobTriggerStreamReader = new StreamReader(blobTriggerStream);
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated with content: {content}", blobTriggerStreamReader.ReadToEnd());
using var blobStreamReader = new StreamReader(blobStream);
logger.LogInformation("Blob sample-container/sample-blob-2 has content: {content}", blobStreamReader.ReadToEnd());
}
}
```

### Writing to stream

```C# Snippet:BlobFunction_WriteStream
public static class BlobFunction_WriteStream
{
[FunctionName("BlobFunction")]
public static async Task Run(
[BlobTrigger("sample-container/sample-blob-1")] Stream blobTriggerStream,
[Blob("sample-container/sample-blob-2", FileAccess.Write)] Stream blobStream,
ILogger logger)
{
await blobTriggerStream.CopyToAsync(blobStream);
logger.LogInformation("Blob sample-container/sample-blob-1 has been copied to sample-container/sample-blob-2");
}
}
```

### Binding to Azure Storage Blob SDK types

```C# Snippet:BlobFunction_BlobBaseClient
public static class BlobFunction_BlobBaseClient
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a few lines of text in between samples?

{
[FunctionName("BlobFunction")]
public static async Task Run(
[BlobTrigger("sample-container/sample-blob-1")] BlobBaseClient blobTriggerClient,
[Blob("sample-container/sample-blob-2")] BlobBaseClient blobClient,
ILogger logger)
{
BlobProperties blobTriggerProperties = await blobTriggerClient.GetPropertiesAsync();
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated on: {datetime}", blobTriggerProperties.LastModified);
BlobProperties blobProperties = await blobClient.GetPropertiesAsync();
logger.LogInformation("Blob sample-container/sample-blob-2 has been updated on: {datetime}", blobProperties.LastModified);
}
}
```

## Troubleshooting

TODO
Please refer to [Monitor Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-monitoring) for troubleshooting guidance.

## Next steps

TODO
Read the [introduction to Azure Function](https://docs.microsoft.com/azure/azure-functions/functions-overview) or [creating an Azure Function guide](https://docs.microsoft.com/azure/azure-functions/functions-create-first-azure-function).

## Contributing

TODO
See the [Storage CONTRIBUTING.md][storage_contrib] for details on building,
testing, and contributing to this library.

This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution. For
details, visit [cla.microsoft.com][cla].

This project has adopted the [Microsoft Open Source Code of Conduct][coc].
For more information see the [Code of Conduct FAQ][coc_faq]
or contact [opencode@microsoft.com][coc_contact] with any
additional questions or comments.

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Fstorage%2FAzure.Storage.Webjobs.Extensions.Blobs%2FREADME.png)

<!-- LINKS -->
[nuget]: https://www.nuget.org/
[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview
[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell
[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli
[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
[azure_sub]: https://azure.microsoft.com/free/
[RequestFailedException]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/core/Azure.Core/src/RequestFailedException.cs
[storage_contrib]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/CONTRIBUTING.md
[cla]: https://cla.microsoft.com
[coc]: https://opensource.microsoft.com/codeofconduct/
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
[coc_contact]: mailto:opencode@microsoft.com
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(RequiredTargetFrameworks)</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<Compile Include="$(AzureStorageWebjobsExtensionSharedTestSources)\**\*.cs" Link="Shared\%(RecursiveDir)\%(Filename)%(Extension)" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Azure.Storage.Webjobs.Extensions.Common\tests\Azure.WebJobs.Extensions.Storage.Common.Tests.csproj" />
<ProjectReference Include="..\src\Azure.WebJobs.Extensions.Storage.Blobs.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.


using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;
using Azure.WebJobs.Extensions.Storage.Common.Tests;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NUnit.Framework;

namespace Azure.WebJobs.Extensions.Storage.Blobs.Samples.Tests
{
public class BlobExtensionSamples
{
[TestCase(typeof(BlobFunction_String))]
[TestCase(typeof(BlobFunction_ReadStream))]
[TestCase(typeof(BlobFunction_WriteStream))]
[TestCase(typeof(BlobFunction_BlobBaseClient))]
public async Task Run_BlobFunction(Type programType)
{
var containerClient = AzuriteNUnitFixture.Instance.GetBlobServiceClient().GetBlobContainerClient("sample-container");
await containerClient.CreateIfNotExistsAsync();
await containerClient.GetBlockBlobClient("sample-blob").UploadTextAsync("content");
await containerClient.GetBlockBlobClient("sample-blob-1").UploadTextAsync("content-1");
await containerClient.GetBlockBlobClient("sample-blob-2").UploadTextAsync("content-2");
await RunTrigger(programType);
}

private async Task RunTrigger(Type programType)
{
await FunctionalTest.RunTriggerAsync(b => {
b.Services.AddAzureClients(builder =>
{
builder.ConfigureDefaults(options => options.Transport = AzuriteNUnitFixture.Instance.GetTransport());
});
b.AddAzureStorageBlobs();
}, programType,
settings: new Dictionary<string, string>() {
// This takes precedence over env variables.
{ "ConnectionStrings:AzureWebJobsStorage", AzuriteNUnitFixture.Instance.GetAzureAccount().ConnectionString }
});
}
}

#region Snippet:BlobFunction_String
public static class BlobFunction_String
{
[FunctionName("BlobFunction")]
public static void Run(
[BlobTrigger("sample-container/sample-blob-1")] string blobTriggerContent,
[Blob("sample-container/sample-blob-2")] string blobContent,
ILogger logger)
{
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated with content: {content}", blobTriggerContent);
logger.LogInformation("Blob sample-container/sample-blob-2 has content: {content}", blobContent);
}
}
#endregion

#region Snippet:BlobFunction_ReadStream
public static class BlobFunction_ReadStream
{
[FunctionName("BlobFunction")]
public static void Run(
[BlobTrigger("sample-container/sample-blob-1")] Stream blobTriggerStream,
[Blob("sample-container/sample-blob-2", FileAccess.Read)] Stream blobStream,
ILogger logger)
{
using var blobTriggerStreamReader = new StreamReader(blobTriggerStream);
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated with content: {content}", blobTriggerStreamReader.ReadToEnd());
using var blobStreamReader = new StreamReader(blobStream);
logger.LogInformation("Blob sample-container/sample-blob-2 has content: {content}", blobStreamReader.ReadToEnd());
}
}
#endregion

#region Snippet:BlobFunction_WriteStream
public static class BlobFunction_WriteStream
{
[FunctionName("BlobFunction")]
public static async Task Run(
[BlobTrigger("sample-container/sample-blob-1")] Stream blobTriggerStream,
[Blob("sample-container/sample-blob-2", FileAccess.Write)] Stream blobStream,
ILogger logger)
{
await blobTriggerStream.CopyToAsync(blobStream);
logger.LogInformation("Blob sample-container/sample-blob-1 has been copied to sample-container/sample-blob-2");
}
}
#endregion

#region Snippet:BlobFunction_BlobBaseClient
public static class BlobFunction_BlobBaseClient
{
[FunctionName("BlobFunction")]
public static async Task Run(
[BlobTrigger("sample-container/sample-blob-1")] BlobBaseClient blobTriggerClient,
[Blob("sample-container/sample-blob-2")] BlobBaseClient blobClient,
ILogger logger)
{
BlobProperties blobTriggerProperties = await blobTriggerClient.GetPropertiesAsync();
logger.LogInformation("Blob sample-container/sample-blob-1 has been updated on: {datetime}", blobTriggerProperties.LastModified);
BlobProperties blobProperties = await blobClient.GetPropertiesAsync();
logger.LogInformation("Blob sample-container/sample-blob-2 has been updated on: {datetime}", blobProperties.LastModified);
}
}
#endregion
}
61 changes: 53 additions & 8 deletions sdk/storage/Azure.Storage.Webjobs.Extensions.Common/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,79 @@
# Azure WebJobs Storage Common client library for .NET

TODO
This package provides infrastruture shared by the other Azure WebJobs Storage libraries.

## Getting started

### Install the package

Install the common library with [NuGet][nuget]:

```Powershell
dotnet add package Azure.WebJobs.Extensions.Storage.Common
```

### Prerequisites

You need an [Azure subscription][azure_sub] and a
[Storage Account][storage_account_docs] to use this package.

To create a new Storage Account, you can use the [Azure Portal][storage_account_create_portal],
[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli].
Here's an example using the Azure CLI:

```Powershell
az storage account create --name <your-resource-name> --resource-group <your-resource-group-name> --location westus --sku Standard_LRS
```

### Authenticate the client

In order for the extensions to access Storage, you will need the connection string which can be found in the [Azure Portal](https://portal.azure.com/) or by using the [Azure CLI](https://docs.microsoft.com/cli/azure) snippet below.

## Key concepts
```bash
az storage account show-connection-string -g <your-resource-group-name> -n <your-resource-name>
```

TODO
The connection string can be supplied through [AzureWebJobsStorage app setting](https://docs.microsoft.com/azure/azure-functions/functions-app-settings).

## Examples
## Key concepts

TODO
## Examples

## Troubleshooting

TODO
Please refer to [Monitor Azure Functions](https://docs.microsoft.com/azure/azure-functions/functions-monitoring) for troubleshooting guidance.

## Next steps

TODO
Read the [introduction to Azure Function](https://docs.microsoft.com/azure/azure-functions/functions-overview) or [creating an Azure Function guide](https://docs.microsoft.com/azure/azure-functions/functions-create-first-azure-function).

## Contributing

TODO
See the [Storage CONTRIBUTING.md][storage_contrib] for details on building,
testing, and contributing to this library.

This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution. For
details, visit [cla.microsoft.com][cla].

This project has adopted the [Microsoft Open Source Code of Conduct][coc].
For more information see the [Code of Conduct FAQ][coc_faq]
or contact [opencode@microsoft.com][coc_contact] with any
additional questions or comments.

![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Fstorage%2FAzure.Storage.Webjobs.Extensions.Blobs%2FREADME.png)

<!-- LINKS -->
[nuget]: https://www.nuget.org/
[storage_account_docs]: https://docs.microsoft.com/azure/storage/common/storage-account-overview
[storage_account_create_ps]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-powershell
[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli
[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
[azure_sub]: https://azure.microsoft.com/free/
[RequestFailedException]: https://github.com/Azure/azure-sdk-for-net/tree/master/sdk/core/Azure.Core/src/RequestFailedException.cs
[storage_contrib]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/storage/CONTRIBUTING.md
[cla]: https://cla.microsoft.com
[coc]: https://opensource.microsoft.com/codeofconduct/
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
[coc_contact]: mailto:opencode@microsoft.com
Loading