Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add toolkit command for Vespa CLI with server implementations #28107

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions client/go/internal/cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ func (c *CLI) configureCommands() {
rootCmd.AddCommand(newVersionCmd(c)) // version
rootCmd.AddCommand(newVisitCmd(c)) // visit
rootCmd.AddCommand(newFeedCmd(c)) // feed
rootCmd.AddCommand(newToolkitCmd(c)) // toolkit
}

func (c *CLI) bindWaitFlag(cmd *cobra.Command, defaultSecs int, value *int) {
Expand Down
107 changes: 107 additions & 0 deletions client/go/internal/cli/cmd/toolkit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package cmd

import (
"bufio"
"context"
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/vespa-engine/vespa/client/go/internal/toolkit"
"github.com/vespa-engine/vespa/client/go/internal/vespa"
"log"
"net/http"
"os"
"os/signal"
"strings"
"sync"
"time"
)

func newToolkitCmd(cli *CLI) *cobra.Command {
return &cobra.Command{
Use: "toolkit",
Short: "Starts the Vespa toolkit servers",
Long: `The 'vespa toolkit' command initializes and starts both the frontend and proxy servers.
The frontend server serves the Vespa toolkit's user interface, while the proxy server acts
as a reverse proxy to the Vespa service, especially for cloud instances. This toolkit provides
a convenient interface for interacting with the Vespa service.`,
DisableAutoGenTag: true,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Println("This command will start the Vespa toolkit which includes frontend and proxy servers.")
fmt.Print("Do you want to continue? (Y/n): ")
reader := bufio.NewReader(os.Stdin)
response, err := reader.ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read user input: %w", err)
}
response = strings.ToLower(strings.TrimSpace(response))

// Treat empty response as "yes" since "Y" is the default
if response == "" || response == "y" || response == "yes" {
target, err := cli.target(targetOptions{})
if err != nil {
return err
}
service, err := target.Service(vespa.QueryService, time.Duration(0)*time.Second, 0, cli.config.cluster())
if err != nil {
return err
}

var wg sync.WaitGroup

// Initialize and start the FrontendServer
var frontendServer *toolkit.FrontendServer
frontendServer = toolkit.NewFrontendServer()
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("Frontend server is running on http://localhost:%d\n", frontendServer.Port)
if err := frontendServer.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Printf("Frontend server stopped with error: %v\n", err)
}
}()

// Only initialize and start the ProxyServer if target is cloud
var proxyServer *toolkit.ProxyServer
proxyServer, err = toolkit.NewProxyServer(service, target)
if err != nil {
return fmt.Errorf("could not initialize proxy server: %w", err)
}
wg.Add(1)
go func() {
defer wg.Done()
fmt.Printf("Proxy server is running on http://localhost:%d\n", proxyServer.Port)
if err := proxyServer.Start(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Printf("Proxy server stopped with error: %v\n", err)
}
}()

// Signal listener for graceful shutdown
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
<-c
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Stop frontend server
if err := frontendServer.Shutdown(ctx); err != nil {
log.Printf("Error stopping frontend server: %v\n", err)
}
// Stop proxy server
if err := proxyServer.Shutdown(ctx); err != nil {
log.Printf("Error stopping proxy server: %v\n", err)
}
// Decrement the wait group for each server to allow the main goroutine to exit
wg.Done()
wg.Done()
}()

wg.Wait()
return nil
} else {
return nil // Exit if the user chooses "no"
}
},
}
}
33 changes: 33 additions & 0 deletions client/go/internal/toolkit/dashboard/assets/favicon-62e9a8c5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading