Skip to content

Commit 3570c0d

Browse files
committed
feat: kubectl ray get token command
Signed-off-by: Rueian <rueiancsie@gmail.com>
1 parent 4df3f2e commit 3570c0d

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

kubectl-plugin/pkg/cmd/get/get.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func NewGetCommand(cmdFactory cmdutil.Factory, streams genericclioptions.IOStrea
2727
cmd.AddCommand(NewGetClusterCommand(cmdFactory, streams))
2828
cmd.AddCommand(NewGetWorkerGroupCommand(cmdFactory, streams))
2929
cmd.AddCommand(NewGetNodesCommand(cmdFactory, streams))
30+
cmd.AddCommand(NewGetTokenCommand(cmdFactory, streams))
3031
return cmd
3132
}
3233

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package get
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/cli-runtime/pkg/genericclioptions"
10+
cmdutil "k8s.io/kubectl/pkg/cmd/util"
11+
12+
"github.com/ray-project/kuberay/kubectl-plugin/pkg/util/client"
13+
"github.com/ray-project/kuberay/kubectl-plugin/pkg/util/completion"
14+
)
15+
16+
type GetTokenOptions struct {
17+
cmdFactory cmdutil.Factory
18+
ioStreams *genericclioptions.IOStreams
19+
namespace string
20+
secret string
21+
}
22+
23+
func NewGetTokenOptions(cmdFactory cmdutil.Factory, streams genericclioptions.IOStreams) *GetTokenOptions {
24+
return &GetTokenOptions{
25+
cmdFactory: cmdFactory,
26+
ioStreams: &streams,
27+
}
28+
}
29+
30+
func NewGetTokenCommand(cmdFactory cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
31+
options := NewGetTokenOptions(cmdFactory, streams)
32+
33+
cmd := &cobra.Command{
34+
Use: "token [SECRET NAME]",
35+
Aliases: []string{"token"},
36+
Short: "Get the auth token from the secret.",
37+
SilenceUsage: true,
38+
ValidArgsFunction: completion.RayClusterCompletionFunc(cmdFactory),
39+
Args: cobra.MaximumNArgs(1),
40+
RunE: func(cmd *cobra.Command, args []string) error {
41+
if err := options.Complete(args, cmd); err != nil {
42+
return err
43+
}
44+
// running cmd.Execute or cmd.ExecuteE sets the context, which will be done by root
45+
k8sClient, err := client.NewClient(cmdFactory)
46+
if err != nil {
47+
return fmt.Errorf("failed to create client: %w", err)
48+
}
49+
return options.Run(cmd.Context(), k8sClient)
50+
},
51+
}
52+
return cmd
53+
}
54+
55+
func (options *GetTokenOptions) Complete(args []string, cmd *cobra.Command) error {
56+
namespace, err := cmd.Flags().GetString("namespace")
57+
if err != nil {
58+
return fmt.Errorf("failed to get namespace: %w", err)
59+
}
60+
options.namespace = namespace
61+
if options.namespace == "" {
62+
options.namespace = "default"
63+
}
64+
65+
if len(args) >= 1 {
66+
options.secret = args[0]
67+
}
68+
69+
return nil
70+
}
71+
72+
func (options *GetTokenOptions) Run(ctx context.Context, k8sClient client.Client) error {
73+
secret, err := k8sClient.KubernetesClient().CoreV1().Secrets(options.namespace).Get(ctx, options.secret, v1.GetOptions{})
74+
if err != nil {
75+
return err
76+
}
77+
fmt.Fprint(options.ioStreams.Out, string(secret.Data["auth_token"]))
78+
return nil
79+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package get
2+
3+
import (
4+
"testing"
5+
6+
"github.com/spf13/cobra"
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
corev1 "k8s.io/api/core/v1"
10+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/cli-runtime/pkg/genericclioptions"
12+
kubefake "k8s.io/client-go/kubernetes/fake"
13+
cmdutil "k8s.io/kubectl/pkg/cmd/util"
14+
15+
"github.com/ray-project/kuberay/kubectl-plugin/pkg/util/client"
16+
rayClientFake "github.com/ray-project/kuberay/ray-operator/pkg/client/clientset/versioned/fake"
17+
)
18+
19+
// Tests the Run() step of the command and ensure that the output is as expected.
20+
func TestTokenGetRun(t *testing.T) {
21+
cmdFactory := cmdutil.NewFactory(genericclioptions.NewConfigFlags(true))
22+
23+
testStreams, _, resBuf, _ := genericclioptions.NewTestIOStreams()
24+
fakeTokenGetOptions := NewGetTokenOptions(cmdFactory, testStreams)
25+
26+
secret := &corev1.Secret{
27+
ObjectMeta: v1.ObjectMeta{
28+
Name: "raycluster-kuberay",
29+
Namespace: "test",
30+
},
31+
Data: map[string][]byte{
32+
"auth_token": []byte("token"),
33+
},
34+
}
35+
36+
kubeClientSet := kubefake.NewClientset(secret)
37+
rayClient := rayClientFake.NewSimpleClientset()
38+
k8sClients := client.NewClientForTesting(kubeClientSet, rayClient)
39+
40+
cmd := &cobra.Command{}
41+
cmd.Flags().StringVarP(&fakeTokenGetOptions.namespace, "namespace", "n", secret.Namespace, "")
42+
err := fakeTokenGetOptions.Complete([]string{secret.Name}, cmd)
43+
require.NoError(t, err)
44+
err = fakeTokenGetOptions.Run(t.Context(), k8sClients)
45+
require.NoError(t, err)
46+
47+
assert.Equal(t, resBuf.Bytes(), secret.Data["auth_token"])
48+
}

0 commit comments

Comments
 (0)