Pic-a-daily: Laboratório 6 - Orquestração com fluxos de trabalho

1. Visão geral

Nos laboratórios anteriores, você criou uma versão orientada a eventos do app Pic-a-daily que usava uma função do Cloud acionada pelo Google Cloud Storage para o serviço de análise de imagens, um contêiner do Cloud Run acionado pelo GCS via Pub/Sub para o serviço de miniaturas e o Eventarc para acionar o serviço de coleta de lixo de imagens no Cloud Run. Também havia um serviço de colagem acionado pelo Cloud Scheduler:

d93345bfc235f81e.png

Neste laboratório, você vai criar uma versão orquestrada do app. Em vez de diferentes tipos de eventos fluindo pelo sistema, você vai usar o Workflows para orquestrar e chamar serviços da seguinte maneira:

b763efcbf5589747.png

O que você vai aprender

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • Fluxos de trabalho

2. Configuração e requisitos

Configuração de ambiente autoguiada

  1. Faça login no console do Cloud e crie um novo projeto ou reutilize um existente. Crie uma conta do Gmail ou do Google Workspace, se ainda não tiver uma.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.

  1. Em seguida, será necessário ativar o faturamento no Console do Cloud para usar os recursos do Google Cloud.

A execução deste codelab não será muito cara, se for o caso. Siga todas as instruções na seção "Limpeza", que orienta você sobre como encerrar recursos para não incorrer em cobranças além deste tutorial. Novos usuários do Google Cloud estão qualificados para o programa de US$300 de avaliação sem custos.

Inicie o Cloud Shell

Embora o Google Cloud e o Spanner possam ser operados remotamente do seu laptop, neste codelab usaremos o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.

No Console do GCP, clique no ícone do Cloud Shell na barra de ferramentas localizada no canto superior direito:

bce75f34b2c53987.png

O provisionamento e a conexão com o ambiente levarão apenas alguns instantes para serem concluídos: Quando o processamento for concluído, você verá algo como:

f6ef2b5f13479f3a.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Todo o trabalho neste laboratório pode ser feito apenas com um navegador.

3. Introdução aos fluxos de trabalho

90fcd42d556e310e.jpeg

É possível usar o Workflows para criar fluxos de trabalho sem servidor que vinculam uma série de tarefas sem servidor em uma ordem definida por você. É possível combinar o poder das APIs do Google Cloud, dos produtos sem servidor, como o Cloud Functions e o Cloud Run, e das chamadas às APIs externas para criar aplicativos flexíveis sem servidor.

Como você pode esperar de um orquestrador, o Workflows permite definir o fluxo da sua lógica de negócios em uma linguagem de definição de fluxo de trabalho baseada em YAML/JSON e fornece uma API Workflows Execution e uma interface do Workflows para acionar esses fluxos.

Ele é mais do que um simples orquestrador com estes recursos integrados e configuráveis:

  • Nova tentativa flexível e tratamento de erros entre as etapas para execução confiável.
  • Análise JSON e transmissão de variáveis entre etapas para evitar código de junção.
  • As fórmulas de expressão para decisões permitem execuções de etapas condicionais.
  • Subfluxos de trabalho para fluxos de trabalho modulares e reutilizáveis.
  • O suporte a serviços externos permite a orquestração de serviços além do Google Cloud.
  • Suporte à autenticação para o Google Cloud e serviços externos para execuções seguras de etapas.
  • Conectores para serviços do Google Cloud, como Pub/Sub, Firestore, Tasks e Secret Manager, para facilitar a integração.

Além disso, o Workflows é um produto sem servidor totalmente gerenciado. Não há servidores para configurar ou escalonar, e você só paga pelo que usa.

4. Ativar APIs

Neste laboratório, você vai conectar serviços do Cloud Functions e do Cloud Run com o Workflows. Você também vai usar o App Engine, o Cloud Build, a API Vision e outros serviços.

No Cloud Shell, verifique se todos os serviços necessários estão ativados:

gcloud services enable \
  appengine.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  compute.googleapis.com \
  firestore.googleapis.com \
  run.googleapis.com \
  vision.googleapis.com \
  workflows.googleapis.com \

Depois de algum tempo, a operação será concluída com êxito:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

5. Acessar o código

