This tutorial shows you how to use Workflows to link a series of services together. By connecting two public HTTP services using Cloud Run functions, an external REST API, and a private Cloud Run service, you can create a flexible, serverless application.
Objectives
In this tutorial, you use the Google Cloud CLI to create a single workflow, connecting one service at a time:
- Deploy two Cloud Run functions: the first function generates a random number, and then passes that number to the second function which multiplies it.
- Using Workflows, connect the two HTTP functions together. Execute the workflow and return a result that is then passed to an external API.
- Using Workflows, connect an external HTTP API
that returns the
log
for a given number. Execute the workflow and return a result that is then passed to a Cloud Run service. - Deploy a Cloud Run service that allows authenticated
access only. The service returns the
math.floor
for a given number. - Using Workflows, connect the Cloud Run service, execute the entire workflow, and return a final result.
The following diagram shows both an overview of the process as well as a visualization of the final workflow:
Costs
In this document, you use the following billable components of Google Cloud:
To generate a cost estimate based on your projected usage,
use the pricing calculator.
Before you begin
Security constraints defined by your organization might prevent you from completing the following steps. For troubleshooting information, see Develop applications in a constrained Google Cloud environment.
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
- Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Artifact Registry, Cloud Build, Cloud Run, Cloud Run functions, Cloud Storage, and Workflows APIs:
gcloud services enable artifactregistry.googleapis.com
cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com - Install the Google Cloud CLI.
-
To initialize the gcloud CLI, run the following command:
gcloud init
-
Create or select a Google Cloud project.
-
Create a Google Cloud project:
gcloud projects create PROJECT_ID
Replace
PROJECT_ID
with a name for the Google Cloud project you are creating. -
Select the Google Cloud project that you created:
gcloud config set project PROJECT_ID
Replace
PROJECT_ID
with your Google Cloud project name.
-
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Artifact Registry, Cloud Build, Cloud Run, Cloud Run functions, Cloud Storage, and Workflows APIs:
gcloud services enable artifactregistry.googleapis.com
cloudbuild.googleapis.com run.googleapis.com cloudfunctions.googleapis.com storage.googleapis.com workflows.googleapis.com - Update the Google Cloud CLI components:
gcloud components update
- If you are running commands inside Cloud Shell, you are already
authenticated with the gcloud CLI; otherwise, sign in using your
account:
gcloud auth login
- Set the default location used in this tutorial:
gcloud config set project PROJECT_ID export REGION=REGION gcloud config set functions/region ${REGION} gcloud config set run/region ${REGION} gcloud config set workflows/location ${REGION}
Replace
REGION
with the supported Workflows location of your choice. -
If you are the project creator, you are granted the basic Owner role (
roles/owner
). By default, this Identity and Access Management (IAM) role includes the permissions necessary for full access to most Google Cloud resources and you can skip this step.If you are not the project creator, required permissions must be granted on the project to the appropriate principal. For example, a principal can be a Google Account (for end users) or a service account (for applications and compute workloads). For more information, see the Roles and permissions page for your event destination.
Required permissions
To get the permissions that you need to complete the tutorial, ask your administrator to grant you the following IAM roles on your project:
-
Cloud Build Editor (
roles/cloudbuild.builds.editor
) -
Cloud Functions Developer (
roles/cloudfunctions.developer
) -
Cloud Run Admin (
roles/run.admin
) -
Create Service Accounts (
roles/iam.serviceAccountCreator
) -
Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) -
Service Account User (
roles/iam.serviceAccountUser
) -
Service Usage Consumer (
roles/serviceusage.serviceUsageConsumer
) -
Storage Admin (
roles/storage.admin
) -
Workflows Editor (
roles/workflows.editor
)
For more information about granting roles, see Manage access to projects, folders, and organizations.
You might also be able to get the required permissions through custom roles or other predefined roles.
-
Cloud Build Editor (
- When you deploy your workflow, you associate it with a specified service
account. Create a service account for Workflows to use:
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
- All Cloud Run services are deployed privately by default
and are only callable by Project Owners, Project Editors, Cloud Run
Admins, and Cloud Run Invokers. To allow the service account to
call an authenticated Cloud Run service, grant the
run.invoker
role to the Workflows service account:gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \ --role "roles/run.invoker"
Deploy the first Cloud Run functions
After receiving an HTTP request, this HTTP function generates a random number between 1 and 100, and then returns the number in JSON format.
Create a directory called
randomgen
and change to it:mkdir ~/randomgen cd ~/randomgen
Create a text file with the filename
main.py
that contains the following Python code:To support a dependency on Flask for HTTP processing, create a text file for the pip package manager. Give it the filename
requirements.txt
and add the following:Deploy the function with an HTTP trigger, and allow unauthenticated access:
gcloud functions deploy randomgen-function \ --gen2 \ --runtime python310 \ --entry-point=randomgen \ --trigger-http \ --allow-unauthenticated
The function might take a few minutes to deploy. Alternatively, you can use the Cloud Run functions interface in the Google Cloud console to deploy the function.
Once the
randomgen
function is deployed, you can confirm thehttpsTrigger.url
property:gcloud functions describe randomgen-function \ --gen2 \ --format="value(serviceConfig.uri)"
Save the URL. You will need to add it to your Workflow source file in later exercises.
You can try out the function with the following curl command:
curl $(gcloud functions describe randomgen-function \ --gen2 \ --format="value(serviceConfig.uri)")
A number is randomly generated and returned.
Deploy the second Cloud Run functions
After receiving an HTTP request, this HTTP function extracts the input
from
the JSON body, multiplies it by 2, and returns the result in JSON format.
Navigate back to your home directory:
cd ~
Create a directory called
multiply
and change to it:mkdir ~/multiply cd ~/multiply
Create a text file with the filename
main.py
that contains the following Python code:To support a dependency on Flask for HTTP processing, create a text file for the pip package manager. Give it the filename
requirements.txt
and add the following:Deploy the function with an HTTP trigger, and allow unauthenticated access:
gcloud functions deploy multiply-function \ --gen2 \ --runtime python310 \ --entry-point=multiply \ --trigger-http \ --allow-unauthenticated
The function might take a few minutes to deploy. Alternatively, you can use the Cloud Run functions interface in the Google Cloud console to deploy the function.
Once the
multiply
function is deployed, you can confirm thehttpsTrigger.url
property:gcloud functions describe multiply-function \ --gen2\ --format="value(serviceConfig.uri)"
Save the URL. You will need to add it to your Workflow source file in later exercises.
You can try out the function with the following curl command:
curl -X POST MULTIPLY_FUNCTION_URL \ -H "Authorization: Bearer $(gcloud auth print-identity-token)" \ -H "Content-Type: application/json" \ -d '{"input": 5}'
The number 10 should be returned.
Connect the two Cloud Run functions in a workflow
A workflow is made up of a series of steps described using the Workflows syntax, which can be written in either YAML or JSON format. This is the workflow's definition. For a detailed explanation, see the Syntax reference page.
Navigate back to your home directory:
cd ~
Create a text file with the filename
workflow.yaml
that contains the following content:- randomgen_function: call: http.get args: url: RANDOMGEN_FUNCTION_URL result: randomgen_result - multiply_function: call: http.post args: url: MULTIPLY_FUNCTION_URL body: input: ${randomgen_result.body.random} result: multiply_result - return_result: return: ${multiply_result}
- Replace
RANDOMGEN_FUNCTION_URL
with the URL of yourrandomgen
function. - Replace
MULTIPLY_FUNCTION_URL
with the URL of yourmultiply
function.
This source file links the two HTTP functions together and returns a final result.
- Replace
After creating the workflow, you can deploy it, which makes it ready for execution.
gcloud workflows deploy WORKFLOW_NAME \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
Replace
WORKFLOW_NAME
with a name for your workflow.Execute the workflow:
gcloud workflows run WORKFLOW_NAME
An execution is a single run of the logic contained in a workflow's definition. All workflow executions are independent, and the rapid scaling of Workflows allows for a high number of concurrent executions.
After the workflow is executed, the output should resemble the following:
result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\"; ... startTime: '2021-05-05T14:17:39.135251700Z' state: SUCCEEDED ...
Connect a public REST service in the workflow
Update your existing workflow and connect a public REST API
(math.js)
that can evaluate mathematical expressions. For example,
curl https://api.mathjs.org/v4/?'expr=log(56)'
.
Note that since you have deployed your workflow, you can also edit it through the Workflows page in the Google Cloud console.
Edit the source file for your workflow and replace it with the following content:
- randomgen_function: call: http.get args: url: RANDOMGEN_FUNCTION_URL result: randomgen_result - multiply_function: call: http.post args: url: MULTIPLY_FUNCTION_URL body: input: ${randomgen_result.body.random} result: multiply_result - log_function: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiply_result.body.multiplied) + ")"} result: log_result - return_result: return: ${log_result}
- Replace
RANDOMGEN_FUNCTION_URL
with the URL of yourrandomgen
function. - Replace
MULTIPLY_FUNCTION_URL
with the URL of yourmultiply
function.
This links the external REST service to the Cloud Run functions, and returns a final result.
- Replace
Deploy the modified workflow:
gcloud workflows deploy WORKFLOW_NAME \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
Deploy a Cloud Run service
Deploy a Cloud Run service that, after receiving an HTTP
request, extracts input
from the JSON body, calculates its math.floor
, and
returns the result.
Create a directory called
floor
and change to it:mkdir ~/floor cd ~/floor
Create a text file with the filename
app.py
that contains the following Python code:In the same directory, create a
Dockerfile
with the following content:Create an Artifact Registry standard repository where you can store your Docker container image:
gcloud artifacts repositories create REPOSITORY \ --repository-format=docker \ --location=${REGION}
Replace
REPOSITORY
with a unique name for the repository.Build the container image:
export SERVICE_NAME=floor gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
Deploy the container image to Cloud Run, ensuring that it only accepts authenticated calls:
gcloud run deploy ${SERVICE_NAME} \ --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \ --no-allow-unauthenticated
When you see the service URL, the deployment is complete. You will need to specify that URL when updating the workflow definition.
Connect the Cloud Run service in the workflow
Update your existing workflow and specify the URL for the Cloud Run service.
Navigate back to your home directory:
cd ~
Edit the source file for your workflow and replace it with the following content:
- randomgen_function: call: http.get args: url: RANDOMGEN_FUNCTION_URL result: randomgen_result - multiply_function: call: http.post args: url: MULTIPLY_FUNCTION_URL body: input: ${randomgen_result.body.random} result: multiply_result - log_function: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiply_result.body.multiplied) + ")"} result: log_result - floor_function: call: http.post args: url: CLOUD_RUN_SERVICE_URL auth: type: OIDC body: input: ${log_result.body} result: floor_result - create_output_map: assign: - outputMap: randomResult: ${randomgen_result} multiplyResult: ${multiply_result} logResult: ${log_result} floorResult: ${floor_result} - return_output: return: ${outputMap}
- Replace
RANDOMGEN_FUNCTION_URL
with the URL of yourrandomgen
function. - Replace
MULTIPLY_FUNCTION_URL
with the URL of yourmultiply
function. - Replace
CLOUD_RUN_SERVICE_URL
with your Cloud Run service URL.
This connects the Cloud Run service in the workflow. Note that the
auth
key ensures that an authentication token is being passed in the call to the Cloud Run service. For more information, see Make authenticated requests from a workflow.- Replace
Deploy the modified workflow:
gcloud workflows deploy WORKFLOW_NAME \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com
Execute the final workflow:
gcloud workflows run WORKFLOW_NAME
The output should resemble the following:
result: '{"floorResult":{"body":"4","code":200 ... "logResult":{"body":"4.02535169073515","code":200 ... "multiplyResult":{"body":{"multiplied":56},"code":200 ... "randomResult":{"body":{"random":28},"code":200 ... startTime: '2023-11-13T21:22:56.782669001Z' state: SUCCEEDED
Congratulations! You have deployed and executed a workflow that connects a series of services together.
To create more complex workflows using expressions, conditional jumps, Base64 encoding or decoding, subworkflows, and more, refer to the Workflows syntax reference and the Standard library overview.
Clean up
If you created a new project for this tutorial, delete the project. If you used an existing project and want to keep it without the changes added in this tutorial, delete resources created for the tutorial.
Delete the project
The easiest way to eliminate billing is to delete the project that you created for the tutorial.
To delete the project:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Delete tutorial resources
Delete the Cloud Run service you deployed in this tutorial.
Delete the workflow you created in this tutorial.
Delete the container image from Artifact Registry.
Remove the Google Cloud CLI default configurations you added during the tutorial setup:
gcloud config unset functions/region gcloud config unset run/region gcloud config unset workflows/location gcloud config unset project