Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote exec of volume mount doesn't work. #1060

Closed
joegasewicz opened this issue Oct 29, 2023 · 3 comments
Closed

Remote exec of volume mount doesn't work. #1060

joegasewicz opened this issue Oct 29, 2023 · 3 comments

Comments

@joegasewicz
Copy link

joegasewicz commented Oct 29, 2023

I want to mount my volume for my droplet via a call to a remote exec:

  provisioner "remote-exec" {
    inline = [
      "mkdir -p /mnt/notto_media_1",
      "mount -o discard,defaults /dev/disk/by-id/scsi-0DO_Volume_notto-media-1 /mnt/notto_media_1",
      "echo /dev/disk/by-id/scsi-0DO_Volume_notto-media-1 /mnt/notto_media_1 ext4 defaults,nofail,discard 0 0 | sudo tee -a /etc/fstab"
    ]
  }

This doesn't work, if i ssh into the droplet where the remote exec is called in, I get no mounted volume:

findmnt /mnt/notto_media_1 # produces nothing

I therefore have to stop my docker compose stack, mount it manually in the droplet, then restart the docker compose stack, this works.

Is there a way to run this mounting from the terraform config script with a remote exec call? I use docker's bind volume to bind to the volume disc via docker compose volume bind:

services:
  main_app:
    image: "bandnoticeboard/nottoboard:main_app-v0.0.4"
    env_file:
      - .env
    volumes:
      - static:/static
      - type: bind
        source: /mnt/notto_media_1
        target: /media
...etc

The main terraform config:

resource "digitalocean_droplet" "nottoboard-web" {
  image  = "docker-20-04"
  name   = "nottoboard-web"
  region = "lon1"
  size   = "s-1vcpu-1gb"
  ssh_keys = [
    data.digitalocean_ssh_key.nottoboard.id
  ]

  connection {
    host = self.ipv4_address
    user = "root"
    type = "ssh"
    private_key = file(var.pvt_key)
    timeout = "2m"
  }
.... etc

resource "digitalocean_volume" "notto-media-1" {
  name   = "notto-media-1"
  region = "lon1"
  size   = 10
  description             = "volume for storing django media file uploads"
}

resource "digitalocean_volume_attachment" "notto-media-1" {
  droplet_id = digitalocean_droplet.nottoboard-web.id
  volume_id = digitalocean_volume.notto-media-1.id
}

@andrewsomething
Copy link
Member

Due to the way Terraform builds its dependency graph, the volume will not be attached to the Droplet before the remote-exec provisioner runs. In your config, digitalocean_volume_attachment depends on digitalocean_droplet already existing. There are a few ways we can acomplish what you want with slightly different approaches.

Pre-formatted volumes are mounted automatically. By setting the initial_filesystem_type, you can exclude the remote-exec piece altogether. With the config below, the volume is automatically mounted to /mnt/notto_media_1/

resource "digitalocean_droplet" "nottoboard-web" {
  image  = "docker-20-04"
  name   = "nottoboard-web"
  region = "lon1"
  size   = "s-1vcpu-1gb"
  ssh_keys = [
   data.digitalocean_ssh_key.nottoboard.id
  ]
}

resource "digitalocean_volume" "notto-media-1" {
  name   = "notto-media-1"
  region = "lon1"
  size   = 10
  initial_filesystem_type = "ext4"
  description             = "volume for storing django media file uploads"
}

resource "digitalocean_volume_attachment" "notto-media-1" {
  droplet_id = digitalocean_droplet.nottoboard-web.id
  volume_id = digitalocean_volume.notto-media-1.id
}

If you need to interact with the volume from the remote-exec provisioner, not just mount it, it is possible by constructing a config that produces a different dependency order.

resource "digitalocean_droplet" "nottoboard-web" {
  image  = "docker-20-04"
  name   = "nottoboard-web"
  region = "nyc1"
  size   = "s-1vcpu-1gb"
  ssh_keys = [
    data.digitalocean_ssh_key.nottoboard.id
  ]
  volume_ids = [ digitalocean_volume.notto-media-1.id ]

  connection {
    host = self.ipv4_address
    user = "root"
    type = "ssh"
    private_key = file(var.pvt_key)
    timeout = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "cloud-init status --wait",
      "touch /mnt/notto_media_1/foo",
      "echo 'hello world' > /mnt/notto_media_1/foo",
    ]
  }
}

resource "digitalocean_volume" "notto-media-1" {
  name                    = "notto-media-1"
  region                  = "nyc1"
  size                    = 10
  initial_filesystem_type = "ext4"
  description             = "volume for storing django media file uploads"
}

In this example, the Droplet depends on the volume. So the volume will be created before the Droplet. Also note the usage of cloud-init status --wait. This is important as the volume is mounted using cloud-init. This command blocks until cloud-init has finished running so that we can be sure the volume is mounted before preceding.

@joegasewicz
Copy link
Author

Thanks very much @andrewsomething that's great. Let me know if you want me to close this issue, thank you.

@andrewsomething
Copy link
Member

Glad that was helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants