Skip to content

Commit

Permalink
[kueuectl] Add list LocalQueue command. (#2157)
Browse files Browse the repository at this point in the history
* [kueuectl] Add list LocalQueue command.

* [kueuectl] Moved integration tests to unit.
  • Loading branch information
mbobrovskyi committed May 13, 2024
1 parent b309a9a commit 5d9c711
Show file tree
Hide file tree
Showing 21 changed files with 965 additions and 31 deletions.
11 changes: 8 additions & 3 deletions cmd/kueuectl/app/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import (
"k8s.io/cli-runtime/pkg/genericiooptions"

"sigs.k8s.io/kueue/cmd/kueuectl/app/create"
"sigs.k8s.io/kueue/cmd/kueuectl/app/list"
"sigs.k8s.io/kueue/cmd/kueuectl/app/resume"
"sigs.k8s.io/kueue/cmd/kueuectl/app/stop"
"sigs.k8s.io/kueue/cmd/kueuectl/app/util"
)

type KueuectlOptions struct {
Expand Down Expand Up @@ -60,9 +62,12 @@ func NewKueuectlCmd(o KueuectlOptions) *cobra.Command {
}
configFlags.AddFlags(flags)

cmd.AddCommand(create.NewCreateCmd(configFlags, o.IOStreams))
cmd.AddCommand(resume.NewResumeCmd(configFlags, o.IOStreams))
cmd.AddCommand(stop.NewStopCmd(configFlags, o.IOStreams))
clientGetter := util.NewClientGetter(configFlags)

cmd.AddCommand(create.NewCreateCmd(clientGetter, o.IOStreams))
cmd.AddCommand(resume.NewResumeCmd(clientGetter, o.IOStreams))
cmd.AddCommand(stop.NewStopCmd(clientGetter, o.IOStreams))
cmd.AddCommand(list.NewListCmd(clientGetter, o.IOStreams))

return cmd
}
3 changes: 1 addition & 2 deletions cmd/kueuectl/app/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package create

import (
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericiooptions"

"sigs.k8s.io/kueue/cmd/kueuectl/app/util"
Expand All @@ -29,7 +28,7 @@ const (
kueuectl create localqueue my-local-queue -c my-cluster-queue`
)

func NewCreateCmd(clientGetter genericclioptions.RESTClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
func NewCreateCmd(clientGetter util.ClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "Create a resource",
Expand Down
12 changes: 3 additions & 9 deletions cmd/kueuectl/app/create/create_localqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"k8s.io/cli-runtime/pkg/printers"

"sigs.k8s.io/kueue/apis/kueue/v1beta1"
"sigs.k8s.io/kueue/client-go/clientset/versioned"
"sigs.k8s.io/kueue/client-go/clientset/versioned/scheme"
kueuev1beta1 "sigs.k8s.io/kueue/client-go/clientset/versioned/typed/kueue/v1beta1"
"sigs.k8s.io/kueue/cmd/kueuectl/app/util"
Expand Down Expand Up @@ -68,7 +67,7 @@ func NewLocalQueueOptions(streams genericiooptions.IOStreams) *LocalQueueOptions
}
}

func NewLocalQueueCmd(clientGetter genericclioptions.RESTClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
func NewLocalQueueCmd(clientGetter util.ClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
o := NewLocalQueueOptions(streams)

cmd := &cobra.Command{
Expand Down Expand Up @@ -101,7 +100,7 @@ func NewLocalQueueCmd(clientGetter genericclioptions.RESTClientGetter, streams g
}

// Complete completes all the required options
func (o *LocalQueueOptions) Complete(clientGetter genericclioptions.RESTClientGetter, cmd *cobra.Command, args []string) error {
func (o *LocalQueueOptions) Complete(clientGetter util.ClientGetter, cmd *cobra.Command, args []string) error {
o.Name = args[0]

var err error
Expand All @@ -112,12 +111,7 @@ func (o *LocalQueueOptions) Complete(clientGetter genericclioptions.RESTClientGe

o.ClusterQueue = v1beta1.ClusterQueueReference(o.UserSpecifiedClusterQueue)

config, err := clientGetter.ToRESTConfig()
if err != nil {
return err
}

clientset, err := versioned.NewForConfig(config)
clientset, err := clientGetter.KueueClientSet()
if err != nil {
return err
}
Expand Down
41 changes: 41 additions & 0 deletions cmd/kueuectl/app/list/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package list

import (
"github.com/spf13/cobra"
)

func addFieldSelectorFlagVar(cmd *cobra.Command, p *string) {
cmd.Flags().StringVar(p, "field-selector", "",
"Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.")
}

func addLabelSelectorFlagVar(cmd *cobra.Command, p *string) {
cmd.Flags().StringVarP(p, "selector", "l", "",
"Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2). Matching objects must satisfy all of the specified label constraints.")
}

func addAllNamespacesFlagVar(cmd *cobra.Command, p *bool) {
cmd.Flags().BoolVarP(p, "all-namespaces", "A", false,
"If present, list the requested object(s) across all namespaces. Namespace in current context is ignored even if specified with --namespace.")
}

func addClusterQueueFilterFlagVar(cmd *cobra.Command, p *string) {
cmd.Flags().StringVarP(p, "clusterqueue", "c", "",
"Filter by cluster queue name which associated with the local queue.")
}
41 changes: 41 additions & 0 deletions cmd/kueuectl/app/list/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package list

import (
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericiooptions"

"sigs.k8s.io/kueue/cmd/kueuectl/app/util"
)

const (
listExample = ` # List LocalQueue
kueuectl list localqueue`
)

func NewListCmd(clientGetter util.ClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "Display resources",
Example: listExample,
}

cmd.AddCommand(NewLocalQueueCmd(clientGetter, streams))

return cmd
}
163 changes: 163 additions & 0 deletions cmd/kueuectl/app/list/list_localqueue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package list

import (
"context"
"fmt"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericiooptions"
"k8s.io/cli-runtime/pkg/printers"

"sigs.k8s.io/kueue/apis/kueue/v1beta1"
"sigs.k8s.io/kueue/client-go/clientset/versioned/scheme"
kueuev1beta1 "sigs.k8s.io/kueue/client-go/clientset/versioned/typed/kueue/v1beta1"
"sigs.k8s.io/kueue/cmd/kueuectl/app/util"
)

const (
lqLong = `Lists LocalQueues that match the given criteria: point to a specific CQ,
being active/inactive, belonging to the specified namespace, matching
the label selector or the field selector.`
lqExample = ` # List LocalQueue
kueuectl list localqueue`
)

type LocalQueueOptions struct {
PrintFlags *genericclioptions.PrintFlags

AllNamespaces bool
Namespace string
FieldSelector string
LabelSelector string
ClusterQueueFilter string

Client kueuev1beta1.KueueV1beta1Interface

PrintObj printers.ResourcePrinterFunc

genericiooptions.IOStreams
}

func NewLocalQueueOptions(streams genericiooptions.IOStreams) *LocalQueueOptions {
return &LocalQueueOptions{
PrintFlags: genericclioptions.NewPrintFlags("").WithTypeSetter(scheme.Scheme),
IOStreams: streams,
}
}

func NewLocalQueueCmd(clientGetter util.ClientGetter, streams genericiooptions.IOStreams) *cobra.Command {
o := NewLocalQueueOptions(streams)

cmd := &cobra.Command{
Use: "localqueue [-–clusterqueue CLUSTER_QUEUE_NAME] [--selector key1=value1] [--field-selector key1=value1] [--all-namespaces]",
// To do not add "[flags]" suffix on the end of usage line
DisableFlagsInUseLine: true,
Aliases: []string{"lq"},
Short: "List LocalQueue",
Long: lqLong,
Example: lqExample,
Run: func(cmd *cobra.Command, args []string) {
cobra.CheckErr(o.Complete(clientGetter, cmd, args))
cobra.CheckErr(o.Run(cmd.Context()))
},
}

o.PrintFlags.AddFlags(cmd)

addAllNamespacesFlagVar(cmd, &o.AllNamespaces)
addFieldSelectorFlagVar(cmd, &o.FieldSelector)
addLabelSelectorFlagVar(cmd, &o.LabelSelector)
addClusterQueueFilterFlagVar(cmd, &o.ClusterQueueFilter)

return cmd
}

// Complete completes all the required options
func (o *LocalQueueOptions) Complete(clientGetter util.ClientGetter, cmd *cobra.Command, args []string) error {
var err error

o.Namespace, _, err = clientGetter.ToRawKubeConfigLoader().Namespace()
if err != nil {
return err
}

clientset, err := clientGetter.KueueClientSet()
if err != nil {
return err
}

o.Client = clientset.KueueV1beta1()

if !o.PrintFlags.OutputFlagSpecified() {
printer := newLocalQueueTablePrinter()
if o.AllNamespaces {
printer.WithNamespace()
}
o.PrintObj = printer.PrintObj
} else {
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = printer.PrintObj
}

return nil
}

// Run performs the list operation.
func (o *LocalQueueOptions) Run(ctx context.Context) error {
namespace := o.Namespace
if o.AllNamespaces {
namespace = ""
}

opts := metav1.ListOptions{LabelSelector: o.LabelSelector, FieldSelector: o.FieldSelector}
list, err := o.Client.LocalQueues(namespace).List(ctx, opts)
if err != nil {
return err
}

o.filterList(list)

if len(list.Items) == 0 {
if !o.AllNamespaces {
fmt.Fprintf(o.ErrOut, "No resources found in %s namespace.\n", o.Namespace)
} else {
fmt.Fprintln(o.ErrOut, "No resources found")
}
return nil
}

return o.PrintObj(list, o.Out)
}

func (o *LocalQueueOptions) filterList(list *v1beta1.LocalQueueList) {
if len(o.ClusterQueueFilter) > 0 {
filteredItems := make([]v1beta1.LocalQueue, 0, len(o.ClusterQueueFilter))
for _, lq := range list.Items {
if lq.Spec.ClusterQueue == v1beta1.ClusterQueueReference(o.ClusterQueueFilter) {
filteredItems = append(filteredItems, lq)
}
}
list.Items = filteredItems
}
}

0 comments on commit 5d9c711

Please sign in to comment.