Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Commit

Permalink
feat: enable user to choose project, domain from CLI
Browse files Browse the repository at this point in the history
Signed-off-by: zychen5186 <brianchen5197@gmail.com>
  • Loading branch information
zychen5186 committed Apr 12, 2024
1 parent bd93aed commit 39820c6
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 57 deletions.
56 changes: 18 additions & 38 deletions pkg/bubbletea/bubbletea_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import (
)

const (
listHeight = 14
defaultWidth = 20
listHeight = 17
defaultWidth = 40
)

var (
// titleStyle = lipgloss.NewStyle().MarginLeft(2)
titleStyle = lipgloss.NewStyle().MarginLeft(2)
itemStyle = lipgloss.NewStyle().PaddingLeft(4)
selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
Expand Down Expand Up @@ -76,17 +76,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit

case "enter":
i, _ := m.list.SelectedItem().(item)
targetArgs = append(targetArgs, string(i))

var isLeaf bool
m.list, isLeaf = newList(string(i))
if isLeaf {
m.quitting = true
rootCmd.SetArgs(targetArgs)
item, _ := m.list.SelectedItem().(item)
m, err := genListModel(m, string(item))
if err != nil || m.quitting {
return m, tea.Quit
}

return m, nil
}
}
Expand All @@ -103,42 +97,24 @@ func (m model) View() string {
return "\n" + m.list.View()
}

