Skip to content

Commit

Permalink
Add kubectl-minio plugin tenant flags and fields (#1907)
Browse files Browse the repository at this point in the history
Add support for --volumes-per-server flag in the kubectl minio plugin during creation or expansion of a tenant
Allow disable antiaffinity with expansion of a tenant
  • Loading branch information
allanrogerr committed Dec 14, 2023
1 parent 856c422 commit 3799aa5
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 49 deletions.
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -200,16 +200,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
github.com/lestrrat-go/jwx v1.2.26 h1:4iFo8FPRZGDYe1t19mQP0zTRqA7n8HnJ5lkIiDvJcB0=
github.com/lestrrat-go/jwx v1.2.26/go.mod h1:MaiCdGbn3/cckbOFSCluJlJMmp9dmZm5hDuIkx8ftpQ=
github.com/lestrrat-go/jwx v1.2.27 h1:cvnTnda/YzdyFuWdEAMkI6BsLtItSrASEVCI3C/IUEQ=
github.com/lestrrat-go/jwx v1.2.27/go.mod h1:Stob9LjSqR3lOmNdxF0/TvZo60V3hUGv8Fr7Bwzla3k=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
Expand Down Expand Up @@ -442,7 +438,6 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
Expand Down
6 changes: 5 additions & 1 deletion kubectl-minio/cmd/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,11 @@ func CapacityPerVolume(capacity string, volumes int32) (*resource.Quantity, erro
if err != nil {
return nil, err
}
return resource.NewQuantity(totalQuantity.Value()/int64(volumes), totalQuantity.Format), nil
quantity := resource.NewQuantity(totalQuantity.Value()/int64(volumes), totalQuantity.Format)
if quantity.Sign() <= 0 {
return nil, errors.New("capacity per volume needs to be greater than zero")
}
return quantity, nil
}

// TotalCapacity returns total capacity of a given tenant
Expand Down
33 changes: 26 additions & 7 deletions kubectl-minio/cmd/resources/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package resources

import (
"errors"

"github.com/minio/kubectl-minio/cmd/helpers"
operator "github.com/minio/operator/pkg/apis/minio.min.io"
miniov2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
Expand All @@ -33,6 +32,7 @@ type TenantOptions struct {
ConfigurationSecretName string
Servers int32
Volumes int32
VolumesPerServer int32
Capacity string
NS string
Image string
Expand All @@ -55,22 +55,35 @@ func (t TenantOptions) Validate() error {
if t.Servers <= 0 {
return errors.New("--servers is required. Specify a value greater than or equal to 1")
}
if t.Volumes <= 0 {
return errors.New("--volumes is required. Specify a positive value")
if t.Volumes <= 0 && t.VolumesPerServer <= 0 {
return errors.New("--volumes or --volumes-per-server is required. Specify either with a value greater than or equal to 1")
}
if t.Volumes > 0 && t.VolumesPerServer > 0 {
return errors.New("only either --volumes or --volumes-per-server may be specified")
}
if t.VolumesPerServer > 0 {
t.Volumes = t.VolumesPerServer * t.Servers
}
if t.Capacity == "" {
return errors.New("--capacity flag is required")
}
_, err := resource.ParseQuantity(t.Capacity)
capacity, err := resource.ParseQuantity(t.Capacity)
if err != nil {
if err == resource.ErrFormatWrong {
return errors.New("--capacity flag is incorrectly formatted. Please use suffix like 'T' or 'Ti' only")
return errors.New("--capacity flag is incorrectly formatted. Use a suffix like 'T' or 'Ti' only")
}
return err
}
if capacity.Sign() <= 0 {
return errors.New("--capacity needs to be greater than zero")
}
if t.Volumes%t.Servers != 0 {
return errors.New("--volumes should be a multiple of --servers")
}
_, err = helpers.CapacityPerVolume(t.Capacity, t.Volumes)
if err != nil {
return err
}
return nil
}

Expand Down Expand Up @@ -104,7 +117,13 @@ func storageClass(sc string) *string {
// NewTenant will return a new Tenant for a MinIO Operator
func NewTenant(opts *TenantOptions, userSecret *v1.Secret) (*miniov2.Tenant, error) {
autoCert := !opts.DisableTLS
volumesPerServer := helpers.VolumesPerServer(opts.Volumes, opts.Servers)
// Derive Volumes or VolumesPerServer in the absence of the other
// Exclusively either variable is guaranteed to exist
if opts.Volumes == 0 {
opts.Volumes = opts.VolumesPerServer * opts.Servers
} else {
opts.VolumesPerServer = helpers.VolumesPerServer(opts.Volumes, opts.Servers)
}
capacityPerVolume, err := helpers.CapacityPerVolume(opts.Capacity, opts.Volumes)
if err != nil {
return nil, err
Expand All @@ -128,7 +147,7 @@ func NewTenant(opts *TenantOptions, userSecret *v1.Secret) (*miniov2.Tenant, err
Console: opts.ExposeConsoleService,
MinIO: opts.ExposeMinioService,
},
Pools: []miniov2.Pool{Pool(opts, volumesPerServer, *capacityPerVolume)},
Pools: []miniov2.Pool{Pool(opts, opts.VolumesPerServer, *capacityPerVolume)},
RequestAutoCert: &autoCert,
Mountpath: helpers.MinIOMountPath,
KES: tenantKESConfig(opts.Name, opts.KmsSecret, opts.KesImage),
Expand Down
23 changes: 19 additions & 4 deletions kubectl-minio/cmd/tenant-create.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ func newTenantCreateCmd(out io.Writer, errOut io.Writer) *cobra.Command {
c := &createCmd{out: out, errOut: errOut}

cmd := &cobra.Command{
Use: "create <TENANTNAME> --pool <POOLNAME> --servers <NSERVERS> --volumes <NVOLUMES> --capacity <SIZE> --namespace <TENANTNS>",
Use: "create <TENANTNAME> --pool <POOLNAME> --servers <NSERVERS> ( --volumes <NVOLUMES> | --volumes-per-server <NVOLUMESPERSERVER> ) --capacity <SIZE> --namespace <TENANTNS>",
Short: "Create a MinIO tenant",
Long: createDesc,
Example: createExample,
Args: func(cmd *cobra.Command, args []string) error {
// The disable-tls parameter default value is false, we cannot rely on the default value binded to the tenantOpts.DisableTLS variable
// The disable-tls parameter default value is false, we cannot rely on the default value bound to the tenantOpts.DisableTLS variable
// to identify if the parameter --disable-tls was actually set on the command line.
// regardless of which value is being set to the flag, if the flag and ONLY if the flag is present, then we disable TLS
c.tenantOpts.DisableTLS = cmd.Flags().Lookup("disable-tls").Changed
Expand All @@ -80,6 +80,7 @@ func newTenantCreateCmd(out io.Writer, errOut io.Writer) *cobra.Command {
f.StringVarP(&c.tenantOpts.PoolName, "pool", "p", "", "name for this pool")
f.Int32Var(&c.tenantOpts.Servers, "servers", 0, "total number of pods in MinIO tenant")
f.Int32Var(&c.tenantOpts.Volumes, "volumes", 0, "total number of volumes in the MinIO tenant")
f.Int32Var(&c.tenantOpts.VolumesPerServer, "volumes-per-server", 0, "number of volumes in each server in the MinIO tenant")
f.StringVar(&c.tenantOpts.Capacity, "capacity", "", "total raw capacity of MinIO tenant in this pool, e.g. 16Ti")
f.StringVarP(&c.tenantOpts.NS, "namespace", "n", "", "k8s namespace for this MinIO tenant")
f.StringVarP(&c.tenantOpts.StorageClass, "storage-class", "s", helpers.DefaultStorageclass, "storage class for this MinIO tenant")
Expand Down Expand Up @@ -182,7 +183,11 @@ func (c *createCmd) populateInteractiveTenant() error {
c.tenantOpts.Name = helpers.AskQuestion("Tenant name", helpers.CheckValidTenantName)
c.tenantOpts.ConfigurationSecretName = fmt.Sprintf("%s-env-configuration", c.tenantOpts.Name)
c.tenantOpts.Servers = int32(helpers.AskNumber("Total of servers", greaterThanZero))
c.tenantOpts.Volumes = int32(helpers.AskNumber("Total of volumes", greaterThanZero))
if helpers.Ask("Define 'Total of volumes'") {
c.tenantOpts.Volumes = int32(helpers.AskNumber("Total of volumes", greaterThanZero))
} else {
c.tenantOpts.VolumesPerServer = int32(helpers.AskNumber("Volumes per server", greaterThanZero))
}
c.tenantOpts.NS = helpers.AskQuestion("Namespace", validateEmptyInput)
c.tenantOpts.Capacity = helpers.AskQuestion("Capacity", validateCapacity)
if err := c.tenantOpts.Validate(); err != nil {
Expand All @@ -192,6 +197,7 @@ func (c *createCmd) populateInteractiveTenant() error {
c.tenantOpts.ExposeMinioService = helpers.Ask("Expose Minio Service")
c.tenantOpts.ExposeConsoleService = helpers.Ask("Expose Console Service")
c.tenantOpts.EnableSFTP = helpers.Ask("Enable SFTP")
c.tenantOpts.DisableAntiAffinity = helpers.Ask("Disable Anti-Affinity (unsupported in production environment)")
return nil
}

Expand All @@ -206,7 +212,16 @@ func validateCapacity(value string) error {
if err := validateEmptyInput(value); err != nil {
return err
}
_, err := resource.ParseQuantity(value)
capacity, err := resource.ParseQuantity(value)
if err != nil {
if err == resource.ErrFormatWrong {
return errors.New("capacity flag is incorrectly formatted. Use a suffix like 'T' or 'Ti' only")
}
return err
}
if capacity.Sign() <= 0 {
return errors.New("capacity needs to be greater than zero")
}
return err
}

Expand Down
18 changes: 12 additions & 6 deletions kubectl-minio/cmd/tenant-expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import (
"encoding/json"
"errors"
"fmt"
"io"

"github.com/minio/kubectl-minio/cmd/helpers"
"github.com/minio/kubectl-minio/cmd/resources"
"io"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
Expand Down Expand Up @@ -51,7 +50,7 @@ func newTenantExpandCmd(out io.Writer, errOut io.Writer) *cobra.Command {
v := &expandCmd{out: out, errOut: errOut}

cmd := &cobra.Command{
Use: "expand <TENANTNAME> --pool <POOLNAME> --servers <NSERVERS> --volumes <NVOLUMES> --capacity <SIZE> --namespace <TENANTNS>",
Use: "expand <TENANTNAME> --pool <POOLNAME> --servers <NSERVERS> ( --volumes <NVOLUMES> | --volumes-per-server <NVOLUMESPERSERVER> ) --capacity <SIZE> --namespace <TENANTNS>",
Short: "Add capacity to existing tenant",
Long: expandDesc,
Example: expandExample,
Expand All @@ -73,12 +72,13 @@ func newTenantExpandCmd(out io.Writer, errOut io.Writer) *cobra.Command {
f.StringVarP(&v.tenantOpts.PoolName, "pool", "p", "", "name for this pool expansion")
f.Int32Var(&v.tenantOpts.Servers, "servers", 0, "total number of pods to add to tenant")
f.Int32Var(&v.tenantOpts.Volumes, "volumes", 0, "total number of volumes to add to tenant")
f.Int32Var(&v.tenantOpts.VolumesPerServer, "volumes-per-server", 0, "number of volumes in each server in the MinIO tenant")
f.StringVar(&v.tenantOpts.Capacity, "capacity", "", "total raw capacity to add to tenant, e.g. 16Ti")
f.StringVarP(&v.tenantOpts.StorageClass, "storage-class", "s", helpers.DefaultStorageclass, "storage class for the expanded MinIO tenant pool (can be different than original pool)")
f.BoolVar(&v.tenantOpts.DisableAntiAffinity, "enable-host-sharing", false, "[TESTING-ONLY] disable anti-affinity to allow pods to be co-located on a single node (unsupported in production environment)")
f.BoolVarP(&v.output, "output", "o", false, "generate MinIO tenant yaml with expansion details")

cmd.MarkFlagRequired("servers")
cmd.MarkFlagRequired("volumes")
cmd.MarkFlagRequired("capacity")
return cmd
}
Expand Down Expand Up @@ -123,7 +123,13 @@ func (v *expandCmd) run() error {
return err
}
currentCapacity := helpers.TotalCapacity(*t)
volumesPerServer := helpers.VolumesPerServer(v.tenantOpts.Volumes, v.tenantOpts.Servers)
// Derive Volumes or VolumesPerServer in the absence of the other
// Exclusively either variable is guaranteed to exist
if v.tenantOpts.Volumes == 0 {
v.tenantOpts.Volumes = v.tenantOpts.VolumesPerServer * v.tenantOpts.Servers
} else {
v.tenantOpts.VolumesPerServer = helpers.VolumesPerServer(v.tenantOpts.Volumes, v.tenantOpts.Servers)
}
capacityPerVolume, err := helpers.CapacityPerVolume(v.tenantOpts.Capacity, v.tenantOpts.Volumes)
if err != nil {
return err
Expand All @@ -134,7 +140,7 @@ func (v *expandCmd) run() error {
v.tenantOpts.PoolName = resources.GeneratePoolName(len(t.Spec.Pools))
}

t.Spec.Pools = append(t.Spec.Pools, resources.Pool(&v.tenantOpts, volumesPerServer, *capacityPerVolume))
t.Spec.Pools = append(t.Spec.Pools, resources.Pool(&v.tenantOpts, v.tenantOpts.VolumesPerServer, *capacityPerVolume))
expandedCapacity := helpers.TotalCapacity(*t)
if !v.output {
fmt.Printf(Bold(fmt.Sprintf("\nExpanding Tenant '%s/%s' from %s to %s\n\n", t.ObjectMeta.Name, t.ObjectMeta.Namespace, currentCapacity, expandedCapacity)))
Expand Down
4 changes: 3 additions & 1 deletion kubectl-minio/cmd/tenant-info.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ func printTenantInfo(tenant miniov2.Tenant) {
}

t := helpers.GetTable()
t.SetHeader([]string{"Pool", "Servers", "Volumes(server)", "Capacity(volume)"})
t.SetHeader([]string{"Pool", "Servers", "Volumes per server", "Volumes", "Capacity per volume", "Capacity"})
for i, z := range tenant.Spec.Pools {
t.Append([]string{
strconv.Itoa(i),
strconv.Itoa(int(z.Servers)),
strconv.Itoa(int(z.VolumesPerServer)),
strconv.Itoa(int(z.VolumesPerServer) * int(z.Servers)),
humanize.IBytes(uint64(z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().Value())),
humanize.IBytes(uint64(z.VolumeClaimTemplate.Spec.Resources.Requests.Storage().Value()) * uint64(z.VolumesPerServer) * uint64(z.Servers)),
})
}
t.Render()
Expand Down
3 changes: 0 additions & 3 deletions kubectl-minio/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ require (
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
Expand All @@ -55,8 +54,6 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/lestrrat-go/jwx v1.2.27 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
github.com/mailru/easyjson v0.7.7 // indirect
Expand Down

0 comments on commit 3799aa5

Please sign in to comment.