cloudstack/data_source_cloudstack_instance.go (150 lines of code) (raw):

// // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // package cloudstack import ( "encoding/json" "fmt" "log" "regexp" "strings" "time" "github.com/apache/cloudstack-go/v2/cloudstack" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func dataSourceCloudstackInstance() *schema.Resource { return &schema.Resource{ Read: dataSourceCloudstackInstanceRead, Schema: map[string]*schema.Schema{ "filter": dataSourceFiltersSchema(), //Computed values "instance_id": { Type: schema.TypeString, Computed: true, }, "account": { Type: schema.TypeString, Computed: true, }, "display_name": { Type: schema.TypeString, Computed: true, }, "state": { Type: schema.TypeString, Computed: true, }, "host_id": { Type: schema.TypeString, Computed: true, }, "zone_id": { Type: schema.TypeString, Computed: true, }, "created": { Type: schema.TypeString, Computed: true, }, "tags": tagsSchema(), "nic": { Type: schema.TypeList, Computed: true, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "ip_address": { Type: schema.TypeString, Computed: true, Optional: true, }, }, }, }, }, } } func dataSourceCloudstackInstanceRead(d *schema.ResourceData, meta interface{}) error { log.Printf("Instance Data Source Read Started") cs := meta.(*cloudstack.CloudStackClient) p := cs.VirtualMachine.NewListVirtualMachinesParams() csInstances, err := cs.VirtualMachine.ListVirtualMachines(p) if err != nil { return fmt.Errorf("Failed to list instances: %s", err) } filters := d.Get("filter") nic := d.Get("nic").([]interface{}) var instances []*cloudstack.VirtualMachine //the if-else block to check whether to filter the data source by an IP address // or by any other exported attributes if len(nic) != 0 { ip_address := nic[0].(map[string]interface{})["ip_address"] for _, i := range csInstances.VirtualMachines { if ip_address == i.Nic[0].Ipaddress { instances = append(instances, i) } } } else { for _, i := range csInstances.VirtualMachines { match, err := applyInstanceFilters(i, filters.(*schema.Set)) if err != nil { return err } if match { instances = append(instances, i) } } } if len(instances) == 0 { return fmt.Errorf("No instance is matching with the specified regex") } //return the latest instance from the list of filtered instances according //to its creation date instance, err := latestInstance(instances) if err != nil { return err } log.Printf("[DEBUG] Selected instances: %s\n", instance.Displayname) return instanceDescriptionAttributes(d, instance) } func instanceDescriptionAttributes(d *schema.ResourceData, instance *cloudstack.VirtualMachine) error { d.SetId(instance.Id) d.Set("instance_id", instance.Id) d.Set("account", instance.Account) d.Set("created", instance.Created) d.Set("display_name", instance.Displayname) d.Set("state", instance.State) d.Set("host_id", instance.Hostid) d.Set("zone_id", instance.Zoneid) d.Set("nic", []interface{}{map[string]string{"ip_address": instance.Nic[0].Ipaddress}}) d.Set("tags", tagsToMap(instance.Tags)) return nil } func latestInstance(instances []*cloudstack.VirtualMachine) (*cloudstack.VirtualMachine, error) { var latest time.Time var instance *cloudstack.VirtualMachine for _, i := range instances { created, err := time.Parse("2006-01-02T15:04:05-0700", i.Created) if err != nil { return nil, fmt.Errorf("Failed to parse creation date of an instance: %s", err) } if created.After(latest) { latest = created instance = i } } return instance, nil } func applyInstanceFilters(instance *cloudstack.VirtualMachine, filters *schema.Set) (bool, error) { var instanceJSON map[string]interface{} i, _ := json.Marshal(instance) err := json.Unmarshal(i, &instanceJSON) if err != nil { return false, err } for _, f := range filters.List() { m := f.(map[string]interface{}) r, err := regexp.Compile(m["value"].(string)) if err != nil { return false, fmt.Errorf("Invalid regex: %s", err) } updatedName := strings.ReplaceAll(m["name"].(string), "_", "") instanceField := instanceJSON[updatedName].(string) if !r.MatchString(instanceField) { return false, nil } } return true, nil }