Pic-a-daily: Lab 6 - Orchestrazione con Workflows

1. Panoramica

Nei lab precedenti, hai creato una versione basata su eventi dell'app Pic-a-daily che utilizzava una funzione Cloud Functions attivata da Google Cloud Storage per il servizio Image Analysis, un GCS ha attivato il container Cloud Run tramite Pub/Sub per il servizio Miniatura ed Eventarc per attivare il servizio Image Garbage Collector su Cloud Run. C'era anche un servizio Collage attivato da Cloud Scheduler:

d93345bfc235f81e.png

In questo lab creerai una versione orchestrata dell'app. Invece di diversi tipi di eventi che fluiscono nel sistema, utilizzerai Workflows per orchestrare e chiamare i servizi nel seguente modo:

b763efcbf5589747.png

Cosa imparerai a fare

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • Workflows

2. Configurazione e requisiti

Configurazione dell'ambiente da seguire in modo autonomo

  1. Accedi alla console Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Ricorda l'ID progetto, un nome univoco in tutti i progetti Google Cloud (il nome precedente è già stato utilizzato e non funzionerà correttamente). Verrà indicato più avanti in questo codelab come PROJECT_ID.

  1. Successivamente, dovrai abilitare la fatturazione in Cloud Console per utilizzare le risorse Google Cloud.

Eseguire questo codelab non dovrebbe costare molto. Assicurati di seguire le istruzioni nella sezione "Pulizia" in cui viene spiegato come arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

Avvia Cloud Shell

Anche se Google Cloud può essere utilizzato da remoto dal tuo laptop, in questo codelab utilizzerai Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Dalla console di Google Cloud, fai clic sull'icona di Cloud Shell nella barra degli strumenti in alto a destra:

bce75f34b2c53987.png

Dovrebbe richiedere solo qualche istante per eseguire il provisioning e connettersi all'ambiente. Al termine, dovresti vedere una schermata simile al seguente:

f6ef2b5f13479f3a.png

Questa macchina virtuale viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita su Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Tutto il lavoro in questo lab può essere svolto semplicemente con un browser.

3. Introduzione a Workflows

90fcd42d556e310e.jpeg

Puoi utilizzare Workflows per creare flussi di lavoro serverless che collegano una serie di attività serverless in un ordine definito da te. Puoi combinare la potenza delle API di Google Cloud, dei prodotti serverless come Cloud Functions e Cloud Run e delle chiamate ad API esterne per creare applicazioni serverless flessibili.

Come ci si potrebbe aspettare da un agente di orchestrazione, Workflows consente di definire il flusso della logica di business in un linguaggio di definizione del flusso di lavoro basato su YAML/JSON e fornisce un'API Workflows Execution e una UI di Workflows per attivare questi flussi.

È molto più di un semplice strumento di orchestrazione, con le seguenti funzionalità integrate e configurabili:

  • Gestione flessibile dei nuovi tentativi e degli errori tra i passaggi, per un'esecuzione affidabile dei passaggi.
  • Analisi JSON e passaggio di variabili tra i passaggi per evitare il glue-code.
  • Le formule di espressione per le decisioni consentono l'esecuzione di passaggi condizionali.
  • Flussi di lavoro secondari per flussi di lavoro modulari e riutilizzabili.
  • Il supporto di servizi esterni consente l'orchestrazione di servizi oltre Google Cloud.
  • Supporto dell'autenticazione per Google Cloud e servizi esterni per l'esecuzione di passaggi sicuri.
  • Connettori ai servizi Google Cloud come Pub/Sub, Firestore, Tasks e Secret Manager per un'integrazione più semplice.

Per non parlare del fatto che Workflows è un prodotto serverless completamente gestito. Nessun server da configurare o scalare e paghi solo per quello che utilizzi.

4. Abilita API

In questo lab collegherai i servizi Cloud Functions e Cloud Run a Workflows. Utilizzerai anche App Engine, Cloud Build, API Vision e altri servizi.

In Cloud Shell, assicurati che tutti i servizi necessari siano abilitati:

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 \

Dopo un po' di tempo, l'operazione dovrebbe essere completata correttamente:

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

5. Ottieni il codice

Ottieni il codice, se non l'hai già fatto nei codelab precedenti:

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

La struttura di cartelle che userai per questo lab sarà la seguente:

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

Le cartelle pertinenti:

  • frontend contiene il frontend di App Engine che riutilizzeremo dal Lab 4.
  • functions contiene le funzioni Cloud Functions create per il flusso di lavoro.
  • services contiene i servizi Cloud Run modificati per il flusso di lavoro.
  • workflows.yaml è il file di definizione del flusso di lavoro.

6. Esplora il file YAML di Workflows

workflows.yaml definisce il flusso di lavoro in una serie di passaggi. Esaminiamolo per capire meglio.

All'inizio del flusso di lavoro, alcuni parametri vengono passati. Verranno passate da due funzioni Cloud Functions che attivano Workflows. Parleremo di queste funzioni più avanti, ma ecco come viene avviato Workflows:

d44a5e18aa9d4660.png

In YAML, puoi vedere che questi parametri sono assegnati a variabili nel passaggio init, ad esempio i nomi di file e bucket che attivano l'evento e gli URL di alcuni servizi Cloud Functions e Cloud Run chiamati da Workflows:

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}

Quindi, Workflows controlla il tipo di evento. Sono supportati due tipi di eventi: object.finalize (emesso quando un file viene salvato nel bucket Cloud Storage) e object.delete (emesso quando un file viene eliminato). Qualsiasi altra impostazione genererà un'eccezione evento non supportato.

dd1f450983655619.png

Questo è il passaggio, nella definizione del flusso di lavoro YAML, in cui controlliamo il tipo di evento di archiviazione file:

    - 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

Nota come Workflows supporta le istruzioni di switch e la gestione delle eccezioni, con l'istruzione switch e le sue varie condizioni, e l'istruzione lift per generare un errore quando l'evento non viene riconosciuto.

Diamo un'occhiata a imageAnalysisCall. Si tratta di una serie di chiamate da Workflows per chiamare l'API Vision per analizzarla, trasformare i dati di risposta dell'API Vision per ordinare le etichette degli elementi riconosciuti nell'immagine, scegliere i colori predominanti, verificare se l'immagine è sicura da visualizzare e quindi salvare i metadati in Cloud Firestore.

Tieni presente che tutte le operazioni vengono eseguite in Workflows, ad eccezione delle funzioni Cloud Functions Vision Transform (di cui eseguiremo il deployment in seguito):

ca2ad16b9cbb436.png

Ecco come appaiono i passaggi in 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

Una volta analizzata l'immagine, i due passaggi successivi consistono nel creare la miniatura dell'immagine e un collage delle immagini più recenti. Per farlo, esegui il deployment di due servizi Cloud Run ed effettua chiamate a questi due servizi da thumbnailCall e collageCall passaggi:

76f9179323c3144.png

Passaggi in 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

Questo ramo dell'esecuzione termina restituendo i codici di stato da ciascun servizio nel passaggio finalizeCompleted:

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

L'altro ramo dell'esecuzione è l'eliminazione di un file dal bucket di archiviazione principale che contiene le versioni ad alta risoluzione delle immagini. In questo ramo, vogliamo eliminare la miniatura dell'immagine nel bucket contenente le miniature ed eliminare i relativi metadati da Firestore. Entrambe queste operazioni vengono eseguite con chiamate HTTP da Workflows:

f172379274dcb3c2.png

Passaggi in 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

Il ramo di eliminazione termina restituendo risultati / codici in ogni passaggio:

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

Nei passaggi seguenti, creeremo tutte le dipendenze esterne di Workflows: bucket, Cloud Functions, servizi Cloud Run e database Firestore.

7. crea i bucket

Sono necessari due bucket per le immagini: uno per salvare le immagini originali ad alta risoluzione e l'altro per salvare le miniature delle immagini.

Crea un bucket pubblico regionale (in questo caso in Europa) con accesso uniforme in cui gli utenti possano caricare le immagini utilizzando lo strumento 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}

Crea un altro bucket regionale pubblico per le miniature:

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}

Puoi verificare che i bucket siano creati e pubblici visitando la sezione Cloud Storage della console Cloud:

15063936edd72f06.png

8. Vision Data Transform (funzione Cloud Functions)

Workflows.yaml inizia con init, eventTypeSwitch, eventTypeNotSupported passaggi. Queste assicurano che gli eventi provenienti dai bucket vengano indirizzati ai passaggi corretti.

Per l'evento object.finalize, il passaggio imageAnalysisCall effettua una chiamata all'API Vision per estrarre i metadati dell'immagine creata. Tutti i passaggi seguenti vengono eseguiti all'interno di Workflows:

daaed43a22d2b0d3.png

Poi dobbiamo trasformare i dati restituiti dall'API Vision prima di poterli salvare in Firestore. Nello specifico, dobbiamo:

  • Elenca le etichette restituite per l'immagine.
  • Recupera il colore dominante dell'immagine.
  • Determina se l'immagine è sicura.

Questa operazione viene eseguita nel codice di una funzione Cloud Functions e Workflows chiama semplicemente questa funzione:

5e120e70c67779cd.png

Esplora il codice

La funzione Cloud Functions è denominata vision-data-transform. Puoi controllare il codice completo in index.js. Come puoi vedere, l'unico scopo di questa funzione è eseguire una trasformazione da JSON a JSON, in modo da archiviare comodamente i metadati dell'immagine in Firestore.

Eseguire il deployment in Cloud Functions

Vai alla cartella:

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

Imposta l'area che preferisci:

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

Esegui il deployment della funzione con:

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

Una volta eseguito il deployment della funzione, il passaggio transformImageAnalysisData di Workflows potrà chiamare questa funzione per eseguire la trasformazione dei dati dell'API Vision.

9. prepara il database

Il passaggio successivo di Workflows consiste nel verificare la sicurezza dell'immagine rispetto ai dati dell'immagine, quindi archiviare le informazioni sull'immagine restituita dall'API Vision nel database Cloud Firestore, un database di documenti NoSQL cloud-native, serverless, veloce e completamente gestito:

6624c616bc7cd97f.png

Entrambe queste operazioni vengono eseguite in Workflows, ma è necessario creare il database Firestore affinché l'archiviazione dei metadati funzioni.

Innanzitutto, crea un'app App Engine nella regione in cui vuoi il database Firestore (requisito per Firestore):

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

Quindi, crea il database Firestore nella stessa regione:

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

I documenti verranno creati in modo programmatico nella nostra raccolta e conterranno quattro campi:

  • name (stringa): il nome file dell'immagine caricata, che è anche la chiave del documento
  • labels (array di stringhe): le etichette degli elementi riconosciuti dall'API Vision
  • color (stringa): il codice colore esadecimale del colore dominante (ad es. #ab12ef)
  • creato (data): il timestamp della data di archiviazione dei metadati di questa immagine
  • thumbnail (booleano): un campo facoltativo che sarà presente e che sarà true se è stata generata un'immagine in miniatura per questa immagine

Dato che cercheremo in Firestore per trovare immagini con miniature disponibili, ordinando i contenuti in base alla data di creazione, dovremo creare un indice di ricerca. Puoi creare l'indice con il seguente comando:

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

Tieni presente che la creazione dell'indice può richiedere fino a 10 minuti circa.

Una volta creato l'indice, puoi visualizzarlo nella console Cloud:

43af1f5103bf423.png

Il passaggio storeMetadata di Workflows ora sarà in grado di archiviare i metadati dell'immagine in Firestore.

10. Servizio miniature (Cloud Run)

Il passo successivo nella catena è creare la miniatura di un'immagine. Questa operazione viene eseguita nel codice di un servizio Cloud Run e Workflows chiama questo servizio nel passaggio thumbnailCall:

84d987647f082b53.png

Esplora il codice

Il servizio Cloud Run è denominato thumbnails. Puoi controllare il codice completo in index.js.

Crea e pubblica l'immagine container

Cloud Run esegue i container, ma prima devi creare l'immagine container (definita in Dockerfile). Google Cloud Build può essere utilizzato per creare immagini container e quindi ospitare in Google Container Registry.

Vai alla cartella:

cd workflows/services/thumbnails/nodejs

Build:

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

Dopo un paio di minuti, la build dovrebbe riuscire e verrà eseguito il deployment del container in Google Container Registry.

Eseguire il deployment in Cloud Run

Imposta alcune variabili e configurazioni necessarie:

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

Esegui il deployment con il seguente 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}

Una volta eseguito il deployment del servizio, il passaggio thumbnailCall di Workflows potrà chiamare questo servizio.

11. Servizio collage (Cloud Run)

Il passaggio successivo della catena consiste nel creare un collage con le immagini più recenti. Questa operazione viene eseguita nel codice di un servizio Cloud Run e Workflows chiama questo servizio nel passaggio collageCall:

591e36149066e1ba.png

Esplora il codice

Il servizio Cloud Run è denominato collage. Puoi controllare il codice completo in index.js.

Crea e pubblica l'immagine container

Cloud Run esegue i container, ma prima devi creare l'immagine container (definita in Dockerfile). Google Cloud Build può essere utilizzato per creare immagini container e quindi ospitare in Google Container Registry.

Vai alla cartella:

cd services/collage/nodejs

Build:

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

Dopo un paio di minuti, la build dovrebbe riuscire e verrà eseguito il deployment del container in Google Container Registry.

Eseguire il deployment in Cloud Run

Imposta alcune variabili e configurazioni necessarie:

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

Schiera:

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}

Una volta eseguito il deployment del servizio, puoi verificare che entrambi i servizi siano in esecuzione nella sezione Cloud Run della console Cloud e che il passaggio collageCall di Workflows possa chiamare questo servizio:

3ae9873f4cbbf423.png

12. Deployment di Workflows

Abbiamo eseguito il deployment di tutte le dipendenze esterne di Workflows. Tutti i passaggi rimanenti (finalizeCompleted, pictureGarbageCollectionGCS, pictureGarbageCollectionFirestore, deleteCompleted) possono essere completati da Workflows.