Se você ainda não fez isso nos laboratórios de programação anteriores, faça o seguinte:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

Você terá a seguinte estrutura de pastas relevante para este laboratório:

frontend
 |
workflows
 |
 ├── functions
 ├── |── trigger-workflow
 ├── |── vision-data-transform
 ├── services
 ├── |── collage
 ├── |── thumbnails
 ├── workflows.yaml

Estas são as pastas relevantes:

  • frontend contém o front-end do App Engine que vamos reutilizar do laboratório 4.
  • O functions contém as funções do Cloud criadas para o fluxo de trabalho.
  • services contém os serviços do Cloud Run modificados para o fluxo de trabalho.
  • workflows.yaml é o arquivo de definição do fluxo de trabalho.

6. Conheça o YAML do Workflows

O arquivo workflows.yaml define o fluxo de trabalho em uma série de etapas. Vamos analisar para entender melhor.

No início do fluxo de trabalho, alguns parâmetros são transmitidos. Eles serão transmitidos por duas funções do Cloud Functions que acionam os fluxos de trabalho. Vamos falar sobre essas funções mais tarde, mas é assim que o Workflows começa:

d44a5e18aa9d4660.png

Em YAML, é possível ver que esses parâmetros são atribuídos a variáveis na etapa init, como os nomes de arquivo e bucket que acionam o evento, e URLs de alguns serviços do Cloud Functions e do Cloud Run que o Workflows vai chamar:

main:
  params: [args]
  steps:
    - init:
        assign:
          - file: ${args.file}
          - bucket: ${args.bucket}
          - gsUri: ${"gs://" + bucket + "/" + file}
          - projectId: ${sys.get_env("GOOGLE_CLOUD_PROJECT_ID")}
          - urls: ${args.urls}

Em seguida, o Workflows verifica o tipo de evento. Há dois tipos de eventos compatíveis: object.finalize (emitido quando um arquivo é salvo no bucket do Cloud Storage) e object.delete (emitido quando um arquivo é excluído). Qualquer outra coisa vai gerar uma exceção de evento não compatível.

dd1f450983655619.png

Esta é a etapa, na definição do fluxo de trabalho YAML, em que verificamos o tipo do evento de armazenamento de arquivos:

    - eventTypeSwitch:
        switch:
            - condition: ${args.eventType == "google.storage.object.finalize"}
              next: imageAnalysisCall
            - condition: ${args.eventType == "google.storage.object.delete"}
              next: pictureGarbageCollectionGCS
    - eventTypeNotSupported:
        raise: ${"eventType " + args.eventType + " is not supported"}
        next: end

Observe como o Workflows oferece suporte a instruções switch e tratamento de exceções, com a instrução switch e as várias condições dela, além da instrução raise para gerar um erro quando o evento não é reconhecido.

Agora, vamos conferir o imageAnalysisCall. Essa é uma série de chamadas dos fluxos de trabalho para chamar a API Vision e analisar a imagem, transformar os dados de resposta da API Vision para classificar os rótulos das coisas reconhecidas na foto, escolher as cores dominantes, verificar se a imagem é segura para exibição e salvar os metadados no Cloud Firestore.

Tudo é feito no Workflows, exceto as funções do Cloud Vision Transform (que vamos implantar mais tarde):

ca2ad16b9cbb436.png

