Terraform with Google Cloud
Terraform with Google Cloud
Google Cloud Overview: 2 Hrs
Introduction to Infrastructure as a code 1hr
- Overview of infrastructure as code (Iac)
- Infrastructure provisioning tools - Terraform and its benefits
Getting started & Setting Up Labs 1hr
- Terraform installation
- Gitbash installation (ide)
- Vscode installation and setup
- Install Terraform plugins in Vscode
- Setting up google cloud account
READ, GENERATE & MODIFY CONFIGURATION 2 hrs
- Hashicorp configuration language (Hcl)
- Terraform configure files
- Terraform state file
- Start to build code
Know Terraform Providers 2 hrs
- Local
- Google Cloud
- Random
- AWS
- Azurerm
Terraform Providers and Datasources 2hrs
- Arguments and Attributes
Google Cloud Overview
- Create Google Cloud Free Account
- Create Project
- Assign access to the newly created project.
- Download and Install Vscode Click Here
- Download and Install terraform Click Here
- Download and Install Gitbash
- Create Account on Gitlab
- Walk through Google Cloud IAM
- Create VM on GCP
- Create a Firewall rule
- Create a service Account and assign permission.
- Configure Google Cloud cli
Steps to Create a virtual Machine
- provider Code
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.20.0"
}
}
}
provider "google" {
# Configuration options
project = "quiet-fusion-348804"
region = "us-central1"
zone = "us-central1-c"
credentials = file("admin.json")
}
- Vm code
resource "google_compute_instance" "default" {
name = "test"
machine_type = "e2-medium"
zone = "us-central1-a"
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-11-bullseye-v20220406"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral public IP
}
}
metadata = {
foo = "bar"
}
}
```t
- Code for Metadata (ssh keys)
```t
resource "google_compute_project_metadata" "my_ssh_key" {
metadata = {
ssh-keys = <<EOF
sssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqU07gbxzO3oeNIX2gq6hmOXPk79HV+YCshoHHlloOGwy1EgRlVtPHVLQDaPpvx1xNn4UFeaKvqpcOZctWQsugq1Zo51V4yhMCEbVGfcyKhgsIuRMBkzimAeeZV77mzaLzNQxeNHOzFBprSuaw63ODtqW+FYOq+RzqfPvohr2UdTT07Ki7IQYhbLJ9zuVTfQIn/ELE59z41vrCBeyZH9Om2Orgz4CKilamY5WDBuYFJqw8QhMKVwRiF+vsJS7iLeo1pPufbRBZqvtA5eU0rG2hjTcJBYsXuKswtelwzgTXmUI/c0cRcjp+4/UYVCh4StUrlRHphDct+qyloSzT+E1zXTIKWfml+0nAnOQIP+V98fzdHHzuYPebVS9mcDbuNz/TZaxtV0RWFt1cTEWBwNZGTpB2tUqUAqJgW5yc9kHKFMm5BDpAiMPQDJUIjLUc1DbHLPOy+Gd7annuFdcGnAVJvSud8yJYNg/ABc3PmB+WyWjnGLk6eUjk6PS708sjYtM= nippy
EOF
}
}
- How to create ssh keys
ssh-keygen -f <keyname>
-
Update network tag for a vm
-
update a vm size for a vm
-
Update deletion protection
-
Update label
-
Update metadata script
-
update service account
-
Create Disk
-
Attach Disk
-
Increase the size of Disk
-
VM code with metadata script
-
Know about multiple provider
-
Visit to terrform registry to check all providers
-
Terraform Lock file
-
check the terraform next version available
-
know the ways to delete resources
-
Create a branch on project and push the code for session wise
# Create a single Compute Engine instance
resource "google_compute_instance" "default" {
name = "flask-vm"
machine_type = "f1-micro"
zone = "us-west1-a"
tags = ["ssh"]
metadata = {
enable-oslogin = "TRUE"
}
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
# Install Flask
metadata_startup_script = "sudo apt-get update; sudo apt-get install -yq build-essential python-pip rsync; pip install flask"
network_interface {
network = "default"
access_config {
# Include this section to give the VM an external IP address
}
}
}
- Create a Firewall rule
resource "google_compute_firewall" "ssh" {
name = "allow-ssh"
allow {
ports = ["22"]
protocol = "tcp"
}
direction = "INGRESS"
network = "default"
priority = 1000
source_ranges = ["0.0.0.0/0"]
target_tags = ["ssh"]
}
Documents from Gooogle Cloud
- Terraform Best practices Terraform Best Practices
Export your Google Cloud resources into Terraform format
- List Project id
gcloud config list project
registry.terraform.io/hashicorp/google.
- Create a network
resource "google_compute_network" "vpc_network" {
name = "terraform-network"
}
- Use the newly create network with vm
resource "google_compute_instance" "vm_instance" {
name = "terraform-instance"
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = google_compute_network.vpc_network.name
access_config {
}
}
}
- Create a static ip
resource "google_compute_address" "vm_static_ip" {
name = "terraform-static-ip"
}
- Update vm with static ip
network_interface {
network = google_compute_network.vpc_network.self_link
access_config {
nat_ip = google_compute_address.vm_static_ip.address
}
}
- Dependency with bucket
# New resource for the storage bucket our application will use.
resource "google_storage_bucket" "example_bucket" {
name = "<UNIQUE-BUCKET-NAME>"
location = "US"
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
}
# Create a new instance that uses the bucket
resource "google_compute_instance" "another_instance" {
# Tells Terraform that this VM instance must be created only after the
# storage bucket has been created.
depends_on = [google_storage_bucket.example_bucket]
name = "terraform-instance-2"
machine_type = "f1-micro"
boot_disk {
initialize_params {
image = "cos-cloud/cos-stable"
}
}
network_interface {
network = google_compute_network.vpc_network.self_link
access_config {
}
}
}
Datasources
data "google_project" "project" {
}
output "project" {
value = data.google_project.project.name
}
output "hhh" {
value = "hello world"
}
data "google_compute_network" "my-network" {
name = "default-us-east1"
}
output "network" {
value = data.google_compute_network.my-network.name
}
data "google_compute_regions" "available" {
}
output "region" {
value = data.google_compute_regions.available.names
}
- Google Cloud Compute Zone
data "google_compute_zones" "available" {
}
resource "google_compute_instance_group_manager" "foo" {
count = length(data.google_compute_zones.available.names)
name = "terraform-test-${count.index}"
instance_template = google_compute_instance_template.foobar.self_link
base_instance_name = "foobar-${count.index}"
zone = data.google_compute_zones.available.names[count.index]
target_size = 1
}
- Create vm as per the availablity zone
resource "google_compute_instance" "default" {
name = "foobar${count.index}"
machine_type = "e2-medium"
zone = data.google_compute_zones.available.names[count.index]
tags = ["jenkins"]
count = length(data.google_compute_zones.available.names)
boot_disk {
initialize_params {
image = "debian-11-bullseye-v20220406"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral public IP
}
}
metadata = {
foo = "bar"
}
}
- For each
resource "google_compute_instance" "default" {
for_each = toset(var.each)
name = "foobar${each.key}"
machine_type = "e2-medium"
zone = "${each.value}"
tags = ["jenkins"]
boot_disk {
initialize_params {
image = "debian-11-bullseye-v20220406"
}
}
network_interface {
subnetwork = google_compute_subnetwork.default.self_link
access_config {
// Ephemeral public IP
}
}
metadata = {
foo = "bar"
}
}
### Learn for for each
variable "each" {
default = ["us-central1-a","us-central1-b","us-central1-c"]
}
- List the active account name
gcloud auth list
- List the project ID
gcloud config list project
- Create a new instance using Gcloud shell
gcloud compute instances create [INSTANCE_NAME] --machine-type n1-standard-2 --zone [ZONE_NAME]
- SSH in to the machine
gcloud compute ssh [INSTANCE_NAME] --zone [YOUR_ZONE]
- RDP a windows server
gcloud compute instances get-serial-port-output [INSTANCE_NAME] --zone [ZONE_NAME]
- Command to check whether the server is ready for an RDP connection
gcloud compute instances get-serial-port-output
- Create a Storage bucket
gsutil mb gs://[BUCKET_NAME]
- Copy a file in to the bucket
gsutil cp [FILE_NAME] gs://[BUCKET_NAME]
- Setting up default compute zone
gcloud config set compute/zone [ZONE_NAME]
- Set the default region:
gcloud config set compute/region [REGION_NAME]
- List the compute engine instances created:
gcloud compute instances list
- Create Kubernetes Cluster
gcloud container clusters create [CLUSTER-NAME]
- Get authentication credentials for the cluster
gcloud container clusters get-credentials [CLUSTER-NAME]
- Stop a vm
gcloud compute instances stop [INSTANCE-NAME]
Day2:
- Variables
- Meta Arguments
- Google Cloud Networking
- Conditions
- Local Values
- Terraform taint and untaint
- Terraform refresh commands
Terraform Variables 2 hrs
- Variable Block
- Approaches for Variable Assignment
- Datatypes for variables
- Fetching data from Map and List
- Count and Count Index
- Conditional Expressions
- Local Values
- Terraform Functions
TERRAFORM PROVISIONER 2 hrs
-
Understanding Provisioners in Terraform
-
Types of Provisioners
-
Implementing remote-exec provisioners
-
Implementing local-exec provisioners
-
Creation-Time & Destroy-Time Provisioners
-
Failure Behavior for Provisioners
Terraform Modules & Workspaces 2 hrs
- Understand DRY principle
- Creating modules for Google Cloud vm
- Creating modules for Google Cloud VPC
- Creating modules for google storage
- Terraform Registry
- Terraform Workspace
- Implementing Terraform workspace
REMOTE STATE MANAGEMENT 2 hrs
- Integrating with GIT for team management
- Security Challenges in Commiting TFState to GIT
- Module Sources in Terraform
- Terraform .gitignore and .terraform
- Remote State Management with Terraform
- Implementing google storage Backend
- Challenges with State File locking
- Terraform State Management
- Importing Existing Resources with Terraform Import
- Document - Remote State Management
- Terraform state pull
- Terraform refresh on state
https://blog.boltops.com/2020/10/03/terraform-hcl-conditional-logic/
- Understand conditions
output "a1" {
value = true ? "is true" : "is false"
}
output "a2" {
value = false ? "is true" : "is false"
}
output "a3" {
value = 1 == 2 ? "is true" : "is false"
}
- More Examples
output "b1" {
value = contains(["a","b","c"], "d") ? "is true" : "is false"
}
output "b2" {
value = keys({a: 1, b: 2, c: 3}) == ["a","b","c"] ? "is true" : "is false"
}
output "b3" {
value = contains(keys({a: 1, b: 2, c: 3}), "b") ? "is true" : "is false"
}
- Dynamic Blocks examples
resource "aws_security_group" "simple" {
name = "demo-simple"
description = "demo-simple"
ingress {
description = "description 0"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "description 1"
from_port = 81
to_port = 81
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
locals {
ports = [80, 81]
}
resource "aws_security_group" "dynamic" {
name = "demo-dynamic"
description = "demo-dynamic"
dynamic "ingress" {
for_each = local.ports
content {
description = "description ${ingress.key}"
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
- Terraform: Variable validation with samples
variable "my_var" {
type = number
default = 0
validation {
condition = var.my_var >= 0
error_message = "Please set my_var to a positive number or 0."
}
}
- Validating the length of a string
# file: variables.tf
variable "hetzner_api_token" {
type = string
description = "Hetzner API token"
validation {
condition = length(var.hetzner_api_token) == 64
error_message = "Must be a 64 character long Hetzner API token."
}
}
- more example
variable "resource_name" {
type = string
description = "Input name of the resource."
validation {
condition = length(var.resource_name) > 5
error_message = "The resource_name must be greater than 5 characters in length."
}
}
variable "string_may_not_contain" {
type = string
default = "test"
validation {
error_message = "Value cannot contain a \"/\"."
condition = !can(regex("/", var.string_may_not_contain))
}
}
variable "string_only_valid_options" {
type = string
default = "approved"
# using regex
validation {
condition = can(regex("^(approved|disapproved)$", var.string_only_valid_options))
error_message = "Invalid input, options: \"approved\", \"disapproved\"."
}
# using contains()
validation {
condition = contains(["approved", "disapproved"], var.string_only_valid_options)
error_message = "Invalid input, options: \"approved\", \"disapproved\"."
}
}
variable "string_like_aws_region" {
type = string
default = "us-east-1"
validation {
condition = can(regex("[a-z][a-z]-[a-z]+-[1-9]", var.string_like_aws_region))
error_message = "Must be valid AWS Region names."
}
variable "num_in_range" {
type = number
default = 1
validation {
condition = var.num_in_range >= 1 && var.num_in_range <= 16 && floor(var.num_in_range) == var.num_in_range
error_message = "Accepted values: 1-16."
}
}
- Code for VPC peering
resource "google_compute_network_peering" "peering1" {
name = "peering1"
network = google_compute_network.default.self_link
peer_network = google_compute_network.other.self_link
}
resource "google_compute_network_peering" "peering2" {
name = "peering2"
network = google_compute_network.other.self_link
peer_network = google_compute_network.default.self_link
}
resource "google_compute_network" "default" {
name = "foobar"
auto_create_subnetworks = "false"
}
resource "google_compute_network" "other" {
name = "other"
auto_create_subnetworks = "false"
}
- Used code for session
### Create a vpc
resource "google_compute_network" "vpc_network" {
name = "vnet01"
auto_create_subnetworks = false
mtu = 1460
}
#### Create a subnet
``t
resource "google_compute_subnetwork" "default" {
name = "test-subnetwork"
ip_cidr_range = "192.168.1.0/24"
region = "us-central1"
network = google_compute_network.vpc_network.self_link
}
Create a firewall rule for ssh allow
resource "google_compute_firewall" "ssh" {
name = "allow-ssh-vnet01"
allow {
ports = ["22","80"]
protocol = "tcp"
}
direction = "INGRESS"
network = "vnet01"
priority = 1001
source_ranges = ["0.0.0.0/0"]
}
resource "google_compute_network" "vpc_network1" {
name = "vnet02"
auto_create_subnetworks = false
mtu = 1460
}
Create a subnet
resource "google_compute_subnetwork" "default1" {
name = "test-subnetwork"
ip_cidr_range = "192.168.2.0/24"
region = "us-west1"
network = google_compute_network.vpc_network1.self_link
}
resource "google_compute_firewall" "ssh-vnet02" {
name = "allow-ssh-vnet02"
allow {
ports = ["22","80"]
protocol = "tcp"
}
direction = "INGRESS"
network = "vnet02"
priority = 1002
source_ranges = ["0.0.0.0/0"]
}
VPC Peering for vnet01 and vnet02
resource "google_compute_network_peering" "peering1" {
name = "peering1"
network = google_compute_network.vpc_network.self_link
peer_network = google_compute_network.vpc_network1.self_link
}
resource "google_compute_network_peering" "peering2" {
name = "peering2"
network = google_compute_network.vpc_network1.self_link
peer_network = google_compute_network.vpc_network.self_link
}
Day3:
- Terraform State Management
- Terraform Workspace
- Terraform Provisioner
- Terraform Troubleshooting
- Terraform Logging
- Terrform Meta Argument for_each
- Terrform conditinal expressions
- Terraform functions
- Terraform Module
TERRAFORM CLOUD & ENTERPRISE CAPABILITIES 2hrs
- Terraform cloud enterprise
- Terraform cloud
- Terraform cloud workflow
- Terraform enterprise
- Terraform registry
- Terraform best practices
Infrastructure as Code with Terraform and GitLab 2 hrs
- GitLab CI - Introduction
- GitLab - CI/CD
- GitLab - CI/CD Variables
- GitLab CI - Permissions
- Configuring GitLab Runners
- Terraform and Gitlab Integration
Infrastructure as Code with Terraform and Jenkins 2 hrs
-
Introduction to Jenkins
-
Jenkins - CI/CD Variables
-
Jenkins Plugins
-
Jenkins Pipelines
-
Jenkins Triggers
-
Jenkins Upstream and Downstream jobs
-
Configuring Jenkins Agents
-
Execute Terraform with Jenkins Pipeline
Install Terraform plugin
Go to Manage Jenkins > Manage Plugins >Available > search Terraform.
Configure Terraform
Go to Manage Jenkins > Global Tool Configuration > It will display Terraform on the list.
- For_Each Example
resource "google_compute_instance" "default" {
for_each = toset(var.each)
name = "foobar${each.key}"
machine_type = "e2-medium"
zone = "${each.value}"
tags = ["jenkins"]
boot_disk {
initialize_params {
image = "debian-11-bullseye-v20220406"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral public IP
}
}
metadata = {
foo = "bar"
}
}
### Learn for for each
variable "each" {
default = ["us-central1-a","us-central1-b","us-central1-c"]
}
resource "google_compute_instance" "default" {
for_each = toset(var.each)
name = "foobar${each.key}"
machine_type = "e2-medium"
zone = "${each.value}"
tags = ["jenkins"]
boot_disk {
initialize_params {
image = "debian-11-bullseye-v20220406"
}
}
network_interface {
network = "default"
access_config {
// Ephemeral public IP
}
}
metadata = {
foo = "bar"
}
}
### Learn for for each
variable "each" {
default = ["us-central1-a","us-central1-b","us-central1-c"]
}
- Add ssh key to login
resource "google_compute_project_metadata" "my_ssh_key" {
metadata = {
ssh-keys = <<EOF
nippy:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCqU07gbxzO3oeNIX2gq6hmOXPk79HV+YCshoHHlloOGwy1EgRlVtPHVLQDaPpvx1xNn4UFeaKvqpcOZctWQsugq1Zo51V4yhMCEbVGfcyKhgsIuRMBkzimAeeZV77mzaLzNQxeNHOzFBprSuaw63ODtqW+FYOq+RzqfPvohr2UdTT07Ki7IQYhbLJ9zuVTfQIn/ELE59z41vrCBeyZH9Om2Orgz4CKilamY5WDBuYFJqw8QhMKVwRiF+vsJS7iLeo1pPufbRBZqvtA5eU0rG2hjTcJBYsXuKswtelwzgTXmUI/c0cRcjp+4/UYVCh4StUrlRHphDct+qyloSzT+E1zXTIKWfml+0nAnOQIP+V98fzdHHzuYPebVS9mcDbuNz/TZaxtV0RWFt1cTEWBwNZGTpB2tUqUAqJgW5yc9kHKFMm5BDpAiMPQDJUIjLUc1DbHLPOy+Gd7annuFdcGnAVJvSud8yJYNg/ABc3PmB+WyWjnGLk6eUjk6PS708sjYtM= nippy@ITEM-S84221
EOF
}
}
- Terraform Backend
https://www.terraform.io/language/settings/backends
[Terraform Backend](https://www.terraform.io/language/settings/backends)
- Example for for_each
resource "google_compute_instance" "default" {
for_each = var.images
name = "${each.key}"
machine_type = var.machine_type
zone = "${each.value}"
allow_stopping_for_update = true
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
}
}
metadata = {
foo = "${each.key}"
value = "${each.value}"
}
metadata_startup_script = "echo hi > /test.txt"
}
- variables used for above code.
variable "name" {
default = "tree1"
description = "This variable will be used for vm name"
}
variable "machine_type" {
default = "e2-medium"
description = "This is for machine type"
}
variable "zone" {
default = "us-central1-a"
}
variable "myvms" {
default = ["prd","qa","dev"]
}
variable "images" {
type = map
default = {
dev = "us-central1-a"
prd = "us-central1-b"
qa = "us-central1-c"
}
}
- Terraform condition
resource "google_compute_instance" "default" {
name = var.name
machine_type = var.machine_type
zone = var.name!="prd" ? "us-central1-a" : "us-central1-b"
allow_stopping_for_update = true
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
}
}
metadata = {
foo = "news"
value = "paper"
}
metadata_startup_script = "echo hi > /test.txt"
}
- Provisioner Example with connection
resource "google_compute_instance" "default" {
name = var.name
machine_type = var.machine_type
zone = "us-central1-a"
allow_stopping_for_update = true
tags = ["foo", "bar"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
network = "default"
access_config {
}
}
metadata = {
foo = "news"
value = "paper"
}
metadata_startup_script = "echo hi > /test.txt"
provisioner "local-exec" {
command = "echo ${self.network_interface.0.network_ip} >> private_ips.txt"
}
provisioner "file" {
source = "provider.tf"
destination = "/tmp/admin.tf"
}
connection {
type = "ssh"
user = "admin"
private_key = file("admin")
host = "${self.network_interface.0.access_config.0.nat_ip}"
}
}
Day 4:
- Terraform Cloud
- Terraform Sentinel Policies
- Terraform with Jenkins
- Terraform with Gitlab
Terraform Authentication with Google Cloud 2 hrs
- Google Cloud Free Trial Account
- Google Cloud Project - Service Account
- Google Provider & version
- Connect Terraform with GCP - I (username/password)
- Connect Terraform with GCP - II (Cloud Shell VM)
- Connect Terraform with GCP - III (Service Account)
- Approach to Resource Provision
Terraform for Google Storage 2 hrs
- [Hands-on] Getting started with Cloud Storage
- [Hands-on] Google Cloud Storage with Terraform - I
- [Hands-on] Google Cloud Storage with Terraform - II
- [Hands-on] Google Cloud Storage with Terraform - III
Terraform for Google Network 2hrs
- [Hands-on] Create VPC from Console
- [Hands-on] Create VPC with Terraform Script
- [Hands-on] Create VPC peering
- [Hands-on] Configure DNS with Terraform
- [Hands-on] Create Subnet - Terraform
- [Hands-on] Create Firewall Rule – Terraform
Terraform for Compute Engine 2 hrs
- [Hands-on] Create Compute Engine - Console
- [Hands-on] Compute Engine - Terraform - I
- [Hands-on] Compute Engine - Terraform - II
- Update Compute Engine parameter - Tearraform
- [Hands-on] Service Account - Terraform
- [Hands-on] Attach Disk - Terraform
- Destroy GCE resources
Terraform for Google Container and Kubernetes 2hrs
-
Setting up Kubernetes standard cluster
-
Setting up Kubernetes cluster(Autopilot)
-
Jenkins pipeline example
pipeline {
agent { label 'agnt' }
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
.Gitlab-ci.yaml file
stages:
- test
- dev
- prd
- destroy
Terraform-version:
stage: test
script:
- terraform version
Terraform-Initialize:
stage: test
script:
- terraform init
Define-variables:
stage: prd
script:
export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
Testing-varibale:
stage: test
script:
- echo $AWS_ACCESS_KEY_ID
Create-a-vm:
stage: dev
before_script:
- terraform init --reconfigure
script:
- terraform apply --auto-approve
destroy:
stage: destroy
script:
- terraform destroy --auto-approve
when: manual
only:
- main
Terraform Sentinel
GitHub Link for Terraform Sentinel Policy
- Enable Terraform Trial
- Create GitHub repo all policies
- Enable Sentinel policy on Terraform cloud
- Login to Terraform using Terraform login command
- Run terraform command from your local system.
More References
Team and Governance for Terraform
https://github.com/hashicorp/terraform-guides/tree/master/governance
https://www.terraform.io/cloud-docs/sentinel https://www.terraform.io/cloud-docs/sentinel/import
- sentinel.hcl
advisory soft-mandatory hard-mandatory
Sentinel Policies and sentinel.hcl
allowed-providers.sentinel enforce-mandatory-tags.sentinel limit-proposed-monthly-cost.sentinel restrict-vm-publisher.sentinel restrict-vm-size.sentinel sentinel.hcl
Terraform refresh
Terrafrom Trace Log Settings
export TF_LOG=TRACE export TF_LOG_PATH=“terraform-trace.log” echo $TF_LOG echo $TF_LOG_PATH
Linux Bash
cd $HOME vi .bashrc
Terraform log settings
export TF_LOG=TRACE export TF_LOG_PATH=“terraform-trace.log”
Verify after saving the file in new terminal
$ echo $TF_LOG TRACE $ echo $TF_LOG_PATH terraform-trace.log
- Jenkinsfile example
pipeline {
agent { label 'agent' }
stages {
stage('checkout the code') {
steps {
sh 'git clone https://github.com/monbostest/terraform-google-myvm.git'
}
}
stage('change the workspace') {
steps {
sh 'cd $WORKSPACE'
}
}
stage('Init') {
steps {
sh 'terraform init'
}
}
stage('Apply') {
steps {
sh 'terraform apply --auto-approve'
}
}
}
}