Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Alexej Disterhoft <[email protected]>
  • Loading branch information
nobbs committed Dec 31, 2023
1 parent f72175e commit ecb094f
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ requiring access to the MapR cluster.`,
rootCmd.AddCommand(
newListCmd(rootOpts),
newVersionCmd(rootOpts),
newUsedByCmd(rootOpts),
)

return rootCmd
Expand Down
105 changes: 105 additions & 0 deletions cmd/cli/usedby.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package cli

import (
"fmt"

"github.com/nobbs/kubectl-mapr-ticket/internal/util"
"github.com/nobbs/kubectl-mapr-ticket/internal/volumes"
"github.com/spf13/cobra"
)

type UsedByOptions struct {
*rootCmdOptions

// Args are the arguments passed to the command
args []string

// SecretName is the name of the secret to find persistent volumes for
SecretName string
}

func NewUsedByOptions(rootOpts *rootCmdOptions) *UsedByOptions {
return &UsedByOptions{
rootCmdOptions: rootOpts,
}
}

func newUsedByCmd(rootOpts *rootCmdOptions) *cobra.Command {
o := NewUsedByOptions(rootOpts)

cmd := &cobra.Command{
Use: "used-by secret",
Short: "List all persistent volumes that use the specified MapR ticket secret",
Long: `List all persistent volumes that use the specified MapR ticket secret and print
some information about them.`,
RunE: func(cmd *cobra.Command, args []string) error {
if err := o.Complete(cmd, args); err != nil {
return err
}

if err := o.Validate(); err != nil {
return err
}

if err := o.Run(cmd, args); err != nil {
return err
}

return nil
},
}

// set IOStreams for the command
cmd.SetIn(o.IOStreams.In)
cmd.SetOut(o.IOStreams.Out)
cmd.SetErr(o.IOStreams.ErrOut)

return cmd
}

func (o *UsedByOptions) Complete(cmd *cobra.Command, args []string) error {
o.args = args

if len(args) > 0 {
o.SecretName = args[0]
}

return nil
}

func (o *UsedByOptions) Validate() error {
// ensure that the secret name was provided
if o.SecretName == "" {
return fmt.Errorf("secret name must be provided")
}

return nil
}

func (o *UsedByOptions) Run(cmd *cobra.Command, args []string) error {
client, err := util.ClientFromFlags(o.kubernetesConfigFlags)
if err != nil {
return err
}

// create list options
opts := []volumes.ListerOption{}

// create lister
lister := volumes.NewLister(client, o.SecretName, *o.kubernetesConfigFlags.Namespace, opts...)

// run the lister
volumes, err := lister.Run()
if err != nil {
return err
}

// print the volumes
// if err := volumes.Print(cmd); err != nil {
// return err
// }

fmt.Printf("%+v\n", volumes)

return nil
}
122 changes: 122 additions & 0 deletions internal/volumes/volumes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package volumes

import (
"context"

coreV1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
typedV1 "k8s.io/client-go/kubernetes/typed/core/v1"
)

var (
// maprCSIProvisioners is a list of the default MapR CSI provisioners
// that we support.
maprCSIProvisioners = []string{
"com.mapr.csi-kdf",
"com.mapr.csi-nfskdf",
}
)

type Lister struct {
client typedV1.PersistentVolumeInterface
secretName string
namespace string
}

type ListerOption func(*Lister)

func NewLister(client kubernetes.Interface, secretName string, namespace string, opts ...ListerOption) *Lister {
l := &Lister{
client: client.CoreV1().PersistentVolumes(),
secretName: secretName,
namespace: namespace,
}

for _, opt := range opts {
opt(l)
}

return l
}

func (l *Lister) Run() ([]coreV1.PersistentVolume, error) {
// Unfortunately, we have to list all persistent volumes and filter them
// ourselves, because there is no way to filter them by label selector.
volumes, err := l.client.List(context.TODO(), metaV1.ListOptions{})
if err != nil {
return nil, err
}

// Filter the volumes to only MapR CSI-based ones
filtered := l.filterVolumesToMaprCSI(volumes.Items)

// Filter the volumes to only ones that use the specified secret
filtered = l.filterVolumeUsesTicket(filtered)

return filtered, nil
}

func (l *Lister) filterVolumesToMaprCSI(volumes []coreV1.PersistentVolume) []coreV1.PersistentVolume {
var filtered []coreV1.PersistentVolume

for _, volume := range volumes {
if l.volumeIsMaprCSIBased(&volume) {
filtered = append(filtered, volume)
}
}

return filtered
}

func (l *Lister) filterVolumeUsesTicket(volumes []coreV1.PersistentVolume) []coreV1.PersistentVolume {
var filtered []coreV1.PersistentVolume

for _, volume := range volumes {
if l.volumeUsesTicket(&volume) {
filtered = append(filtered, volume)
}
}

return filtered
}

func (l *Lister) volumeUsesTicket(volume *coreV1.PersistentVolume) bool {
// Check if the volume uses a CSI driver
if volume.Spec.CSI == nil {
return false
}

// Check if the volume uses a NodePublishSecretRef
if volume.Spec.CSI.NodePublishSecretRef == nil {
return false
}

// Check if the volume uses the specified secret
if volume.Spec.CSI.NodePublishSecretRef.Name != l.secretName {
return false
}

// Check if the volume uses the specified namespace
if volume.Spec.CSI.NodePublishSecretRef.Namespace != l.namespace {
return false
}

return true
}

func (l *Lister) volumeIsMaprCSIBased(volume *coreV1.PersistentVolume) bool {
// Check if the volume is MapR CSI-based
if volume.Spec.CSI == nil {
return false
}

// Check if the volume is provisioned by one of the MapR CSI provisioners
for _, provisioner := range maprCSIProvisioners {
if volume.Spec.CSI.Driver == provisioner {
return true
}
}

return false
}

0 comments on commit ecb094f

Please sign in to comment.