From f901e711dd4e8cd59b3a1e34c58a1a03564bd13a Mon Sep 17 00:00:00 2001 From: dandaolrian <86479955+dandaolrian@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:01:14 +0200 Subject: [PATCH] feat(file): ensure upload of ISO/VSTMPL is completed upon resource creation (#471) * feat(provider): ensure upload of ISO/VSTMPL completes before starting VM and add timeout to config for this * remove `ForceNew: true` for the timeout attribute * minor docs update --------- Co-authored-by: dandaolrian Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --- Makefile | 1 + docs/resources/virtual_environment_file.md | 5 ++++- proxmox/nodes/storage.go | 11 +++++++++++ proxmoxtf/resource/file.go | 11 ++++++++++- proxmoxtf/resource/file_test.go | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ea3346608..306e8da75 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ example: example-build example-init example-apply example-destroy example-apply: export TF_CLI_CONFIG_FILE="$(shell pwd -P)/example.tfrc" \ + && export TF_REATTACH_PROVIDERS='{"registry.terraform.io/bpg/proxmox":{"Protocol":"grpc","ProtocolVersion":6,"Pid":82711,"Test":true,"Addr":{"Network":"unix","String":"/var/folders/xx/4plpx_3133lbctp7b7v1yfch0000gn/T/plugin3121225613"}}}' \ && export TF_DISABLE_CHECKPOINT="true" \ && export TF_PLUGIN_CACHE_DIR="$(TERRAFORM_PLUGIN_CACHE_DIRECTORY)" \ && cd ./example \ diff --git a/docs/resources/virtual_environment_file.md b/docs/resources/virtual_environment_file.md index ae3b32ff1..fa48f024b 100644 --- a/docs/resources/virtual_environment_file.md +++ b/docs/resources/virtual_environment_file.md @@ -76,6 +76,8 @@ EOF - `data` - (Required) The raw data. - `file_name` - (Required) The file name. - `resize` - (Optional) The number of bytes to resize the file to. +- `timeout_upload` - (Optional) Timeout for uploading ISO/VSTMPL files in + seconds (defaults to 1800). ## Attribute Reference @@ -96,7 +98,8 @@ created as another temporary file). ## Import -Instances can be imported using the `node_name`, `datastore_id`, `content_type` and the `file_name`, e.g., +Instances can be imported using the `node_name`, `datastore_id`, `content_type` +and the `file_name`, e.g., ```bash $ terraform import proxmox_virtual_environment_file.cloud_config pve/local/snippets/example.cloud-config.yaml diff --git a/proxmox/nodes/storage.go b/proxmox/nodes/storage.go index 23437214f..609d98796 100644 --- a/proxmox/nodes/storage.go +++ b/proxmox/nodes/storage.go @@ -144,6 +144,7 @@ func (c *Client) APIUpload( ctx context.Context, datastoreID string, d *api.FileUploadRequest, + uploadTimeout int, ) (*DatastoreUploadResponseBody, error) { tflog.Debug(ctx, "uploading file to datastore using PVE API", map[string]interface{}{ "file_name": d.FileName, @@ -276,5 +277,15 @@ func (c *Client) APIUpload( return nil, fmt.Errorf("error uploading file to datastore %s: %w", datastoreID, err) } + if resBody.UploadID == nil { + return nil, fmt.Errorf("error uploading file to datastore %s: no uploadID", datastoreID) + } + + err = c.Tasks().WaitForTask(ctx, *resBody.UploadID, uploadTimeout, 5) + + if err != nil { + return nil, fmt.Errorf("error uploading file to datastore %s: failed waiting for upload - %w", datastoreID, err) + } + return resBody, nil } diff --git a/proxmoxtf/resource/file.go b/proxmoxtf/resource/file.go index 7ab916cef..8fc82c324 100644 --- a/proxmoxtf/resource/file.go +++ b/proxmoxtf/resource/file.go @@ -40,6 +40,7 @@ const ( dvResourceVirtualEnvironmentFileSourceFileFileName = "" dvResourceVirtualEnvironmentFileSourceFileInsecure = false dvResourceVirtualEnvironmentFileSourceRawResize = 0 + dvResourceVirtualEnvironmentFileTimeoutUpload = 1800 mkResourceVirtualEnvironmentFileContentType = "content_type" mkResourceVirtualEnvironmentFileDatastoreID = "datastore_id" @@ -58,6 +59,7 @@ const ( mkResourceVirtualEnvironmentFileSourceRawData = "data" mkResourceVirtualEnvironmentFileSourceRawFileName = "file_name" mkResourceVirtualEnvironmentFileSourceRawResize = "resize" + mkResourceVirtualEnvironmentFileTimeoutUpload = "timeout_upload" ) // File returns a resource that manages files on a node. @@ -190,6 +192,12 @@ func File() *schema.Resource { MaxItems: 1, MinItems: 0, }, + mkResourceVirtualEnvironmentFileTimeoutUpload: { + Type: schema.TypeInt, + Description: "Timeout for uploading ISO/VSTMPL files in seconds", + Optional: true, + Default: dvResourceVirtualEnvironmentFileTimeoutUpload, + }, }, CreateContext: fileCreate, ReadContext: fileRead, @@ -425,7 +433,8 @@ func fileCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag switch *contentType { case "iso", "vztmpl": - _, err = capi.Node(nodeName).APIUpload(ctx, datastoreID, request) + uploadTimeout := d.Get(mkResourceVirtualEnvironmentFileTimeoutUpload).(int) + _, err = capi.Node(nodeName).APIUpload(ctx, datastoreID, request, uploadTimeout) default: // For all other content types, we need to upload the file to the node's // datastore using SFTP. diff --git a/proxmoxtf/resource/file_test.go b/proxmoxtf/resource/file_test.go index 622b64a74..768c570d9 100644 --- a/proxmoxtf/resource/file_test.go +++ b/proxmoxtf/resource/file_test.go @@ -40,6 +40,7 @@ func TestFileSchema(t *testing.T) { mkResourceVirtualEnvironmentFileContentType, mkResourceVirtualEnvironmentFileSourceFile, mkResourceVirtualEnvironmentFileSourceRaw, + mkResourceVirtualEnvironmentFileTimeoutUpload, }) test.AssertComputedAttributes(t, s, []string{ @@ -59,6 +60,7 @@ func TestFileSchema(t *testing.T) { mkResourceVirtualEnvironmentFileNodeName: schema.TypeString, mkResourceVirtualEnvironmentFileSourceFile: schema.TypeList, mkResourceVirtualEnvironmentFileSourceRaw: schema.TypeList, + mkResourceVirtualEnvironmentFileTimeoutUpload: schema.TypeInt, }) sourceFileSchema := test.AssertNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentFileSourceFile)