<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: waddy</title>
    <description>The latest articles on DEV Community by waddy (@waddy).</description>
    <link>https://dev.to/waddy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F311387%2Fc41b8c9d-567a-4463-80d6-b4a4448d1ee4.jpeg</url>
      <title>DEV Community: waddy</title>
      <link>https://dev.to/waddy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/waddy"/>
    <language>en</language>
    <item>
      <title>Getting started to using Terraform to manage Google Cloud resources</title>
      <dc:creator>waddy</dc:creator>
      <pubDate>Fri, 13 Jan 2023 06:49:59 +0000</pubDate>
      <link>https://dev.to/waddy/getting-started-to-using-terraform-to-manage-google-cloud-resources-o6a</link>
      <guid>https://dev.to/waddy/getting-started-to-using-terraform-to-manage-google-cloud-resources-o6a</guid>
      <description>&lt;p&gt;One of the tools for managing Google Cloud resources is &lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;. Let's use it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the gcloud command to be able to create Google Cloud credentials&lt;/li&gt;
&lt;li&gt;Create a Cloud Storage bucket for Terraform state management&lt;/li&gt;
&lt;li&gt;Initialize Terraform and deploy resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proceed with this flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install gcloud command
&lt;/h2&gt;

&lt;p&gt;Install the gcloud command locally. This command is used to connect the local machine to the Google Cloud project and generate credentials. It is also used to create a Cloud Storage bucket for managing Terraform state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/sdk/docs/install#mac" rel="noopener noreferrer"&gt;https://cloud.google.com/sdk/docs/install#mac&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My machine is macOS. Please refer to this document and consult with your environment to install it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Google Cloud project and generate credentials
&lt;/h2&gt;

&lt;p&gt;If you do not already have a Google Cloud project, create one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project" rel="noopener noreferrer"&gt;https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have created a Google Cloud project, you are ready to generate credentials. Credentials are necessary to connect to Google Cloud from your local machine, and there are two main ways to obtain them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;create a service account on Google Cloud and download the credential&lt;/li&gt;
&lt;li&gt;create a credential using your user account (@gmail.com) under which you created your Google Cloud project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here we will proceed with the second method.&lt;/p&gt;

&lt;p&gt;First, configure the gcloud config. Run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config configurations create &amp;lt;optional, but the name of the project you created is safe&amp;gt;.

# Example
gcloud configurations create graphql-training
Created [graphql-training].
Activated [graphql-training].
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, set the account name and project name to the created profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud config set core/account &amp;lt;the email address you used for your Google Cloud login&amp;gt;.
gcloud config set core/project &amp;lt;Project name for Google Cloud&amp;gt;.

# Example
gcloud config set core/account test@example.com
gcloud config set core/project graphql-training
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This operation updates the status of the gcloud command and sets the project name and account name as config. From here, a "login" operation will create credential information on the local machine. Enter the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth login 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A browser will then open and ask you to authenticate. Select the corresponding Google Cloud account and allow the integration. This will generate credentials on your local machine. The location is &lt;code&gt;~/.config/gcloud/credentials.db&lt;/code&gt;. This credential will be used when executing the following command line on the local machine&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gcloud &lt;/li&gt;
&lt;li&gt;bq # CLI for BigQuery&lt;/li&gt;
&lt;li&gt;gsutil # CLI for Cloud Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And one more authentication process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth application-default login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will also open a browser and ask you to authenticate. If you allow the linkage, another credential will be generated on your local machine. The location is &lt;code&gt;~/.config/gcloud/application_default_credentials.json.db&lt;/code&gt;. This credential is used for authentication when running programs using the Google Cloud SDK; Terraform will also use this file.&lt;/p&gt;

&lt;p&gt;Now you are ready to operate on your Google Project from your local machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create buckets for Terraform state management
&lt;/h2&gt;

&lt;p&gt;Terraform manages the state of resources created on Google Cloud with a file called &lt;code&gt;tfstate&lt;/code&gt; and detects differences. Of course, you can keep &lt;code&gt;tfstate&lt;/code&gt; locally, but if you work with colleagues, you can prevent conflicts by managing this file in cloud storage. Cloud Storage is available as shared storage, so let's manage the status here. We will use the &lt;code&gt;gsutil&lt;/code&gt; command, so install this command as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloud.google.com/storage/docs/gsutil_install" rel="noopener noreferrer"&gt;https://cloud.google.com/storage/docs/gsutil_install&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, create a bucket for state management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gsutil mb gs://&amp;lt;any bucket name&amp;gt;

# Example.
gsutil mb gs://graphql-training-artifacts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mb&lt;/code&gt; is making a bucket (maybe). It's Ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform initialization
&lt;/h2&gt;

&lt;p&gt;You can install Terraform and use it, but since Terraform provides Docker image as well, you don't need to install it. Create a bash file like the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#! /bin/bash

command=${@:1} 

