Select Git revision

Florent Gluck authored
- added route to retrieve a single VM from its UUID - added route to retrieve a single template from its UUID client: - added vmlistsingle to test above route (but then commented out) - added tpllistsingle to test above route (but then commented out)
helper.go 5.63 KiB
package cmdVM
import (
"fmt"
"regexp"
"errors"
"strings"
"encoding/json"
"nexus-client/cmd"
"nexus-common/vm"
u "nexus-client/utils"
g "nexus-client/globals"
"github.com/google/uuid"
"github.com/go-resty/resty/v2"
)
func printRegexUsage(c cmd.Command) {
for _, desc := range c.GetDesc() {
u.PrintlnErr(desc)
}
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
u.PrintlnErr("USAGE: ",c.GetName()," [ID ...] [regex ...]")
u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
}
func printRegexUsageDetails() {
u.PrintlnErr("The action only applies to VMs matching the specified IDs or regexes.")
const usage string = `Any number of IDs or regexes can be specified.
The regex only matches the VM's name and is case-insensitive.
Regex examples:
"." -> matches any VMs
"bla" -> matches any VMs containing "bla" in their name`
u.PrintlnErr(usage)
}
// Prints a list of filtered VMs for a given route.
// Return 0 if everything went well or 1 in case of failure.
func printFilteredVMs(c cmd.Command, args []string, route string) int {
if len(args) < 1 {
c.PrintUsage()
return 1
}
// Check if a "-l" argument is specified
foundLongOutputFlag := -1
for idx, arg := range args {
if arg == "-l" {
foundLongOutputFlag = idx
}
}
if foundLongOutputFlag >= 0 {
args = u.RemoveArgAtIndex(args, foundLongOutputFlag)
}
vms, err := getFilteredVMs(route, args)
if err != nil {
u.PrintlnErr("Error: "+err.Error())
return 1
}
if foundLongOutputFlag >= 0 {
for _, vm := range vms {
str, err := vm.String()
if err != nil {
u.PrintlnErr("Failed decoding VM "+vm.ID.String()+" to string. Skipped.")
} else {
u.Println(str)
}
}
} else {
// Compute the length of the longest name and state (used for padding columns)
nameLen := 0
idLen := 0
stateLen := 0
for _, vm := range vms {
l := len(vm.Name)
if l > nameLen {
nameLen = l
}
idLen = len(vm.ID.String()) // ID is a UUID of constant length
l = len(vm.State)
if l > stateLen {
stateLen = l
}
}
paddedFmt := fmt.Sprintf("%%-%ds | %%-%ds | %%-%ds\n",nameLen, idLen, stateLen)
for _, vm := range vms {
fmt.Printf(paddedFmt, vm.Name, vm.ID, vm.State)
}
}
return 0
}
// Returns a list of filtered VMs for a given route.
// Filters are based on patterns describing IDs or regexes.
// Patterns can either be:
// - any number of "VM IDs" (UUID)
// - any number of "VM names"
// - any combination of "VM IDs" and "VM names"
// - any regular expression (it applies to the VM's name only)
// Remark: the matching is case-insensitive
// Regular expression examples:
// "." -> matches everything
// "bla" -> matches any VM name containing "bla"
func getFilteredVMs(route string, patterns []string) ([]vm.VMNetworkSerialized, error) {
if len(patterns) < 1 {
return nil, errors.New("At least one ID or regex must be specified")
}
client := g.GetInstance().Client
host := g.GetInstance().Host
var ids []string
var regexes []string
for _, pattern := range patterns {
_, err := uuid.Parse(pattern)
if err != nil {
regexes = append(regexes, pattern)
} else {
ids = append(ids, pattern)
}
}
resp, err := client.R().Get(host+route)
if err != nil {
return nil, err
}
vmsList := []vm.VMNetworkSerialized{}
if resp.IsSuccess() {
vms, err := deserializeVMs(resp)
if err != nil {
return nil, err
}
for _, vm := range vms {
found := false
for _, id := range ids {
if id == vm.ID.String() {
vmsList = append(vmsList, vm)
found = true
break
}
}
if found {
continue
}
for _, regex := range regexes {
match, err := regexp.MatchString(strings.ToLower(regex), strings.ToLower(vm.Name))
if err != nil {
return nil, errors.New("Error matching \""+regex+"\": "+err.Error())
} else {
if match {
vmsList = append(vmsList, vm)
break
}
}
}
}
return vmsList, nil
} else {
return nil, errors.New("Error: "+resp.Status()+": "+resp.String())
}
}
// Deserialize a list of VMs from an http response (no filtering).
func deserializeVMs(resp *resty.Response) ([]vm.VMNetworkSerialized, error) {
vms := []vm.VMNetworkSerialized{}
if err := json.Unmarshal(resp.Body(), &vms); err != nil {
return nil, err
}
return vms, nil
}
// Deserialize a single VM from an http response.
func deserializeVM(resp *resty.Response) (*vm.VMNetworkSerialized, error) {
var vm *vm.VMNetworkSerialized = &vm.VMNetworkSerialized{}
if err := json.Unmarshal(resp.Body(), vm); err != nil {
return vm, err
}
return vm, nil
}