Skip to main content

dtcloud_image (Resource)

Manages a disk image and the file behind it.

Creating one is two requests and a wait: the first opens an empty record, the second uploads the file, and the image is usable only once it reaches active. Both happen during apply, because an image with no data is a record no machine can boot from.

Example Usage​

resource "dtcloud_image" "golden" {
name = "golden-ubuntu-22.04"
source_file = "${path.module}/images/ubuntu-22.04.qcow2"
disk_format = "qcow2"
os_distro = "ubuntu"
min_disk = 20

min_ram = 2048
visibility = "private"
uefi = false
tags = ["golden", "ubuntu"]
}

Schema​

Required​

  • disk_format (String) Format of the file, such as qcow2 or iso. The accepted values come from the platform's own configuration rather than from a list in the provider, so an unsupported one is refused by the API during apply. Not the same thing as the type attribute, which is a display category derived from it. Changing this forces a new resource to be created.
  • name (String) Name of the image. Can be changed in place. Names are not unique on the platform, which is why dtcloud_image prefers a lookup by id.
  • source_volume_id (String) Volume to capture. Its contents at the moment of the call become the image; later writes to the volume do not reach it. The volume survives, and the image outlives it. There is no endpoint that replaces the data of an existing image, so pointing this at another volume builds a new one. Changing this forces a new resource to be created.

Optional​

  • container_format (String) Container wrapped around the disk data, bare unless you have a reason. Write-only: no endpoint reports it back. Changing this forces a new resource to be created.
  • min_disk (Number) Smallest volume, in GB, a machine built from this image needs. The capture derives it from the size of the source volume; set it to override, on create or later. The API reports it as the text 20 GB, which the provider parses back into a number.
  • os_distro (String) Distribution the image carries, such as debian12. The capture takes this from the source volume, so leaving it out inherits whatever the volume was built from. Set it to override, on create or later; the accepted values are the platform's and are checked by the API.
  • timeouts (Block, Optional) (see below for nested schema)
  • visibility (String) Who can see the image: private, shared or community. Defaults to shared. Can be changed in place. public is not accepted: publishing needs the publicize_image permission, which customer accounts are not granted, and the platform answers 403 on both the capture and the update.

Read-Only​

  • id (String) The ID of this resource.
  • os_type (String) linux or windows, when the platform reports it. Frequently empty here: the details endpoint passes the value straight through, while the list endpoint behind dtcloud_images guesses it from os_distro when it is missing.
  • size (String) Size of the captured data, as the platform formats it — 1.2 GB or 250 MB. There is no endpoint that reports it as a number. An image with no data yet reads as 0 MB.
  • status (String) Status reported by the platform. active is the only status a machine can be built from; queued and saving mean the data is not there yet, and killed means the capture failed.
  • type (String) How the platform categorises the image: ISO or Template (VM). This is not disk_format — it is derived from it, and the two are not interchangeable.
  • uefi (Boolean) Whether the image boots with UEFI firmware. Inherited from the source volume; there is no endpoint that sets it.

Nested Schema for timeouts​

Optional:

  • create (String)
  • delete (String)
  • update (String)

Behaviour worth knowing​

  • What changes in place. name, os_distro, min_disk and visibility, one request each. Everything else builds a new image, the file included: no endpoint replaces the data of an existing image.
  • The file is sent during apply, in full. A large image makes for a long apply, and the create timeout has to cover the transfer as well as the platform's own work afterwards. The file size is declared before the transfer starts, so an image too large for the platform is refused before anything is sent.
  • A failed upload leaves nothing behind. The platform deletes an image whose upload fails. There is no half-built record to clean up, and the next apply creates the image again.
  • Write-only arguments. min_ram and tags are accepted when the image is created and reported by no endpoint, so they cannot drift and do not survive an import. disk_format is not read back either: the platform reports the derived type instead.
  • protected is deliberately not exposed. The API accepts it when an image is created but cannot clear it afterwards, which would make the image impossible to destroy through this provider. If a destroy is refused because the image was marked protected elsewhere, the mark has to be cleared outside Terraform.

Timeouts​

create defaults to 2 hours, update to 15 minutes and delete to 30 minutes. The create default covers the upload itself, which takes as long as sending the file over your connection; raise it for a large image on a slow link. Override them with a timeouts block:

resource "dtcloud_image" "golden" {
# ...

timeouts {
create = "6h"
}
}

Import​

# The file behind an image, its format, min_ram and tags are not reported by any
# endpoint: read the import notes before the first apply.
terraform import dtcloud_image.golden 1f6b8d24-3e70-49ca-8d15-4b2f7a9c6e77

name, os_distro, min_disk, visibility and uefi are read back. source_file, source_file_hash, disk_format, min_ram and tags are not reported by any endpoint, so they are empty after an import. All five force a new image, so the first plan proposes to rebuild it even when the configuration matches what was uploaded. To keep the imported image, ignore them:

resource "dtcloud_image" "golden" {
# ...

lifecycle {
ignore_changes = [source_file, source_file_hash, disk_format, min_ram, tags]
}
}