### Navigate to Quickstart Directory Source: https://docs.cloud.google.com/docs/terraform/get-started-with-terraform Change the current directory to the quickstart sample for creating a VM. ```bash cd terraform-docs-samples/compute/quickstart/create_vm ``` -------------------------------- ### Terraform Import Output Example Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Example output showing a successful import of a Google Compute Instance into Terraform state. ```text module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1: Importing from ID "projects/PROJECT_ID/zones/us-central1-a/instances/instance-1"... module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1: Import prepared! Prepared google_compute_instance for import module.examples-projects-PROJECT_ID-ComputeInstance-us-central1-a.google_compute_instance.instance_1: Refreshing state... [id=projects/PROJECT_ID/zones/us-central1-a/instances/instance-1] Import successful! The resources that were imported are shown above. These resources are now in your Terraform state and will henceforth be managed by Terraform. ``` -------------------------------- ### Navigate to Create VM Directory Source: https://docs.cloud.google.com/docs/terraform/create-vm-instance Change the directory to the quickstart sample for creating a VM instance. ```bash cd terraform-docs-samples/compute/quickstart/create_vm ``` -------------------------------- ### Install Config Connector (Alternative) Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Use this command if the standard installation fails due to the Google Cloud CLI component manager being disabled. ```bash sudo apt-get install google-cloud-sdk-config-connector ``` -------------------------------- ### Initialize Terraform Workspace Source: https://docs.cloud.google.com/docs/terraform/get-started-with-terraform Prepare your working directory for Terraform commands by initializing the backend and installing necessary provider plugins. ```bash terraform init ``` -------------------------------- ### Install Terraform Tools Source: https://docs.cloud.google.com/docs/terraform/policy-validation/quickstart Installs the necessary terraform-tools component for policy validation. ```bash sudo apt-get install google-cloud-sdk-terraform-tools ``` -------------------------------- ### Initialize Google Cloud CLI Source: https://docs.cloud.google.com/docs/terraform/authentication Run this command after installing the Google Cloud CLI to initialize it for your environment. ```bash gcloud init ``` -------------------------------- ### Example Terraform Modules File Source: https://docs.cloud.google.com/docs/terraform/resource-management/import This file points to all modules from sub-resources generated by the import command. ```hcl provider "google" { project = "PROJECT_ID" } module "OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeFirewall" { source = "./OUTPUT_DIRECTORY/projects/PROJECT_ID/ComputeFirewall" } module "OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeBackendService-global" { source = "./OUTPUT_DIRECTORY/projects/PROJECT_ID/ComputeBackendService/global" } ``` -------------------------------- ### Verify gcloud CLI installation Source: https://docs.cloud.google.com/docs/terraform/policy-validation/validate-policies Check if the gcloud CLI is installed and accessible by running the help command for `gcloud beta terraform vet`. ```bash gcloud beta terraform vet --help ``` -------------------------------- ### Install Config Connector CLI Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Install the command-line interface for Config Connector, which is used for exporting Google Cloud resources to Terraform. If the standard command fails, use the alternative command. ```bash gcloud components install config-connector ``` ```bash sudo apt-get install google-cloud-sdk-config-connector ``` -------------------------------- ### Install terraform-tools component Source: https://docs.cloud.google.com/docs/terraform/policy-validation/validate-policies Update gcloud components and install the terraform-tools component required for policy validation. ```bash gcloud components update gcloud components install terraform-tools ``` -------------------------------- ### Example Terraform Import Script Source: https://docs.cloud.google.com/docs/terraform/resource-management/import This shell script contains a list of terraform import commands for importing modules into the Terraform state. ```bash #!/bin/sh # Terraform Import Script generated by gcloud cli terraform import module.OUTPUT_DIRECTORY-projects-PROJECT_ID-ComputeFirewall.google_compute_firewall.allow_ssh projects/PROJECT_ID/global/firewalls/allow-ssh ``` -------------------------------- ### Example Constraint Definition Source: https://docs.cloud.google.com/docs/terraform/policy-validation/create-cai-constraints Create a constraint to enforce a specific policy. This example restricts address types to 'INTERNAL' and specifies matching criteria. ```yaml apiVersion: constraints.gatekeeper.sh/v1beta1 kind: GCPComputeAddressAddressTypeAllowlistConstraintV1 metadata: name: gcp_compute_address_internal_only spec: severity: high match: ancestries: - "**" parameters: allowed_address_types: - "INTERNAL" ``` -------------------------------- ### List Supported Resource Types Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Run this command to get a list of all resource types that can be exported to Terraform format. You can optionally redirect the output to a file. ```bash gcloud beta resource-config list-resource-types ``` ```bash gcloud beta resource-config list-resource-types >> strings.txt ``` -------------------------------- ### Install Config Connector CLI Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Install the Config Connector command-line interface (CLI) in Cloud Shell. This is required to use the Terraform bulk-export tool. ```bash gcloud components install config-connector ``` -------------------------------- ### Prepare Directory and File for Resource Types Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Create a directory and a text file to list the resource types you want to export. Each resource type should be on a new line. ```bash cd && mkdir tf-output && cd tf-output ``` ```text ComputeBackendBucket ComputeBackendService ComputeForwardingRule ``` -------------------------------- ### Initialize Terraform with Provider Upgrade Source: https://docs.cloud.google.com/docs/terraform/basic-commands Initialize Terraform and upgrade to the latest available version of the Google provider. ```bash terraform init -upgrade ``` -------------------------------- ### Initialize Terraform Source: https://docs.cloud.google.com/docs/terraform/basic-commands Initialize Terraform in a new or existing configuration directory. This downloads necessary providers and sets up the backend. ```bash terraform init ``` -------------------------------- ### Example JSON Violation Output Source: https://docs.cloud.google.com/docs/terraform/policy-validation/validate-policies This is an example of the JSON output when violations are found during policy validation. It details the constraint, configuration, message, and metadata of the violation. ```json [ { "constraint": "GCPIAMAllowedPolicyMemberDomainsConstraintV2.service_accounts_only", "constraint_config": { "api_version": "constraints.gatekeeper.sh/v1alpha1", "kind": "GCPIAMAllowedPolicyMemberDomainsConstraintV2", "metadata": { "annotations": { "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.", "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only", "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml" }, "name": "service-accounts-only" }, "spec": { "match": { "target": [ "organizations/**" ] }, "parameters": { "domains": [ "gserviceaccount.com" ] }, "severity": "high" } }, "message": "IAM policy for //cloudresourcemanager.googleapis.com/projects/PROJECT_ID contains member from unexpected domain: user:me@example.com", "metadata": { "ancestry_path": "organizations/ORG_ID/projects/PROJECT_ID", "constraint": { "annotations": { "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.", "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only", "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml" }, "labels": {}, "parameters": { "domains": [ "gserviceaccount.com" ] } }, "details": { "member": "user:me@example.com", "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID" } }, "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID", "severity": "high" } ] ``` -------------------------------- ### Connect to VM Instance Source: https://docs.cloud.google.com/docs/terraform/create-vm-instance Use this command to establish an SSH connection to your newly created VM instance. Ensure you replace `us-central1-a` and `my-vm` with your specific zone and instance name. ```bash gcloud compute ssh --zone=us-central1-a my-vm ``` -------------------------------- ### Clone and Duplicate Sample Policy Library Source: https://docs.cloud.google.com/docs/terraform/policy-validation/create-policy-library Clone the Google-provided sample policy library and set its remote to your organization's repository. This is the initial step to create your custom policy library. ```bash git clone https://github.com/GoogleCloudPlatform/policy-library.git cd policy-library git remote set-url origin POLICY_LIBRARY_REPO git push origin main ``` -------------------------------- ### Review VM Instance Configuration (main.tf) Source: https://docs.cloud.google.com/docs/terraform/create-vm-instance View the Terraform configuration file that defines the Compute Engine VM instance. ```hcl resource "google_compute_instance" "default" { name = "my-vm" machine_type = "n1-standard-1" zone = "us-central1-a" boot_disk { initialize_params { image = "ubuntu-minimal-2210-kinetic-amd64-v20230126" } } network_interface { network = "default" access_config {} } } ``` -------------------------------- ### Create Directory and Terraform File Source: https://docs.cloud.google.com/docs/terraform/basic-commands Create a new directory for your Terraform configuration and a main configuration file with a .tf extension. ```bash mkdir DIRECTORY && cd DIRECTORY && touch main.tf ``` -------------------------------- ### Terraform Destroy Confirmation Source: https://docs.cloud.google.com/docs/terraform/create-vm-instance This is an example of the output you can expect after confirming the `terraform destroy` command, indicating that all resources have been successfully removed. ```bash Destroy complete! Resources: 1 destroyed. ``` -------------------------------- ### Create a Flask app file Source: https://docs.cloud.google.com/docs/terraform/deploy-flask-web-server Creates a Python file named 'app.py' using the nano editor. ```bash nano app.py ``` -------------------------------- ### Create a Google Cloud project using gcloud CLI Source: https://docs.cloud.google.com/docs/terraform/create-vm-instance Use this command to create a new Google Cloud project. Replace `PROJECT_ID` with your desired project name. ```bash gcloud projects create PROJECT_ID ``` -------------------------------- ### Validation Result Source: https://docs.cloud.google.com/docs/terraform/policy-validation/quickstart Example output from the validation command, showing a violation of the IAM domain constraint because the provided email is not from a service account. ```json [ { "constraint": "GCPIAMAllowedPolicyMemberDomainsConstraintV2.service_accounts_only", "constraint_config": { "api_version": "constraints.gatekeeper.sh/v1alpha1", "kind": "GCPIAMAllowedPolicyMemberDomainsConstraintV2", "metadata": { "annotations": { "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.", "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only", "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml" }, "name": "service-accounts-only" }, "spec": { "match": { "target": [ "organizations/**" ] }, "parameters": { "domains": [ "gserviceaccount.com" ] }, "severity": "high" } }, "message": "IAM policy for //cloudresourcemanager.googleapis.com/projects/PROJECT_ID contains member from unexpected domain: user:user@example.com", "metadata": { "ancestry_path": "organizations/ORG_ID/projects/PROJECT_ID", "constraint": { "annotations": { "description": "Checks that members that have been granted IAM roles belong to allowlisted domains.", "validation.gcp.forsetisecurity.org/originalName": "service_accounts_only", "validation.gcp.forsetisecurity.org/yamlpath": "policies/constraints/iam_service_accounts_only.yaml" }, "labels": {}, "parameters": { "domains": [ "gserviceaccount.com" ] } }, "details": { "member": "user:user@example.com", "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID" } }, "resource": "//cloudresourcemanager.googleapis.com/projects/PROJECT_ID", "severity": "high" } ] ``` -------------------------------- ### Create a Service Account with gcloud Source: https://docs.cloud.google.com/docs/terraform/authentication Use this command to create a new service account. Replace SERVICE_ACCOUNT_NAME with your desired name. ```bash gcloud iam service-accounts create SERVICE_ACCOUNT_NAME ``` -------------------------------- ### Test Flask app with curl Source: https://docs.cloud.google.com/docs/terraform/deploy-flask-web-server Uses curl to send an HTTP GET request to the Flask application running on localhost:5000 within the VM. ```bash curl http://0.0.0.0:5000 ``` -------------------------------- ### Conditionally Instantiate Resource with `count` Source: https://docs.cloud.google.com/docs/terraform/best-practices/general-style-structure Use the `count` meta-argument to conditionally create a resource. This example prevents resource creation when the `readers` list is empty. ```terraform variable "readers" { description = "..." type = list default = [] } resource "resource_type" "reference_name" { // Do not create this resource if the list of readers is empty. count = length(var.readers) == 0 ? 0 : 1 ... } ``` -------------------------------- ### Create Output Directory Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Create a directory to store the exported Terraform configuration files. ```bash mkdir OUTPUT_DIRECTORY ``` -------------------------------- ### Display Terraform Configuration Source: https://docs.cloud.google.com/docs/terraform/get-started-with-terraform View the contents of the main.tf file, which defines the Google Cloud resources to be created. ```bash cat main.tf ``` -------------------------------- ### Import Block for VPC Network Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Example of an import block for a Virtual Private Cloud network. Specify the provider-defined resource ID and the Terraform resource address. ```hcl import { # Provider-defined resource ID of the cloud resource to be imported id = "projects/PROJECT_ID/global/networks/my-network" # Terraform resource address to be created to = google_compute_network.my_network } ``` -------------------------------- ### Sample Terraform Plan JSON Data Source: https://docs.cloud.google.com/docs/terraform/policy-validation/create-terraform-constraints This is an example of the resource change data structure found in a Terraform plan JSON. It is used as input for constraint validation. ```json { "format_version": "0.2", "terraform_version": "1.0.10", "resource_changes": [ { "address": "google_compute_address.internal_with_subnet_and_address", "mode": "managed", "type": "google_compute_address", "name": "internal_with_subnet_and_address", "provider_name": "registry.terraform.io/hashicorp/google", "change": { "actions": [ "create" ], "before": null, "after": { "address": "10.0.42.42", "address_type": "INTERNAL", "description": null, "name": "my-internal-address", "network": null, "prefix_length": null, "region": "us-central1", "timeouts": null }, "after_unknown": { "creation_timestamp": true, "id": true, "network_tier": true, "project": true, "purpose": true, "self_link": true, "subnetwork": true, "users": true }, "before_sensitive": false, "after_sensitive": { "users": [] } } } ], // other data } ``` -------------------------------- ### Export Project Configuration to Directory Structure Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Export your project's entire configuration to a specified directory. The `--path` flag indicates the output location, and the HCL code for each resource will be saved in separate .tf files within a structured hierarchy. ```bash gcloud beta resource-config bulk-export \ --path=OUTPUT_DIRECTORY \ --project=PROJECT_ID \ --resource-format=terraform ``` -------------------------------- ### Pin Module Version with Constraint Source: https://docs.cloud.google.com/docs/terraform/best-practices/reusable-modules When referencing a shared module, use a version constraint to pin to the major version for stability. This example pins to version 20.0. ```terraform module "gke" { source = "terraform-google-modules/kubernetes-engine/google" version = "~> 20.0" } ``` -------------------------------- ### Get Project ID in Cloud Shell Source: https://docs.cloud.google.com/docs/terraform/resource-management/managing-infrastructure-as-code Use this command to retrieve the ID of your currently configured Google Cloud project within the Cloud Shell environment. ```bash gcloud config get-value project ``` -------------------------------- ### Recommended Output for Instance Name Source: https://docs.cloud.google.com/docs/terraform/best-practices/general-style-structure This snippet shows the recommended way to define an output that references an attribute from a resource, ensuring it's part of the dependency graph. ```Terraform output "name" { description = "Name of instance" value = google_compute_instance.main.name } ``` -------------------------------- ### Define Minimum Required Provider Versions Source: https://docs.cloud.google.com/docs/terraform/best-practices/reusable-modules Shared modules must define the minimum required provider versions in a `required_providers` block. This example specifies a minimum version of 4.0.0 for the Google provider. ```terraform terraform { required_providers { google = { source = "hashicorp/google" version = ">= 4.0.0" } } } ``` -------------------------------- ### Define Compute Engine VM resource in Terraform Source: https://docs.cloud.google.com/docs/terraform/deploy-flask-web-server Creates a Debian 11 Compute Engine instance with the f1-micro machine type and installs Flask using a startup script. An external IP is assigned. ```hcl # Create a single Compute Engine instance resource "google_compute_instance" "default" { name = "flask-vm" machine_type = "f1-micro" zone = "us-west1-a" tags = ["ssh"] boot_disk { initialize_params { image = "debian-cloud/debian-11" } } # Install Flask metadata_startup_script = "sudo apt-get update; sudo apt-get install -yq build-essential python3-pip rsync; pip install flask" network_interface { subnetwork = google_compute_subnetwork.default.id access_config { # Include this section to give the VM an external IP address } } } ``` -------------------------------- ### Example CAI Asset Data for Compute Address Source: https://docs.cloud.google.com/docs/terraform/policy-validation/create-cai-constraints This JSON represents a sample export of a Google Cloud Compute Address resource as Cloud Asset Inventory data. It is used for developing and testing Rego policies. ```json [ { "name": "//compute.googleapis.com/projects/789/regions/us-central1/addresses/my-internal-address", "asset_type": "compute.googleapis.com/Address", "ancestors: [ "organization/123", "folder/456", "project/789" ], "resource": { "version": "v1", "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/compute/v1/rest", "discovery_name": "Address", "parent": "//cloudresourcemanager.googleapis.com/projects/789", "data": { "address": "10.0.42.42", "addressType": "INTERNAL", "name": "my-internal-address", "region": "projects/789/global/regions/us-central1" } } }, ] ``` -------------------------------- ### Plan Import with Configuration Generation Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Use the `terraform plan` command with the `-generate-config-out` flag to preview import operations and generate resource configuration files. ```bash terraform plan -generate-config-out=generated_resources.tf ``` -------------------------------- ### Skip Stages in Terratest Source: https://docs.cloud.google.com/docs/terraform/best-practices/testing Control which stages of a Terratest run are executed by setting environment variables. For example, `SKIP_STAGE_NAME="true"` will skip the specified stage, allowing focused testing on specific parts of the infrastructure. ```bash SKIP_STAGE_NAME="true" ``` -------------------------------- ### Project Root Module with GCS Backend and Project Factory Module Source: https://docs.cloud.google.com/docs/terraform/best-practices/root-modules This snippet shows a project's root module configuration, including the backend definition for Google Cloud Storage and the instantiation of a project factory module. It also demonstrates how to expose the project ID as an output. ```terraform # Project root module terraform { backend "gcs" { bucket = "BUCKET" } } module "project" { source = "terraform-google-modules/project-factory/google" ... } output "project_id" { value = module.project.project_id description = "The ID of the created project" } ``` -------------------------------- ### Networks Root Module Referencing Remote State Source: https://docs.cloud.google.com/docs/terraform/best-practices/root-modules This example illustrates a networks root module that utilizes data from a remote state source to configure network resources. It fetches the project ID from a remote GCS backend to use in its own module instantiation. ```terraform # Networks root module data "terraform_remote_state" "network_project" { backend = "gcs" config = { bucket = "BUCKET" } } module "vpc" { source = "terraform-google-modules/network/google" version = "~> 9.0" project_id = data.terraform_remote_state.network_project.outputs.project_id network_name = "vpc-1" ... } ``` -------------------------------- ### Export Resource Types Using a File Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Use the `--resource-types-file` flag to specify a file containing the list of resource types to export. The `--path` flag indicates the output directory. ```bash gcloud beta resource-config bulk-export \ --resource-types-file=types.txt \ --path=tf-output \ --project=PROJECT_ID \ --resource-format=terraform ``` -------------------------------- ### Enable Google Cloud APIs Source: https://docs.cloud.google.com/docs/terraform/resource-management/managing-infrastructure-as-code Enable the necessary Google Cloud APIs for Cloud Build and Compute Engine. This command ensures that the required services are active for your project. ```bash gcloud services enable cloudbuild.googleapis.com compute.googleapis.com ``` -------------------------------- ### Display Main Terraform Configuration Source: https://docs.cloud.google.com/docs/terraform/resource-management/store-state View the contents of the main.tf file, which defines the resources for the remote backend. ```bash cat main.tf ``` -------------------------------- ### CI/CD Pipeline for Terraform Policy Validation Source: https://docs.cloud.google.com/docs/terraform/policy-validation/validate-policies This bash script demonstrates how to use `gcloud beta terraform vet` within a CI/CD pipeline. It plans, shows the plan in JSON, clones a policy library, vets the plan against policies, and conditionally proceeds with `terraform apply` based on the validation results. ```bash terraform plan -out=tfplan.tfplan terraform show -json ./tfplan.tfplan > ./tfplan.json git clone POLICY_LIBRARY_REPO POLICY_LIBRARY_DIR VIOLATIONS=$(gcloud beta terraform vet tfplan.json --policy-library=POLICY_LIBRARY_DIR --format=json) retVal=$? if [ $retVal -eq 2 ]; then # Optional: parse the VIOLATIONS variable as json and check the severity level echo "$VIOLATIONS" echo "Violations found; not proceeding with terraform apply" exit 1 fi if [ $retVal -ne 0]; then echo "Error during gcloud beta terraform vet; not proceeding with terraform apply" exit 1 fi echo "No policy violations detected; proceeding with terraform apply" terraform apply ``` -------------------------------- ### Import Existing Compute Instance with Terraform CLI Source: https://docs.cloud.google.com/docs/terraform/understanding-apis-and-terraform Use the `terraform import` command to bring an existing Google Compute Engine instance under Terraform management. Ensure the resource ID format is correct for your instance. ```bash terraform import google_compute_instance.my_instance projects/your-gcp-project-id/zones/us-central1-a/instances/my-vm ``` -------------------------------- ### Test Rego with Sample Data Source: https://docs.cloud.google.com/docs/terraform/policy-validation/create-cai-constraints Use this Rego test file to validate your policy logic with sample data. Ensure your data.json is placed in the correct fixtures directory. ```rego package templates.gcp.GCPComputeAddressAddressTypeAllowlistConstraintV1 import data.test.fixtures.gcp_compute_address_address_type_allowlist_constraint_v1_test.assets as assets test_violation_with_disallowed_address_type { parameters := { "allowed_address_types": "EXTERNAL" } violations := violation with input.review as assets[_] with input.parameters as parameters count(violations) == 1 } ``` -------------------------------- ### Enable Cloud Storage API Source: https://docs.cloud.google.com/docs/terraform/resource-management/store-state Enable the Cloud Storage API for your Google Cloud project. This is necessary for creating and managing Cloud Storage buckets. ```bash gcloud services enable storage.googleapis.com ``` -------------------------------- ### Create Service Account for Export Source: https://docs.cloud.google.com/docs/terraform/resource-management/export Create a service account that will be used for the export process. This service account needs specific roles to perform the export. ```bash gcloud beta services identity create --service=cloudasset.googleapis.com ``` -------------------------------- ### Clone Terraform GitOps Repository Source: https://docs.cloud.google.com/docs/terraform/resource-management/managing-infrastructure-as-code Clone your forked infrastructure repository into Cloud Shell to begin managing your infrastructure as code. ```bash cd ~ git clone https://github.com/YOUR_GITHUB_USERNAME/solutions-terraform-cloudbuild-gitops.git cd ~/solutions-terraform-cloudbuild-gitops ``` -------------------------------- ### Export Resources as Terraform Configuration Source: https://docs.cloud.google.com/docs/terraform/resource-management/import Run the bulk export command to output the project's entire configuration to a specified directory in Terraform format. ```bash gcloud beta resource-config bulk-export \ --path=OUTPUT_DIRECTORY \ --project=PROJECT_ID \ --resource-format=terraform ``` -------------------------------- ### Basic Flask application Source: https://docs.cloud.google.com/docs/terraform/deploy-flask-web-server A simple Flask application that runs on all interfaces and responds with 'Hello Cloud!' to requests on the root path. ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello_cloud(): return 'Hello Cloud!' app.run(host='0.0.0.0') ``` -------------------------------- ### Apply Terraform Configuration Source: https://docs.cloud.google.com/docs/terraform/get-started-with-terraform Provision the Google Cloud resources defined in your Terraform configuration by applying the plan. You will be prompted to confirm the action. ```bash terraform apply ``` -------------------------------- ### Terraform Apply Output for Production Environment Source: https://docs.cloud.google.com/docs/terraform/resource-management/managing-infrastructure-as-code This output confirms the successful application of Terraform configurations to the production environment, detailing the created resources. ```bash Step #3 - "tf apply": external_ip = EXTERNAL_IP_VALUE Step #3 - "tf apply": firewall_rule = prod-allow-http Step #3 - "tf apply": instance_name = prod-apache2-instance Step #3 - "tf apply": network = prod Step #3 - "tf apply": subnet = prod-subnet-01 ``` -------------------------------- ### Generate Terraform Plan Source: https://docs.cloud.google.com/docs/terraform/policy-validation/quickstart Creates a Terraform plan file, which outlines the changes that will be applied to your infrastructure. You may be prompted to authorize this action. ```bash terraform plan -out=test.tfplan ```