mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-07-05 21:43:59 +00:00
Initial work on source change detection in file resource
This commit is contained in:
parent
cc49bb80d7
commit
f343ae5790
12
README.md
12
README.md
@ -146,7 +146,7 @@ This data source doesn't accept arguments.
|
|||||||
* `comment` - The user comment
|
* `comment` - The user comment
|
||||||
* `email` - The user's email address
|
* `email` - The user's email address
|
||||||
* `enabled` - Whether the user account is enabled
|
* `enabled` - Whether the user account is enabled
|
||||||
* `expiration_date` - The user account's expiration date
|
* `expiration_date` - The user account's expiration date (RFC 3339)
|
||||||
* `first_name` - The user's first name
|
* `first_name` - The user's first name
|
||||||
* `groups` - The user's groups
|
* `groups` - The user's groups
|
||||||
* `keys` - The user's keys
|
* `keys` - The user's keys
|
||||||
@ -161,7 +161,7 @@ This data source doesn't accept arguments.
|
|||||||
* `comments` - The user comments
|
* `comments` - The user comments
|
||||||
* `emails` - The users' email addresses
|
* `emails` - The users' email addresses
|
||||||
* `enabled` - Whether a user account is enabled
|
* `enabled` - Whether a user account is enabled
|
||||||
* `expiration_dates` - The user accounts' expiration dates
|
* `expiration_dates` - The user accounts' expiration dates (RFC 3339)
|
||||||
* `first_names` - The users' first names
|
* `first_names` - The users' first names
|
||||||
* `groups` - The users' groups
|
* `groups` - The users' groups
|
||||||
* `keys` - The users' keys
|
* `keys` - The users' keys
|
||||||
@ -188,12 +188,16 @@ This data source doesn't accept arguments.
|
|||||||
###### Arguments
|
###### Arguments
|
||||||
* `datastore_id` - (Required) The datastore id
|
* `datastore_id` - (Required) The datastore id
|
||||||
* `node_name` - (Required) The node name
|
* `node_name` - (Required) The node name
|
||||||
* `override_file_name` - (Optional) The file name to use in the datastore (leave undefined to use source file name)
|
* `override_file_name` - (Optional) The file name to use instead of the source file name
|
||||||
* `source` - (Required) A path to a local file or a URL
|
* `source` - (Required) A path to a local file or a URL
|
||||||
|
* `source_changed` - (Optional) Whether the source has changed (leave undefined to use built-in detection)
|
||||||
* `template` - (Required) Whether this is a container template (`vztmpl` instead of `iso`)
|
* `template` - (Required) Whether this is a container template (`vztmpl` instead of `iso`)
|
||||||
|
|
||||||
###### Attributes
|
###### Attributes
|
||||||
|
* `file_modification_date` - The file modification date (RFC 3339)
|
||||||
* `file_name` - The datastore file name
|
* `file_name` - The datastore file name
|
||||||
|
* `file_size` - The file size in bytes
|
||||||
|
* `file_tag` - The file tag
|
||||||
|
|
||||||
##### Group (proxmox_virtual_environment_group)
|
##### Group (proxmox_virtual_environment_group)
|
||||||
|
|
||||||
@ -241,7 +245,7 @@ This resource doesn't expose any additional attributes.
|
|||||||
* `comment` - (Optional) The user comment
|
* `comment` - (Optional) The user comment
|
||||||
* `email` - (Optional) The user's email address
|
* `email` - (Optional) The user's email address
|
||||||
* `enabled` - (Optional) Whether the user account is enabled
|
* `enabled` - (Optional) Whether the user account is enabled
|
||||||
* `expiration_date` - (Optional) The user account's expiration date
|
* `expiration_date` - (Optional) The user account's expiration date (RFC 3339)
|
||||||
* `first_name` - (Optional) The user's first name
|
* `first_name` - (Optional) The user's first name
|
||||||
* `groups` - (Optional) The user's groups
|
* `groups` - (Optional) The user's groups
|
||||||
* `keys` - (Optional) The user's keys
|
* `keys` - (Optional) The user's keys
|
||||||
|
@ -9,10 +9,22 @@ output "resource_proxmox_virtual_environment_file_alpine_template_datastore_id"
|
|||||||
value = "${proxmox_virtual_environment_file.alpine_template.datastore_id}"
|
value = "${proxmox_virtual_environment_file.alpine_template.datastore_id}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "resource_proxmox_virtual_environment_file_alpine_template_file_modification_date" {
|
||||||
|
value = "${proxmox_virtual_environment_file.alpine_template.file_modification_date}"
|
||||||
|
}
|
||||||
|
|
||||||
output "resource_proxmox_virtual_environment_file_alpine_template_file_name" {
|
output "resource_proxmox_virtual_environment_file_alpine_template_file_name" {
|
||||||
value = "${proxmox_virtual_environment_file.alpine_template.file_name}"
|
value = "${proxmox_virtual_environment_file.alpine_template.file_name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output "resource_proxmox_virtual_environment_file_alpine_template_file_size" {
|
||||||
|
value = "${proxmox_virtual_environment_file.alpine_template.file_size}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "resource_proxmox_virtual_environment_file_alpine_template_file_tag" {
|
||||||
|
value = "${proxmox_virtual_environment_file.alpine_template.file_tag}"
|
||||||
|
}
|
||||||
|
|
||||||
output "resource_proxmox_virtual_environment_file_alpine_template_id" {
|
output "resource_proxmox_virtual_environment_file_alpine_template_id" {
|
||||||
value = "${proxmox_virtual_environment_file.alpine_template.id}"
|
value = "${proxmox_virtual_environment_file.alpine_template.id}"
|
||||||
}
|
}
|
||||||
|
1
go.sum
1
go.sum
@ -77,6 +77,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||||
|
@ -15,18 +15,23 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/danitso/terraform-provider-proxmox/proxmox"
|
"github.com/danitso/terraform-provider-proxmox/proxmox"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mkResourceVirtualEnvironmentFileDatastoreID = "datastore_id"
|
mkResourceVirtualEnvironmentFileDatastoreID = "datastore_id"
|
||||||
mkResourceVirtualEnvironmentFileFileName = "file_name"
|
mkResourceVirtualEnvironmentFileFileModificationDate = "file_modification_date"
|
||||||
mkResourceVirtualEnvironmentFileOverrideFileName = "override_file_name"
|
mkResourceVirtualEnvironmentFileFileName = "file_name"
|
||||||
mkResourceVirtualEnvironmentFileNodeName = "node_name"
|
mkResourceVirtualEnvironmentFileFileSize = "file_size"
|
||||||
mkResourceVirtualEnvironmentFileSource = "source"
|
mkResourceVirtualEnvironmentFileFileTag = "file_tag"
|
||||||
mkResourceVirtualEnvironmentFileTemplate = "template"
|
mkResourceVirtualEnvironmentFileOverrideFileName = "override_file_name"
|
||||||
|
mkResourceVirtualEnvironmentFileNodeName = "node_name"
|
||||||
|
mkResourceVirtualEnvironmentFileSource = "source"
|
||||||
|
mkResourceVirtualEnvironmentFileSourceChanged = "source_changed"
|
||||||
|
mkResourceVirtualEnvironmentFileTemplate = "template"
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceVirtualEnvironmentFile() *schema.Resource {
|
func resourceVirtualEnvironmentFile() *schema.Resource {
|
||||||
@ -38,14 +43,32 @@ func resourceVirtualEnvironmentFile() *schema.Resource {
|
|||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
mkResourceVirtualEnvironmentFileFileModificationDate: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "The file modification date",
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
mkResourceVirtualEnvironmentFileFileName: &schema.Schema{
|
mkResourceVirtualEnvironmentFileFileName: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The datastore file name",
|
Description: "The file name",
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
|
mkResourceVirtualEnvironmentFileFileSize: &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "The file size in bytes",
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
mkResourceVirtualEnvironmentFileFileTag: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "The file tag",
|
||||||
|
Computed: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
mkResourceVirtualEnvironmentFileOverrideFileName: &schema.Schema{
|
mkResourceVirtualEnvironmentFileOverrideFileName: &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The file name to use in the datastore (leave undefined to use source file name)",
|
Description: "The file name to use instead of the source file name",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: "",
|
Default: "",
|
||||||
@ -62,6 +85,13 @@ func resourceVirtualEnvironmentFile() *schema.Resource {
|
|||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
mkResourceVirtualEnvironmentFileSourceChanged: &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Description: "Whether the source has changed since the last run",
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Default: false,
|
||||||
|
},
|
||||||
mkResourceVirtualEnvironmentFileTemplate: &schema.Schema{
|
mkResourceVirtualEnvironmentFileTemplate: &schema.Schema{
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Description: "Whether this is a container template",
|
Description: "Whether this is a container template",
|
||||||
@ -96,8 +126,8 @@ func resourceVirtualEnvironmentFileCreate(d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
var sourceReader io.Reader
|
var sourceReader io.Reader
|
||||||
|
|
||||||
if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
|
if resourceVirtualEnvironmentFileIsURL(d, m) {
|
||||||
log.Printf("[DEBUG] Downloading file '%s'", source)
|
log.Printf("[DEBUG] Downloading file from '%s'", source)
|
||||||
|
|
||||||
res, err := http.Get(source)
|
res, err := http.Get(source)
|
||||||
|
|
||||||
@ -184,7 +214,7 @@ func resourceVirtualEnvironmentFileGetFileName(d *schema.ResourceData, m interfa
|
|||||||
source := d.Get(mkResourceVirtualEnvironmentFileSource).(string)
|
source := d.Get(mkResourceVirtualEnvironmentFileSource).(string)
|
||||||
|
|
||||||
if fileName == "" {
|
if fileName == "" {
|
||||||
if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
|
if resourceVirtualEnvironmentFileIsURL(d, m) {
|
||||||
downloadURL, err := url.ParseRequestURI(source)
|
downloadURL, err := url.ParseRequestURI(source)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -225,6 +255,12 @@ func resourceVirtualEnvironmentFileGetVolumeID(d *schema.ResourceData, m interfa
|
|||||||
return &volumeID, nil
|
return &volumeID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resourceVirtualEnvironmentFileIsURL(d *schema.ResourceData, m interface{}) bool {
|
||||||
|
source := d.Get(mkResourceVirtualEnvironmentFileSource).(string)
|
||||||
|
|
||||||
|
return strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://")
|
||||||
|
}
|
||||||
|
|
||||||
func resourceVirtualEnvironmentFileRead(d *schema.ResourceData, m interface{}) error {
|
func resourceVirtualEnvironmentFileRead(d *schema.ResourceData, m interface{}) error {
|
||||||
config := m.(providerConfiguration)
|
config := m.(providerConfiguration)
|
||||||
veClient, err := config.GetVEClient()
|
veClient, err := config.GetVEClient()
|
||||||
@ -245,8 +281,82 @@ func resourceVirtualEnvironmentFileRead(d *schema.ResourceData, m interface{}) e
|
|||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
if v.VolumeID == d.Id() {
|
if v.VolumeID == d.Id() {
|
||||||
fileName, _ := resourceVirtualEnvironmentFileGetFileName(d, m)
|
fileName, _ := resourceVirtualEnvironmentFileGetFileName(d, m)
|
||||||
|
source := d.Get(mkResourceVirtualEnvironmentFileSource).(string)
|
||||||
|
|
||||||
|
var fileModificationDate string
|
||||||
|
var fileSize int64
|
||||||
|
var fileTag string
|
||||||
|
|
||||||
|
if resourceVirtualEnvironmentFileIsURL(d, m) {
|
||||||
|
res, err := http.Head(source)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
fileSize = res.ContentLength
|
||||||
|
httpLastModified := res.Header.Get("Last-Modified")
|
||||||
|
|
||||||
|
if httpLastModified != "" {
|
||||||
|
timeParsed, err := time.Parse(time.RFC1123, httpLastModified)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
timeParsed, err = time.Parse(time.RFC1123Z, httpLastModified)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileModificationDate = timeParsed.UTC().Format(time.RFC3339)
|
||||||
|
} else {
|
||||||
|
d.Set(mkResourceVirtualEnvironmentFileFileModificationDate, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
httpTag := res.Header.Get("ETag")
|
||||||
|
|
||||||
|
if httpTag != "" {
|
||||||
|
httpTagParts := strings.Split(httpTag, "\"")
|
||||||
|
|
||||||
|
if len(httpTagParts) > 1 {
|
||||||
|
fileTag = httpTagParts[1]
|
||||||
|
} else {
|
||||||
|
fileTag = ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileTag = ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f, err := os.Open(source)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
fileInfo, err := f.Stat()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileModificationDate = fileInfo.ModTime().UTC().Format(time.RFC3339)
|
||||||
|
fileSize = fileInfo.Size()
|
||||||
|
fileTag = fmt.Sprintf("%x-%x", fileInfo.ModTime().UTC().Unix(), fileInfo.Size())
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFileModificationDate := d.Get(mkResourceVirtualEnvironmentFileFileModificationDate).(string)
|
||||||
|
lastFileSize := int64(d.Get(mkResourceVirtualEnvironmentFileFileSize).(int))
|
||||||
|
lastFileTag := d.Get(mkResourceVirtualEnvironmentFileFileTag).(string)
|
||||||
|
|
||||||
|
d.Set(mkResourceVirtualEnvironmentFileFileModificationDate, fileModificationDate)
|
||||||
d.Set(mkResourceVirtualEnvironmentFileFileName, *fileName)
|
d.Set(mkResourceVirtualEnvironmentFileFileName, *fileName)
|
||||||
|
d.Set(mkResourceVirtualEnvironmentFileFileSize, fileSize)
|
||||||
|
d.Set(mkResourceVirtualEnvironmentFileFileTag, fileTag)
|
||||||
|
d.Set(mkResourceVirtualEnvironmentFileSourceChanged, lastFileModificationDate != fileModificationDate || lastFileSize != fileSize || lastFileTag != fileTag)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -32,16 +32,24 @@ func TestResourceVirtualEnvironmentFileSchema(t *testing.T) {
|
|||||||
|
|
||||||
testOptionalArguments(t, s, []string{
|
testOptionalArguments(t, s, []string{
|
||||||
mkResourceVirtualEnvironmentFileOverrideFileName,
|
mkResourceVirtualEnvironmentFileOverrideFileName,
|
||||||
|
mkResourceVirtualEnvironmentFileSourceChanged,
|
||||||
})
|
})
|
||||||
|
|
||||||
testComputedAttributes(t, s, []string{
|
testComputedAttributes(t, s, []string{
|
||||||
|
mkResourceVirtualEnvironmentFileFileModificationDate,
|
||||||
mkResourceVirtualEnvironmentFileFileName,
|
mkResourceVirtualEnvironmentFileFileName,
|
||||||
|
mkResourceVirtualEnvironmentFileFileSize,
|
||||||
|
mkResourceVirtualEnvironmentFileFileTag,
|
||||||
})
|
})
|
||||||
|
|
||||||
testSchemaValueTypes(t, s, []string{
|
testSchemaValueTypes(t, s, []string{
|
||||||
mkResourceVirtualEnvironmentFileDatastoreID,
|
mkResourceVirtualEnvironmentFileDatastoreID,
|
||||||
|
mkResourceVirtualEnvironmentFileFileModificationDate,
|
||||||
mkResourceVirtualEnvironmentFileFileName,
|
mkResourceVirtualEnvironmentFileFileName,
|
||||||
|
mkResourceVirtualEnvironmentFileFileSize,
|
||||||
|
mkResourceVirtualEnvironmentFileFileTag,
|
||||||
mkResourceVirtualEnvironmentFileOverrideFileName,
|
mkResourceVirtualEnvironmentFileOverrideFileName,
|
||||||
|
mkResourceVirtualEnvironmentFileSourceChanged,
|
||||||
mkResourceVirtualEnvironmentFileNodeName,
|
mkResourceVirtualEnvironmentFileNodeName,
|
||||||
mkResourceVirtualEnvironmentFileSource,
|
mkResourceVirtualEnvironmentFileSource,
|
||||||
mkResourceVirtualEnvironmentFileTemplate,
|
mkResourceVirtualEnvironmentFileTemplate,
|
||||||
@ -49,6 +57,10 @@ func TestResourceVirtualEnvironmentFileSchema(t *testing.T) {
|
|||||||
schema.TypeString,
|
schema.TypeString,
|
||||||
schema.TypeString,
|
schema.TypeString,
|
||||||
schema.TypeString,
|
schema.TypeString,
|
||||||
|
schema.TypeInt,
|
||||||
|
schema.TypeString,
|
||||||
|
schema.TypeString,
|
||||||
|
schema.TypeBool,
|
||||||
schema.TypeString,
|
schema.TypeString,
|
||||||
schema.TypeString,
|
schema.TypeString,
|
||||||
schema.TypeBool,
|
schema.TypeBool,
|
||||||
|
Loading…
Reference in New Issue
Block a user