Azure Architecture Icons

Olá pessoal, tudo bem?

Quantas vezes nós não deparamos com a dificuldade em encontrar os ícones corretos para montar um diagrama de Arquitetura do Azure?

A Microsoft lançou recentemente um pacote de ícones do Azure para download em SVG através desse link.

Deixo aqui também o convite para acessar o Azure Architecture Center, aqui você pode encontrar muito conteúdo legal sobre Azure.

Espero que tenha gostado da dica e até a próxima.

Obrigado!

Azure Labs – Workshop Online Gratuito: End-to-end Development Microsoft Cloud

Olá pessoal, tudo bem?

Na última quarta-feira dia 21 participei do Azure Labs. Nesse workshop, primeiramente, demonstrei uma visão geral do poder do Azure para o desenvolvedor de software e logo na sequência falei sobre todos os serviços do Azure Storage e como eles podem lhe ajudar no seu dia-a-dia de desenvolvedor. Por fim, também atuei de moderador no chat tirando dúvidas relacionadas ao Azure.

Vale mencionar que tivemos um público excepcional nesse workshop chegando a quase 300 pessoas simultâneas.

E para quem tiver interesse no código utilizado sobre Azure Storage, ele pode ser acessado através desse link.

Abaixo algumas imagens do workshop:

Azure Overview

Azure Storage

Moderador do Chat

JunDevelopers Summit 2020

Olá pessoal,

Nesse sábado 12/09 participei do JunDevelopers Summit 2020, evento em que palestrei sobre a Construção de uma aplicação escalável e de baixo custo no Azure utilizando Azure Storage e Azure Functions.

Para que quiser baixar o código fonte utilizado na palestra, é só clicar nesse link.

Os slides utilizados na minha palestra, você confere logo abaixo:

E o vídeo aqui:

Deixo aqui meus agradecimentos a todos que puderam participar.

Até a próxima!

Redimensionando imagens com Azure Functions e Azure Storage

Olá pessoal, tudo bem? Nesse post vamos aprender como fazer um redimensionamento de imagens altamente escalável e muito simples utilizando Azure Functions e Azure Storage.

Primeiramente vamos criar uma conta de Storage no Azure e na sequência 2 containers no serviço de Blob. O primeiro container vai se chamar images (onde nossa Function vai monitorar), e o segundo vai se chamar thumbnails (onde salvaremos a nossa imagem redimensionada).

Dica: Caso esteja utilizando o sistema operacional Windows, você pode utilizar o Azure Storage Emulator para simular o serviço de Storage do Azure.

Logo depois de criarmos o serviço de Storage (seja no Azure ou simulando localmente através do Azure Storage Emulator), vamos abrir o Terminal (Ctrl + ‘) do Visual Studio Code, e digitarmos:

func init

Note que vão aparecer 4 opções de seleção, nesse caso, selecione a opção “dotnet”, e então, espere que termine a criação do nosso Function App.

Logo depois, nosso próximo passo será o de criar nossa Azure Function, e para isso, utilize o comando abaixo:

func new

Agora, dentre as diversas opções de Azure Functions, vamos escolher o tipo BlobTrigger e daremos a ela o nome de ImageResizerTrigger.

Seguindo, abra o arquivo .csproj do seu projeto e adicione o package da SixLabors.ImageSharp nele, igual a linha abaixo:

<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-rc0001" />

Na sequência o Visual Studio Code pedirá para que você faça um Restore na aplicação.

Assim que o Restore finalizar, abra o arquivo ImageResizerTrigger.cs e substitua-o com o código abaixo:

