Skip to content
Snippets Groups Projects
Commit c5074946 authored by Florent Gluck's avatar Florent Gluck
Browse files

VM accesses can be set and deleted in bulk using regex

parent acafdae0
No related branches found
No related tags found
No related merge requests found
......@@ -44,8 +44,8 @@ Regex examples:
}
// Returns a list of filtered templates for a given route.
// The filter is based on the specified IDs and regexes.
// The filters argument can either be:
// Filters are based on patterns describing IDs or regexes.
// Patterns can either be:
// - any number of "template IDs" (UUID)
// - any number of "template names"
// - any combination of "template IDs" and "template names"
......@@ -55,24 +55,24 @@ Regex examples:
// "" -> matches everything
// "." -> matches everything
// "bla" -> matches any template name containing "bla"
func printFilteredTemplates(c cmd.Command, filters []string, route string) int {
client := g.GetInstance().Client
host := g.GetInstance().Host
if len(filters) < 1 {
func printFilteredTemplates(c cmd.Command, patterns []string, route string) int {
if len(patterns) < 1 {
c.PrintUsage()
return 1
}
client := g.GetInstance().Client
host := g.GetInstance().Host
var ids []string
var regexes []string
for _, filter := range filters {
_, err := uuid.Parse(filter)
for _, pattern := range patterns {
_, err := uuid.Parse(pattern)
if err != nil {
regexes = append(regexes, filter)
regexes = append(regexes, pattern)
} else {
ids = append(ids, filter)
ids = append(ids, pattern)
}
}
......
......@@ -53,14 +53,14 @@ Regex examples:
// "." -> matches everything
// "bla" -> matches any user containing "bla"
func printFilteredUsers(c cmd.Command, regexes []string, route string) int {
client := g.GetInstance().Client
host := g.GetInstance().Host
if len(regexes) < 1 {
c.PrintUsage()
return 1
}
client := g.GetInstance().Client
host := g.GetInstance().Host
resp, err := client.R().Get(host+route)
if err != nil {
u.PrintlnErr("Error: "+err.Error())
......
......@@ -87,8 +87,8 @@ func printFilteredVMs(c cmd.Command, args []string, route string) int {
}
// Returns a list of filtered VMs for a given route.
// The filter is based on the specified IDs and regexes.
// The filters argument can either be:
// 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"
......@@ -98,26 +98,28 @@ func printFilteredVMs(c cmd.Command, args []string, route string) int {
// "" -> matches everything
// "." -> matches everything
// "bla" -> matches any VM name containing "bla"
func getFilteredVMs(route string, filters []string) ([]VM, error) {
func getFilteredVMs(route string, patterns []string) ([]VM, 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 _, filter := range filters {
_, err := uuid.Parse(filter)
for _, pattern := range patterns {
_, err := uuid.Parse(pattern)
if err != nil {
regexes = append(regexes, filter)
regexes = append(regexes, pattern)
} else {
ids = append(ids, filter)
ids = append(ids, pattern)
}
}
resp, err := client.R().Get(host+route)
if err != nil {
//u.PrintlnErr("Error: "+err.Error())
//return 1
return nil, err
}
......@@ -126,8 +128,6 @@ func getFilteredVMs(route string, filters []string) ([]VM, error) {
if resp.IsSuccess() {
vms, err := getVMs(resp)
if err != nil {
//u.PrintlnErr("Error: "+err.Error())
//return 1
return nil, err
}
......@@ -136,7 +136,6 @@ func getFilteredVMs(route string, filters []string) ([]VM, error) {
for _, id := range ids {
if id == vm.ID.String() {
vmsList = append(vmsList, vm)
//u.Println(vm.String())
found = true
break
}
......@@ -147,11 +146,9 @@ func getFilteredVMs(route string, filters []string) ([]VM, error) {
for _, regex := range regexes {
match, err := regexp.MatchString(strings.ToLower(regex), strings.ToLower(vm.Name))
if err != nil {
//u.PrintlnErr("Error matching \""+regex+"\": "+err.Error())
return nil, errors.New("Error matching \""+regex+"\": "+err.Error())
} else {
if match {
//u.Println(vm.String())
vmsList = append(vmsList, vm)
break
}
......@@ -161,8 +158,6 @@ func getFilteredVMs(route string, filters []string) ([]VM, error) {
return vmsList, nil
} else {
return nil, errors.New("Error: "+resp.Status()+": "+resp.String())
//u.PrintlnErr("Error: "+resp.Status()+": "+resp.String())
//return 1
}
}
......
package cmdVM
import (
"errors"
"net/mail"
u "nexus-client/utils"
g "nexus-client/globals"
)
......@@ -9,17 +11,29 @@ type DelAccess struct {
Name string
}
type vmDelAccessParameters struct {
}
func (cmd *DelAccess)GetName() string {
return cmd.Name
}
func (cmd *DelAccess)GetDesc() string {
return "Delete the VM access for a given user."
return "Delete a user's VM access in one or more VMs (regex matching)."
}
func (cmd *DelAccess)PrintUsage() {
u.PrintlnErr(cmd.GetDesc())
u.PrintlnErr("Usage: "+cmd.Name+" vmID email")
u.PrintlnErr("Usage: "+cmd.GetName()+" [ID ...] [regex ...] email")
const usage string = `Only VMs matching the specified IDs or regexes will have their VM access deleted.
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
"." -> matches any VMs
"bla" -> matches any VMs containing "bla" in their name`
u.PrintlnErr(usage)
}
func (cmd *DelAccess)Run(args []string) int {
......@@ -27,25 +41,67 @@ func (cmd *DelAccess)Run(args []string) int {
host := g.GetInstance().Host
argc := len(args)
if argc != 2 {
if argc < 1 {
cmd.PrintUsage()
return 1
}
vmID := args[0]
email := args[1]
email, patterns, err := cmd.parseArgs(args)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
resp, err := client.R().Delete(host+"/vms/"+vmID+"/access/"+email)
vms, err := getFilteredVMs("/vms/editaccess", patterns)
if err != nil {
u.PrintlnErr("Error: "+err.Error())
u.PrintlnErr(err.Error())
return 1
}
statusCode := 0
for _, vm := range(vms) {
uuid := vm.ID.String()
resp, err := client.R().Delete(host+"/vms/"+uuid+"/access/"+email)
if err != nil {
u.PrintlnErr("Failed removing VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+"): "+err.Error())
statusCode = 1
} else {
if resp.IsSuccess() {
u.Println(resp)
return 0
u.Println("Removed VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+")")
} else {
u.PrintlnErr("Error: "+resp.Status()+": "+resp.String())
return 1
u.PrintlnErr("Failed removing VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+"): "+resp.Status()+": "+resp.String())
statusCode = 1
}
}
}
return statusCode
}
func (cmd *DelAccess)parseArgs(args []string) (string, []string, error) {
var patterns []string
emailFound := false
var email string
for _, arg := range args {
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 {
// An email address was found
if emailFound {
return "", nil, errors.New("Only one email address must be specified")
}
email = parsed.Address
emailFound = true
}
}
if !emailFound {
return "", nil, errors.New("An email address must be specified")
}
return email, patterns, nil
}
......@@ -30,8 +30,8 @@ func (cmd *Edit)GetDesc() string {
func (cmd *Edit)PrintUsage() {
u.PrintlnErr(cmd.GetDesc())
u.PrintlnErr("Usage: "+cmd.GetName()+" [ID ...] [regex ...] [name=\"new name\"] [cpus=n] [ram=n] [nic=none/user]")
u.PrintlnErr("Only VMs matching the specified IDs or regexes will be edited.")
const usage string = `Any number of IDs or regexes can be specified.
const usage string = `Only VMs matching the specified IDs or regexes will be edited.
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
......@@ -44,17 +44,57 @@ nic must be either "none" or "user`
u.PrintlnErr(usage)
}
func (cmd *Edit)getStringVal(s string, prefix string) string {
if strings.HasPrefix(s, prefix) {
parts := strings.Split(s, prefix)
return parts[1]
func (cmd *Edit)Run(args []string) int {
client := g.GetInstance().Client
host := g.GetInstance().Host
argc := len(args)
if argc < 1 {
cmd.PrintUsage()
return 1
}
return ""
vmParams, patterns, err := cmd.parseArgs(args)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
if vmParams == nil {
cmd.PrintUsage()
return 1
}
vms, err := getFilteredVMs("/vms/edit", patterns)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
statusCode := 0
for _, vm := range(vms) {
uuid := vm.ID.String()
resp, err := client.R().SetBody(vmParams).Put(host+"/vms/"+uuid)
if err != nil {
u.PrintlnErr("Failed editing VM \""+vm.Name+"\" ("+uuid+"): "+err.Error())
statusCode = 1
} else {
if resp.IsSuccess() {
u.Println("Edited VM \""+vm.Name+"\" ("+uuid+")")
} else {
u.PrintlnErr("Failed editing VM \""+vm.Name+"\" ("+uuid+"): "+resp.Status()+": "+resp.String())
statusCode = 1
}
}
}
return statusCode
}
func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
vmParams := &vmEditParameters {}
var regex []string
var patterns []string
atLeastOneArg := false
for _, arg := range args {
......@@ -91,61 +131,20 @@ func (cmd *Edit)parseArgs(args []string) (*vmEditParameters, []string, error) {
continue
}
regex = append(regex, arg)
patterns = append(patterns, arg)
}
if atLeastOneArg {
return vmParams, regex, nil
return vmParams, patterns, nil
} else {
return nil, nil, nil
}
}
func (cmd *Edit)Run(args []string) int {
client := g.GetInstance().Client
host := g.GetInstance().Host
argc := len(args)
if argc < 1 {
cmd.PrintUsage()
return 1
}
vmParams, regex, err := cmd.parseArgs(args)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
if vmParams == nil {
cmd.PrintUsage()
return 1
}
vms, err := getFilteredVMs("/vms/edit", regex)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
statusCode := 0
for _, vm := range(vms) {
uuid := vm.ID.String()
resp, err := client.R().SetBody(vmParams).Put(host+"/vms/"+uuid)
if err != nil {
u.PrintlnErr("Failed editing VM \""+vm.Name+"\" ("+uuid+"): "+err.Error())
statusCode = 1
} else {
if resp.IsSuccess() {
u.Println("Edited VM \""+vm.Name+"\" ("+uuid+")")
} else {
u.PrintlnErr("Failed editing VM \""+vm.Name+"\" ("+uuid+"): "+resp.Status()+": "+resp.String())
statusCode = 1
}
}
func (cmd *Edit)getStringVal(s string, prefix string) string {
if strings.HasPrefix(s, prefix) {
parts := strings.Split(s, prefix)
return parts[1]
}
return statusCode
return ""
}
package cmdVM
import (
"errors"
"net/mail"
u "nexus-client/utils"
g "nexus-client/globals"
)
......@@ -14,12 +16,21 @@ func (cmd *SetAccess)GetName() string {
}
func (cmd *SetAccess)GetDesc() string {
return "Set the VM access for a given user."
return "Set a user's VM access in one or more VMs (regex matching)."
}
func (cmd *SetAccess)PrintUsage() {
u.PrintlnErr(cmd.GetDesc())
u.PrintlnErr("Usage: "+cmd.Name+" vmID email [capability ...]")
u.PrintlnErr("Usage: "+cmd.GetName()+" [ID ...] [regex ...] email [capability ...]")
const usage string = `Capabilities must be specified after the email.
Only VMs matching the specified IDs or regexes will have their VM access set.
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
"." -> matches any VMs
"bla" -> matches any VMs containing "bla" in their name`
u.PrintlnErr(usage)
}
func (cmd *SetAccess)Run(args []string) int {
......@@ -27,34 +38,80 @@ func (cmd *SetAccess)Run(args []string) int {
host := g.GetInstance().Host
argc := len(args)
if argc < 2 {
if argc < 1 {
cmd.PrintUsage()
return 1
}
vmID := args[0]
email := args[1]
email, caps, patterns, err := cmd.parseArgs(args)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
vms, err := getFilteredVMs("/vms/editaccess", patterns)
if err != nil {
u.PrintlnErr(err.Error())
return 1
}
type VMAccessForUserArgs struct {
type vmAccessForUserArgs struct {
Access map[string]int `json:"access" validate:"required"`
}
userUpdatedAccessArgs := &VMAccessForUserArgs { make(map[string]int) }
for _, cap := range args[2:] {
userUpdatedAccessArgs := &vmAccessForUserArgs { make(map[string]int) }
for _, cap := range caps {
userUpdatedAccessArgs.Access[cap] = 1
}
resp, err := client.R().SetBody(userUpdatedAccessArgs).Put(host+"/vms/"+vmID+"/access/"+email)
statusCode := 0
for _, vm := range(vms) {
uuid := vm.ID.String()
resp, err := client.R().SetBody(userUpdatedAccessArgs).Put(host+"/vms/"+uuid+"/access/"+email)
if err != nil {
u.PrintlnErr("Error: "+err.Error())
return 1
u.PrintlnErr("Failed removing VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+"): "+err.Error())
statusCode = 1
} else {
if resp.IsSuccess() {
u.Println("Removed VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+")")
} else {
u.PrintlnErr("Failed removing VM access for "+email+" in VM \""+vm.Name+"\" ("+uuid+"): "+resp.Status()+": "+resp.String())
statusCode = 1
}
}
}
if resp.IsSuccess() {
u.Println(resp)
return 0
return statusCode
}
func (cmd *SetAccess)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 {
u.PrintlnErr("Error: "+resp.Status()+": "+resp.String())
return 1
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
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment