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 Cloud Function attivata da Google Cloud Storage per il servizio di analisi delle immagini, un container Cloud Run attivato da GCS tramite Pub/Sub per il servizio di generazione di miniature ed Eventarc per attivare il servizio di raccolta dei rifiuti di immagini su Cloud Run. Era presente 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 scorrono 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 autonomo

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Ricorda l'ID progetto, un nome univoco tra tutti i progetti Google Cloud (il nome sopra è già stato utilizzato e non funzionerà per te, mi dispiace). In questo codelab verrà chiamato PROJECT_ID.

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

L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Assicurati di seguire le istruzioni riportate nella sezione "Pulizia", che ti consiglia come arrestare le risorse in modo da non incorrere in addebiti oltre questo tutorial. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.

Avvia Cloud Shell

Sebbene Google Cloud possa essere gestito da remoto dal tuo laptop, in questo codelab utilizzerai Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

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

bce75f34b2c53987.png

Bastano pochi istanti per eseguire il provisioning e connettersi all'ambiente. Al termine, dovresti vedere un risultato simile a questo:

f6ef2b5f13479f3a.png

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

3. Introduzione a Workflows

90fcd42d556e310e.jpeg

Puoi utilizzare Workflows per creare workflow 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 aspetta da un orchestratore, Workflows ti consente di definire il flusso della logica di business in un linguaggio di definizione del workflow basato su YAML/JSON e fornisce un'API Workflows Execution e un'interfaccia utente di Workflows per attivare questi flussi.

È molto più di un semplice orchestratore grazie a queste funzionalità integrate e configurabili:

  • Gestione flessibile dei tentativi e degli errori tra i passaggi per un'esecuzione affidabile.
  • Analisi JSON e passaggio di variabili tra i passaggi per evitare il codice di collegamento.
  • Le formule di espressione per le decisioni consentono l'esecuzione di fasi condizionali.
  • Subworkflow per workflow modulari e riutilizzabili.
  • Il supporto dei servizi esterni consente l'orchestrazione dei servizi al di fuori di Google Cloud.
  • Supporto dell'autenticazione per Google Cloud e servizi esterni per l'esecuzione sicura dei passaggi.
  • Connettori ai servizi Google Cloud come Pub/Sub, Firestore, Tasks e Secret Manager per una più facile integrazione.

Inoltre, Workflows è un prodotto serverless completamente gestito. Nessun server da configurare o scalare e paghi solo per ciò che utilizzi.

4. Abilita API

In questo lab collegherai i servizi Cloud Functions e Cloud Run con Workflows. Utilizzerai anche App Engine, Cloud Build, l'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

Se non l'hai già fatto nei precedenti codelab, recupera il codice:

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

Avrai la seguente struttura di cartelle pertinente per questo lab:

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

Queste sono le cartelle pertinenti:

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

6. Esplorare il file YAML di Workflows

Il file workflows.yaml definisce il flusso di lavoro in una serie di passaggi. Vediamo insieme per capire meglio.

All'inizio del flusso di lavoro, vengono trasmessi alcuni parametri. Verranno trasmessi da due funzioni Cloud che attivano i workflow. Vedremo queste funzioni più avanti, ma ecco come inizia il flusso di lavoro:

d44a5e18aa9d4660.png

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

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}

Successivamente, 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 altro valore genererà un'eccezione di evento non supportato.

dd1f450983655619.png

Ecco il passaggio, nella definizione del flusso di lavoro YAML, in cui controlliamo il tipo di evento di archiviazione dei 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 i workflow supportano le istruzioni switch e la gestione delle eccezioni, con l'istruzione switch e le sue varie condizioni e l'istruzione raise per generare un errore quando l'evento non viene riconosciuto.

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

Tieni presente che tutto viene eseguito in Workflows, tranne Vision Transform Cloud Functions (che verrà eseguita il deployment in un secondo momento):

ca2ad16b9cbb436.png

Ecco l'aspetto dei 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. A questo scopo, vengono eseguiti il deployment di due servizi Cloud Run e vengono effettuate chiamate a questi servizi dai passaggi thumbnailCall e collageCall:

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 di ogni servizio nel passaggio finalizeCompleted:

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

L'altro ramo dell'esecuzione si verifica quando un file viene eliminato 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 le 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

L'eliminazione del ramo termina restituendo risultati / codici da ogni passaggio:

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

Nei passaggi successivi, creeremo tutte le dipendenze esterne dei workflow: bucket, Cloud Functions, servizi Cloud Run e database Firestore.

7. Crea i bucket

Hai bisogno di due bucket per le immagini: uno per salvare le immagini originali ad alta risoluzione e uno per salvare le miniature delle immagini.

Crea un bucket pubblico regionale (in questo caso in Europa) con accesso uniforme per gli utenti per 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)

Workflows.yaml inizia con i passaggi init, eventTypeSwitch e eventTypeNotSupported. Questi 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 questi passaggi vengono eseguiti in Workflows:

daaed43a22d2b0d3.png

Successivamente, dobbiamo trasformare i dati restituiti dall'API Vision prima di poterli salvare in Firestore. Più 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 e Workflows chiama semplicemente questa funzione:

5e120e70c67779cd.png

Esplora il codice

La funzione Cloud si chiama 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.

Esegui il deployment in Cloud Functions

