Harness and Google AppEngine

Here is another post in the Custom Deployer series, similar to what @rohan, @lukehertert, and @luisredda have posted before!

This post will be about Google AppEngine support in Harness and here is the Git repo with all of the templates that are being used: Git Repo


To start this post off, you will need the following requirements before we begin:

  1. Your source code and the AppEngine app.yaml file need to be either in a TAR file or in a Git repository to clone from.
  2. A GCP Service Account with the appropriate access to deploy to and read from AppEngine and fetch a file from the designated storage location (In this example we are using a GCS Bucket). You will also need a JSON key file for the Service Account. Keep track of the JSON key file and the email address for the service account. If you have multiple AppEngine Applications, one for every GCP Project, make sure that you have the Service Account Email and Service Account JSON key file for every GCP Project that you want to deploy to. NOTE: If you are not storing your Source Code and app.yaml file in a GCS bucket, you will need to configure the Download script to use the appropriate secret and command to download the desired package.
  3. The GCP Project ID to deploy to. Because AppEngine only allows for a single Application per GCP Project, you’ll need the Project ID for any projects that you want to deploy to.
  4. The output of gcloud app instances list --service=<SERVICE NAME> --project=<PROJECT ID> --format=json. We will use this output for mapping later.
  5. If a GitHub PAT, or equivalent token for other Git repository is required to clone a repository, you will need to configure the Download script to leverage said Token for the git clone command.


The first thing that you will need to do is create the appropriate Secrets, Delegate Profile, and Cloud Provider in Harness (NOTE The Cloud Provider part is to access a GCS bucket with the desired artifact. If you are using an Artifact Repository like Artifactory or Nexus, please follow this doc instead). Initially you will need to convert you Service Account JSON key file to a base64 string. If you are on a mac you can use base64 /path/to/key-file.json | pbcopy to copy the base64 output to your clipboard. Then you will go to Harness > Security > Secrets Management > Encrypted Text > + Add Encrypted Text > Name: gae_sa and Value: paste in the base64 string > Check the Scope to Account checkbox > Click Submit. After that is done, you will need to create a Delegate Profile (Setup > Harness Delegates > Delegate Profiles > Add Delegate Profile or add this script to an already created profile > Add Delegate Profile to a Delegate > Add a Custom Selector named appengine to the Delegate.

Next, you will need to create a Custom Deployer in the Harness Template Library called Google AppEngine.

  • Two Infrastructure Variables are required: gcp_project_id and service_name
  • The Fetch Instances script can be found in the Git Repo at the top of this post
  • Host Object Array Path will be $
  • The Host Attributes section will be filled out with the information from the output of the gcloud app instances list --service=<SERVICE NAME> --project=<PROJECT ID> --format=json command. You will need to use dot-notation to reference the appropriate information. NOTE: hostname is required and you can use the instance.name part of the output for the relative JSON Path. See the following example:
  • HARNESS SETUP: image

Once the Custom Deployer is created you will need to create two Service Commands in the Template Library.

The first service command will be called gae_deploy_package and two variables will need to be added to it: serviceAccount and projectID. Once you hit Submit you will then click the blue + icon, select Exec, change the name in the blue banner to Setup gcloud, and add this script to the box and click Submit. You will need to add one more Exec to the list, like before, and call this one Download, Extract, and Deploy. Then you will add this script to the box and click Submit. NOTE If you are using GCS for the storage of the TAR artifact, then nothing will need to change. However, if you are using some other storage location you will need to tweak everything above the gcloud command to get the appropriate credentials and the correct download command.



If you are needing to deploy to AppEngine from a Git repository, you can follow the above step, but change the second part of the service command to use this script instead and add the gitRepo variable as well.




Now that the appropriate Secrets, Delegate Profiles, Custom Deployer, and Service Commands have been created, you will now need to setup a Harness Application to leverage these pieces.

In the desired Harness Application, you will need to create a Service: Services > + Add Service > Give the Service the same name as the AppEngine Service (NOTE Best practice would be a naming convention that starts with a lowercase letter and doesn’t use any special characters other than _). The Deployment Type will be Google AppEngine, which is the Custom Deployer we previously created and Artifact Type will be TAR (or other artifact type if not using TAR). In this example we are using a TAR in GCS, so we will be able to use the Artifact Source to point to the GCS bucket and desired Artifact.



After the Service has been created, we will then need to go to the appropriate Environment and add a new Infrastructure Definition. The name will be google-appengine, cloud provider type will be custom, deployment type will be Google AppEngine, version will be Latest, gcp_project_id will be the desired GCP project ID, and service_name will be ${service.name}. Then you can click Submit.

The last part of the process is to create a Workflow. The name of the workflow should be something related to AppEngine, the workflow type is Basic Deployment, the environment, service, and infrastructure definition are the ones that we created above.

In the workflow, in the Deploy phase, select + Add Step > Template Library from the top section > select the Link button to the right of gae_deploy_package

Once that is selected, the next screen to show will be setting up the template. Change the Timeout to be 20m, Delegate Selector will be the selector that was added at the top of the post, serviceAccount will be the email address of the GCP Service Account, and the projectID will be the GCP ProjectID (which you can get from the Service Account email address), then click Submit at the bottom right.

The last thing to do is to switch the Fetch Instances command to be after the template we just added. You also need to make sure that you click the Fetch Instances command and add the same Delegate Selector to the command and click Submit.

Now you are able to deploy it out and check the progress of the deployment!

You should also be able to see the Service Instances in the Services Dashboard

Let me know if you have any questions! Don’t forget to Like, Comment, and Share!