Confira como as etapas aparecem em YAML:

    - imageAnalysisCall:
        call: http.post
        args:
          url: https://vision.googleapis.com/v1/images:annotate
          headers:
            Content-Type: application/json
          auth:
            type: OAuth2
          body:
            requests:
            - image:
                source:
                  gcsImageUri: ${gsUri}
              features:
              - type: LABEL_DETECTION
              - type: SAFE_SEARCH_DETECTION
              - type: IMAGE_PROPERTIES
        result: imageAnalysisResponse
    - transformImageAnalysisData:
        call: http.post
        args:
          url: ${urls.VISION_DATA_TRANSFORM_URL}
          auth:
            type: OIDC
          body: ${imageAnalysisResponse.body}
        result: imageMetadata
    - checkSafety:
        switch:
          - condition: ${imageMetadata.body.safe == true}
            next: storeMetadata
        next: end
    - storeMetadata:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file + "?updateMask.fieldPaths=color&updateMask.fieldPaths=labels&updateMask.fieldPaths=created"}
          auth:
            type: OAuth2
          method: PATCH
          body:
            name: ${"projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
            fields:
              color:
                stringValue: ${imageMetadata.body.color}
              created:
                timestampValue: ${imageMetadata.body.created}
              labels:
                arrayValue:
                  values: ${imageMetadata.body.labels}
        result: storeMetadataResponse

Depois que a imagem é analisada, as próximas duas etapas são criar a miniatura da imagem e uma colagem das imagens mais recentes. Isso é feito implantando dois serviços do Cloud Run e fazendo chamadas para eles nas etapas thumbnailCall e collageCall:

76f9179323c3144.png

Etapas em YAML:

   - thumbnailCall:
        call: http.post
        args:
          url: ${urls.THUMBNAILS_URL}
          auth:
            type: OIDC
          body:
              gcsImageUri: ${gsUri}
        result: thumbnailResponse
    - collageCall:
        call: http.get
        args:
          url: ${urls.COLLAGE_URL}
          auth:
            type: OIDC
        result: collageResponse

Essa ramificação da execução termina retornando códigos de status de cada serviço na etapa finalizeCompleted:

    - finalizeCompleted:
        return:
          imageAnalysis: ${imageAnalysisResponse.code}
          storeMetadata: ${storeMetadataResponse.code}
          thumbnail: ${thumbnailResponse.code}
          collage: ${collageResponse.code}

A outra ramificação da execução ocorre quando um arquivo é excluído do bucket de armazenamento principal, que contém as versões de alta resolução das fotos. Nesta ramificação, queremos excluir a miniatura da imagem no bucket que contém miniaturas e excluir os metadados dela do Firestore. Ambas são feitas com chamadas HTTP dos fluxos de trabalho:

f172379274dcb3c2.png

Etapas em YAML:

    - pictureGarbageCollectionGCS:
        try:
          call: http.request
          args:
            url: ${"https://storage.googleapis.com/storage/v1/b/thumbnails-" + projectId + "/o/" + file}
            auth:
              type: OAuth2
            method: DELETE
          result: gcsDeletionResult
        except:
          as: e
          steps:
              - dummyResultInOutVar:
                  assign:
                      - gcsDeletionResult:
                          code: 200
                          body: "Workaround for empty body response"
    - pictureGarbageCollectionFirestore:
        call: http.request
        args:
          url: ${"https://firestore.googleapis.com/v1/projects/" + projectId + "/databases/(default)/documents/pictures/" + file}
          auth:
            type: OAuth2
          method: DELETE
        result: firestoreDeletionResult

A ramificação de exclusão termina retornando resultados / códigos de cada etapa:

    - deleteCompleted:
        return:
          gcsDeletion: ${gcsDeletionResult}
          firestoreDeletion: ${firestoreDeletionResult.code}

Nas etapas a seguir, vamos criar todas as dependências externas dos fluxos de trabalho: buckets, funções do Cloud, serviços do Cloud Run e banco de dados do Firestore.

7. Criar os buckets

Você precisa de dois buckets para imagens: um para salvar as imagens originais de alta resolução e outro para salvar as miniaturas.

Crie um bucket regional público (neste caso, na Europa) com acesso uniforme para que os usuários façam upload de fotos usando a ferramenta gsutil:

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_PICTURES}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_PICTURES}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_PICTURES}

Crie outro bucket público regional para miniaturas:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
gsutil mb -l EU gs://${BUCKET_THUMBNAILS}
gsutil uniformbucketlevelaccess set on gs://${BUCKET_THUMBNAILS}
gsutil iam ch allUsers:objectViewer gs://${BUCKET_THUMBNAILS}

Para verificar se os buckets foram criados e estão públicos, acesse a seção do Cloud Storage no Console do Cloud:

15063936edd72f06.png

8. Transformação de dados do Vision (função do Cloud)

O arquivo Workflows.yaml começa com as etapas init, eventTypeSwitch e eventTypeNotSupported. Eles garantem que os eventos dos agrupamentos sejam encaminhados para as etapas corretas.

Para o evento object.finalize, a etapa imageAnalysisCall faz uma chamada à API Vision para extrair os metadados da imagem criada. Todas essas etapas são realizadas nos fluxos de trabalho:

