Select Git revision
vmAddAccess.go
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 := ¶ms.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 := ¶ms.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
}