From c7b70d0f974aaef5a2175e1f6e999639c8b2806b Mon Sep 17 00:00:00 2001 From: Pierre Lafievre Date: Thu, 28 Mar 2024 16:56:48 +0100 Subject: [PATCH 1/5] F #322: fixes for data_opennebula_templates --- opennebula/data_opennebula_templates.go | 114 ++++++++++++++++++------ website/docs/d/templates.html.markdown | 1 + 2 files changed, 88 insertions(+), 27 deletions(-) diff --git a/opennebula/data_opennebula_templates.go b/opennebula/data_opennebula_templates.go index 7f2b436c3..54752f80b 100644 --- a/opennebula/data_opennebula_templates.go +++ b/opennebula/data_opennebula_templates.go @@ -7,12 +7,16 @@ import ( "regexp" "sort" "strconv" + "strings" templateSc "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/template" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +var orderTypes = []string{"ASC", "DESC"} +var sortOnTemplatesValues = []string{"id", "name", "cpu", "vcpu", "memory", "register_date"} + func dataOpennebulaTemplates() *schema.Resource { return &schema.Resource{ ReadContext: datasourceOpennebulaTemplatesRead, @@ -28,12 +32,30 @@ func dataOpennebulaTemplates() *schema.Resource { "sort_on": { Type: schema.TypeString, Optional: true, - Description: "Attribute used to sort the templates list, it has to be an ", + Description: "Attribute used to sort the templates list, only works on integer attributes.", + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToUpper(v.(string)) + + if !contains(value, sortOnTemplatesValues) { + errors = append(errors, fmt.Errorf("type %q must be one of: %s", k, strings.Join(sortOnTemplatesValues, ","))) + } + + return + }, }, "order": { Type: schema.TypeString, Optional: true, Description: "Ordering of the sort: ASC or DESC", + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToUpper(v.(string)) + + if !contains(value, orderTypes) { + errors = append(errors, fmt.Errorf("type %q must be one of: %s", k, strings.Join(orderTypes, ","))) + } + + return + }, }, "templates": { Type: schema.TypeList, @@ -46,7 +68,7 @@ func dataOpennebulaTemplates() *schema.Resource { Type: schema.TypeInt, Optional: false, Computed: true, - Description: "Name of the Template", + Description: "ID of the Template", }, "name": { Type: schema.TypeString, @@ -209,38 +231,76 @@ func datasourceOpennebulaTemplatesRead(ctx context.Context, d *schema.ResourceDa templatesMaps = append(templatesMaps, templateMap) } - sortOnAttr := d.Get("sort_on").(string) - ordering := d.Get("order").(string) - var orderingFn func(int, int) bool - switch ordering { - case "ASC": - orderingFn = func(i, j int) bool { - return templatesMaps[i][sortOnAttr].(int) > templatesMaps[j][sortOnAttr].(int) - } - case "DESC": - orderingFn = func(i, j int) bool { - return templatesMaps[i][sortOnAttr].(int) < templatesMaps[j][sortOnAttr].(int) + var sortOnAttr, ordering string + nameRegStr := d.Get("name_regex").(string) + sortOnAttr = d.Get("sort_on").(string) + + if len(sortOnAttr) > 0 && len(templatesMaps) > 1 { + ordering = d.Get("order").(string) + var orderingFn func(int, int) bool + switch ordering { + case "ASC": + switch templatesMaps[0][sortOnAttr].(type) { + case int: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(int) > templatesMaps[j][sortOnAttr].(int) + } + case string: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(string) > templatesMaps[j][sortOnAttr].(string) + } + case float64: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(float64) > templatesMaps[j][sortOnAttr].(float64) + } + default: + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "can't sort templates", + Detail: fmt.Sprintf("%s attribute type comparison is not handled", sortOnAttr), + }) + return diags + } + case "DESC": + switch templatesMaps[0][sortOnAttr].(type) { + case int: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(int) < templatesMaps[j][sortOnAttr].(int) + } + case string: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(string) < templatesMaps[j][sortOnAttr].(string) + } + case float64: + orderingFn = func(i, j int) bool { + return templatesMaps[i][sortOnAttr].(float64) < templatesMaps[j][sortOnAttr].(float64) + } + default: + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "can't sort templates", + Detail: fmt.Sprintf("%s attribute type comparison is not handled", sortOnAttr), + }) + return diags + } } - } - // will crash if sortOnAttr is the name of an attributes with another type than integer - sort.Slice(templatesMaps, func(i, j int) bool { - return orderingFn(i, j) - }) - nameRegStr := d.Get("name_regex").(string) + // will crash if sortOnAttr is the name of an attributes with another type than integer + sort.Slice(templatesMaps, func(i, j int) bool { + return orderingFn(i, j) + }) + } d.SetId(fmt.Sprintf("%x", sha512.Sum512([]byte(ordering+sortOnAttr+nameRegStr)))) err = d.Set("templates", templatesMaps) if err != nil { - if err != nil { - diags = append(diags, diag.Diagnostic{ - Severity: diag.Error, - Summary: "failed to set templates", - Detail: err.Error(), - }) - return diags - } + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "failed to set templates", + Detail: err.Error(), + }) + return diags } return nil diff --git a/website/docs/d/templates.html.markdown b/website/docs/d/templates.html.markdown index ae46a00ad..3c265e214 100644 --- a/website/docs/d/templates.html.markdown +++ b/website/docs/d/templates.html.markdown @@ -25,6 +25,7 @@ data "opennebula_templates" "example" { ## Argument Reference * `name_regex` - (Optional) Filter templates by name with a RE2 regular expression. +* `sort_on` - (Optional) Attribute used to sort the template list among: `id`, `name`, `cpu`, `vcpu`, `memory`, `register_date`. * `has_cpu` - (Optional) Indicate if a CPU value has been defined. * `cpu` - (Optional) Amount of CPU shares assigned to the VM. * `has_vcpu` - (Optional) Indicate if a VCPU value has been defined. From 2e265231ca2b1af988394b47970b460cf424370b Mon Sep 17 00:00:00 2001 From: Pierre Lafievre Date: Thu, 28 Mar 2024 16:57:45 +0100 Subject: [PATCH 2/5] F #485: add opennebula_virtual_machines data source --- CHANGELOG.md | 6 + .../data_opennebula_virtual_machines.go | 383 ++++++++++++++++++ opennebula/provider.go | 1 + website/docs/d/virtual_machines.markdown | 50 +++ 4 files changed, 440 insertions(+) create mode 100644 opennebula/data_opennebula_virtual_machines.go create mode 100644 website/docs/d/virtual_machines.markdown diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ad24983d..041d245e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 1.5.0 (Unreleased) + +FEATURES: + +* **New Data Source**: `opennebula_virtual_machines` (#485) + # 1.4.1 (Unreleased) FEATURES: diff --git a/opennebula/data_opennebula_virtual_machines.go b/opennebula/data_opennebula_virtual_machines.go new file mode 100644 index 000000000..0209c421f --- /dev/null +++ b/opennebula/data_opennebula_virtual_machines.go @@ -0,0 +1,383 @@ +package opennebula + +import ( + "context" + "crypto/sha512" + "errors" + "fmt" + "regexp" + "sort" + "strconv" + "strings" + + vmSc "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/vm" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var sortOnVMsValues = []string{"id", "name", "cpu", "vcpu", "memory"} + +func dataOpennebulaVirtualMachines() *schema.Resource { + return &schema.Resource{ + ReadContext: datasourceOpennebulaVirtualMachinesRead, + + Schema: map[string]*schema.Schema{ + "cpu": func() *schema.Schema { + s := cpuSchema() + + s.ValidateFunc = func(v interface{}, k string) (ws []string, errs []error) { + value := v.(float64) + + if value == 0 { + errs = append(errs, errors.New("cpu should be strictly greater than 0")) + } + + return + } + return s + }(), + "vcpu": func() *schema.Schema { + s := vcpuSchema() + + s.ValidateFunc = func(v interface{}, k string) (ws []string, errs []error) { + value := v.(int) + + if value == 0 { + errs = append(errs, errors.New("vcpu should be strictly greater than 0")) + } + + return + } + return s + }(), + "memory": func() *schema.Schema { + s := memorySchema() + + s.ValidateFunc = func(v interface{}, k string) (ws []string, errs []error) { + value := v.(int) + + if value == 0 { + errs = append(errs, errors.New("memory should be strictly greater than 0")) + } + + return + } + return s + }(), + "tags": tagsSchema(), + "name_regex": { + Type: schema.TypeString, + Optional: true, + Description: "Filter VMs by name with a RE2 a regular expression", + }, + "sort_on": { + Type: schema.TypeString, + Optional: true, + Description: "Attribute used to sort the VMs list, only works on integer attributes.", + + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToUpper(v.(string)) + + if !contains(value, sortOnVMsValues) { + errors = append(errors, fmt.Errorf("type %q must be one of: %s", k, strings.Join(sortOnVMsValues, ","))) + } + + return + }, + }, + "order": { + Type: schema.TypeString, + Optional: true, + Description: "Ordering of the sort: ASC or DESC", + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := strings.ToUpper(v.(string)) + + if !contains(value, orderTypes) { + errors = append(errors, fmt.Errorf("type %q must be one of: %s", k, strings.Join(orderTypes, ","))) + } + + return + }, + }, + "virtual_machines": { + Type: schema.TypeList, + Optional: false, + Computed: true, + Description: "List of matching vms", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeInt, + Optional: false, + Computed: true, + Description: "ID of the VM", + }, + "name": { + Type: schema.TypeString, + Optional: false, + Computed: true, + Description: "Name of the VM", + }, + "cpu": func() *schema.Schema { + s := cpuSchema() + s.Optional = false + s.Computed = true + return s + }(), + "vcpu": func() *schema.Schema { + s := vcpuSchema() + s.Optional = false + s.Computed = true + return s + }(), + "memory": func() *schema.Schema { + s := memorySchema() + s.Optional = false + s.Computed = true + return s + }(), + "disk": func() *schema.Schema { + s := diskSchema() + s.Computed = true + s.Optional = false + return s + }(), + "nic": func() *schema.Schema { + s := nicSchema() + s.Computed = true + s.Optional = false + return s + }(), + "vmgroup": func() *schema.Schema { + s := vmGroupSchema() + s.Computed = true + s.Optional = false + s.MaxItems = 0 + s.Description = "Virtual Machine Group to associate with during VM creation only." + return s + }(), + "tags": func() *schema.Schema { + s := tagsSchema() + s.Computed = true + s.Optional = false + return s + }(), + }, + }, + }, + }, + } +} + +func virtualMachinesFilter(d *schema.ResourceData, meta interface{}) ([]*vmSc.VM, error) { + + config := meta.(*Configuration) + controller := config.Controller + + vms, err := controller.VMs().Info() + if err != nil { + return nil, err + } + + // filter VMs with user defined criterias + cpu, cpuOk := d.GetOk("cpu") + vcpu, vcpuOk := d.GetOk("vcpu") + memory, memoryOk := d.GetOk("memory") + tagsInterface, tagsOk := d.GetOk("tags") + tags := tagsInterface.(map[string]interface{}) + nameRegStr := d.Get("name_regex").(string) + var nameReg *regexp.Regexp + if len(nameRegStr) > 0 { + nameReg = regexp.MustCompile(nameRegStr) + } + + matched := make([]*vmSc.VM, 0, 1) + for i, vm := range vms.VMs { + + if nameReg != nil && !nameReg.MatchString(vm.Name) { + continue + } + tplCPU, err := vm.Template.GetCPU() + if err != nil { + continue + } + if cpuOk && tplCPU != cpu.(float64) { + continue + } + + tplVCPU, err := vm.Template.GetVCPU() + if err != nil { + continue + } + if vcpuOk && tplVCPU != vcpu.(int) { + continue + } + + tplMemory, err := vm.Template.GetMemory() + if err != nil { + continue + } + if memoryOk && tplMemory != memory.(int) { + continue + } + + if tagsOk && !matchTags(vm.UserTemplate.Template, tags) { + continue + } + + matched = append(matched, &vms.VMs[i]) + } + + if len(matched) == 0 { + return nil, fmt.Errorf("no VMs match the constraints") + } + + return matched, nil +} + +func datasourceOpennebulaVirtualMachinesRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + + var diags diag.Diagnostics + + vms, err := virtualMachinesFilter(d, meta) + if err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "VMs filtering failed", + Detail: err.Error(), + }) + return diags + } + + vmsMaps := make([]map[string]interface{}, 0, len(vms)) + for _, vm := range vms { + + cpu, _ := vm.Template.GetCPU() + vcpu, _ := vm.Template.GetVCPU() + memory, _ := vm.Template.GetMemory() + + // builds disks list + disks := vm.Template.GetDisks() + diskList := make([]interface{}, 0, len(disks)) + + for _, disk := range disks { + diskList = append(diskList, flattenDisk(disk)) + } + + // builds nics list + nics := vm.Template.GetNICs() + nicList := make([]interface{}, 0, len(nics)) + + for _, nic := range nics { + nicList = append(nicList, flattenNIC(nic)) + } + + // builds VM Groups list + dynTemplate := vm.Template.Template + vmgMap := make([]map[string]interface{}, 0, 1) + vmgIdStr, _ := dynTemplate.GetStrFromVec("VMGROUP", "VMGROUP_ID") + vmgid, _ := strconv.ParseInt(vmgIdStr, 10, 32) + vmgRole, _ := dynTemplate.GetStrFromVec("VMGROUP", "ROLE") + + vmgMap = append(vmgMap, map[string]interface{}{ + "vmgroup_id": vmgid, + "role": vmgRole, + }) + + // tags + tplPairs := pairsToMap(vm.UserTemplate.Template) + + vmMap := map[string]interface{}{ + "name": vm.Name, + "id": vm.ID, + "cpu": cpu, + "vcpu": vcpu, + "memory": memory, + "disk": diskList, + "nic": nicList, + "vmgroup": vmgMap, + } + + if len(tplPairs) > 0 { + vmMap["tags"] = tplPairs + } + + vmsMaps = append(vmsMaps, vmMap) + } + + var sortOnAttr, ordering string + nameRegStr := d.Get("name_regex").(string) + sortOnAttr = d.Get("sort_on").(string) + + if len(sortOnAttr) > 0 && len(vmsMaps) > 1 { + + ordering = d.Get("order").(string) + var orderingFn func(int, int) bool + switch ordering { + case "ASC": + switch vmsMaps[0][sortOnAttr].(type) { + case int: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(int) > vmsMaps[j][sortOnAttr].(int) + } + case string: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(string) > vmsMaps[j][sortOnAttr].(string) + } + case float64: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(float64) > vmsMaps[j][sortOnAttr].(float64) + } + default: + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "can't sort VMs", + Detail: fmt.Sprintf("%s attribute type comparison is not handled", sortOnAttr), + }) + return diags + } + case "DESC": + switch vmsMaps[0][sortOnAttr].(type) { + case int: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(int) < vmsMaps[j][sortOnAttr].(int) + } + case string: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(string) < vmsMaps[j][sortOnAttr].(string) + } + case float64: + orderingFn = func(i, j int) bool { + return vmsMaps[i][sortOnAttr].(float64) < vmsMaps[j][sortOnAttr].(float64) + } + default: + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "can't sort VMs", + Detail: fmt.Sprintf("%s attribute type comparison is not handled", sortOnAttr), + }) + return diags + } + } + + // will crash if sortOnAttr is the name of an attributes with another type than integer + sort.Slice(vmsMaps, func(i, j int) bool { + return orderingFn(i, j) + }) + } + + d.SetId(fmt.Sprintf("%x", sha512.Sum512([]byte(ordering+sortOnAttr+nameRegStr)))) + + err = d.Set("virtual_machines", vmsMaps) + if err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "failed to set virtual_machines", + Detail: err.Error(), + }) + return diags + + } + + return nil +} diff --git a/opennebula/provider.go b/opennebula/provider.go index 6403aa6a4..c68454876 100644 --- a/opennebula/provider.go +++ b/opennebula/provider.go @@ -80,6 +80,7 @@ func Provider() *schema.Provider { "opennebula_datastore": dataOpennebulaDatastore(), "opennebula_zone": dataOpennebulaZone(), "opennebula_marketplace": dataOpennebulaMarketplace(), + "opennebula_virtual_machines": dataOpennebulaVirtualMachines(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/website/docs/d/virtual_machines.markdown b/website/docs/d/virtual_machines.markdown new file mode 100644 index 000000000..463ac5012 --- /dev/null +++ b/website/docs/d/virtual_machines.markdown @@ -0,0 +1,50 @@ +--- +layout: "opennebula" +page_title: "OpenNebula: opennebula_virtual_machines" +sidebar_current: "docs-opennebula-datasource-virtual-machines" +description: |- + Get the virtual machine information for a given name. +--- + +# opennebula_virtual_machines + +Use this data source to retrieve virtual machines information. + +## Example Usage + +```hcl +data "opennebula_virtual_machines" "example" { + name_regex = "test.*" + sort_on = "register_date" + order = "ASC" +} +``` + + +## Argument Reference + +* `name_regex` - (Optional) Filter virtual machines by name with a RE2 regular expression. +* `sort_on` - (Optional) Attribute used to sort the VMs list among: `id`, `name`, `cpu`, `vcpu`, `memory`. +* `cpu` - (Optional) Amount of CPU shares assigned to the VM. +* `vcpu` - (Optional) Number of CPU cores presented to the VM. +* `memory` - (Optional) Amount of RAM assigned to the VM in MB. +* `tags` - (Optional) virtual machine tags (Key = Value). +* `order` - (Optional) Ordering of the sort: ASC or DESC. + +## Attribute Reference + +The following attributes are exported: + +* `virtual_machines` - For each filtered virtual machine, this section collect a list of attributes. See [virtual-machines-attributes](#virtual-machines-attributes) + +## Virtual machines attributes + +* `id` - ID of the virtual machine. +* `name` - Name of the virtual machine. +* `cpu` - Amount of CPU shares assigned to the VM. +* `vcpu` - Number of CPU cores presented to the VM. +* `memory` - Amount of RAM assigned to the VM in MB. +* `disk` - Disk parameters +* `nic` - NIC parameters +* `vmgroup` - VM group parameters +* `tags` - Tags of the virtual machine (Key = Value). From 1897511b7609fdc72a8555fc51989a9bc477961b Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 14 Nov 2024 10:59:16 +0100 Subject: [PATCH 3/5] F #485: add opennebula_virtual_machines tests Signed-off-by: Jaime --- .../data_opennebula_virtual_machines.go | 2 +- .../data_opennebula_virtual_machines_test.go | 450 ++++++++++++++++++ website/docs/d/virtual_machines.markdown | 2 +- 3 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 opennebula/data_opennebula_virtual_machines_test.go diff --git a/opennebula/data_opennebula_virtual_machines.go b/opennebula/data_opennebula_virtual_machines.go index 0209c421f..c77f72c29 100644 --- a/opennebula/data_opennebula_virtual_machines.go +++ b/opennebula/data_opennebula_virtual_machines.go @@ -76,7 +76,7 @@ func dataOpennebulaVirtualMachines() *schema.Resource { Description: "Attribute used to sort the VMs list, only works on integer attributes.", ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { - value := strings.ToUpper(v.(string)) + value := strings.ToLower(v.(string)) if !contains(value, sortOnVMsValues) { errors = append(errors, fmt.Errorf("type %q must be one of: %s", k, strings.Join(sortOnVMsValues, ","))) diff --git a/opennebula/data_opennebula_virtual_machines_test.go b/opennebula/data_opennebula_virtual_machines_test.go new file mode 100644 index 000000000..1049badac --- /dev/null +++ b/opennebula/data_opennebula_virtual_machines_test.go @@ -0,0 +1,450 @@ +package opennebula + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccVirtualMachineDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVirtualMachineDestroy, + Steps: []resource.TestStep{ + { + Config: testAccVirtualMachinesDataSourceInvalidCPU, + ExpectError: regexp.MustCompile("cpu should be strictly greater than 0"), + }, + { + Config: testAccVirtualMachinesDataSourceInvalidVCPU, + ExpectError: regexp.MustCompile("vcpu should be strictly greater than 0"), + }, + { + Config: testAccVirtualMachinesDataSourceInvalidMemory, + ExpectError: regexp.MustCompile("memory should be strictly greater than 0"), + }, + { + Config: testAccVirtualMachinesDataSourceInvalidSort, + ExpectError: regexp.MustCompile("type \"sort_on\" must be one of: id,name,cpu,vcpu,memory"), + }, + { + Config: testAccVirtualMachinesDataSourceInvalidOrder, + ExpectError: regexp.MustCompile("type \"order\" must be one of: ASC,DESC"), + }, + { + Config: testAccVirtualMachinesDataSourceNoMatchingVMs, + ExpectError: regexp.MustCompile("no VMs match the constraints"), + }, + { + Config: testAccVirtualMachinesDataSourceBasic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.cpu", + "0.1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.vcpu", + "2", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.memory", + "128", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.disk.0.volatile_type", + "swap", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.nic.0.ip", + "172.20.0.1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.vmgroup.0.vmgroup_id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.basic", + "virtual_machines.0.tags.%", + "1", + ), + ), + }, + { + Config: testAccVirtualMachinesDataSourceBasicSort, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_asc", + "virtual_machines.0.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_asc", + "virtual_machines.0.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_asc", + "virtual_machines.1.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_asc", + "virtual_machines.1.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.cpu_desc", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.cpu_desc", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.cpu_desc", + "virtual_machines.1.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.cpu_desc", + "virtual_machines.1.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc", + "virtual_machines.1.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc", + "virtual_machines.1.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.vcpu_asc", + "virtual_machines.0.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.vcpu_asc", + "virtual_machines.0.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.vcpu_asc", + "virtual_machines.1.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.vcpu_asc", + "virtual_machines.1.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.name_desc", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.name_desc", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.name_desc", + "virtual_machines.1.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.name_desc", + "virtual_machines.1.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_desc_cpu", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_desc_cpu", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.id_desc_cpu", + "virtual_machines.0.cpu", + "0.1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc_vcpu", + "virtual_machines.0.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc_vcpu", + "virtual_machines.0.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.mem_asc_vcpu", + "virtual_machines.0.vcpu", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_name", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_name", + "virtual_machines.0.name", + "vm-0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_mem", + "virtual_machines.0.id", + "1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_mem", + "virtual_machines.0.name", + "vm-1", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_tags", + "virtual_machines.0.id", + "0", + ), + resource.TestCheckResourceAttr( + "data.opennebula_virtual_machines.static_tags", + "virtual_machines.0.name", + "vm-0", + ), + ), + }, + }, + }) +} + +var testAccVirtualMachinesDataSourceInvalidCPU = ` +data "opennebula_virtual_machines" "test" { + name_regex = "test.*" + sort_on = "id" + order = "ASC" + cpu = 0 +} +` +var testAccVirtualMachinesDataSourceInvalidVCPU = ` +data "opennebula_virtual_machines" "test" { + name_regex = "test.*" + sort_on = "id" + order = "ASC" + vcpu = 0 +} +` +var testAccVirtualMachinesDataSourceInvalidMemory = ` +data "opennebula_virtual_machines" "test" { + name_regex = "test.*" + sort_on = "id" + order = "ASC" + memory = 0 +} +` +var testAccVirtualMachinesDataSourceInvalidSort = ` +data "opennebula_virtual_machines" "test" { + name_regex = "test.*" + sort_on = "unsupported_field" + order = "ASC" +} +` +var testAccVirtualMachinesDataSourceInvalidOrder = ` +data "opennebula_virtual_machines" "test" { + name_regex = "test.*" + sort_on = "id" + order = "unsupported_order" +} +` +var testAccVirtualMachinesDataSourceNoMatchingVMs = ` +data "opennebula_virtual_machines" "test" { + name_regex = "noMatchingVM.*" +} +` +var testAccFirstVirtualMachine = ` +resource "opennebula_virtual_machine" "first_vm" { + name = "vm-0" + group = "oneadmin" + permissions = "642" + memory = 128 + cpu = 0.1 + vcpu = 2 + sched_requirements = "CLUSTER_ID!=\"123\"" + + disk { + volatile_type = "swap" + size = 16 + target = "vda" + } + + nic { + network_mode_auto = false + ip = "172.20.0.1" + } +} +` +var testAccSecondVirtualMachine = ` +resource "opennebula_virtual_machine" "second_vm" { + name = "vm-1" + group = "oneadmin" + permissions = "642" + memory = 64 + cpu = 0.2 + vcpu = 1 +} +` + +var testAccVirtualMachinesDataSourceBasic = testAccFirstVirtualMachine + ` +data "opennebula_virtual_machines" "basic" { + name_regex = "vm.*" + + depends_on = [opennebula_virtual_machine.first_vm] +} +` +var testAccVirtualMachinesDataSourceBasicSort = testAccFirstVirtualMachine + testAccSecondVirtualMachine + ` +data "opennebula_virtual_machines" "id_asc" { + name_regex = "vm.*" + sort_on = "id" + order = "ASC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "cpu_desc" { + name_regex = "vm.*" + sort_on = "cpu" + order = "DESC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "mem_asc" { + name_regex = "vm.*" + sort_on = "memory" + order = "ASC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "vcpu_asc" { + name_regex = "vm.*" + sort_on = "vcpu" + order = "DESC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "name_desc" { + name_regex = "vm.*" + sort_on = "name" + order = "DESC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "id_desc_cpu" { + name_regex = "vm.*" + sort_on = "id" + cpu = 0.1 + order = "DESC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "mem_asc_vcpu" { + name_regex = "vm-*" + sort_on = "memory" + vcpu = 1 + order = "ASC" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "static_name" { + name_regex = "vm-0" + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "static_mem" { + memory = 64 + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} + +data "opennebula_virtual_machines" "static_tags" { + tags = { + sched_requirements = "CLUSTER_ID!=\"123\"" + } + + depends_on = [ + opennebula_virtual_machine.first_vm, + opennebula_virtual_machine.second_vm + ] +} +` diff --git a/website/docs/d/virtual_machines.markdown b/website/docs/d/virtual_machines.markdown index 463ac5012..0c34ac1f9 100644 --- a/website/docs/d/virtual_machines.markdown +++ b/website/docs/d/virtual_machines.markdown @@ -15,7 +15,7 @@ Use this data source to retrieve virtual machines information. ```hcl data "opennebula_virtual_machines" "example" { name_regex = "test.*" - sort_on = "register_date" + sort_on = "id" order = "ASC" } ``` From 6d8819ad454519312e31a23709d48c603e7dbd91 Mon Sep 17 00:00:00 2001 From: Jaime Date: Thu, 14 Nov 2024 16:30:55 +0100 Subject: [PATCH 4/5] F #485: data_opennebula_virtual_machines add infoextended Signed-off-by: Jaime --- .../data_opennebula_virtual_machines.go | 2 +- .../data_opennebula_virtual_machines_test.go | 80 ------------------- 2 files changed, 1 insertion(+), 81 deletions(-) diff --git a/opennebula/data_opennebula_virtual_machines.go b/opennebula/data_opennebula_virtual_machines.go index c77f72c29..f54c55de9 100644 --- a/opennebula/data_opennebula_virtual_machines.go +++ b/opennebula/data_opennebula_virtual_machines.go @@ -174,7 +174,7 @@ func virtualMachinesFilter(d *schema.ResourceData, meta interface{}) ([]*vmSc.VM config := meta.(*Configuration) controller := config.Controller - vms, err := controller.VMs().Info() + vms, err := controller.VMs().InfoExtended() if err != nil { return nil, err } diff --git a/opennebula/data_opennebula_virtual_machines_test.go b/opennebula/data_opennebula_virtual_machines_test.go index 1049badac..4c80cdffd 100644 --- a/opennebula/data_opennebula_virtual_machines_test.go +++ b/opennebula/data_opennebula_virtual_machines_test.go @@ -40,11 +40,6 @@ func TestAccVirtualMachineDataSource(t *testing.T) { { Config: testAccVirtualMachinesDataSourceBasic, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.basic", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.basic", "virtual_machines.0.name", @@ -90,111 +85,56 @@ func TestAccVirtualMachineDataSource(t *testing.T) { { Config: testAccVirtualMachinesDataSourceBasicSort, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.id_asc", - "virtual_machines.0.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_asc", "virtual_machines.0.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.id_asc", - "virtual_machines.1.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_asc", "virtual_machines.1.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.cpu_desc", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.cpu_desc", "virtual_machines.0.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.cpu_desc", - "virtual_machines.1.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.cpu_desc", "virtual_machines.1.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.mem_asc", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.mem_asc", "virtual_machines.0.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.mem_asc", - "virtual_machines.1.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.mem_asc", "virtual_machines.1.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.vcpu_asc", - "virtual_machines.0.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.vcpu_asc", "virtual_machines.0.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.vcpu_asc", - "virtual_machines.1.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.vcpu_asc", "virtual_machines.1.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.name_desc", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.name_desc", "virtual_machines.0.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.name_desc", - "virtual_machines.1.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.name_desc", "virtual_machines.1.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.id_desc_cpu", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_desc_cpu", "virtual_machines.0.name", @@ -205,11 +145,6 @@ func TestAccVirtualMachineDataSource(t *testing.T) { "virtual_machines.0.cpu", "0.1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.mem_asc_vcpu", - "virtual_machines.0.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.mem_asc_vcpu", "virtual_machines.0.name", @@ -220,31 +155,16 @@ func TestAccVirtualMachineDataSource(t *testing.T) { "virtual_machines.0.vcpu", "1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.static_name", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.static_name", "virtual_machines.0.name", "vm-0", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.static_mem", - "virtual_machines.0.id", - "1", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.static_mem", "virtual_machines.0.name", "vm-1", ), - resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.static_tags", - "virtual_machines.0.id", - "0", - ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.static_tags", "virtual_machines.0.name", From b10a0f8abe2d13b3024279a22401160dd4c182ad Mon Sep 17 00:00:00 2001 From: Jaime Date: Fri, 15 Nov 2024 08:26:13 +0100 Subject: [PATCH 5/5] F #485: fix sort on field Signed-off-by: Jaime --- .../data_opennebula_virtual_machines.go | 4 +- .../data_opennebula_virtual_machines_test.go | 42 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/opennebula/data_opennebula_virtual_machines.go b/opennebula/data_opennebula_virtual_machines.go index f54c55de9..5918f0e25 100644 --- a/opennebula/data_opennebula_virtual_machines.go +++ b/opennebula/data_opennebula_virtual_machines.go @@ -314,7 +314,7 @@ func datasourceOpennebulaVirtualMachinesRead(ctx context.Context, d *schema.Reso ordering = d.Get("order").(string) var orderingFn func(int, int) bool switch ordering { - case "ASC": + case "DESC": switch vmsMaps[0][sortOnAttr].(type) { case int: orderingFn = func(i, j int) bool { @@ -336,7 +336,7 @@ func datasourceOpennebulaVirtualMachinesRead(ctx context.Context, d *schema.Reso }) return diags } - case "DESC": + case "ASC": switch vmsMaps[0][sortOnAttr].(type) { case int: orderingFn = func(i, j int) bool { diff --git a/opennebula/data_opennebula_virtual_machines_test.go b/opennebula/data_opennebula_virtual_machines_test.go index 4c80cdffd..4969bdfd7 100644 --- a/opennebula/data_opennebula_virtual_machines_test.go +++ b/opennebula/data_opennebula_virtual_machines_test.go @@ -77,8 +77,8 @@ func TestAccVirtualMachineDataSource(t *testing.T) { ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.basic", - "virtual_machines.0.tags.%", - "1", + "virtual_machines.0.tags.SCHED_REQUIREMENTS", + "CLUSTER_ID!=\"123\"", ), ), }, @@ -88,52 +88,52 @@ func TestAccVirtualMachineDataSource(t *testing.T) { resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_asc", "virtual_machines.0.name", - "vm-1", + "vm-0", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_asc", "virtual_machines.1.name", - "vm-0", + "vm-1", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.cpu_desc", "virtual_machines.0.name", - "vm-0", + "vm-1", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.cpu_desc", "virtual_machines.1.name", - "vm-1", + "vm-0", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.mem_asc", "virtual_machines.0.name", - "vm-0", + "vm-1", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.mem_asc", "virtual_machines.1.name", - "vm-1", + "vm-0", ), resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.vcpu_asc", + "data.opennebula_virtual_machines.vcpu_desc", "virtual_machines.0.name", - "vm-1", + "vm-0", ), resource.TestCheckResourceAttr( - "data.opennebula_virtual_machines.vcpu_asc", + "data.opennebula_virtual_machines.vcpu_desc", "virtual_machines.1.name", - "vm-0", + "vm-1", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.name_desc", "virtual_machines.0.name", - "vm-0", + "vm-1", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.name_desc", "virtual_machines.1.name", - "vm-1", + "vm-0", ), resource.TestCheckResourceAttr( "data.opennebula_virtual_machines.id_desc_cpu", @@ -177,7 +177,7 @@ func TestAccVirtualMachineDataSource(t *testing.T) { } var testAccVirtualMachinesDataSourceInvalidCPU = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_invalid_id" { name_regex = "test.*" sort_on = "id" order = "ASC" @@ -185,7 +185,7 @@ data "opennebula_virtual_machines" "test" { } ` var testAccVirtualMachinesDataSourceInvalidVCPU = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_invalid_vcpu" { name_regex = "test.*" sort_on = "id" order = "ASC" @@ -193,7 +193,7 @@ data "opennebula_virtual_machines" "test" { } ` var testAccVirtualMachinesDataSourceInvalidMemory = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_invalid_memory" { name_regex = "test.*" sort_on = "id" order = "ASC" @@ -201,21 +201,21 @@ data "opennebula_virtual_machines" "test" { } ` var testAccVirtualMachinesDataSourceInvalidSort = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_invalid_sort" { name_regex = "test.*" sort_on = "unsupported_field" order = "ASC" } ` var testAccVirtualMachinesDataSourceInvalidOrder = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_invalid_order" { name_regex = "test.*" sort_on = "id" order = "unsupported_order" } ` var testAccVirtualMachinesDataSourceNoMatchingVMs = ` -data "opennebula_virtual_machines" "test" { +data "opennebula_virtual_machines" "test_no_matching" { name_regex = "noMatchingVM.*" } ` @@ -293,7 +293,7 @@ data "opennebula_virtual_machines" "mem_asc" { ] } -data "opennebula_virtual_machines" "vcpu_asc" { +data "opennebula_virtual_machines" "vcpu_desc" { name_regex = "vm.*" sort_on = "vcpu" order = "DESC"