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 asqcow2oriso. 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 thetypeattribute, 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 whydtcloud_imageprefers 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,bareunless 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 text20 GB, which the provider parses back into a number.os_distro(String) Distribution the image carries, such asdebian12. 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,sharedorcommunity. Defaults toshared. Can be changed in place.publicis not accepted: publishing needs thepublicize_imagepermission, 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)linuxorwindows, when the platform reports it. Frequently empty here: the details endpoint passes the value straight through, while the list endpoint behinddtcloud_imagesguesses it fromos_distrowhen it is missing.size(String) Size of the captured data, as the platform formats it —1.2 GBor250 MB. There is no endpoint that reports it as a number. An image with no data yet reads as0 MB.status(String) Status reported by the platform.activeis the only status a machine can be built from;queuedandsavingmean the data is not there yet, andkilledmeans the capture failed.type(String) How the platform categorises the image:ISOorTemplate (VM). This is notdisk_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_diskandvisibility, 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
createtimeout 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_ramandtagsare accepted when the image is created and reported by no endpoint, so they cannot drift and do not survive an import.disk_formatis not read back either: the platform reports the derivedtypeinstead. protectedis 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]
}
}