docker run -it --rm \
  -v $PWD:/work \}
  -v $HOME/.config/gcloud:/.config/gcloud \
  -w /work \
  -e GOOGLE_APPLICATION_CREDENTIALS=/.config/gcloud/application_default_credentials.json \
  --entrypoint "/bin/sh" \ -e
  hashicorp/terraform:latest \
  -c "terraform $command"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are running the &lt;code&gt;terraform&lt;/code&gt; command using a container called &lt;code&gt;hashicorp/terraform&lt;/code&gt;. You are also using the credentials you just created on your local machine. Now, let's define the Terraform resources. Create the following file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_version = "~&amp;gt; 1.0.0"
  backend "gcs" {
    prefix = "tfstate/v1"
  }
}

## project ##
provider "google" {
  project = var.gcp_project_id
  region = var.primary_region
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file does not create a resource yet, but let's check it once it works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x tf.sh
./tf.sh init -backend-config="bucket=&amp;lt;bucket created by gsutil&amp;gt;"

# Example :
./tf.sh init -backend-config="bucket=graphql-training-artifacts"

---
Initializing the backend...

Successfully configured the backend "gcs"! Terraform will automatically
Terraform will automatically use this backend unless the backend configuration changes.

Initializing provider plugins...
- Finding the latest version of hashicorp/google-beta...
- Finding the latest version of hashicorp/google...
- Installing hashicorp/google-beta v4.6.0...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see something like this, you have succeeded. Please look at &lt;code&gt;graphql-training-artifacts/tfstate/v1&lt;/code&gt; in Google Cloud Storage in your browser. The state management file &lt;code&gt;default.tfstate&lt;/code&gt; should have been created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an Artifact Repository repository
&lt;/h2&gt;

&lt;p&gt;Once you've done this, you can create as many resources as you want. You can create any resources you want, create an Artifact Registry repository. Create the file &lt;code&gt;modules/artifact-registry.tf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tree
.
├── README.md
├──main.tf
├── modules
modules └── artifact-registry
modules │ └── artifact-registry.tf
└── tf.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "gcp_project_id" {}
variable "artifact_registry_location" {
  type = string
  # https://cloud.google.com/storage/docs/locations
  description = "Where to locate the Artifact Registry location."
}

# Artifact Registry repository for backend applications
resource "google_artifact_registry_repository" "backend" {
  provider = google-beta

  project = var.gcp_project_id
  location = var.artifact_registry_location
  repository_id = "backend"
  description = "backend application"
  format = "DOCKER"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also modify &lt;code&gt;main.tf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Artifact Registry repository to use for Cloud Run deployments.
+module "artifact-registry" {
+module "artifact-registry" { source = ". /modules/artifact-registry"
+ gcp_project_id = var.gcp_project_id
+ artifact_registry_location = var.primary_region
+}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see the &lt;code&gt;var.xxxx&lt;/code&gt; type of variable in the above example, you can incorporate information that you don't want to expose. Create a new file &lt;code&gt;variable.tf&lt;/code&gt; to inject values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "gcp_project_id" {}
variable "primary_region" {}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By defining this file, you can call it in your resource definitions like &lt;code&gt;var.gcp_project_id&lt;/code&gt;. Next, how do you inject the actual value? There are several ways, here we will use the create a &lt;code&gt;terraform.tfvars&lt;/code&gt; file and do not version control this file policy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/language/values/variables#variable-definitions-tfvars-files" rel="noopener noreferrer"&gt;https://www.terraform.io/language/values/variables#variable-definitions-tfvars-files&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcp_project_id = "gql-training"
primary_region = "us-central1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have set the values of the variables to be injected, let's run &lt;code&gt;init&lt;/code&gt; and &lt;code&gt;plan&lt;/code&gt;. These commands will not create any resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./tf.sh init

Initializing modules...
- artifact-registry in modules/artifact-registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you define a new module, you will need to do &lt;code&gt;init&lt;/code&gt; again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./tf.sh plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.artifact-registry.google_artifact_registry_repository.backend will be created
  + resource "google_artifact_registry_repository" "backend" {
      + create_time = (known after apply)
      + description = "backend application"
      + format = "DOCKER"
      + id = (known after apply)
      + location = "us-central1"
      + name = (known after apply)
      + project = "xxxxxxxxx"
      + repository_id = "backend"
      + update_time = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see something like this. If the plan is as you intended, type the command to actually apply it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./tf.sh apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may get an error message saying that you need to enable the API. Since Terraform uses such APIs to manage resources, some things can only be created with the API enabled. Just follow the guide and enable the API from your browser. After that, run it again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./tf.sh apply

Resources: 1 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a message like this, you are good to go. Finally, view the Artifact Registry in your browser and confirm that the resources have been created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--55c4UbaX--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa00f34d1c2ddd9a31b848d15.png%253Fsha%253D59bc4c53b0146757f7b58841d48bcde737cf55a1" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--55c4UbaX--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa00f34d1c2ddd9a31b848d15.png%253Fsha%253D59bc4c53b0146757f7b58841d48bcde737cf55a1" width="1200" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We created Google Cloud resources using Terraform. Please give it a try.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;The source code introduced in this article is available in the following repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cm-wada-yusuke/gql-nest-prisma-training/tree/main/google-cloud-terraform" rel="noopener noreferrer"&gt;https://github.com/cm-wada-yusuke/gql-nest-prisma-training/tree/main/google-cloud-terraform&lt;/a&gt;&lt;/p&gt;

</description>
      <category>data</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
