From 997337e277ca601084ef7b9bd998d2f30549c95a Mon Sep 17 00:00:00 2001 From: Dan Petersen Date: Fri, 13 Dec 2019 00:04:11 +0100 Subject: [PATCH] Improve file resource --- proxmox/virtual_environment_datastores.go | 52 +++++++++++++- proxmox/virtual_environment_groups.go | 4 +- proxmox/virtual_environment_pools.go | 4 +- proxmox/virtual_environment_roles.go | 4 +- proxmox/virtual_environment_users.go | 4 +- resource_virtual_environment_file.go | 83 ++++++++++++++++++----- 6 files changed, 125 insertions(+), 26 deletions(-) diff --git a/proxmox/virtual_environment_datastores.go b/proxmox/virtual_environment_datastores.go index 6bb9e599..005547ca 100644 --- a/proxmox/virtual_environment_datastores.go +++ b/proxmox/virtual_environment_datastores.go @@ -10,10 +10,27 @@ import ( "io" "io/ioutil" "mime/multipart" + "net/url" "os" "sort" ) +// VirtualEnvironmentDatastoreFileListResponseBody contains the body from a datastore content list response. +type VirtualEnvironmentDatastoreFileListResponseBody struct { + Data []*VirtualEnvironmentDatastoreFileListResponseData `json:"data,omitempty"` +} + +// VirtualEnvironmentDatastoreFileListResponseData contains the data from a datastore content list response. +type VirtualEnvironmentDatastoreFileListResponseData struct { + ContentType string `json:"content"` + FileFormat string `json:"format"` + FileSize int `json:"size"` + ParentVolumeID *string `json:"parent,omitempty"` + SpaceUsed *int `json:"used,omitempty"` + VirtualMachineID *int `json:"vmid,omitempty"` + VolumeID string `json:"volid"` +} + // VirtualEnvironmentDatastoreListRequestBody contains the body for a datastore list request. type VirtualEnvironmentDatastoreListRequestBody struct { ContentTypes CustomCommaSeparatedList `json:"content,omitempty" url:"content,omitempty,comma"` @@ -56,10 +73,41 @@ type VirtualEnvironmentDatastoreUploadResponseBody struct { UploadID *string `json:"data,omitempty"` } +// DeleteDatastoreFile deletes a file in a datastore. +func (c *VirtualEnvironmentClient) DeleteDatastoreFile(nodeName, datastoreID, volumeID string) error { + err := c.DoRequest(hmDELETE, fmt.Sprintf("nodes/%s/storage/%s/content/%s", url.PathEscape(nodeName), url.PathEscape(datastoreID), url.PathEscape(volumeID)), nil, nil) + + if err != nil { + return err + } + + return nil +} + +// ListDatastoreFiles retrieves a list of the files in a datastore. +func (c *VirtualEnvironmentClient) ListDatastoreFiles(nodeName, datastoreID string) ([]*VirtualEnvironmentDatastoreFileListResponseData, error) { + resBody := &VirtualEnvironmentDatastoreFileListResponseBody{} + err := c.DoRequest(hmGET, fmt.Sprintf("nodes/%s/storage/%s/content", url.PathEscape(nodeName), url.PathEscape(datastoreID)), nil, resBody) + + if err != nil { + return nil, err + } + + if resBody.Data == nil { + return nil, errors.New("The server did not include a data object in the response") + } + + sort.Slice(resBody.Data, func(i, j int) bool { + return resBody.Data[i].VolumeID < resBody.Data[j].VolumeID + }) + + return resBody.Data, nil +} + // ListDatastores retrieves a list of nodes. func (c *VirtualEnvironmentClient) ListDatastores(nodeName string, d *VirtualEnvironmentDatastoreListRequestBody) ([]*VirtualEnvironmentDatastoreListResponseData, error) { resBody := &VirtualEnvironmentDatastoreListResponseBody{} - err := c.DoRequest(hmGET, fmt.Sprintf("nodes/%s/storage", nodeName), d, resBody) + err := c.DoRequest(hmGET, fmt.Sprintf("nodes/%s/storage", url.PathEscape(nodeName)), d, resBody) if err != nil { return nil, err @@ -144,7 +192,7 @@ func (c *VirtualEnvironmentClient) UploadFileToDatastore(d *VirtualEnvironmentDa } resBody := &VirtualEnvironmentDatastoreUploadResponseBody{} - err = c.DoRequest(hmPOST, fmt.Sprintf("nodes/%s/storage/%s/upload", d.NodeName, d.DatastoreID), reqBody, resBody) + err = c.DoRequest(hmPOST, fmt.Sprintf("nodes/%s/storage/%s/upload", url.PathEscape(d.NodeName), url.PathEscape(d.DatastoreID)), reqBody, resBody) if err != nil { return nil, err diff --git a/proxmox/virtual_environment_groups.go b/proxmox/virtual_environment_groups.go index bd29111c..63cdc2a3 100644 --- a/proxmox/virtual_environment_groups.go +++ b/proxmox/virtual_environment_groups.go @@ -51,7 +51,7 @@ func (c *VirtualEnvironmentClient) CreateGroup(d *VirtualEnvironmentGroupCreateR // DeleteGroup deletes an access group. func (c *VirtualEnvironmentClient) DeleteGroup(id string) error { - return c.DoRequest(hmDELETE, fmt.Sprintf("access/groups/%s", id), nil, nil) + return c.DoRequest(hmDELETE, fmt.Sprintf("access/groups/%s", url.PathEscape(id)), nil, nil) } // GetGroup retrieves an access group. @@ -94,5 +94,5 @@ func (c *VirtualEnvironmentClient) ListGroups() ([]*VirtualEnvironmentGroupListR // UpdateGroup updates an access group. func (c *VirtualEnvironmentClient) UpdateGroup(id string, d *VirtualEnvironmentGroupUpdateRequestBody) error { - return c.DoRequest(hmPUT, fmt.Sprintf("access/groups/%s", id), d, nil) + return c.DoRequest(hmPUT, fmt.Sprintf("access/groups/%s", url.PathEscape(id)), d, nil) } diff --git a/proxmox/virtual_environment_pools.go b/proxmox/virtual_environment_pools.go index 9cebeae4..2cd9295e 100644 --- a/proxmox/virtual_environment_pools.go +++ b/proxmox/virtual_environment_pools.go @@ -60,7 +60,7 @@ func (c *VirtualEnvironmentClient) CreatePool(d *VirtualEnvironmentPoolCreateReq // DeletePool deletes an pool. func (c *VirtualEnvironmentClient) DeletePool(id string) error { - return c.DoRequest(hmDELETE, fmt.Sprintf("pools/%s", id), nil, nil) + return c.DoRequest(hmDELETE, fmt.Sprintf("pools/%s", url.PathEscape(id)), nil, nil) } // GetPool retrieves an pool. @@ -105,5 +105,5 @@ func (c *VirtualEnvironmentClient) ListPools() ([]*VirtualEnvironmentPoolListRes // UpdatePool updates an pool. func (c *VirtualEnvironmentClient) UpdatePool(id string, d *VirtualEnvironmentPoolUpdateRequestBody) error { - return c.DoRequest(hmPUT, fmt.Sprintf("pools/%s", id), d, nil) + return c.DoRequest(hmPUT, fmt.Sprintf("pools/%s", url.PathEscape(id)), d, nil) } diff --git a/proxmox/virtual_environment_roles.go b/proxmox/virtual_environment_roles.go index bd90ae4d..5b9a4db0 100644 --- a/proxmox/virtual_environment_roles.go +++ b/proxmox/virtual_environment_roles.go @@ -46,7 +46,7 @@ func (c *VirtualEnvironmentClient) CreateRole(d *VirtualEnvironmentRoleCreateReq // DeleteRole deletes an access role. func (c *VirtualEnvironmentClient) DeleteRole(id string) error { - return c.DoRequest(hmDELETE, fmt.Sprintf("access/roles/%s", id), nil, nil) + return c.DoRequest(hmDELETE, fmt.Sprintf("access/roles/%s", url.PathEscape(id)), nil, nil) } // GetRole retrieves an access role. @@ -95,5 +95,5 @@ func (c *VirtualEnvironmentClient) ListRoles() ([]*VirtualEnvironmentRoleListRes // UpdateRole updates an access role. func (c *VirtualEnvironmentClient) UpdateRole(id string, d *VirtualEnvironmentRoleUpdateRequestBody) error { - return c.DoRequest(hmPUT, fmt.Sprintf("access/roles/%s", id), d, nil) + return c.DoRequest(hmPUT, fmt.Sprintf("access/roles/%s", url.PathEscape(id)), d, nil) } diff --git a/proxmox/virtual_environment_users.go b/proxmox/virtual_environment_users.go index 05651519..527e8ac7 100644 --- a/proxmox/virtual_environment_users.go +++ b/proxmox/virtual_environment_users.go @@ -97,7 +97,7 @@ func (c *VirtualEnvironmentClient) CreateUser(d *VirtualEnvironmentUserCreateReq // DeleteUser deletes an user. func (c *VirtualEnvironmentClient) DeleteUser(id string) error { - return c.DoRequest(hmDELETE, fmt.Sprintf("access/users/%s", id), nil, nil) + return c.DoRequest(hmDELETE, fmt.Sprintf("access/users/%s", url.PathEscape(id)), nil, nil) } // GetUser retrieves an user. @@ -158,5 +158,5 @@ func (c *VirtualEnvironmentClient) ListUsers() ([]*VirtualEnvironmentUserListRes // UpdateUser updates an user. func (c *VirtualEnvironmentClient) UpdateUser(id string, d *VirtualEnvironmentUserUpdateRequestBody) error { - return c.DoRequest(hmPUT, fmt.Sprintf("access/users/%s", id), d, nil) + return c.DoRequest(hmPUT, fmt.Sprintf("access/users/%s", url.PathEscape(id)), d, nil) } diff --git a/resource_virtual_environment_file.go b/resource_virtual_environment_file.go index 6e9ac882..430c8f3e 100644 --- a/resource_virtual_environment_file.go +++ b/resource_virtual_environment_file.go @@ -8,6 +8,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "github.com/danitso/terraform-provider-proxmox/proxmox" "github.com/hashicorp/terraform/helper/schema" @@ -113,28 +114,78 @@ func resourceVirtualEnvironmentFileCreate(d *schema.ResourceData, m interface{}) return resourceVirtualEnvironmentFileRead(d, m) } -func resourceVirtualEnvironmentFileRead(d *schema.ResourceData, m interface{}) error { - /* - config := m.(providerConfiguration) - veClient, err := config.GetVEClient() +func resourceVirtualEnvironmentFileGetVolumeID(d *schema.ResourceData, m interface{}) string { + datastoreID := d.Get(mkResourceVirtualEnvironmentFileDatastoreID).(string) + fileName := d.Get(mkResourceVirtualEnvironmentFileFileName).(string) + source := d.Get(mkResourceVirtualEnvironmentFileSource).(string) + template := d.Get(mkResourceVirtualEnvironmentFileTemplate).(bool) - if err != nil { - return err - } - */ + if fileName == "" { + fileName = filepath.Base(source) + } - return nil + contentType := "iso" + + if template { + contentType = "vztmpl" + } + + return fmt.Sprintf("%s:%s/%s", datastoreID, contentType, fileName) } -func resourceVirtualEnvironmentFileDelete(d *schema.ResourceData, m interface{}) error { - /* - config := m.(providerConfiguration) - veClient, err := config.GetVEClient() +func resourceVirtualEnvironmentFileRead(d *schema.ResourceData, m interface{}) error { + config := m.(providerConfiguration) + veClient, err := config.GetVEClient() - if err != nil { - return err + if err != nil { + return err + } + + datastoreID := d.Get(mkResourceVirtualEnvironmentFileDatastoreID).(string) + nodeName := d.Get(mkResourceVirtualEnvironmentFileNodeName).(string) + + list, err := veClient.ListDatastoreFiles(nodeName, datastoreID) + + if err != nil { + return err + } + + volumeID := resourceVirtualEnvironmentFileGetVolumeID(d, m) + + for _, v := range list { + if v.VolumeID == volumeID { + return nil } - */ + } + + d.SetId("") + + return nil +} + +func resourceVirtualEnvironmentFileDelete(d *schema.ResourceData, m interface{}) error { + config := m.(providerConfiguration) + veClient, err := config.GetVEClient() + + if err != nil { + return err + } + + datastoreID := d.Get(mkResourceVirtualEnvironmentFileDatastoreID).(string) + nodeName := d.Get(mkResourceVirtualEnvironmentFileNodeName).(string) + volumeID := resourceVirtualEnvironmentFileGetVolumeID(d, m) + + err = veClient.DeleteDatastoreFile(nodeName, datastoreID, volumeID) + + if err != nil { + if strings.Contains(err.Error(), "HTTP 404") { + d.SetId("") + + return nil + } + + return err + } d.SetId("")