diff --git a/src/cmdUser/userAdd.go b/src/cmdUser/userAdd.go index fc8f4f337383b4474ceb5b7d1a054a79f95a084c..7f7251e215b9182d62e3c549ba79efe3e0e96d78 100644 --- a/src/cmdUser/userAdd.go +++ b/src/cmdUser/userAdd.go @@ -80,7 +80,7 @@ func (cmd *Add)Run(args []string) int { csvFile := args[0] file, err := os.Open(csvFile) if err != nil { - u.PrintlnErr("Failed opening \""+csvFile+"\" "+err.Error()) + u.PrintlnErr("Error: "+err.Error()) return 1 } defer file.Close() @@ -93,13 +93,13 @@ func (cmd *Add)Run(args []string) int { break } if err != nil { - u.PrintlnErr("Failed reading "+err.Error()) + u.PrintlnErr("FAILED reading "+err.Error()) continue } columnCount := len(columns) if columnCount < 5 { - u.PrintlnErr("Failed reading record on line ",line,": 5 columns are expected") + u.PrintlnErr("FAILED reading record on line ",line,": expecting 5 columns") continue } @@ -118,7 +118,7 @@ func (cmd *Add)Run(args []string) int { } if err := cmd.runRequest(cargs); err != nil { - u.PrintlnErr("Failed creating user "+cargs.Email+": "+err.Error()) + u.PrintlnErr("FAILED creating user "+cargs.Email+": "+err.Error()) } else { u.Println("Successfully created user "+cargs.Email) } @@ -141,7 +141,6 @@ func (cmd *Add)runRequest(args *cmdArgs) error { } if resp.IsSuccess() { - u.Println(resp) return nil } else { return errors.New("Error: "+resp.Status()+": "+resp.String()) diff --git a/src/cmdUser/userDel.go b/src/cmdUser/userDel.go index 6306b2177e59247efc1b87955ea70e330877ed2a..ade8ba55e8ec473e3cb6a9a1403f4994eb4ab94f 100644 --- a/src/cmdUser/userDel.go +++ b/src/cmdUser/userDel.go @@ -1,6 +1,10 @@ package cmdUser import ( + "io" + "os" + "errors" + "encoding/csv" u "nexus-client/utils" g "nexus-client/globals" ) @@ -25,13 +29,12 @@ func (cmd *Del)PrintUsage() { } u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――") u.PrintlnErr("USAGE: "+cmd.Name+" email [email ...]") + u.PrintlnErr(" "+cmd.Name+" file.csv") u.PrintlnErr("―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――") + u.PrintlnErr("file.csv 1-column CSV file containing emails of users to delete.") } func (cmd *Del)Run(args []string) int { - client := g.GetInstance().Client - host := g.GetInstance().Host - argc := len(args) if argc < 1 { cmd.PrintUsage() @@ -40,21 +43,80 @@ func (cmd *Del)Run(args []string) int { statusCode := 0 - // Iterates through each user (email) to delete - for i:= range(args) { - email := args[i] - resp, err := client.R().Delete(host+"/users/"+email) + if argc == 1 && !u.IsEmail(args[0]) { + // Single argument and it's a CSV file + csvFile := args[0] + + if u.IsEmail(csvFile) { + cmd.PrintUsage() + return 1 + } + + file, err := os.Open(csvFile) if err != nil { u.PrintlnErr("Error: "+err.Error()) - statusCode = 1 - } else { - if resp.IsSuccess() { - u.Println("User "+email+" deleted.") + return 1 + } + defer file.Close() + reader := csv.NewReader(file) + 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 != 1 { + u.PrintlnErr("FAILED reading record on line ",line,": expecting 1 column") + statusCode = 1 + continue + } + + email := columns[0] + if err := cmd.runRequest(email); err != nil { + u.PrintlnErr(err.Error()) + statusCode = 1 } else { - u.PrintlnErr("Error: "+resp.Status()+": "+resp.String()) + u.Println("Successfully deleted user "+email) + } + } + } else { + // Argument(s) is/are email addresses + + // Iterates through each user (email) to delete + for i:= range(args) { + email := args[i] + if err := cmd.runRequest(email); err != nil { + u.PrintlnErr(err.Error()) statusCode = 1 + } else { + u.Println("Successfully deleted user "+email) } } } + return statusCode } + +func (cmd *Del)runRequest(email string) error { + client := g.GetInstance().Client + host := g.GetInstance().Host + + resp, err := client.R().Delete(host+"/users/"+email) + if err != nil { + return errors.New("Error: "+err.Error()) + } + + if resp.IsSuccess() { + return nil + } else { + return errors.New("Error: "+resp.Status()+": "+resp.String()) + } +} diff --git a/src/cmdVM/vmCreate.go b/src/cmdVM/vmCreate.go index bfd6c6b93d7037defacf4bc967b1e754c3cff978..80bd2602cdb0be99aea13039031e677dc1ed3270 100644 --- a/src/cmdVM/vmCreate.go +++ b/src/cmdVM/vmCreate.go @@ -36,7 +36,7 @@ template ID of the template to VM will be based on. count Number of VMs to create (if not specified, one is created). If specified and > 1, each VM's name is postfixed with [n], where n ranges from 1..count. -file.csv Single-column CSV file defining the students names. +file.csv 1-column CSV file defining the students names. Each VM's name is postfixed with each entry in the CSV file.` u.PrintlnErr(usage) } @@ -71,10 +71,9 @@ func (cmd *Create)Run(args []string) int { if argc == 6 { count, err = strconv.Atoi(args[5]) if err != nil { - // It's not a number, so we assume it's a CSV file. - // Checks if the file exists. - file := args[5] - csvEntries, err = u.ReadCSVColumn(file, 0) + // It's not a number, we assume it's a CSV file and parse it. + csvFile := args[5] + csvEntries, err = u.ReadCSVColumn(csvFile, 0) if err != nil { u.PrintlnErr(err.Error()) return 1 diff --git a/src/utils/csv.go b/src/utils/csv.go index 44c832e3c08dea49dac8ab592134631681ee95e9..6c98c164795cc957b9dc13c622cad923bb78b014 100644 --- a/src/utils/csv.go +++ b/src/utils/csv.go @@ -12,7 +12,7 @@ import ( func ReadCSVColumn(csvFile string, column int) ([]string, error) { file, err := os.Open(csvFile) if err != nil { - return nil, errors.New("Failed opening \""+csvFile+"\"") + return nil, errors.New("Error: "+err.Error()) } defer file.Close() reader := csv.NewReader(file) @@ -24,7 +24,7 @@ func ReadCSVColumn(csvFile string, column int) ([]string, error) { break } if err != nil { - return nil, errors.New("Failed reading \""+csvFile+"\"") + return nil, errors.New("Failed reading "+err.Error()) } if column >= len(record) { return nil, errors.New("Failed reading \""+csvFile+"\": column out of bound") diff --git a/src/utils/utils.go b/src/utils/utils.go index 017661182a56b234f96d18524b9fc9d66d133a67..1c09b93add95866eb18e0f8260e42b9919320ffa 100644 --- a/src/utils/utils.go +++ b/src/utils/utils.go @@ -6,6 +6,7 @@ import ( "fmt" "bytes" "errors" + "net/mail" "archive/tar" "path/filepath" "compress/gzip" @@ -98,4 +99,9 @@ func GetRandomTempFilename() (string, error) { } randName := "temp_"+uuid.String() return filepath.Join(tempDir, randName), nil -} \ No newline at end of file +} + +func IsEmail(email string) bool { + _, err := mail.ParseAddress(email) + return err == nil +} diff --git a/src/version/version.go b/src/version/version.go index 4e09f458aa411ead435ec642a0a99947c6f5d74e..4157545f4716e07195168b8f3b9da391d9bf31a6 100644 --- a/src/version/version.go +++ b/src/version/version.go @@ -8,7 +8,7 @@ import ( const ( major = 1 minor = 4 - bugfix = 0 + bugfix = 1 ) type Version struct {