Wprowadzenie
Jak już doskonale wiecie, S3 używane jest do przechowywania plików. W tym wpisie utworzymy funkcję Lambda reagującą na zdarzenia zachodzące na S3, np. dodanie nowego pliku do naszego kubełka.
W tym celu wykorzystamy handler funkcji, który jest punktem startowym posiadającym szczegóły dotyczące zdarzenia do jakiego doszło. W tym wpisie przejdziemy przez proces konfiguracji S3, dodanie wyzwalacza Lambdy oraz zapisanie logów potwierdzających przesłanie plików do S3.
Kolejne kroki, które wykonamy w ramach tego wpisu:
- Utworzymy kubełek S3;
-
Utworzymy rolę, która ma uprawnienia do działania z S3 oraz Lambdą;
-
Utworzymy funkcję Lambda i dodamy S3 jako wyzwalacz.
Tworzenie roli dla S3 i Lambda
Korzystając z wyszukiwarki usług przechodzimy do Identity and Access Management (IAM) wybierając z panelu nawigacyjnego po lewej stronie Roles:
Klikamy przycisk Create role a następnie wybieramy Lambdę jako usługę, która będzie korzystać z tej roli. Klikamy Next: Permissions:
Z poziomu widoku dostępnych polityk wybieramy: AmazonS3FullAccess, AmazonLambda_FullAccess oraz CloudWatchFullAccess. Kilikamy przycisk Next: Tags oraz od razu robimy Review:
Ostatni krok w tym punkcie to sprawdzenie czy trzy powyższe polityki zostały przypisane do roli, następnie zdefiniowane nazwy dla roli oraz kliknięcie przycisku Create role:
Lambda z wyzwalaczem na S3
W tej części wpisu dodamy Lambdę a następnie ustawimy na niej wyzwalacz (trigger) na S3.
Powoli będę ograniczał podstawowe kroki ponieważ omówiliśmy je dokładnie w poprzednim cyklu. Pierwszy krok to dodanie nowej Lambdy z poziomu konsoli AWS, określnie nazwy funkcji oraz przypisanie polityki, którą utworzyliśmy w poprzednim kroku:
Po pomyślnym utworzeniu funkcji klikamy przycisk Add trigger dostępny z poziomu widoku szczegółowego danej lambdy i dokonujemy poniższej konfiguracji:
Klikamy przycisk Add. Na poniższym zrzucie ekranu możecie zobaczyć, że nasza Lambda będzie reagować na dodanie obiektu do S3:
Pora na modyfikację kodu naszej funkcji w celu wyświetlenia informacji dotyczącej akcji przeprowadzonej na S3. W tym celu wykorzystamy parameter event, który ma w sobie szczegóły zdarzenia związanego z akcją na S3. Dokonamy również logowania informacji dotyczącej nazwy kubełka oraz samego pliku, który został dodany. Spójrzcie na poniższy kod:
using System;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.S3;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace AWSLambda4
{
public class Function
{
IAmazonS3 S3Client { get; set; }
public Function()
{
S3Client = new AmazonS3Client();
}
/// <summary>
/// A simple function that takes a string and does a ToUpper
/// </summary>
/// <param name="input"></param>
/// <param name="context"></param>
/// <returns></returns>
public async Task<string> FunctionHandler(S3Event @event, ILambdaContext context)
{
var s3Event = @event.Records?[0].S3;
if(s3Event == null)
{
return null;
}
try
{
var bucketName = s3Event.Bucket.Name;
var fileName = s3Event.Object.Key;
var response = await this.S3Client.GetObjectMetadataAsync(s3Event.Bucket.Name, s3Event.Object.Key);
var message = $"Dodano plik do: {bucketName} -> {fileName}";
context.Logger.LogLine(message);
return response.Headers.ContentType;
}
catch (Exception ex)
{
context.Logger.LogLine($"Error getting object {s3Event.Object.Key} from bucket {s3Event.Bucket.Name}. Make sure they exist and your bucket is in the same region as this function.");
context.Logger.LogLine(ex.Message);
context.Logger.LogLine(ex.StackTrace);
throw;
}
}
}
}
Powyższy kod napisałem wykorzystując Visual Studio 2019 dodając nowy projekt w dokładnie ten sam sposób jak w poprzednim wpisie. Modyfikacje polegają na dołączeniu odpowiednich paczek oraz napisaniu prostego kodu spełniającego nasze założenia.
Co dalej? W momencie przygotowywania tego wpisu AWS nie obsługuje środowiska .NET Core 3.1 z poziomu konsoli – nie możemy wkleić kodu tak jak w poprzednim wpisie. Z drugiej strony dodaliśmy już nasza funkcję wraz z wyzwalaczem więc szkoda byłoby ponawiać te kroki i tworzyć od nowa funkcję. Wyjściem z tej sytuacji jest nieznaczna modyfikacja naszego projektu z VS mająca na celu zmianę pliku aws-lambda-tools-defaults.json w poniższy sposób w celu automatycznej publikacji z poziomu naszego środowiska:
{
"Information" : [
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
"dotnet lambda help",
"All the command line options for the Lambda command can be specified in this file."
],
"profile" : "default",
"region" : "us-east-1",
"configuration" : "Release",
"framework" : "netcoreapp3.1",
"function-runtime" : "dotnetcore3.1",
"function-memory-size" : 512,
"function-timeout" : 15,
"function-handler" : "AWSLambda4::AWSLambda4.Function::FunctionHandler",
"function-name" : "lambdaWithS3",
"function-description" : "",
"package-type" : "Zip",
"function-role" : "arn:aws:iam::689983305523:role/LambdaWithS3Service",
"tracing-mode" : "PassThrough",
"environment-variables" : "",
"image-tag" : ""
}
Zwróćcie uwagę na nazwę funkcji (function-name), która jest zgodna z funkcją dodaną z poziomu konsoli AWS. AWSLambda4 to nazwa projektu, który utworzyłem. Pozostałe parametry to zdefiniowanie handlera oraz roli, która jest przypisana do danej funkcji. Nie musicie tego robić ręcznie – korzystając z wtyczki AWS plik ten zostanie automatycznie zmodyfikowany na bazie waszych ustawień.
Testy
W tym momencie możemy dodać pliczek do S3, przejść następnie do CloudWatch i z poziomu LogGroups przejrzeć dziennik zdarzeń naszej funkcji Lambda. Powinniście zobaczyć log dotyczący zdarzenia do którego doszło:
Możecie poeksperytmentować z powyższym kodem, zobaczyć jakie dodatkowe informacje niesie event, wyświetlić szczegółowe informacje w dzienniku zdarzeń, itd. W następnym wpisie wykorzystamy bazę danych DynamoDB - wraz z dodaniem danych do tabeli dojdzie do uruchomienia funkcji Lambda, która wykorzystując usługę AWS SNS wyśle wiadomość do obiorcy informując o tym jakie dane zostały dodane.