digitalocean / terraform-provider-digitalocean

Terraform DigitalOcean provider
https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs
Mozilla Public License 2.0
509 stars 278 forks source link

Second ssh key cannot be added to a droplet via terraform #1068

Open vzuevsky opened 1 year ago

vzuevsky commented 1 year ago

Bug Report

Describe the bug

Official documentation: https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/ssh_key Offers an option to import an ssh key from DO:

SSH Keys can be imported using the ssh key id, e.g.
terraform import digitalocean_ssh_key.mykey 263654

That cannot be done in practice because DO does not report correct IDs for ssh keys.

Affected Resource(s)

Expected Behavior

I should be able create droplets with Terraform with more than one key (I used at initialization) in its authorized_keys file e.g.,

resource "digitalocean_droplet" "bla" {

  name   = "blabla"
  size   = "s-2vcpu-4gb"
  image  = "debian-10-x64"
  region = "ams2"
  ipv6   = true
  ssh_keys = [
               data.digitalocean_ssh_key.mySshKey.id,
               data.digitalocean_ssh_key.uncleBob.id,
             ]

Actual Behavior

Second ssh_key cannot be imported or otherwise injected into main.tf.

Steps to Reproduce

  1. terraform apply --> initially ok
  2. insert second ssh key in a new droplet definition.
  3. terraform apply --> Error: Reference to undeclared resource
andrewsomething commented 1 year ago

Hi @vzuevsky,

Terraform supports creating Droplets with multiple SSH keys. DigitalOcean (and Terraform in turn) does not currently support adding additional SSH keys to a Droplet via the API after it has been created.

Can you explain in more detail what you mean by:

DO does not report correct IDs for ssh keys.

The error Reference to undeclared resource is a Terraform error suggesting that you have not defined the resource you are referencing in your configuration. Could you share a full example?

vzuevsky commented 1 year ago

Thanks for quick reply @andrewsomething

Terraform supports creating Droplets with multiple SSH keys: this is understood - I create a new droplet in existing project by adding resource definition (quoted above) to main.tf

Original ssh key was never defined in main.tf, terraform pulled it from DO at first apply. I cannot (should not) define the second key either, because it is in DO, not on my local machine.

As per documentation I tried terraform import but I have no way to obtain correct ID, which is required for the command - DO does not expose it in GUI.

vzuevsky commented 1 year ago

@andrewsomething

To clarify - I ask about a standard way to add ssh keys existing in DO to a new droplet via terraform:

How am I to break that viscous circle?

andrewsomething commented 1 year ago

In order to reference an imported resource, you must also write a resource configuration block.

Before you run terraform import you must manually write a resource configuration block for the resource. The resource block describes where Terraform should map the imported object.

See: https://developer.hashicorp.com/terraform/cli/import

Say the SSH key 12345 already exists on my DigitalOcean account. To import that into Terraform and use it with a Droplet, you must first add the digitalocean_ssh_key declaration to your config. E.g.

resource "digitalocean_ssh_key" "example" {
  name       = "my-key"
  public_key = file("/home/user/.ssh/id_rsa.pub")
}

resource "digitalocean_droplet" "example" {
  image  = "ubuntu-22-04-x64"
  name   = "example"
  region = "nyc1"
  size   = "s-1vcpu-1gb"
  ssh_keys = [
    digitalocean_ssh_key.example.id
  ]
}

Now you can run terraform import digitalocean_ssh_key.example 12345. Then after it has been imported, it can be referenced by the Droplet.

If you do not want to tie the lifecycle of the SSH key to the Terraform configuration, you might want to use the data source instead. No import is needed in this case.

data "digitalocean_ssh_key" "example" {
  name       = "my-key"
}

resource "digitalocean_droplet" "example" {
  image  = "ubuntu-22-04-x64"
  name   = "example"
  region = "nyc1"
  size   = "s-1vcpu-1gb"
  ssh_keys = [
    data.digitalocean_ssh_key.example.id
  ]
}

I cannot (should not) define the second key either, because it is in DO, not on my local machine.

In this case, it sounds like the data source approach is the best fit for you.

vzuevsky commented 1 year ago

@andrewsomething neither of your kind suggestions would work in principle:

The second option wouldn't work because a required parameter is missing:

https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/resources/ssh_key#attributes-reference

The first option wouldn't work because there is no way to extract 12345 ID from DigitalOcean GUI - I can only see fingerprint, name, and key itself.

andrewsomething commented 1 year ago

@vzuevsky

The second example is using the data source, not the resource. For the data source, only the name is required. See: https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs/data-sources/ssh_key

vzuevsky commented 1 year ago

@andrewsomething 🤦 I completely missed the data stanza... Than you so much!