È il momento di eseguire il deployment di Workflows.

Vai alla cartella che contiene il file workflows.yaml ed eseguine il deployment con:

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

In pochi secondi, il deployment del flusso di lavoro dovrebbe avvenire, e puoi vederlo nella sezione Flussi di lavoro di Cloud Console:

94a720149e5df9c5.png

Puoi fare clic sul flusso di lavoro e modificarlo, se vuoi. Durante l'editing, ottieni una bella rappresentazione visiva del flusso di lavoro:

55441b158f6027f3.png

Puoi anche eseguire il flusso di lavoro dalla console Cloud manualmente con i parametri giusti. Lo eseguiremo automaticamente in risposta agli eventi di Cloud Storage nel passaggio successivo.

13. Trigger di Workflows (Cloud Functions)

Il deployment del flusso di lavoro è stato eseguito ed è pronto. Ora dobbiamo attivare Workflows quando un file viene creato o eliminato in un bucket Cloud Storage. Si tratta, rispettivamente, di storage.object.finalize e storage.object.delete.

Workflows contiene API e librerie client per creare, gestire ed eseguire flussi di lavoro che puoi utilizzare. In questo caso, utilizzerai l'API Workflows Execution e, in particolare, la sua libreria client Node.js per attivare il flusso di lavoro.

Attiverai i flussi di lavoro dalla funzione Cloud Functions in ascolto degli eventi Cloud Storage. Poiché una funzione Cloud Functions può rimanere in ascolto di un solo tipo di evento, eseguirai il deployment di due funzioni Cloud Functions per ascoltare gli eventi di creazione ed eliminazione:

c4d79646de729e4.png

Esplora il codice

La funzione Cloud Functions è denominata trigger-workflow. Puoi controllare il codice completo in index.js.

Eseguire il deployment in Cloud Functions

Vai alla cartella:

cd workflows/functions/trigger-workflow/nodejs

Imposta alcune variabili e configurazioni necessarie:

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}

Esegui il deployment della funzione che risponde per finalizzare gli eventi:

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}

Esegui il deployment della seconda funzione che risponde all'eliminazione degli eventi:

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}

Al termine del deployment, nella console Cloud vedrai entrambe le funzioni:

7d60c8b7851f39f5.png

14. Frontend (App Engine)

In questo passaggio creerai un frontend web su Google App Engine da Pic-a-daily: Lab 4. Crea un frontend web che consentirà agli utenti di caricare immagini dall'applicazione web e di sfogliare le immagini caricate e le relative miniature.

223fb2281614d053.png

Puoi scoprire di più su App Engine e leggere la descrizione del codice in Pic-a-daily: Lab 4—Create a web frontend.

Esplora il codice

L'app App Engine è denominata frontend. Puoi controllare il codice completo in index.js.

Esegui il deployment in App Engine

Vai alla cartella:

cd frontend

Imposta la regione che preferisci e sostituisci anche GOOGLE_CLOUD_PROJECT in app.yaml con l'ID progetto effettivo:

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

Schiera:

gcloud app deploy app.yaml -q

Dopo un paio di minuti, ti verrà comunicato che l'applicazione gestisce il traffico:

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

Puoi anche visitare la sezione App Engine di Cloud Console per vedere che è stato eseguito il deployment dell'app ed esplorare funzionalità di App Engine come il controllo delle versioni e la suddivisione del traffico:

f4bd5f4de028bd83.png

15. Testare i flussi di lavoro

Per eseguire il test, accedi all'URL predefinito di App Engine per l'app dell'app (https://<YOUR_PROJECT_ID>.appspot.com/). Dovresti vedere la UI frontend attiva e in esecuzione.

1649ac060441099.png

Carica un'immagine. Questo dovrebbe attivare Workflows e potrai visualizzarne l'esecuzione nello stato Active nella console Cloud:

b5a2a3d7a2bc094.png

Al termine di Workflows, è possibile fare clic sull'ID esecuzione e visualizzare l'output da diversi servizi:

8959df5098c21548.png

Carica altre 3 immagini. Dovresti anche vedere la miniatura e il collage delle immagini nei bucket Cloud Storage e nel frontend di App Engine aggiornati:

d90c786ff664a5dc.png

16. Libera spazio (facoltativo)

Se non intendi conservare l'app, puoi eseguire la pulizia delle risorse per risparmiare sui costi ed essere nel complesso un buon cittadino del cloud eliminando l'intero progetto:

gcloud projects delete ${GOOGLE_CLOUD_PROJECT} 

17. Complimenti!

Hai creato una versione orchestrata dell'app utilizzando Workflows per orchestrare e chiamare i servizi.

Argomenti trattati

  • App Engine
  • Cloud Firestore
  • Cloud Functions
  • Cloud Run
  • Workflows