func genList(items []list.Item) list.Model {
func genList(items []list.Item, title string) list.Model {
l := list.New(items, itemDelegate{}, defaultWidth, listHeight)
// l.Title = "Choose one of the commands"
l.SetShowStatusBar(false)
l.SetShowTitle(false)
l.SetShowStatusBar(false)
l.SetFilteringEnabled(false)
// l.Styles.Title = titleStyle
if title != "" {
l.Title = title
l.SetShowTitle(true)
l.Styles.Title = titleStyle
}
l.Styles.PaginationStyle = paginationStyle
l.Styles.HelpStyle = helpStyle

return l
}

func ifRunBubbleTea(_rootCmd cobra.Command) (*cobra.Command, bool, error) {
cmd, flags, err := _rootCmd.Find(os.Args[1:])
if err != nil {
return cmd, false, err
}

err = _rootCmd.ParseFlags(flags)
if err != nil {
return nil, false, err
}

format, err := _rootCmd.Flags().GetString("format")
if format != "bubbletea" || err != nil {
return nil, false, err
} else {
return cmd, true, err
}
}

func Bubbletea(_rootCmd *cobra.Command) error {

rootCmd = _rootCmd
targetArgs = os.Args[1:]

currentCmd, run, err := ifRunBubbleTea(*rootCmd)
if err != nil {
Expand All @@ -147,15 +123,19 @@ func Bubbletea(_rootCmd *cobra.Command) error {
return nil
}

InitCommandFlagMap()

items := generateSubCmdItems(currentCmd)

l := genList(items)
l := genList(items, "")
m := model{list: l}

if _, err := tea.NewProgram(m).Run(); err != nil {
fmt.Println("Error running program:", err)
os.Exit(1)
}

rootCmd.SetArgs(append(os.Args[1:], newArgs...))

return nil
}
193 changes: 174 additions & 19 deletions pkg/bubbletea/bubbletea_util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
package bubbletea

import (
"context"
"fmt"
"os"
"strings"

"github.com/charmbracelet/bubbles/list"
"github.com/flyteorg/flyte/flyteidl/clients/go/admin"
"github.com/flyteorg/flytectl/cmd/config/subcommand/project"
cmdcore "github.com/flyteorg/flytectl/cmd/core"
"github.com/flyteorg/flytectl/pkg/pkce"
"github.com/spf13/cobra"
)

Expand All @@ -12,26 +21,186 @@ type Command struct {
}

var (
rootCmd *cobra.Command
newArgs []string
flags []string
)
var (
DOMAIN_NAME = [3]string{"development", "staging", "production"}
isCommand = true
nameToCommand = map[string]Command{}
rootCmd *cobra.Command
targetArgs []string
)

// Check if -f bubbletea is in args
func ifRunBubbleTea(_rootCmd cobra.Command) (*cobra.Command, bool, error) {
cmd, flags, err := _rootCmd.Find(os.Args[1:])
if err != nil {
return cmd, false, err
}

err = _rootCmd.ParseFlags(flags)
if err != nil {
return nil, false, err
}

format, err := _rootCmd.Flags().GetString("format")
if format != "bubbletea" || err != nil {
return nil, false, err
} else {
return cmd, true, err
}
}

// Generate a []list.Item of cmd's subcommands
func generateSubCmdItems(cmd *cobra.Command) []list.Item {
items := []list.Item{}

for _, subcmd := range cmd.Commands() {
nameToCommand[subcmd.Use] = Command{
subCmdName := strings.Fields(subcmd.Use)[0]
nameToCommand[subCmdName] = Command{
Cmd: subcmd,
Name: subcmd.Use,
Name: subCmdName,
Short: subcmd.Short,
}
items = append(items, item(subcmd.Use))
items = append(items, item(subCmdName))
}

return items
}

// Generate list.Model for domain names
func genDomainListModel(m model) (model, error) {
items := []list.Item{}
for _, domain := range DOMAIN_NAME {
items = append(items, item(domain))
}

m.list = genList(items, "Please choose one of the domains")
return m, nil
}

// Get the "get" "project" cobra.Command item
func extractGetProjectCmd() *cobra.Command {
var getProjectCmd *cobra.Command

for _, cmd := range rootCmd.Commands() {
if cmd.Use == "get" {
getProjectCmd = cmd
break
}
}
for _, cmd := range getProjectCmd.Commands() {
if cmd.Use == "project" {
getProjectCmd = cmd
break
}
}
return getProjectCmd
}

// Get all the project names from the configured endpoint
func getProjects(getProjectCmd *cobra.Command) ([]string, error) {
ctx := context.Background()
rootCmd.PersistentPreRunE(rootCmd, []string{})
adminCfg := admin.GetConfig(ctx)

clientSet, err := admin.ClientSetBuilder().WithConfig(admin.GetConfig(ctx)).
WithTokenCache(pkce.TokenCacheKeyringProvider{
ServiceUser: fmt.Sprintf("%s:%s", adminCfg.Endpoint.String(), pkce.KeyRingServiceUser),
ServiceName: pkce.KeyRingServiceName,
}).Build(ctx)
if err != nil {
return nil, err
}
cmdCtx := cmdcore.NewCommandContext(clientSet, getProjectCmd.OutOrStdout())

projects, err := cmdCtx.AdminFetcherExt().ListProjects(ctx, project.DefaultConfig.Filter)
if err != nil {
return nil, err
}

projectNames := []string{}
for _, p := range projects.Projects {
projectNames = append(projectNames, p.Id)
}

return projectNames, nil
}

// Generate list.Model for project names from the configured endpoint
func genProjectListModel(m model) (model, error) {
getProjectCmd := extractGetProjectCmd()
projects, err := getProjects(getProjectCmd)
if err != nil {
return m, err
}

items := []list.Item{}
for _, project := range projects {
items = append(items, item(project))
}

m.list = genList(items, "Please choose one of the projects")

return m, nil
}

// Generate list.Model of options for different flags
func genFlagListModel(m model, f string) (model, error) {
var err error

switch f {
case "-p":
m, err = genProjectListModel(m)
case "-d":
m, err = genDomainListModel(m)
}

return m, err
}

// Generate list.Model of subcommands from a given command
func genCmdListModel(m model, c string) model {
if len(nameToCommand[c].Cmd.Commands()) == 0 {
return m
}

items := generateSubCmdItems(nameToCommand[c].Cmd)
l := genList(items, "")
m.list = l

return m
}

// Generate list.Model after user chose one of the item
func genListModel(m model, item string) (model, error) {
newArgs = append(newArgs, item)

if isCommand {
m = genCmdListModel(m, item)
var ok bool
if flags, ok = commandFlagMap[sliceToString(newArgs)]; ok { // If found in commandFlagMap means last command
isCommand = false
} else {
return m, nil
}
}
if len(flags) > 0 {
nextFlag := flags[0]
flags = flags[1:]
newArgs = append(newArgs, nextFlag)
var err error
m, err = genFlagListModel(m, nextFlag)
if err != nil {
return m, err
}
} else {
m.quitting = true
return m, nil
}
return m, nil
}

// func isValidCommand(curArg string, cmd *cobra.Command) (*cobra.Command, bool) {
// for _, subCmd := range cmd.Commands() {
// if subCmd.Use == curArg {
Expand All @@ -54,17 +223,3 @@ func generateSubCmdItems(cmd *cobra.Command) []list.Item {

// return findSubCmdItems(subCmd, inputArgs[1:])
// }

func newList(i string) (list.Model, bool) {

items := []list.Item{}

if len(nameToCommand[i].Cmd.Commands()) == 0 {
return list.New(items, itemDelegate{}, defaultWidth, listHeight), true
}

items = generateSubCmdItems(nameToCommand[i].Cmd)
l := genList(items)

return l, false
}
Loading

0 comments on commit 39820c6

Please sign in to comment.