Skip to content

Commit

Permalink
lxc: Adds cluster role <add>/<remove> commands.
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Laing <[email protected]>
  • Loading branch information
markylaing committed Apr 1, 2022
1 parent 28d3366 commit 632000d
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lxc/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ func (c *cmdCluster) Command() *cobra.Command {
clusterGroupCmd := cmdClusterGroup{global: c.global, cluster: c}
cmd.AddCommand(clusterGroupCmd.Command())

clusterRoleCmd := cmdClusterRole{global: c.global, cluster: c}
cmd.AddCommand(clusterRoleCmd.Command())

// Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706
cmd.Args = cobra.NoArgs
cmd.Run = func(cmd *cobra.Command, args []string) { cmd.Usage() }
Expand Down
145 changes: 145 additions & 0 deletions lxc/cluster_role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package main

import (
"fmt"

"github.com/spf13/cobra"

"github.com/lxc/lxd/lxd/util"
"github.com/lxc/lxd/shared"
cli "github.com/lxc/lxd/shared/cmd"
"github.com/lxc/lxd/shared/i18n"
)

type cmdClusterRole struct {
global *cmdGlobal
cluster *cmdCluster
}

func (c *cmdClusterRole) Command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("role")
cmd.Short = i18n.G("Manage cluster roles")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(`Manage cluster roles`))

// Add
clusterRoleAddCmd := cmdClusterRoleAdd{global: c.global, cluster: c.cluster, clusterRole: c}
cmd.AddCommand(clusterRoleAddCmd.Command())

// Remove
clusterRoleRemoveCmd := cmdClusterRoleRemove{global: c.global, cluster: c.cluster, clusterRole: c}
cmd.AddCommand(clusterRoleRemoveCmd.Command())

// Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706
cmd.Args = cobra.NoArgs
cmd.Run = func(cmd *cobra.Command, args []string) { cmd.Usage() }
return cmd
}

type cmdClusterRoleAdd struct {
global *cmdGlobal
cluster *cmdCluster
clusterRole *cmdClusterRole
}

func (c *cmdClusterRoleAdd) Command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("add", i18n.G("[<remote>:]<member> <role[,role...]>"))
cmd.Short = i18n.G("Add roles to a cluster member")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Add roles to a cluster member`))

cmd.RunE = c.Run

return cmd
}

func (c *cmdClusterRoleAdd) Run(cmd *cobra.Command, args []string) error {
exit, err := c.global.CheckArgs(cmd, args, 2, 2)
if exit {
return err
}

resources, err := c.global.ParseServers(args[0])
if err != nil {
return err
}

resource := resources[0]

if resource.name == "" {
return fmt.Errorf(i18n.G("Missing cluster member name"))
}

// Extract the current value
member, etag, err := resource.server.GetClusterMember(resource.name)
if err != nil {
return err
}

memberWritable := member.Writable()
newRoles := util.SplitNTrimSpace(args[1], ",", -1, false)
for _, newRole := range newRoles {
if shared.StringInSlice(newRole, memberWritable.Roles) {
return fmt.Errorf(i18n.G("Member %q already has role %q"), resource.name, newRole)
}
}

memberWritable.Roles = append(memberWritable.Roles, newRoles...)

return resource.server.UpdateClusterMember(resource.name, memberWritable, etag)
}

type cmdClusterRoleRemove struct {
global *cmdGlobal
cluster *cmdCluster
clusterRole *cmdClusterRole
}

func (c *cmdClusterRoleRemove) Command() *cobra.Command {
cmd := &cobra.Command{}
cmd.Use = usage("remove", i18n.G("[<remote>:]<member> <role[,role...]>"))
cmd.Short = i18n.G("Remove roles from a cluster member")
cmd.Long = cli.FormatSection(i18n.G("Description"), i18n.G(
`Remove roles from a cluster member`))

cmd.RunE = c.Run

return cmd
}

func (c *cmdClusterRoleRemove) Run(cmd *cobra.Command, args []string) error {
exit, err := c.global.CheckArgs(cmd, args, 2, 2)
if exit {
return err
}

resources, err := c.global.ParseServers(args[0])
if err != nil {
return err
}

resource := resources[0]

if resource.name == "" {
return fmt.Errorf(i18n.G("Missing cluster member name"))
}

// Extract the current value
member, etag, err := resource.server.GetClusterMember(resource.name)
if err != nil {
return err
}

memberWritable := member.Writable()
rolesToRemove := util.SplitNTrimSpace(args[1], ",", -1, false)
for _, roleToRemove := range rolesToRemove {
if !shared.StringInSlice(roleToRemove, memberWritable.Roles) {
return fmt.Errorf(i18n.G("Member %q does not have role %q"), resource.name, roleToRemove)
}
}

memberWritable.Roles = shared.RemoveElementsFromStringSlice(memberWritable.Roles, rolesToRemove...)

return resource.server.UpdateClusterMember(resource.name, memberWritable, etag)
}

0 comments on commit 632000d

Please sign in to comment.