Question

How to create resources with Terraform for a specific DO project

Posted April 6, 2021 703 views
TerraformDigitalOcean Spaces

Hello,

Context

We created our first project on DO called “A”.
Now, we want to create another project called “Dev”, where we wish to deploy our development environment with a few resources (droplets, load balancer, k8s, etc.) using Terraform.

I already read all the articles on https://www.digitalocean.com/community/tutorial_series/how-to-manage-infrastructure-with-terraform and none specify how to resolve my problem.

Problem

The problem is that every time I terraform apply the resource ends up in project “A” (it is not only with the DO Spaces).

Currently

I want to use TF to provision a droplet test and publish our terraform.tfstate using a DO Spaces as the backend.

Firstly, I created (using the GUI) the DO Spaces called tf-state under “Dev” then executed TF commands. I discovered that is necessary to create the DO Spaces beforehand terraform init, otherwise it won’t work.

Code

So, I proceed to execute my TF folder, like so:

# Provider
terraform {
  required_providers {
    digitalocean = {
      source  = "digitalocean/digitalocean"
      version = "2.7.0"
    }
  }
  required_version = ">=0.14.9"
}

provider "digitalocean" {
  token = var.do_token

  spaces_access_id  = var.access_id
  spaces_secret_key = var.secret_key
}

# Project
resource "digitalocean_project" "dev" {
  name        = "dev"
  description = "Development details..."
  purpose     = "Service or API"
  environment = "Development"
  resources = [
    digitalocean_droplet.test.urn,
    digitalocean_spaces_bucket.tf-state.urn
  ]
}

# Backend
terraform {
  backend "s3" {
    endpoint                    = "fra1.digitaloceanspaces.com/"
    region                      = "us-west-1"
    key                         = "terraform.tfstate"
    bucket                      = "tf-state"
    skip_credentials_validation = true
    skip_metadata_api_check     = true
  }
}

# Bucket
resource "digitalocean_spaces_bucket" "tf-state" {
  name   = "tf-state"
  region = var.region
}

# Droplet
resource "digitalocean_droplet" "test" {
  name   = "test"
  size   = "s-1vcpu-1gb"
  image  = var.image
  region = var.region
}

Everything goes well when running:

terraform init \
-backend-config="access_key=$SPACES_ACCESS_KEY_ID" \
-backend-config="secret_key=$SPACES_SECRET_ACCESS_KEY"

But, when running terraform apply I get a message:

Error: Error creating Spaces bucket: BucketAlreadyExists: Bucket already exists
        status code: 409, request id: , host id: 

A solution is to comment # Bucket and the called line in the resource:

# Project
resource "digitalocean_project" "dev" {
  name        = "dev"
  description = "Development details..."
  purpose     = "Service or API"
  environment = "Development"
  resources = [
    digitalocean_droplet.test.urn,
    # digitalocean_spaces_bucket.tf-state.urn <= commented line
  ]
}

# Commented block
# # Bucket
# resource "digitalocean_spaces_bucket" "tf-state" {
#   name   = "tf-state"
#   region = var.region
# }

By doing this, all works, but the DO Spaces tf-state is transfered to the project “A”.

Question 1

It is quite cumbersome to track all the resources in "digitalocean_project" "dev" that are related to “Dev”. Is it possible to instruct TF to apply by default the provisioning to a specific project, like “Dev” (i.e. create another token for the new project)?

Question 2

How to create a DO Spaces bound to a specific project?

Any help is greatly appreciated.

Thanks,

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

×
Submit an Answer
1 answer

Hi,

Question 1

@camilocoelho wrote
Is it possible to instruct TF to apply by default the provisioning to a specific project, like “Dev” (i.e. create another token for the new project)?

From my own experience, I can say that it is not possible, unfortunately. And TF doc seems to confirm it:

Note: A Terraform managed project cannot be set as a default project.

Project has got is_default parameter that cannot be changed with TF. If you try to do that, you will get an error like this:

Error: "is_default": this field cannot be set

Even if you apply a workaround by setting this field with another tool interacting with DO API, like doctl or curl, TF will not create new resources within this project by default. New resource, like e.g. droplet, will not be assigned to any project, unless your default project is not managed by TF.

Question 2

@camilocoelho wrote
How to create a DO Spaces bound to a specific project?

It looks like you are trying to add backend s3 bucket to the infrastructure managed with TF (specifically to the project dev). As it is your backend, you had had to create the bucket before you executed terraform init, hadn’t you ? In such case, TF behavior seems to be OK to me. TF reports that this bucket already exists (that is true), and is not able to assign the bucket to dev project because the bucket is not known to TF (you had to comment out the bucket declaration in your .tf file). You could experiment with terraform import command to add this bucket to TF managed infrastracture, however, all this concept seems to be inconsistent to me. Imagine the scenario:
you are at the early stage of deploying your TF infrastructure, and you get stuck on some issue. Trying to fix it, you apply different solutions getting some mess in your infrastructure. At the end of the day, you decide to start everything again, from the scratch. You execute terraform destroy. What will happen then ? Your backend s3 bucket is a part of your TF infrastructure. Should it be destroyed then ? Interesting. If I have some free time next week, I will check it out. If you will do some tests on it, please share the results here.

You should not have an issue with a bucket that is created within your TF infrastructure, however, you have to explicitly specify the project you want to assign a resource to.