Vai alla cartella:

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

Imposta la regione 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à chiamarla per eseguire la trasformazione dei dati dell'API Vision.

9. Prepara il database

Il passaggio successivo nei flussi di lavoro consiste nel controllare la sicurezza dell'immagine dai dati dell'immagine e quindi archiviare le informazioni sull'immagine restituite dall'API Vision nel database Cloud Firestore, un database di documenti NoSQL veloce, serverless, completamente gestito e cloud-native:

6624c616bc7cd97f.png

Entrambe le operazioni vengono eseguite in Workflows, ma devi creare il database Firestore per l'archiviazione dei metadati.

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

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

Successivamente, 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 del 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)
  • created (data): il timestamp di quando sono stati archiviati i metadati di questa immagine
  • thumbnail (booleano): un campo facoltativo che sarà presente e sarà true se è stata generata un'immagine miniatura per questa immagine

Poiché eseguiremo la ricerca in Firestore per trovare le immagini per cui sono disponibili miniature e l'ordinamento 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 potrà archiviare i metadati dell'immagine in Firestore.

10. Servizio miniature (Cloud Run)

Il passaggio successivo della catena consiste nel creare una 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 si chiama 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 poi ospitarle 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 minuto o due, la build dovrebbe riuscire e il container verrà eseguito il deployment in Google Container Registry.

Esegui 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 Workflows thumbnailCall potrà chiamarlo.

11. Servizio di collage (Cloud Run)

Il passaggio successivo della catena consiste nel creare un collage dalle 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 si chiama 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 poi ospitarle 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 minuto o due, la build dovrebbe riuscire e il container verrà eseguito il deployment in Google Container Registry.

Esegui 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:

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 di Cloud Console e che il passaggio collageCall di Workflows possa chiamare questo servizio:

3ae9873f4cbbf423.png

12. Deployment dei workflow

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

È il momento di eseguire il deployment dei flussi di lavoro.

Vai alla cartella contenente il file workflows.yaml ed esegui il deployment con:

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

Dopo alcuni secondi, il flusso di lavoro dovrebbe essere implementato e puoi visualizzarlo nella sezione Workflows di Cloud Console:

94a720149e5df9c5.png

Se vuoi, puoi fare clic sul flusso di lavoro e modificarlo. Durante la modifica, ottieni una rappresentazione visiva del workflow:

55441b158f6027f3.png

Puoi anche eseguire il flusso di lavoro manualmente dalla console Cloud con i parametri corretti. Verrà eseguito automaticamente in risposta agli eventi Cloud Storage nel passaggio successivo.

13. Trigger di flussi di lavoro (Cloud Functions)

Il flusso di lavoro è stato implementato ed è pronto. Ora dobbiamo attivare i flussi di lavoro quando un file viene creato o eliminato in un bucket Cloud Storage. Si tratta rispettivamente degli eventi storage.object.finalize e storage.object.delete.

I workflow hanno API e librerie client per creare, gestire ed eseguire i workflow che puoi utilizzare. In questo caso, utilizzerai l'API Workflows Execution e, più nello specifico, la relativa libreria client Node.js per attivare il flusso di lavoro.

Attiverai i workflow da Cloud Function in ascolto degli eventi Cloud Storage. Poiché una funzione Cloud Functions può essere in ascolto di un solo tipo di evento, devi eseguire il deployment di due funzioni Cloud Functions per ascoltare sia gli eventi di creazione sia quelli di eliminazione:

c4d79646de729e4.png

Esplora il codice

La funzione Cloud si chiama trigger-workflow. Puoi controllare il codice completo in index.js.

Esegui 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 agli eventi di finalizzazione:

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 agli eventi di eliminazione:

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, puoi visualizzare entrambe le funzioni in Cloud Console:

7d60c8b7851f39f5.png

14. Frontend (App Engine)

In questo passaggio, crei un frontend web su Google App Engine da Pic-a-daily: Lab 4—Create a web frontend che consentirà agli utenti di caricare immagini dall'applicazione web, nonché 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 si chiama 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

Esegui il deployment:

gcloud app deploy app.yaml -q

Dopo un minuto o due, ti verrà comunicato che l'applicazione sta gestendo 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 verificare che l'app sia stata implementata ed esplorare le funzionalità di App Engine come il controllo delle versioni e la suddivisione del traffico:

f4bd5f4de028bd83.png

15. Testare i workflow

Per eseguire il test, vai all'URL App Engine predefinito per l'app (https://<YOUR_PROJECT_ID>.appspot.com/) e dovresti vedere l'interfaccia utente frontend in esecuzione.

1649ac060441099.png

Carica un'immagine. In questo modo dovresti attivare i workflow e puoi visualizzare l'esecuzione del workflow nello stato Active in Cloud Console:

b5a2a3d7a2bc094.png

Al termine del flusso di lavoro, puoi fare clic sull'ID esecuzione e visualizzare l'output di diversi servizi:

8959df5098c21548.png

Carica altre tre foto. Dovresti anche vedere l'anteprima e il collage delle immagini nei bucket Cloud Storage e nel frontend di App Engine aggiornati:

d90c786ff664a5dc.png

16. Pulizia (facoltativo)

Se non intendi conservare l'app, puoi ripulire le risorse per risparmiare sui costi ed essere 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