public static void Run([BlobTrigger("images/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, 
            [Blob("thumbnails/{name}", FileAccess.Write)] Stream outputBlob, ILogger log)
        {
            log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");

            using (var image = Image.Load(myBlob))
            {
                var resizeOptions = new ResizeOptions
                {
                    Size = new Size(640, 480),
                    Compand = true,
                    Mode = ResizeMode.Max
                };

                image.Mutate(ctx => ctx.Resize(resizeOptions));
                image.Save(outputBlob, new JpegEncoder { Quality = 80 });
            }
        }

Dessa forma, note no nosso código, que a nossa Azure Function estará sempre olhando para o container images, e seu “output” será sempre no container thumbnails.

Importante: A propriedade Connection esta “setada” com o valor: AzureWebJobsStorage. Esse valor na verdade esta contido no arquivo local.settings.json e você deverá colocar a string de conexão do seu Storage no mesmo.

Assim, faça o upload de uma imagem no container images e note que a imagem será automaticamente redimensionada e salva no container thumbnails, conforme nós queríamos.

Por fim, caso tenha interesse em mais conteúdos relacionados a Azure Functions e Azure Storage, convido você a dar uma olhada na série: Criando um CRUD Serverless com Azure Functions.

Espero que tenham gostado e até a próxima. Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 4

Olá pessoal, tudo bem? Neste post derradeiro sobre como criar um CRUD Serverless com Azure Functions, vamos aprender como orquestrar nossas API’s utilizando o Azure API Management. O intuito desse post não é explicar em detalhes esse serviço, mas sim em focar como podemos deixar nossas API’s mais seguras.

Primeiramente, acesse o https://portal.azure.com e clique em Create a Resource, e logo na sequência na barra de busca pesquise por API Management.

Preencha as informações necessárias e aguarde a criação do serviço terminar (isso leva em média 20 minutos). Agora nosso próximo passo será importar nossas API’s e para isso na barra esquerda clique em API’s e em seguida selecione Function App. No modal que aparecer clique em Browse, depois em Function App e então selecione a aplicação Serverless que publicamos na parte 3 do artigo, e após o preenchimento dos dados clique em Create.

Observe que você pode criar um sufixo para a chamada das API’s editando o campo API URL suffix. Outro ponto interessante é que ele nos mostra todas as nossas API’s (HttpTriggers) e quais desejamos importar (por padrão todas vem selecionadas).

Dessa forma, terminada a importação, vamos adicionar um “Produto” para a nossa API. Por padrão temos duas opções: Starter e Unlimited, tendo a possibilidade criarmos um customizado também caso necessário.

Após selecionado o produto, vamos clicar em Developer portal e logo abaixo do nome de login (provavelmente ADMINISTRATOR), selecione a opção Profile. Note que clicando nessa opção apareceram os dois produtos disponíveis (Starter e Unlimited) como duas Keys para cada um. Essas keys serão fundamentais para que nossas API’s funcionem pois sem elas, se tentarmos acessa-las aparecerá o seguinte erro:

{
  "statusCode": 401,
  "message": "Access denied due to invalid subscription key. Make sure to provide a valid key for an active subscription."
}

Então nosso próximo passo será autorizar a chamada das nossas API’s e para isso será necessário passar um Header da requisição chamado Ocp-Apim-Subscription-Key e como valor a Key do produto em questão. Note que se você fizer a chamada de alguma API ela vai funcionar perfeitamente.

Agora vamos implementar algumas Policies para nossa aplicação. Habilitaremos o CORS, na sequência as chamadas para um determinado range de IP’s e por fim restringir um numero abusivo de chamadas as nossas API’s em um pequeno espaço de tempo.

Para isso selecione nosso conjunto de API’s e clique em base nas opções de Inbound processing e em seguida adicione o código abaixo para habilitar o CORS (lembre-se que todo o código deve ser colocado dentro da tag de inbound):

<cors>
    <allowed-origins>
        <origin>{SUA_URL}</origin>
    </allowed-origins>
    <allowed-methods>
        <method>*</method>
    </allowed-methods>
    <allowed-headers>
        <header>*</header>
    </allowed-headers>
    <expose-headers>
        <header>*</header>
    </expose-headers>
</cors>

Agora vamos liberar apenas um range de IP:

<ip-filter action="allow">
    <address-range from="<IP_INICIO>" to="<IP_FIM>" />
</ip-filter>

Por último, com o código abaixo, restringiremos por 15 segundos o acesso as nossas API’s caso alguém acesse alguma delas 3 vezes seguidas em sequência.

<rate-limit-by-key calls="3" renewal-period="15" counter-key="@(context.Request.IpAddress)" increment-condition="@(context.Response.StatusCode == 200)" />

Bom pessoal e assim finalizamos nossa série Criando um CRUD Serverless com Azure Functions.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Espero que tenham gostado e até a próxima.

Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 3

Olá pessoal, tudo bem?

Seguindo a nossa série em que vamos criar um CRUD Serverless com Azure Functions, hoje desenvolveremos a listagem dos nossos registros, a publicação da nossa Function App no Azure e por fim a publicação de um site estático consumindo nossas API’s no Azure Storage.

Primeiramente vamos trabalhar na listagem dos registros, e portanto, começaremos criando nossa Function através do comando abaixo:

func new

Feito isso, como já é sabido, aparecerão diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e então nós daremos a ela o nome de ListPeople.

Abra o arquivo criado (ListPeople.cs) e vamos altera-lo com o código abaixo:

public static async Task<IEnumerable<Person>> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation("ListPeople function started a request.");

    var tableQuery = new TableQuery<Person>();
    TableContinuationToken continuationToken = null;

    TableQuerySegment<Person> tableQueryResult;
    do
    {
        tableQueryResult = await cloudTable.ExecuteQuerySegmentedAsync(tableQuery, continuationToken);
        continuationToken = tableQueryResult.ContinuationToken;
    } while (continuationToken != null);

    log.LogInformation("ListPeople function finished a request.");

    return tableQueryResult.Results;
}

Observe que o código mudou levemente em relação as HttpTriggers anteriores. Nesse código mudamos o retorno da Função, sendo que agora ela retorna um IEnumerable de Person e para que isso seja possível utilizamos o comando TableQuerySegment para trazer todos os registros da nossa tabela.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Agora vamos testar nossa função de listagem de registros (para isso recomendo utilizar um Client REST da sua preferência) acessando o novo endpoint criado: ListPeople: [GET] http://localhost:7071/api/ListPeople, e observe ele retornou todos os registros cadastrados.

Ao contrário do que vimos na parte 1 e parte 2 do artigo, não criaremos nenhuma QueueTrigger, pois não iremos enfileirar nenhuma consulta, ao invés disso, vamos criar mais uma HttpTrigger e dessa vez será para trazer um único registro ao invés da listagem toda.

Novamente vamos utilizar o comando abaixo:

func new

Feito escolheremos novamente o tipo HttpTrigger e para essa função daremos o nome de GetPerson.

Abra o arquivo criado (GetPerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<Person> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation("GetPerson function started a request.");

    var partitionKey = "Person";
    var rowKey = req.Query["id"];

    TableOperation person = TableOperation.Retrieve<Person>(partitionKey, rowKey);
    TableResult result = await cloudTable.ExecuteAsync(person);

    log.LogInformation("GetPerson function finished a request.");

    return (Person)result.Result;
}

Note que o código acima não é bem semelhante ao que já produzimos nas Funções anteriores e então vamos mais uma vez testar a nossa aplicação, utilizando o comando:

func start

Mais uma vez vamos acessar o novo endpoint criado: GetPerson: [GET] http://localhost:7071/api/GetPerson, (lembre-se de passar o RowKey via QueryString sob o parâmetro de nome id ), e observe ele retornou o registro cadastrado.

Agora finalmente vamos publicar tudo isso no Azure, e para isso (caso ainda não tenha instalado), vamos instalar a extensão do Azure Functions no VsCode e com ela instalada, você irá clicar na opção Deploy to Function App…, e em seguida selecione sua Subscription no Azure (caso possua mais de uma), nosso próximo passo será selecionar Create a New Function App in Azure, feito isso ele irá lhe pedir um nome (necessita ser único globalmente), e por fim selecione a Region em que deseja fazer o deploy.

Agora é so aguardar alguns minutos para que o deploy seja finalizado no Azure.

Bônus

Para deixarmos nosso CRUD mais profissional podemos criar uma Single Page Application utilizando Angular e publicar isso no Azure, gastando apenas o custo de armazenamento, sem que seja cobrado qualquer custo de computação. Para realizarmos esse próximo passo, deixo abaixo um vídeo que eu publiquei no canal Azure na Prática fazendo um passo a passo de como fazer isso.

Por sim para quem tiver interesse todo o código da nossa Function App encontra-se no meu GitHub, inclusive contendo uma Single Page Application feita em Angular, pronta para ser publicada. Lembrando que no próximo e último artigo da série de posts, vou demonstrar como utilizarmos o Azure API Management pra a orquestração das nossas API’s criadas na nossa Function App.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 2

Olá pessoal, tudo bem?

Seguindo a nossa série em que vamos criar um CRUD Serverless com Azure Functions, hoje desenvolveremos a parte de edição e de exclusão do nosso registro.

Primeiramente vamos trabalhar na edição, e portanto, começaremos criando nossa Function através do comando abaixo:

func new

Feito isso, como já é sabido, aparecerão diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e então nós daremos a ela o nome de EditPerson.

Abra o arquivo criado (EditPerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "put", Route = null)]HttpRequest req,
    [Queue("EditPerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem,
    ILogger log)
{
    log.LogInformation("EditPerson function started a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    await queueItem.AddAsync(requestBody);

    log.LogInformation("EditPerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que o código não é muito diferente do código da nossa HttpTrigger que criamos na parte 1 do nosso post.

Dica: Observe que na chamada da nossa HttpTrigger existe uma propriedade chamada Route, ela serve para customizarmos a rota da nossa Function caso você queira, do contrário o padrão será sempre o nome da sua HttpTrigger.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Note que agora nós temos dois endpointsCreatePerson: [POST] http://localhost:7071/api/CreatePerson e EditPerson: [PUT] http://localhost:7071/api/EditPerson e com isso já é possível testar nossa função de edição (para isso recomendo utilizar um Client REST da sua preferência), porém dessa vez precisaremos passar além das propriedades Name e Email as propriedades para encontrar o registro em si e elas são a PartitionKey e o RowKey. Com isso seu body deve ficar muito parecido com que se encontra logo abaixo:

{
	"name": "Blog do Ericson - Edit",
	"email": "ericson@email.com",
        "partitionKey": "Person",
        "rowKey": "<GUID_DO_REGISTRO>"
}

Feito isso abra a ferramenta Microsoft Azure Storage Explorer e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada EditPerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo, assim como na parte 1 do nosso post, será o de desenfileirar a mensagem e salva-la no nosso banco de dados e para isso vamos criar nossa próxima Azure Function, e para isso, novamente vamos utilizar o comando abaixo:

func new

Dessa vez escolheremos o tipo QueueTrigger e colocaremos o nome dela de EditPersonQueue e em seguida, vamos altera-la com o código abaixo:

public static void Run(
    [QueueTrigger("EditPerson", Connection = "AzureWebJobsStorage")]string queueItem,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation($"EditPersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);

    var tableOperation = TableOperation.InsertOrReplace(data);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"EditPersonQueue trigger function finished.");
}

Note que novamente não há muita mudança em relação nossa Queue Trigger criada no post anterior.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila EditPerson, e agora o registro encontra-se editado na nossa tabela Person.

Agora que a edição esta finalizada e funcionando perfeitamente, vamos para o próximo passo que é o de excluir o nosso registro, e para isso vamos novamente criar mais uma função através do comando abaixo:

func new

Novamente, escolha o tipo HttpTrigger e então nós daremos a ela o nome de DeletePerson.

Abra o arquivo criado (DeletePerson.cs) e vamos altera-lo com o código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "delete", Route = null)]HttpRequest req,
    [Queue("DeletePerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem,
    ILogger log)
{
    log.LogInformation("DeletPerson function started a request.");

    await queueItem.AddAsync(
        JsonConvert.SerializeObject(
            new Person
            {
                PartitionKey = "Person",
                RowKey = req.Query["id"]
            }
        )
    );

    log.LogInformation("DeletePerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que agora nossa HttpTrigger, ao contrario das criadas anteriormente, espera como body apenas o Partition Key (coloquei ele já direto no código, mas você pode passa-lo como parâmetro caso queira) e o RowKey que será passado via QueryString sob o parâmetro de nome id.

Vamos agora executar nosso Function App utilizando o comando abaixo:

func start

Note que agora nós temos três endpointsDeletePerson: [DELETE] http://localhost:7071/api/DeletePerson, CreatePerson: [POST] http://localhost:7071/api/CreatePerson e EditPerson: [PUT] http://localhost:7071/api/EditPerson e com isso já é possível testar nossa função de exclusão (para isso recomendo utilizar um Client REST da sua preferência), porém dessa vez conforme precisaremos apenas do RowKey e com isso sua QueryString deve ficar muito parecido com que se encontra logo abaixo:

http://localhost:7071/api/DeletePerson?id=<GUID_DO_REGISTRO>

Feito isso abra a ferramenta Microsoft Azure Storage Explorer e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada DeletePerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo, assim como na parte 1 do nosso post, será o de desenfileirar a mensagem e salva-la no nosso banco de dados e para isso vamos criar nossa próxima Azure Function, e para isso, novamente vamos utilizar o comando abaixo:

func new

Dessa vez escolheremos o tipo QueueTrigger e colocaremos o nome dela de DeletePersonQueue e em seguida, vamos altera-la com o código abaixo:

public static void Run(
    [QueueTrigger("DeletePerson", Connection = "AzureWebJobsStorage")]string queueItem,
    [Table("Person")]CloudTable cloudTable,
    ILogger log)
{
    log.LogInformation($"DeletePersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);

    var person = new DynamicTableEntity(data?.PartitionKey, data?.RowKey);
    person.ETag = "*";

    var tableOperation = TableOperation.Delete(person);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"DeletePersonQueue trigger function finished.");
}

Note que dessa vez houve uma certa mudança em relação nossa Queue Trigger criada no post anterior.

Aqui nos primeiros temos que recuperar o registro da nossa Table Person, baseando-se na PartitionKey e no RowKey antes de mais nada e na sequência setar a propriedade ETag. Falando rapidamente sobre essa propriedade, ela consegue atuar no caso de concorrência de alterações de um registro, como aqui eu quero excluir o mesmo eu estou setando com o * e isso significa que eu estou dizendo para o Tables não se preocupar em monitorar essa exclusão.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila DeletePerson, e agora o registro também não existe mais na nossa tabela Person.

Bom pessoal, e com isso finalizamos a segunda parte do nosso CRUD Serverless em que editamos e excluímos o nosso registro. No nosso próximo post vamos trabalhar na exibição dos registros já cadastrados e na publicação do nosso Function App no Azure.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Criando um CRUD Serverless com Azure Functions – Parte 1

Olá pessoal tudo bem?

Iniciaremos através deste post uma série sobre como montar um CRUD completo utilizando a última versão (3) do Azure Functions.

Importante: Para concluirmos o CRUD de maneira satisfatória, vamos precisar instalar as seguintes ferramentas:

No Visual Studio Code recomendo fortemente instalar a extensão do Azure Functions, pois ela vai nos ajudar bastante.

Assim que todas as instalações forem concluídas, vamos executar o Azure Storage Emulator (caso o mesmo já não esteja em execução), e então na sequência, vamos criar nosso projeto no Visual Studio Code, abrindo seu Terminal (Ctrl + ‘) e em seguida digitando o seguinte comando:

func init

Feito vão aparecer 4 opções de seleção, nesse caso, selecione a primeira opção “dotnet”, e então, espere que termine a criação do nosso Function App.

Nosso próximo passo será o de criar nossa primeira Azure Function, e para isso digite o comando abaixo:

func new

Feito isso apareceram diversas opções de Azure Functions, cada uma para um propósito diferente, e no nosso caso escolheremos o tipo HttpTrigger e daremos a ela o nome de CreatePerson.

Abra o arquivo criado (CreatePerson.cs) e observe que ele já veio com um código padrão. Esse código nada mais faz, do que esperar um parâmetro chamado name e no fim exibirá uma mensagem de boas vindas.

Note que a função possui um cabeçalho, e ele e de extrema importância, pois é através dele que “injetaremos” os serviços que desejamos consumir na nossa Function.

Dica 1: Por boas práticas inclusive recomendadas no livro Clean Code do Robert C. Martin (Cap. 3 – Functions), uma Função deve ser extremamente pequena e no caso das Azure Functions isso não é excessão, lembre sempre que se uma Função tiver mais de um propósito, faça uma refatoração da mesma.

Dica 2: Quando suas Azure Functions estiverem publicadas no Azure, caso o plano escolhido seja o Consumption (mais barato), uma função tem tempo limite de 10 minutos para executar, logo já é mais que um bom motivo para suas funções serem “pequenas”.

Voltando para a nossa função CreatePreson vamos substitui o código padrão pelo código abaixo:

public static async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequest req, 
    [Queue("CreatePerson", Connection = "AzureWebJobsStorage")]IAsyncCollector<string> queueItem, 
    ILogger log)
{
    log.LogInformation("CreatePerson function started a request.");

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    await queueItem.AddAsync(requestBody);

    log.LogInformation("CreatePerson function finished a request.");

    return new OkObjectResult($"Obrigado! Seu registro já esta sendo processado.");
}

Observe que o Visual Studio Code vai indicar um erro, na palavra Queue e na propriedade Connection. Isso deve ao fato de que ele não encontrou as mesmas e portanto precisamos importar o SDK do Azure Storage na nossa aplicação, e para fazer isso, abra o arquivo .csproj do seu projeto e logo abaixo da linha em que ele adiciona a referência do SDK das Azure Functions, adicione a seguinte referência:

<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="3.0.10" />

Com isso ele vai pedir para fazer o Restore do seu projeto e em seguida os erros deixarão de existir.

Comentando sobre o código da nossa Function, nós basicamente “injetamos” a possibilidade de lidar com as Queues do Azure Storage, e então através da nossa HttpTrigger receberemos o conteúdo contido no body da nossa requisição e então, enfileiraremos esse conteúdo no serviço de mensageria do Azure Storage. Note também, que na propriedade Connection eu passo um valor chamado “AzureWebJobsStorage”, nesse caso, vamos abrir o arquivo local.settings.json e localizar a propriedade “AzureWebJobsStorage” e então, substituir o conteúdo dela para a String de Conexão do nosso Azure Storage Emulator. Caso você possua Mac ou Linux você pode indicar nesse local a String de Conexão do seu Azure Storage no Azure.

Como desejamos fazer um CRUD completo, vou utilizar a classe abaixo (Person.cs) como referência para o nosso cadastro.

using Microsoft.WindowsAzure.Storage.Table;

namespace AzureFunctions
{
    public class Person : TableEntity
    {
        public string Name { get; set; }
        public string Email { get; set; }

        public Person() { }
    }
}

Observe que na classe Person eu já herdo a classe TableEntity para já facilitar a inserção dos nosso dados em um outro serviço do Azure Storage chamado Azure Tables.

Feito isso, vamos testar nosso Function App, e para isso digite o seguinte comando:

func start

Note que ele criou o seguinte endpoint para nós: CreatePerson: [POST] http://localhost:7071/api/CreatePerson e com isso já é possível testar nossa função (para isso recomendo utilizar um Client REST da sua preferência) passando o seguinte body:

{
	"name": "Blog do Ericson",
	"email": "ericson@email.com"
}

Feito isso abra a ferramenta Microsoft Azure Storage Explorer (instalada previamente no inicio do post) e localize dentro de Storage Account o serviços de Queues e abrindo-o note que foi criada uma Queue chamada CreatePerson. Abra a mesma e note que o body que passamos para o nosso endpoint estará armazenado na fila.

Agora nosso próximo passo será desenfileirar a mensagem e salva-la em um banco de dados, e seguindo nosso exemplo esse banco de dados sera o serviço de Tables (banco de dados NoSQL de chave-valor) do Azure Storage.

Vamos então criar uma nova Azure Function, digitando o novamente o comando abaixo:

func new

Feito isso, novamente aparecerão diversas opções de Azure Functions, e dessa vez escolheremos o tipo QueueTrigger e nós daremos a ela o nome de CreatePersonQueue. Após a criação da mesma substitua o código gerado pelo template pelo código abaixo:

public static void Run(
    [QueueTrigger("CreatePerson", Connection = "AzureWebJobsStorage")]string queueItem, 
    [Table("Person")]CloudTable cloudTable, 
    ILogger log)
{
    log.LogInformation($"CreatePersonQueue trigger function started.");

    var data = JsonConvert.DeserializeObject<Person>(queueItem);
    data.PartitionKey = "Person";
    data.RowKey = Guid.NewGuid().ToString();

    var tableOperation = TableOperation.Insert(data);
    cloudTable.ExecuteAsync(tableOperation);

    log.LogInformation($"CreatePersonQueue trigger function finished.");
}

No código acima, vamos deserializar a mensagem para o tipo Person e em seguida precisamos criar duas propriedades obrigatórias para que se possa utilizar o serviço de Tables do Azure Storage. Explicando de maneira bem resumida, a RowKey teria uma função similar ao de um ID de um banco de dados relacional e a PartitionKey teria a função de ajustar o particionamento automático do serviço de Tables do Azure Storage.

Com isso vamos executar nosso Function App novamente através do comando:

func start

E então abra novamente o Microsoft Azure Storage Explorer e note que a mensagem sumiu da fila, e agora a mesma encontra-se salva na tabela Person (criada automaticamente) dentro do serviço de Tables.

Bom pessoal, e com isso finalizamos a primeira parte do nosso CRUD Serverless em que criamos nosso registro. No nosso próximo post vamos trabalhar na edição e exclusão dele.

E para finalizar deixo aqui um convite.

Que tal aprender mais sobre Docker, Kubernetes e a implementação de soluções baseadas em containers utilizando o Microsoft Azure, em um workshop que acontecerá durante um sábado todo (dia 04/04) em São Paulo Capital e implementando um case na prática?

Acesse então o link a seguir para efetuar sua inscrição (já incluso camiseta, emissão de certificado e almoço para os participantes) com o desconto: http://bit.ly/anp-docker-blog-ericson

Até mais pessoal.

Abraços e Obrigado!

Exibindo o último commit do git na sua aplicação ASP.NET Core

Nesse post vou demonstrar como exibir o último commit do Git na sua aplicação ASP.NET Core.

Primeiramente clique com o botão direito sobre sobre sua aplicação e clique em Properties, em seguida clique em Build Events e na sequência clique em Edit Pre-build e digite a seguinte linha de código que se encontra no bloco abaixo:

git log -1 > "$(ProjectDir)versao.txt"

O comando acima pega o log do último commit e cria um arquivo chamado versao.txt no diretório base do seu projeto. Observe que utilizei a macro ProjectDir para automaticamente criar meu arquivo com o último log no diretório base do projeto. Caso queira saber mais sobre macros, na tela de Edit Pre-build, clique no botão Macros >> haverão muitas opções que poderão lhe auxiliar, caso queira fazer algo mais elaborado.

Nosso próximo passo será colocar nosso arquivo versao.txt “embutido” na nossa aplicação e para isso, clique sobre o arquivo versao.txt com o botão direito e em seguida clique em Properties. Na opção BuildAction selecione Embedded resource e na opção Copy to Output Directory selecione Copy always.

Por fim, agora vamos ler nosso arquivo versao.txt para exibir dentro da sua aplicação, utilizando o código abaixo:

string gitVersion = string.Empty;
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SuaAplicacao.versao.txt"))
using (var reader = new StreamReader(stream))
{
    gitVersion = reader.ReadToEnd();
}

Note que a variável gitVersion receberá o conteúdo do último commit.

Espero que tenham gostado do artigo e até a próximo!

Obrigado!

AZ-900 – Azure Fundamentals

Olá pessoal, tudo bem?

Ontem (08/01), tirei a certificação AZ-900 – Azure Fundamentals, e vou contar para vocês aqui como foi todo o processo de estudo até a prova.

O que cai na prova?

Abaixo, vou fazer um resumos dos principais assuntos que são cobrados na prova, lembrando que para essa prova você não precisa saber implementa-los de fato, apenas saber como eles funcionam e suas diferenças.

A prova AZ-900 é divida em quatro tópicos de estudo, sendo eles:

  1. Conceitos de Nuvem
    • Entender a diferença entre IaaS, PaaS e SaaS.
    • Entender a diferença entre nuvem, privada, pública e híbrida.
    • Entender a diferença entre CapEx e OpEx.
    • Entender a diferença entre Elasticidade, Escalabilidade, Disponibilidade, Disaster Recovery e etc.
  2. Serviços do Azure
    • Entender a arquitetura do Azure (Regiões, Zonas de disponibilidade e etc).
    • Entender os principais serviços do Azure (Computação, Storage, Dados, Rede e etc).
    • Entender como funciona o Portal do Azure, Azure Cli, Powershell e Cloud Shell.
    • Entender a utilidade do Azure Advisor.
  3. Segurança, Privacidade e Conformidade
    • Entender a diferença entre Network Security Group (NSG), Firewall, Proteção DDoS.
    • Entender como funciona o Azure Active Directory.
    • Entender para que serve o Azure Key-Vault
    • Entender as metodologias de segurança do Azure (Policies, Locks e etc).
    • Entender as opções de monitoramento e Log (Azure Monitor, Log Analytics e etc).
    • Entender as diferentes normas de conformidade do Azure variando de acordo com cada país.
  4. Precificação e Suporte
    • Entender a diferença entre uma assinatura “Free” e em uma assinatura “normal”.
    • Entender para que serve uma Subscription.
    • Entender a diferença entre os planos de suporte do Azure (Basic, Standart, Professional e etc).
    • Entender o SLA do Azure.

Como estudar para a prova?

Primeiramente sugiro fortemente que caso você já não tenha, crie uma conta no Azure, pois ela será fundamental para o aprendizado.

Feito isso, existe um guia de estudo que a própria Microsoft disponibilizou, contendo os principais tópicos abordados no exame. Caso você já tenha familiaridade com os conceitos de Cloud Computing e com o Azure, esse guia deve ser suficiente para que você passe na prova, entretanto se você ainda não é familiarizado com esse conceitos sugiro complementar seus estudos com as seguintes opções:

Como comprar e aonde fazer a prova?

A prova AZ-900 é um pouco mais barata que as demais provas do Azure, custando hoje $60. Essa prova pode ser adquirida através do site da Microsoft Learning.

Quando estiver comprando você terá a opção de escolher entre fazer a prova em um Testing Center ou na sua casa/escritório, eu escolhi fazer na minha casa mesmo e a experiência foi ótima. Claro que existem regras para se fazer o exame na sua casa e elas devem ser seguidas a risca do contrário você perde o exame. Nesse vídeo feito pela própria Microsoft é retratado de maneira bem fiel como funciona todo o processo.

Últimas dicas

Conforme mencionei no inicio do texto, você não vai implementar nada no Azure, a prova é 100% conceitual, logo a palavra-chave aqui para que você tenha sucesso no dia do exame é: entender as diferenças entre os serviços, entre os modelos e etc. Saber qual serviço é mais adequado para cada situação.

Boa sorte!