Skip to content

Latest commit

 

History

History

1. Bootstrap phase

The bootstrap phase establishes the 3 initial pipelines of the Enterprise Application blueprint. These pipelines are:

  • the Multitenant Infrastructure pipeline
  • the Application Factory
  • the Fleet-Scope pipeline

An overview of the deployment methodology for the Enterprise Application blueprint is shown below. Enterprise Application blueprint deployment diagram

Each pipeline has the following associated resources:

  • 2 Cloud Build triggers
    • 1 trigger to run Terraform Plan commands upon changes to a non-main git branch
    • 1 trigger to run Terraform Apply commands upon changes to the main git branch
  • 3 Cloud Storage buckets
    • Terraform State bucket, to store the current state
    • Build Artifacts bucket, to store any artifacts generated during the build process, such as .tfplan files
    • Build Logs bucket, to store the logs from the build process
  • 1 service account for executing the Cloud Build build process

Usage

Pre-requisites

Secrets Project

You will need a Google Cloud project with Secret Manager to store your git credentials, throughout the documentation this will be referenced as $GIT_SECRET_PROJECT.

Cloud Build with Github Pre-requisites

To proceed with GitHub as your git provider you will need:

  • An authenticated GitHub account. The steps in this documentation assumes you have a configured SSH key for cloning and modifying repositories.

  • A private GitHub repository for each one of the repositories below:

    • Multitenant (eab-multitenant)
    • Fleetscope (eab-fleetscope)
    • Application Factory (eab-applicationfactory)

    Note: Default names for the repositories are, in sequence: eab-multitenant, eab-fleetscope and eab-applicationfactory; If you choose other names for your repository make sure you update terraform.tfvars the repository names under cloudbuildv2_repository_config variable.

  • Install Cloud Build App on Github. After the installation, take note of the application id, it will be used later.

  • Create Personal Access Token on Github with repo and read:user (or if app is installed in org use read:org) - After creating the token in Secret Manager, you will use the secret id in the terraform.tfvars file.

  • Create a secret for the Github Cloud Build App ID:

    APP_ID_VALUE=<replace_with_app_id>
    printf $APP_ID_VALUE | gcloud secrets create github-app-id --project=$GIT_SECRET_PROJECT --data-file=-
  • Take note of the secret id, it will be used in terraform.tfvars later on:

    gcloud secrets describe github-app-id --project=$GIT_SECRET_PROJECT --format="value(name)"
  • Create a secret for the Github Personal Access Token:

    GITHUB_TOKEN=<replace_with_token>
    printf $GITHUB_TOKEN | gcloud secrets create github-pat --project=$GIT_SECRET_PROJECT --data-file=-
  • Take note of the secret id, it will be used in terraform.tfvars later on:

    gcloud secrets describe github-pat --project=$GIT_SECRET_PROJECT --format="value(name)"
  • Populate your terraform.tfvars file in 1-bootstrap with the Cloud Build 2nd Gen configuration variable, here is an example:

    cloudbuildv2_repository_config = {
       repo_type = "GITHUBv2"
    
       repositories = {
          multitenant = {
             repository_name = "eab-multitenant"
             repository_url  = "https://github.com/your-org/eab-multitenant.git"
          }
    
          applicationfactory = {
             repository_name = "eab-applicationfactory"
             repository_url  = "https://github.com/your-org/eab-applicationfactory.git"
          }
    
          fleetscope = {
             repository_name = "eab-fleetscope"
             repository_url  = "https://github.com/your-org/eab-fleetscope.git"
          }
       }
    
       github_secret_id                            = "projects/REPLACE_WITH_PRJ_NUMBER/secrets/github-pat" # Personal Access Token Secret
       github_app_id_secret_id                     = "projects/REPLACE_WITH_PRJ_NUMBER/secrets/github-app-id" # App ID value secret
    }

Cloud Build with Gitlab Pre-requisites

