Skip to content
Snippets Groups Projects
Select Git revision
  • fd5fe28a0190c67aed2c9272466085a69070a655
  • live_exam_os_ubuntu default protected
2 results

helper.go

Blame
  • Florent Gluck's avatar
    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)
    fd5fe28a
    History
    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
    }