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 usou 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 coletor 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 teste sem custo financeiro.

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 ao Workflows

90fcd42d556e310e.jpeg

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

Como você espera de um orquestrador, o Workflows permite que você defina 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 a interface do Workflows para acionar esses fluxos.

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

  • Flexibilidade na nova tentativa e tratamento de erros entre as etapas para uma execução confiável das etapas.
  • Análise JSON e passagem de variáveis entre as etapas para evitar o código agrupador.
  • 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 outros serviços além do Google Cloud.
  • Suporte de autenticação para o Google Cloud e serviços externos para execuções de etapas seguras.
  • Conectores a 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 totalmente gerenciado e sem servidor. Você não precisa configurar nem escalonar servidores, e você paga apenas pelo que usa.

4. Ativar APIs

Neste laboratório, você conectará os 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 \

Após algum tempo, a operação deverá ser concluída com êxito:

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

5. Acessar o código

Acesse o código, caso ainda não tenha feito os codelabs anteriores:

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

Você terá a seguinte estrutura de pastas que é 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 será reutilizado do Laboratório 4.
  • 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. analise o YAML do Workflows

O workflows.yaml define o fluxo de trabalho em uma série de etapas. Vamos passar por ela para entender melhor.

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

d44a5e18aa9d4660.png

No 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 evento compatíveis: object.finalize (emitido quando um arquivo é salvo em um 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 do YAML, em que verificamos o tipo de 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 processamento de exceções, com a instrução switch e suas várias condições e a instrução de aumento para gerar um erro quando o evento não é reconhecido.

A seguir, vamos dar uma olhada no imageAnalysisCall. Essa é uma série de chamadas do Workflows para chamar a API Vision para analisar a imagem, transformar os dados de resposta da API Vision para classificar os rótulos dos itens reconhecidos na imagem, escolher as cores dominantes, verificar se a imagem é segura para exibição e salvar os metadados no Cloud Firestore.

Observe que tudo é feito no Workflows, exceto o Vision Transform Cloud Functions (que vamos implantar mais tarde):

ca2ad16b9cbb436.png

Esta é a aparência das etapas no 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. Para isso, implante dois serviços do Cloud Run e faça chamadas para eles a partir das 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 com o retorno de 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 é quando um arquivo é excluído do bucket de armazenamento principal, contendo as versões de alta resolução das imagens. Nesta ramificação, queremos excluir a miniatura da imagem, no bucket que contém miniaturas, e excluir os metadados do Firestore. Ambos são feitos com chamadas HTTP do Workflows:

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 com o retorno de resultados / códigos de cada etapa:

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

Nas etapas a seguir, vamos criar todas as dependências externas do Workflows: buckets, Cloud Functions, serviços do Cloud Run e banco de dados do Firestore.

7. Criar os buckets

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

Crie um bucket regional público (neste caso, na Europa) com acesso uniforme para os usuários fazerem 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 regional público 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 são públicos, acesse a seção "Cloud Storage" do 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. Elas garantem que os eventos provenientes dos buckets sejam roteados 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 no Workflows:

daaed43a22d2b0d3.png

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

  • Liste os rótulos retornados para a imagem.
  • Recupere a cor dominante da imagem.
  • Determinar se a imagem está segura.

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

5e120e70c67779cd.png

Conhecer o código

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

Como fazer a implantação 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

A próxima etapa do Workflows é verificar a segurança da imagem nos dados da imagem e, em seguida, armazenar as informações sobre a imagem retornada pela API Vision no banco de dados do Cloud Firestore, um banco de dados de documentos NoSQL rápido, totalmente gerenciado, sem servidor e nativo da nuvem:

6624c616bc7cd97f.png

Essas duas ações são feitas no Workflows, mas você precisa criar o banco de dados do Firestore para que o armazenamento de metadados funcione.

Primeiro, crie um aplicativo do App Engine na região em que você quer armazenar 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 programaticamente na nossa coleção e conterão 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 de cor hexadecimal da cor dominante (ou seja, #ab12ef).
  • created (data): o carimbo de data/hora de quando os metadados da imagem foram armazenados
  • miniatura (booleano): um campo opcional que vai estar presente e ser verdadeiro se uma imagem em miniatura tiver sido gerada para a imagem

Como vamos pesquisar no Firestore para encontrar imagens que tenham miniaturas disponíveis e classificar ao longo da data de criação, precisaremos criar um índice de pesquisa. Você pode 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, você poderá vê-lo no Console do Cloud:

43af1f5103bf423.png

A etapa storeMetadata dos fluxos de trabalho poderá armazenar os metadados da imagem no Firestore agora.

10. Serviço de miniatura (Cloud Run)

A próxima etapa da cadeia é criar uma miniatura de imagem. Isso é feito no código de 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 se chama thumbnails. Confira o código completo em index.js.

Criar e publicar a imagem do contêiner

O Cloud Run executa contêineres, mas primeiro você precisa criar a imagem do contêiner (definida em Dockerfile). O Google Cloud Build pode ser usado para criar imagens de contêiner e hospedá-lo no Google 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}

Após um ou dois minutos, a versão será bem-sucedida 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 thumbnailCall do Workflows poderá chamar esse serviço.

11. Serviço de colagem (Cloud Run)

A próxima etapa é criar uma colagem com as imagens mais recentes. Isso é feito no código de 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 se chama collage. Confira o código completo em index.js.

Criar e publicar a imagem do contêiner

O Cloud Run executa contêineres, mas primeiro você precisa criar a imagem do contêiner (definida em Dockerfile). O Google Cloud Build pode ser usado para criar imagens de contêiner e hospedá-lo no Google 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}