To proceed with Gitlab as your git provider you will need:

  • An authenticated Gitlab account. The steps in this documentation assumes you have a configured SSH key for cloning and modifying repositories.

  • A private GitLab repository for each one of the repositories below:

    • Multitenant (eab-multitenant)
    • Fleetscope (eab-fleetscope)
    • Application Factory (eab-applicationfactory)

    Note: Default names for the repositories are, in sequence: eab-multitenant, eab-fleetscope and eab-applicationfactory; If you choose other names for your repository make sure you update terraform.tfvars the repository names under cloudbuildv2_repository_config variable.

  • An access token with the api scope to use for connecting and disconnecting repositories.

  • An access token with the read_api scope to ensure Cloud Build repositories can access source code in repositories.

  • Create a secret for the Gitlab API Access Token:

    GITLAB_API_TOKEN=<replace_with_app_id>
    printf $GITLAB_API_TOKEN | gcloud secrets create gitlab-api-token --project=$GIT_SECRET_PROJECT --data-file=-
  • Take note of the secret id, it will be used in terraform.tfvars later on:

    gcloud secrets describe gitlab-api-token --project=$GIT_SECRET_PROJECT --format="value(name)"
  • Create a secret for the Gitlab Read API Access Token:

    GITLAB_READ_API_TOKEN=<replace_with_token>
    printf $GITLAB_READ_API_TOKEN | gcloud secrets create gitlab-read-api-token --project=$GIT_SECRET_PROJECT --data-file=-
  • Take note of the secret id, it will be used in terraform.tfvars later on:

    gcloud secrets describe gitlab-read-api-token --project=$GIT_SECRET_PROJECT --format="value(name)"
  • Generate a random 36 character string that will be used as the Webhook Secret:

    GITLAB_WEBHOOK=<replace_with_webhook>
    printf $GITLAB_WEBHOOK | gcloud secrets create gitlab-webhook --project=$GIT_SECRET_PROJECT --data-file=-

    NOTE: for testing purposes, you may use the following command to generate the webhook in bash: GITLAB_WEBHOOK=$(cat /dev/urandom | tr -dc "[:alnum:]" | head -c 36)

  • Take note of the secret id, it will be used in terraform.tfvars later on:

    gcloud secrets describe gitlab-webhook --project=$GIT_SECRET_PROJECT --format="value(name)"
  • Populate your terraform.tfvars file in 1-bootstrap with the Cloud Build 2nd Gen configuration variable, here is an example:

    cloudbuildv2_repository_config = {
       repo_type = "GITLABv2"
    
       repositories = {
          multitenant = {
             repository_name = "eab-multitenant"
             repository_url  = "https://gitlab.com/your-group/eab-multitenant.git"
          }
    
          applicationfactory = {
             repository_name = "eab-applicationfactory"
             repository_url  = "https://gitlab.com/your-group/eab-applicationfactory.git"
          }
    
          fleetscope = {
             repository_name = "eab-fleetscope"
             repository_url  = "https://gitlab.com/your-group/eab-fleetscope.git"
          }
       }
    
       gitlab_authorizer_credential_secret_id         = "projects/REPLACE_WITH_PRJ_NUMBER/secrets/gitlab-api-token"
       gitlab_read_authorizer_credential_secret_id    = "projects/REPLACE_WITH_PRJ_NUMBER/secrets/gitlab-read-api-token"
       gitlab_webhook_secret_id                       = "projects/REPLACE_WITH_PRJ_NUMBER/secrets/gitlab-webhook"
    }

Deploying with Cloud Build

Deploying on Enterprise Foundation blueprint

If you have previously deployed the Enterprise Foundation blueprint, create the pipelines in this phase by pushing the contents of this folder to a workload repo created at stage 5. Instead of deploying to multiple environments, create these pipelines in the common folder of the foundation.

Start at "5. Clone the bu1-example-app repo". Replace the contents of that repo with the contents of this folder.

Running Terraform locally

Requirements

You will need a project to host your resources, you can manually create it:

example-organization
└── fldr-common
    └── prj-c-eab-bootstrap

Step-by-Step

  1. The next instructions assume that you are in the terraform-google-enterprise-application/1-bootstrap folder.

    cd terraform-google-enterprise-application/1-bootstrap
  2. Rename terraform.example.tfvars to terraform.tfvars.

    mv terraform.example.tfvars terraform.tfvars
  3. Update the terraform.tfvars file with your project id. If you are using Github or Gitlab as your Git provider for Cloud Build, you will need to configure the cloudbuildv2_repository_config variable as described in the following sections:

You can now deploy the common environment for these pipelines.

  1. Run init and plan and review the output.

    terraform init
    terraform plan
  2. Run apply.

    terraform apply

If you receive any errors or made any changes to the Terraform config or terraform.tfvars, re-run terraform plan before you run terraform apply.

Updating backend.tf files on the repository

Within the repository, you'll find backend.tf files that define the GCS bucket for storing the Terraform state. By running the commands below, instances of UPDATE_ME placeholders in these files will be automatically replaced with the actual name of your GCS bucket.

  1. Running the series of commands below will update the remote state bucket for backend.tf files on the repository.

    export backend_bucket=$(terraform output -raw state_bucket)
    echo "backend_bucket = ${backend_bucket}"
    
    cp backend.tf.example backend.tf
    cd ..
    
    for i in `find . -name 'backend.tf'`; do sed -i'' -e "s/UPDATE_ME/${backend_bucket}/" $i; done
  2. Re-run terraform init. When you're prompted, agree to copy Terraform state to Cloud Storage.

    cd 1-bootstrap
    
    terraform init

Inputs

Name Description Type Default Required
bucket_force_destroy When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. bool false no
bucket_prefix Name prefix to use for buckets created. string "bkt" no
cloudbuildv2_repository_config Configuration for integrating repositories with Cloud Build v2:
- repo_type: Specifies the type of repository. Supported types are 'GITHUBv2', 'GITLABv2', and 'CSR'.
- repositories: A map of repositories to be created. The key must match the exact name of the repository. Each repository is defined by:
- repository_name: The name of the repository.
- repository_url: The URL of the repository.
- github_secret_id: (Optional) The personal access token for GitHub authentication.
- github_app_id_secret_id: (Optional) The application ID for a GitHub App used for authentication.
- gitlab_read_authorizer_credential_secret_id: (Optional) The read authorizer credential for GitLab access.
- gitlab_authorizer_credential_secret_id: (Optional) The authorizer credential for GitLab access.
- gitlab_webhook_secret_id: (Optional) The secret ID for the GitLab WebHook..
Note: When using GITLABv2, specify gitlab_read_authorizer_credential and gitlab_authorizer_credential and gitlab_webhook_secret_id.
Note: When using GITHUBv2, specify github_pat and github_app_id.
Note: If 'cloudbuildv2_repository_config' variable is not configured, CSR (Cloud Source Repositories) will be used by default.
object({
repo_type = string # Supported values are: GITHUBv2, GITLABv2 and CSR
# repositories to be created
repositories = object({
multitenant = object({
repository_name = optional(string, "eab-multitenant")
repository_url = string
}),
applicationfactory = object({
repository_name = optional(string, "eab-applicationfactory")
repository_url = string
}),
fleetscope = object({
repository_name = optional(string, "eab-fleetscope")
repository_url = string
}),
})
# Credential Config for each repository type
github_secret_id = optional(string)
github_app_id_secret_id = optional(string)
gitlab_read_authorizer_credential_secret_id = optional(string)
gitlab_authorizer_credential_secret_id = optional(string)
gitlab_webhook_secret_id = optional(string)
})
{
"repo_type": "CSR",
"repositories": {
"applicationfactory": {
"repository_url": ""
},
"fleetscope": {
"repository_url": ""
},
"multitenant": {
"repository_url": ""
}
}
}
no
common_folder_id Folder ID in which to create all application admin projects, must be prefixed with 'folders/' string n/a yes
envs Environments
map(object({
billing_account = string
folder_id = string
network_project_id = string
network_self_link = string
org_id = string
subnets_self_links = list(string)
}))
n/a yes
location Location for build buckets. string "us-central1" no
project_id Project ID for initial resources string n/a yes
tf_apply_branches List of git branches configured to run terraform apply Cloud Build trigger. All other branches will run plan by default. list(string)
[
"development",
"nonproduction",
"production"
]
no
trigger_location Location of for Cloud Build triggers created in the workspace. If using private pools should be the same location as the pool. string "us-central1" no

Outputs

Name Description
artifacts_bucket Bucket for storing TF plans
cb_service_accounts_emails Service Accounts for the Multitenant Administration Cloud Build Triggers
logs_bucket Bucket for storing TF logs
project_id Project ID
source_repo_urls Source repository URLs
state_bucket Bucket for storing TF state
tf_project_id Google Artifact registry terraform project id.
tf_repository_name Name of Artifact Registry repository for Terraform image.
tf_tag_version_terraform Docker tag version terraform.