Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new command, users list and delete. Also, create automatic port f… #69

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION ?= 0.3.0
VERSION ?= 0.7.0

COMMIT := $(shell git rev-parse --short HEAD)
DATE := $(shell date +%Y%m%d)
Expand Down Expand Up @@ -83,7 +83,7 @@ $(LOCALBIN):
GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint
ENVTEST ?= $(LOCALBIN)/setup-envtest

GOLINT_VERSION ?= 1.56.2
GOLINT_VERSION ?= 1.61.0

.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
Expand Down
8 changes: 8 additions & 0 deletions cmd/kubectl-k8ssandra/tasks/tasks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package tasks

/*
Task operations.

tasks list [--cluster || --datacenter]
tasks create <task> [--datacenter || --cluster] <args>
*/
9 changes: 6 additions & 3 deletions cmd/kubectl-k8ssandra/users/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ var (
# Add new users to CassandraDatacenter
%[1]s add [<args>]

# Add new user example to CassandraDatacenter dc2 with password prompting
%[1]s add --dc dc1 --username example --superuser

# Add new superusers to CassandraDatacenter dc1 from a path /tmp/users.txt
%[1]s add --dc dc1 --path /tmp/users.txt --superuser
`
errNoDcDc = fmt.Errorf("target CassandraDatacenter is required")
errDoubleDefinition = fmt.Errorf("either --path or --username is allowed, not both")
errMissingUsername = fmt.Errorf("if --password is set, --username is required")
errMissingUsername = fmt.Errorf("--username is required")
)

type addOptions struct {
Expand Down Expand Up @@ -73,7 +76,7 @@ func NewAddCmd(streams genericclioptions.IOStreams) *cobra.Command {
fl := cmd.Flags()
fl.StringVar(&o.secretPath, "path", "", "path to users data")
fl.StringVar(&o.datacenter, "dc", "", "target datacenter")
fl.BoolVar(&o.superuser, "superuser", true, "create users as superusers")
fl.BoolVar(&o.superuser, "superuser", true, "create users as superusers") // TODO Set default to false
fl.StringVarP(&o.username, "username", "u", "", "username to add")
fl.StringVarP(&o.password, "password", "p", "", "password to set for the user")
o.configFlags.AddFlags(fl)
Expand Down Expand Up @@ -155,5 +158,5 @@ func (c *addOptions) Run() error {
}
}

return users.AddNewUser(ctx, kubeClient, c.datacenter, c.username, c.password, c.superuser)
return users.Add(ctx, kubeClient, c.datacenter, c.username, c.password, c.superuser)
}
114 changes: 114 additions & 0 deletions cmd/kubectl-k8ssandra/users/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package users

import (
"context"
"fmt"

"github.com/k8ssandra/k8ssandra-client/pkg/kubernetes"
"github.com/k8ssandra/k8ssandra-client/pkg/users"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

var (
userDeleteExample = `
# Delete users from CassandraDatacenter
%[1]s delete [<args>]

# Delete user tryme from CassandraDatacenter dc1
%[1]s delete --dc dc1 --username tryme
`
)

type deleteOptions struct {
configFlags *genericclioptions.ConfigFlags
genericclioptions.IOStreams
namespace string
datacenter string

// For manual entering from CLI
username string
}

func newDeleteOptions(streams genericclioptions.IOStreams) *deleteOptions {
return &deleteOptions{
configFlags: genericclioptions.NewConfigFlags(true),
IOStreams: streams,
}
}

// NewCmd provides a cobra command wrapping newAddOptions
func NewDeleteCmd(streams genericclioptions.IOStreams) *cobra.Command {
o := newDeleteOptions(streams)

cmd := &cobra.Command{
Use: "delete [flags]",
Short: "Delete user from CassandraDatacenter installation",
Example: fmt.Sprintf(userDeleteExample, "kubectl k8ssandra users"),
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.Validate(); err != nil {
return err
}
if err := o.Run(); err != nil {
return err
}

return nil
},
}

fl := cmd.Flags()
fl.StringVar(&o.datacenter, "dc", "", "target datacenter")
fl.StringVarP(&o.username, "username", "u", "", "username to add")
o.configFlags.AddFlags(fl)
return cmd
}

// Complete parses the arguments and necessary flags to options
func (c *deleteOptions) Complete(cmd *cobra.Command, args []string) error {
var err error

c.namespace, _, err = c.configFlags.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}

if c.username == "" && len(args) > 0 {
c.username = args[0]
}

return nil
}

// Validate ensures that all required arguments and flag values are provided
func (c *deleteOptions) Validate() error {
if c.datacenter == "" {
return errNoDcDc
}

if c.username == "" {
return errMissingUsername
}

return nil
}

// Run processes the input, creates a connection to Kubernetes and processes a secret to add the users
func (c *deleteOptions) Run() error {
restConfig, err := c.configFlags.ToRESTConfig()
if err != nil {
return err
}

kubeClient, err := kubernetes.GetClientInNamespace(restConfig, c.namespace)
if err != nil {
return err
}

ctx := context.Background()

return users.Delete(ctx, kubeClient, c.datacenter, c.username)
}
151 changes: 151 additions & 0 deletions cmd/kubectl-k8ssandra/users/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package users

import (
"context"
"errors"
"fmt"

"github.com/charmbracelet/bubbles/table"
"github.com/charmbracelet/lipgloss"
"github.com/k8ssandra/k8ssandra-client/pkg/users"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

var (
userListExample = `
# List users of CassandraDatacenter or K8ssandraCluster
%[1]s list [<args>]

# List users of CassandraDatacenter dc1
%[1]s list --dc dc1

# List users of K8ssandraCluster cluster1
%[1]s list --cluster cluster1
`

errNoDcOrCluster = errors.New("either cluster or datacenter target is required")
)

type listOptions struct {
configFlags *genericclioptions.ConfigFlags
genericclioptions.IOStreams
namespace string
datacenter string
cluster string
}

func newListOptions(streams genericclioptions.IOStreams) *listOptions {
return &listOptions{
configFlags: genericclioptions.NewConfigFlags(true),
IOStreams: streams,
}
}

// NewCmd provides a cobra command wrapping newAddOptions
func NewListCmd(streams genericclioptions.IOStreams) *cobra.Command {
o := newListOptions(streams)

cmd := &cobra.Command{
Use: "list [flags]",
Short: "List users of CassandraDatacenter or K8ssandraCluster installation",
Example: fmt.Sprintf(userListExample, "kubectl k8ssandra users"),
RunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.Validate(); err != nil {
return err
}
if err := o.Run(); err != nil {
return err
}

return nil
},
}

fl := cmd.Flags()
fl.StringVar(&o.datacenter, "dc", "", "target datacenter")
// fl.StringVar(&o.cluster, "cluster", "", "target cluster")
o.configFlags.AddFlags(fl)
return cmd
}

// Complete parses the arguments and necessary flags to options
func (c *listOptions) Complete(cmd *cobra.Command, args []string) error {
var err error

c.namespace, _, err = c.configFlags.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}

return nil
}

// Validate ensures that all required arguments and flag values are provided
func (c *listOptions) Validate() error {
if c.datacenter == "" && c.cluster == "" {
return errNoDcOrCluster
}

return nil
}

// Run processes the input, creates a connection to Kubernetes and processes a secret to add the users
func (c *listOptions) Run() error {
restConfig, err := c.configFlags.ToRESTConfig()
if err != nil {
return err
}

ctx := context.Background()

users, err := users.List(ctx, restConfig, c.namespace, c.datacenter)
if err != nil {
return err
}

columns := []table.Column{
{Title: "Name", Width: 30},
{Title: "Superuser", Width: 10},
{Title: "Login", Width: 7},
{Title: "Options", Width: 10},
{Title: "Datacenters", Width: 10},
}

rows := make([]table.Row, 0, len(users))

for _, user := range users {
row := table.Row{
user.Name,
user.Super,
user.Login,
user.Options,
user.Datacenters,
}
rows = append(rows, row)
}

t := table.New(
table.WithColumns(columns),
table.WithRows(rows),
)

s := table.DefaultStyles()
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")).
BorderBottom(true).
Bold(false)
s.Selected = s.Selected.
Foreground(lipgloss.Color("229")).
Background(lipgloss.Color("57")).
Bold(false)
t.SetStyles(s)

fmt.Print(t.View())

return nil
}
7 changes: 7 additions & 0 deletions cmd/kubectl-k8ssandra/users/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
)

/*
users list
users delete (does mgmt-api have this ability?)
*/

type ClientOptions struct {
configFlags *genericclioptions.ConfigFlags
genericclioptions.IOStreams
Expand All @@ -28,6 +33,8 @@ func NewCmd(streams genericclioptions.IOStreams) *cobra.Command {

// Add subcommands
cmd.AddCommand(NewAddCmd(streams))
cmd.AddCommand(NewDeleteCmd(streams))
cmd.AddCommand(NewListCmd(streams))
o.configFlags.AddFlags(cmd.Flags())

return cmd
Expand Down
Loading
Loading