daaed43a22d2b0d3.png

Em seguida, precisamos transformar os dados retornados da API Vision antes de salvá-los no Firestore. Mais especificamente, precisamos:

  • Liste os rótulos retornados para a imagem.
  • Recupera a cor dominante da imagem.
  • Determine se a imagem é segura.

Isso é feito em código em uma função do Cloud, e o Workflows simplesmente chama essa função:

5e120e70c67779cd.png

Conhecer o código

A função do Cloud é chamada vision-data-transform. Confira o código completo em index.js. Como você pode ver, o único propósito dessa função é fazer uma transformação de JSON para JSON, para armazenar os metadados da imagem de maneira conveniente no Firestore.

Implantar no Cloud Functions

Navegue até a pasta:

cd workflows/functions/vision-data-transform/nodejs

Defina a região de sua escolha:

export REGION=europe-west1
gcloud config set functions/region ${REGION}

Implante a função com:

export SERVICE_NAME=vision-data-transform
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=vision_data_transform \
  --trigger-http \
  --allow-unauthenticated

Depois que a função for implantada, a etapa transformImageAnalysisData do Workflows poderá chamar essa função para fazer a transformação de dados da API Vision.

9. Preparar o banco de dados

Em seguida, nos fluxos de trabalho, verifique a segurança da imagem com base nos dados dela e armazene as informações sobre a foto retornada pela API Vision no banco de dados Cloud Firestore, um banco de dados de documentos NoSQL rápido, totalmente gerenciado, sem servidor e nativo da nuvem:

6624c616bc7cd97f.png

Ambos são feitos no Workflows, mas é necessário criar o banco de dados do Firestore para que o armazenamento de metadados funcione.

Primeiro, crie um app do App Engine na região em que você quer o banco de dados do Firestore (um requisito do Firestore):

export REGION_FIRESTORE=europe-west2
gcloud app create --region=${REGION_FIRESTORE}

Em seguida, crie o banco de dados do Firestore na mesma região:

gcloud firestore databases create --region=${REGION_FIRESTORE}

Os documentos serão criados de forma programática na nossa coleção e vão conter quatro campos:

  • name (string): o nome do arquivo da imagem enviada, que também é a chave do documento.
  • labels (matriz de strings): os rótulos dos itens reconhecidos pela API Vision.
  • color (string): o código hexadecimal da cor dominante (por exemplo, #ab12ef)
  • created (data): o carimbo de data/hora de quando os metadados da imagem foram armazenados.
  • thumbnail (booleano): um campo opcional que estará presente e será verdadeiro se uma imagem em miniatura tiver sido gerada para essa foto.

Como vamos pesquisar no Firestore para encontrar fotos com miniaturas disponíveis e classificar pela data de criação, precisamos criar um índice de pesquisa. É possível criar o índice com o seguinte comando:

gcloud firestore indexes composite create --collection-group=pictures \
  --field-config field-path=thumbnail,order=descending \
  --field-config field-path=created,order=descending

A criação do índice pode levar até 10 minutos.

Depois que o índice for criado, ele vai aparecer no console do Cloud:

43af1f5103bf423.png

A etapa storeMetadata do Workflows agora pode armazenar os metadados da imagem no Firestore.

10. Serviço de miniatura (Cloud Run)

Em seguida, crie uma miniatura de uma imagem. Isso é feito no código em um serviço do Cloud Run, e o Workflows chama esse serviço na etapa thumbnailCall:

84d987647f082b53.png

Conhecer o código

O serviço do Cloud Run é chamado de thumbnails. Confira o código completo em index.js.

Criar e publicar a imagem de contêiner

O Cloud Run executa contêineres, mas primeiro é necessário criar a imagem do contêiner (definida em Dockerfile). O Google Cloud Build pode ser usado para criar imagens de contêiner e hospedá-las no Container Registry.

Navegue até a pasta:

cd workflows/services/thumbnails/nodejs

Crie:

export SERVICE_SRC=thumbnails
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

Depois de um ou dois minutos, a build será concluída, e o contêiner será implantado no Google Container Registry.

Implantar no Cloud Run

Defina algumas variáveis e configurações necessárias:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

Implante com o seguinte comando:

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

Depois que o serviço for implantado, a etapa Workflows thumbnailCall poderá chamar esse serviço.

11. Serviço de colagem (Cloud Run)

Em seguida, crie uma colagem com as imagens mais recentes. Isso é feito no código em um serviço do Cloud Run, e o Workflows chama esse serviço na etapa collageCall:

591e36149066e1ba.png

Conhecer o código

O serviço do Cloud Run é chamado de collage. Confira o código completo em index.js.

Criar e publicar a imagem de contêiner

O Cloud Run executa contêineres, mas primeiro é necessário criar a imagem do contêiner (definida em Dockerfile). O Google Cloud Build pode ser usado para criar imagens de contêiner e hospedá-las no Container Registry.

Navegue até a pasta:

cd services/collage/nodejs

Crie:

export SERVICE_SRC=collage
export SERVICE_NAME=${SERVICE_SRC}-service
gcloud builds submit \
  . \
  --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}

