Skip to content
Snippets Groups Projects
Select Git revision
  • efd5d8f388327b7b986e890f69c63a95da79b951
  • master default protected
2 results

source

Blame
  • vmAddAccess.go 4.96 KiB
    package cmdVM
    
    import (
    	"encoding/csv"
    	"errors"
    	"io"
    	"net/mail"
    	u "nexus-client/utils"
    	"nexus-common/caps"
    	"nexus-common/params"
    	g "nexus-libclient/globals"
    	libclient "nexus-libclient/vm"
    	"os"
    	"strings"
    )
    
    type AddAccess struct {
    	Name string
    }
    
    func (cmd *AddAccess) GetName() string {
    	return cmd.Name
    }
    
    func (cmd *AddAccess) GetDesc() []string {
    	return []string{
    		"Adds a user's VM access in one or more VMs.",
    		"If not the VM's owner: requires VM_SET_ACCESS user capability and VM_SET_ACCESS VM access capability."}
    }
    
    func (cmd *AddAccess) PrintUsage() {
    	for _, desc := range cmd.GetDesc() {
    		u.PrintlnErr(desc)
    	}
    	u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
    	u.PrintlnErr("USAGE: " + cmd.GetName() + " [ID ...] [regex ...] email [capability ...]")
    	u.PrintlnErr("       " + cmd.GetName() + " file.csv")
    	u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――")
    	usage := `file.csv   3-column CSV file specifying which VMs must have which VM access added:
                   column1    VM ID
                   column2    email for which the VM Access must be removed
                   column3    capabilities (space separated)
    List of VM access capabilities:
    `
    	caps := caps.GetVMAccessCapsNames()
    	i := 0
    	count := 0
    	for _, v := range caps {
    		if i == 0 {
    			usage += "           "
    		}
    		usage += v + " "
    		i += 1
    		count += 1
    		if i >= 5 && count < len(caps) {
    			usage = u.AppendNewLine(usage)
    			i = 0
    		}
    	}
    	u.PrintlnErr(usage)
    	printRegexUsageDetails()
    }
    
    func (cmd *AddAccess) Run(args []string) int {
    	argc := len(args)
    	if argc < 1 {
    		cmd.PrintUsage()
    		return 1
    	}
    
    	statusCode := 0
    
    	if argc == 1 {
    		// Single argument and it's a CSV file
    		csvFile := args[0]
    
    		file, err := os.Open(csvFile)
    		if err != nil {
    			u.PrintlnErr("Error: " + err.Error())
    			return 1
    		}
    		defer file.Close()
    		reader := csv.NewReader(file)
    		reader.Comma = g.CsvFieldSeparator // specify the column separator
    		reader.Comment = '#'               // lines starting with this symbol are to be ignored
    
    		line := 0
    		for {
    			line += 1
    			columns, err := reader.Read()
    			if err == io.EOF {
    				break
    			}
    			if err != nil {
    				u.PrintlnErr("FAILED reading " + err.Error())
    				statusCode = 1
    				continue
    			}
    
    			columnCount := len(columns)
    			if columnCount != 3 {
    				u.PrintlnErr("FAILED reading record on line ", line, ": expecting 3 columns")
    				statusCode = 1
    				continue
    			}
    
    			vmID := columns[0]
    
    			email := columns[1]
    			if !u.IsEmail(email) {
    				u.PrintlnErr("FAILED reading record on line ", line, ": ", email, " is not a valid email")
    				statusCode = 1
    				continue
    			}
    
    			vmAccessCaps := &params.VMAddAccess{make(caps.Capabilities)}
    
    			capsStr := strings.TrimSpace(columns[2])
    			if len(capsStr) > 0 {
    				capabilities := strings.Split(capsStr, " ")
    				for _, cap := range capabilities {
    					vmAccessCaps.Access[cap] = 1
    				}
    			}
    
    			if err := libclient.VMAddAccess(vmID, vmID, email, vmAccessCaps); err != nil {
    				u.PrintlnErr(err)
    				statusCode = 1
    			} else {
    				u.Println("Successfully set VM access for " + email + " in VM \"" + vmID + "\"")
    			}
    		}
    	} else {
    		// Multiple arguments: not a CSV file
    
    		email, capabilities, patterns, err := cmd.parseArgs(args)
    		if err != nil {
    			u.PrintlnErr(err)
    			return 1
    		}
    
    		vms, err := getFilteredVMs(libclient.GetEditAccessVMs, patterns)
    		if err != nil {
    			u.PrintlnErr(err)
    			return 1
    		}
    
    		if len(vms) == 0 {
    			u.PrintlnErr("Error: VM(s) not found.")
    			return 1
    		}
    
    		vmAccessCaps := &params.VMAddAccess{make(caps.Capabilities)}
    		for _, cap := range capabilities {
    			vmAccessCaps.Access[cap] = 1
    		}
    
    		for _, vm := range vms {
    			if err := libclient.VMAddAccess(vm.ID.String(), vm.Name, email, vmAccessCaps); err != nil {
    				u.PrintlnErr(err)
    				statusCode = 1
    			} else {
    				u.Println("Successfully set VM access for " + email + " in VM \"" + vm.Name + "\"")
    			}
    		}
    	}
    
    	return statusCode
    }
    
    func (cmd *AddAccess) parseArgs(args []string) (string, []string, []string, error) {
    	var patterns []string
    	var capabilities []string
    	emailFound := false
    	var email string
    
    	for _, arg := range args {
    		// Before or after the email addres?
    		if !emailFound {
    			// Before the email address: it's either a "pattern" (ID or regex) or an email
    			parsed, err := mail.ParseAddress(arg)
    			if err != nil {
    				// Not an email address, then must be a "pattern" (ID or regex)
    				patterns = append(patterns, arg)
    			} else {
    				email = parsed.Address
    				emailFound = true
    			}
    		} else {
    			// After the email address: it's a capability
    			capabilities = append(capabilities, arg)
    		}
    	}
    
    	if !emailFound {
    		return "", nil, nil, errors.New("An email address must be specified")
    	}
    
    	return email, capabilities, patterns, nil
    }