Após um ou dois minutos, a versão será bem-sucedida 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

Implantação:

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 Cloud Run do console do Cloud e a etapa collageCall dos fluxos de trabalho poderá chamar este 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 pelo próprio Workflows.

Chegou a hora de implantar o Workflows.

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. Ele vai aparecer na seção "Fluxos de trabalho" do console do Cloud:

94a720149e5df9c5.png

É possível clicar no fluxo de trabalho e editá-lo, se você quiser. Durante a edição, você consegue uma boa representação visual do fluxo de trabalho:

55441b158f6027f3.png

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

13. Gatilhos de fluxos de trabalho (Cloud Functions)

O fluxo de trabalho está implantado e pronto. Agora, precisamos acionar o Workflows quando um arquivo for 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. Neste caso, você vai usar a API Workflows Execution e, mais especificamente, a biblioteca de cliente Node.js para acionar o fluxo de trabalho.

Você acionará os fluxos de trabalho da 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 de trigger-workflow. Confira o código completo em index.js.

Como fazer a implantação 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 respondendo a eventos "finalizar":

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 respondendo 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 estiver concluída, as duas funções vão aparecer no console do Cloud:

7d60c8b7851f39f5.png

14. Front-end (App Engine)

Nesta etapa, você vai criar um front-end da Web no Google App Engine em Pic-a-daily: Lab 4: Create a Web frontend que permitirá que os usuários façam upload de imagens do aplicativo da Web, além de navegar pelas imagens enviadas e suas miniaturas.

223fb2281614d053.png

Saiba mais sobre o App Engine e leia a descrição do código em Pic-a-daily: Lab 4: Create a Web frontend.

Conhecer o código

O nome do aplicativo do App Engine é 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 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

Implantação:

gcloud app deploy app.yaml -q

Após um ou dois minutos, você verá 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 "App Engine" do console do Cloud para ver se o app foi implantado e conhecer os recursos do App Engine, como controle de versões e divisão de tráfego:

f4bd5f4de028bd83.png

15. Teste os fluxos de trabalho

Para testar, acesse o URL padrão do App Engine para o aplicativo (https://<YOUR_PROJECT_ID>.appspot.com/) e você verá a interface de front-end funcionando.

1649ac060441099.png

Faça upload de uma imagem. Isso acionará o fluxo de trabalho, e você poderá conferir a execução dele no estado Active no console do Cloud:

b5a2a3d7a2bc094.png

Quando os fluxos de trabalho forem concluídos, será possível clicar no ID da execução e conferir a saída de diferentes serviços:

8959df5098c21548.png

Carregue mais 3 fotos. A miniatura e a colagem das imagens nos buckets do Cloud Storage e no front-end do App Engine também vão aparecer atualizadas:

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