Depois de um ou dois minutos, a build será concluída, e o contêiner será implantado no Google Container Registry.

Implantar no Cloud Run

Defina algumas variáveis e configurações necessárias:

export BUCKET_THUMBNAILS=thumbnails-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
gcloud config set run/region ${REGION}
gcloud config set run/platform managed

Implantar:

gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --no-allow-unauthenticated \
    --memory=1Gi \
    --update-env-vars BUCKET_THUMBNAILS=${BUCKET_THUMBNAILS}

Depois que o serviço for implantado, verifique se os dois serviços estão em execução na seção do Cloud Run do console do Cloud. A etapa collageCall dos fluxos de trabalho poderá chamar esse serviço:

3ae9873f4cbbf423.png

12. Implantação de fluxos de trabalho

Implantamos todas as dependências externas do Workflows. Todas as etapas restantes (finalizeCompleted, pictureGarbageCollectionGCS, pictureGarbageCollectionFirestore, deleteCompleted) podem ser concluídas pelos próprios fluxos de trabalho.

É hora de implantar os fluxos de trabalho.

Navegue até a pasta que contém o arquivo workflows.yaml e implante-o com:

export WORKFLOW_REGION=europe-west4
export WORKFLOW_NAME=picadaily-workflows
gcloud workflows deploy ${WORKFLOW_NAME} \
  --source=workflows.yaml \
  --location=${WORKFLOW_REGION}

Em alguns segundos, o fluxo de trabalho será implantado e poderá ser visto na seção "Fluxos de trabalho" do Console do Cloud:

94a720149e5df9c5.png

Clique no fluxo de trabalho e edite-o, se quiser. Durante a edição, você recebe uma representação visual agradável do fluxo de trabalho:

55441b158f6027f3.png

Também é possível executar o fluxo de trabalho manualmente no console do Cloud com os parâmetros corretos. Em vez disso, vamos executá-lo automaticamente em resposta a eventos do Cloud Storage na próxima etapa.

13. Gatilhos do Workflows (Cloud Functions)

O fluxo de trabalho é implantado e fica pronto. Agora, precisamos acionar os fluxos de trabalho quando um arquivo é criado ou excluído em um bucket do Cloud Storage. São eventos storage.object.finalize e storage.object.delete, respectivamente.

Os fluxos de trabalho têm APIs e bibliotecas de cliente para criar, gerenciar e executar fluxos de trabalho que você pode usar. Nesse caso, você vai usar a API Execution do Workflows e, mais especificamente, a biblioteca de cliente Node.js para acionar o fluxo de trabalho.

Você vai acionar o Workflows com uma função do Cloud que detecta eventos do Cloud Storage. Como uma função do Cloud só pode detectar um tipo de evento, você vai implantar duas funções do Cloud para detectar eventos de criação e exclusão:

c4d79646de729e4.png

Conhecer o código

A função do Cloud é chamada trigger-workflow. Confira o código completo em index.js.

Implantar no Cloud Functions

Navegue até a pasta:

cd workflows/functions/trigger-workflow/nodejs

Defina algumas variáveis e configurações necessárias:

export BUCKET_PICTURES=uploaded-pictures-${GOOGLE_CLOUD_PROJECT}
export REGION=europe-west1
export WORKFLOW_NAME=picadaily-workflows
export WORKFLOW_REGION=europe-west4
export COLLAGE_URL=$(gcloud run services describe collage-service --format 'value(status.url)')
export THUMBNAILS_URL=$(gcloud run services describe thumbnails-service --format 'value(status.url)')
export VISION_DATA_TRANSFORM_URL=$(gcloud functions describe vision-data-transform --format 'value(httpsTrigger.url)')
gcloud config set functions/region ${REGION}

Implante a função que responde aos eventos de finalização:

export SERVICE_NAME=trigger-workflow-on-finalize
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.finalize \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

Implante a segunda função que responde a eventos de exclusão:

export SERVICE_NAME=trigger-workflow-on-delete
gcloud functions deploy ${SERVICE_NAME} \
  --source=. \
  --runtime nodejs10 \
  --entry-point=trigger_workflow \
  --trigger-resource=${BUCKET_PICTURES} \
  --trigger-event=google.storage.object.delete \
  --allow-unauthenticated \
  --set-env-vars GOOGLE_CLOUD_PROJECT=${GOOGLE_CLOUD_PROJECT},WORKFLOW_REGION=${WORKFLOW_REGION},WORKFLOW_NAME=${WORKFLOW_NAME},THUMBNAILS_URL=${THUMBNAILS_URL},COLLAGE_URL=${COLLAGE_URL},VISION_DATA_TRANSFORM_URL=${VISION_DATA_TRANSFORM_URL}

Quando a implantação for concluída, você poderá ver as duas funções no Console do Cloud:

7d60c8b7851f39f5.png

14. Front-end (App Engine)

Nesta etapa, você cria um front-end da Web no Google App Engine usando o Pic-a-daily: laboratório 4 — Criar um front-end da Web, que permite aos usuários fazer upload de imagens do aplicativo da Web e navegar pelas imagens enviadas e pelas miniaturas delas.

223fb2281614d053.png

Saiba mais sobre o App Engine e leia a descrição do código em Pic-a-daily: laboratório 4 — Criar um front-end da Web.

Conhecer o código

O app do App Engine se chama frontend. Confira o código completo em index.js.

Faça a implantação no App Engine

Navegue até a pasta:

cd frontend

Defina a região de sua escolha e substitua o GOOGLE_CLOUD_PROJECT em app.yaml pelo ID do projeto real:

export REGION=europe-west1
gcloud config set compute/region ${REGION}
sed -i -e "s/GOOGLE_CLOUD_PROJECT/${GOOGLE_CLOUD_PROJECT}/" app.yaml

Implantar:

gcloud app deploy app.yaml -q

Depois de um ou dois minutos, você vai receber uma mensagem informando que o aplicativo está veiculando tráfego:

Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 8 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://GOOGLE_CLOUD_PROJECT.appspot.com]
You can stream logs from the command line by running:
  $ gcloud app logs tail -s default
To view your application in the web browser run:
  $ gcloud app browse

Você também pode acessar a seção do App Engine no console do Cloud para ver se o app foi implantado e conhecer recursos do App Engine, como controle de versões e divisão de tráfego:

f4bd5f4de028bd83.png

15. Testar os Workflows

Para testar, acesse o URL padrão do App Engine para o app https://<YOUR_PROJECT_ID>.appspot.com/ e confira se a interface do usuário de front-end está funcionando.

1649ac060441099.png

Faça o upload de uma imagem. Isso vai acionar os fluxos de trabalho, e você poderá ver a execução do fluxo de trabalho no estado Active no Console do Cloud:

b5a2a3d7a2bc094.png

Quando o Workflows terminar, clique no ID de execução e confira a saída de diferentes serviços:

8959df5098c21548.png

Faça upload de mais três fotos. Você também vai ver a miniatura e a colagem das imagens nos buckets do Cloud Storage e o front-end do App Engine atualizado:

d90c786ff664a5dc.png

16. Limpeza (opcional)

Se você não pretende manter o app, limpe os recursos para economizar custos e ser um bom cidadão da nuvem excluindo todo o projeto:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

17. Parabéns!

Você criou uma versão orquestrada do app usando o Workflows para orquestrar e chamar serviços.

O que vimos

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • Fluxos de trabalho