Working with Workspaces and Backends in Terraform
Tags: terraform, devops, aws, cloud
Published: 2021-04-30 21:02:08

Terraform manages infrastructure with state files. By default you have a single workspace, default. So when you run `terraform plan` and `terraform apply` you are working the default workspace prepared by terraform.
But with workspaces we can have multiple states. What this means, we can have different server setup with different state files managing that server setup(keep records of what has been deployed at every time). Also it cuts down the amount of copy and paste you will be doing.

To set up workspaces in terraform is very easy. The command `terraform workspace new <name of workspace>` does that. Assuming I needed different workspaces to keep tabs on my deployment for DEV, QA and PROD. This will be simply achieved by running-
`terraform workspace new DEV`, `terraform workspace new QA` and `terraform workspace new PROD`. This creates three different sub-folders under the *terraform.tfstate.d* folder
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ycxmyg9q1tc4gn3u25lo.png)

Workspace created! How do we run our Terraform code in a specific workspace? Simply run `terraform workspace select <name of workspace>`. Terraform will throw you a prompt on what workspace you are working in. Go head and run `terraform plan` and `terraform apply`
___
This is all well and good if you are building infrastructure alone because you are an amazing engineer. More often than not, tasks are performed in teams and we need some collaboration to get things done effectively. How do we achieve this with workspaces🤔? We should use some backend to store these state files✨😎.

Using AWS as our provider, I'll demonstrate 
___
We create an S3 bucket to store the state files.
{% gist https://gist.github.com/KlenamJohnson-Fiah/371eab689aac4e921d5515b2eff5846c file=s3_backend.tf %}

**Note:** bucket name must be unique because the s3 namespace is a shared one. You get an error like 
`Error: Error creating S3 bucket: BucketAlreadyExists: The requested bucket name is not available. The bucket namespace is shared by all users of the system. Please select a different name and try again.
        status code: 409, request id: EMBTK255FN7K3QDT, host id: 20vAPtmPGrMG/2tec=` 
if the bucket name has been taken.

Now we need some way to lock our file when we are deploying to avoid your team from walking over each other. This way just one person can deploy at a time. We will use AWS DynamoDB to achieve this  
{% gist https://gist.github.com/KlenamJohnson-Fiah/371eab689aac4e921d5515b2eff5846c file=dynamodb_backend.tf %}

The table must have a primary key named _"LockID"_ and type _"S"_ (type *string*). You get an error if this isn't so. Error below:
`Error: Error locking destination state: Error acquiring the state lock: 2 errors occurred:
        * ValidationException: One or more parameter values were invalid: Missing the key Locker in the item
        status code: 400, request id: 7BRN5V5Q92K0393GO5AEMVJF66Q9ASUAAJG
        * ValidationException: The provided key element does not match the schema
        status code: 400, request id: KDJ19AI5UB2TJBSQ9ASUAAJG`

With all this in place we can now `terraform init` -> `terraform plan` -> `terraform apply`.
___

The final step to achieve our objective will be to declare our backend in terraform.  
{% gist https://gist.github.com/KlenamJohnson-Fiah/371eab689aac4e921d5515b2eff5846c file=terraform_backend.tf %}
 
Again we need to initialize. `terraform init`
Done correctly Terraform will seek permission to make of a copy of your state to the backend.
```
Initializing the backend...
Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local" backend to the newly configured "s3" backend. No existing state was found in the newly configured "s3" backend. Do you want to copy this state to the new "s3" backend? Enter "yes" to copy and "no" to start with an empty state.

Enter a value:    
```
Real easy, huh?!🙃

If you go into your S3 bucket you should see a path `env:/ ` with  all your workspaces listed with each it's own state file.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/043o12ai18ml7pxzewlf.png)

The terraform has good [documentation](https://www.terraform.io/docs/language/settings/backends/s3.html) on this.

*+++Header Photo credit: Pixabay's mozlase__+++*

                       Happy Computing!!💻✌️