improve cli code
This commit is contained in:
@@ -1,92 +1,121 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
)
|
||||
|
||||
func DeleteCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux delete [project-name | all]
|
||||
var usage = `Usage:
|
||||
flux delete [project-name | all]
|
||||
|
||||
Options:
|
||||
project-name: The name of the project to delete
|
||||
all: Delete all projects
|
||||
|
||||
Flux will delete the deployment of the app in the current directory or the specified project.`)
|
||||
return nil
|
||||
}
|
||||
Options:
|
||||
project-name: The name of the project to delete
|
||||
all: Delete all projects
|
||||
|
||||
if len(args) == 1 {
|
||||
if args[0] == "all" {
|
||||
var response string
|
||||
fmt.Print("Are you sure you want to delete all projects? this will delete all volumes and containers associated and cannot be undone. \n[y/N] ")
|
||||
fmt.Scanln(&response)
|
||||
Flags:
|
||||
%s
|
||||
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
}
|
||||
Flux will delete the deployment of the app in the current directory or the specified project.
|
||||
`
|
||||
|
||||
response = ""
|
||||
func deleteAll(ctx models.CommandCtx, noConfirm *bool) error {
|
||||
if !*noConfirm {
|
||||
var response string
|
||||
fmt.Print("Are you sure you want to delete all projects? this will delete all volumes and containers associated and cannot be undone. [y/N] ")
|
||||
fmt.Scanln(&response)
|
||||
|
||||
fmt.Printf("Are you really sure you want to delete all projects? \n[y/N] ")
|
||||
fmt.Scanln(&response)
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
}
|
||||
response = ""
|
||||
|
||||
req, err := http.NewRequest("DELETE", config.DeamonURL+"/deployments", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete deployments: %v", err)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete deployments: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// since we are deleting **all** projects, I feel better asking for confirmation twice
|
||||
fmt.Printf("Are you really sure you want to delete all projects? [y/N] ")
|
||||
fmt.Scanln(&response)
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
responseBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading response body: %v", err)
|
||||
}
|
||||
|
||||
responseBody = []byte(strings.TrimSuffix(string(responseBody), "\n"))
|
||||
|
||||
return fmt.Errorf("delete failed: %s", responseBody)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully deleted all projects\n")
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("DELETE", ctx.Config.DeamonURL+"/deployments", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete deployments: %v", err)
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete deployments: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
responseBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading response body: %v", err)
|
||||
}
|
||||
|
||||
responseBody = []byte(strings.TrimSuffix(string(responseBody), "\n"))
|
||||
|
||||
return fmt.Errorf("delete failed: %s", responseBody)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully deleted all projects\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteCommand(ctx models.CommandCtx, args []string) error {
|
||||
fs := flag.NewFlagSet("delete", flag.ExitOnError)
|
||||
fs.Usage = func() {
|
||||
var buf bytes.Buffer
|
||||
// Redirect flagset to print to buffer instead of stdout
|
||||
fs.SetOutput(&buf)
|
||||
fs.PrintDefaults()
|
||||
|
||||
fmt.Printf(usage, strings.TrimRight(buf.String(), "\n"))
|
||||
}
|
||||
|
||||
noConfirm := fs.Bool("no-confirm", false, "Skip confirmation prompt")
|
||||
|
||||
err := fs.Parse(args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
args = fs.Args()
|
||||
|
||||
if len(args) == 1 && args[0] == "all" {
|
||||
return deleteAll(ctx, noConfirm)
|
||||
}
|
||||
|
||||
projectName, err := GetProjectName("delete", args)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("\tfailed to get project name: %v.\n\tSee flux delete --help for more information", err)
|
||||
}
|
||||
|
||||
// ask for confirmation
|
||||
fmt.Printf("Are you sure you want to delete %s? this will delete all volumes and containers associated with the deployment, and cannot be undone. \n[y/N] ", projectName)
|
||||
var response string
|
||||
fmt.Scanln(&response)
|
||||
if !*noConfirm {
|
||||
fmt.Printf("Are you sure you want to delete %s? this will delete all volumes and containers associated with the deployment, and cannot be undone. \n[y/N] ", projectName)
|
||||
var response string
|
||||
fmt.Scanln(&response)
|
||||
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
if strings.ToLower(response) != "y" {
|
||||
fmt.Println("Aborting...")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("DELETE", config.DeamonURL+"/deployments/"+projectName, nil)
|
||||
req, err := http.NewRequest("DELETE", ctx.Config.DeamonURL+"/deployments/"+projectName, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete app: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
@@ -12,9 +11,11 @@ import (
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
@@ -152,23 +153,35 @@ func compressDirectory(compression pkg.Compression) ([]byte, error) {
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func DeployCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux deploy
|
||||
|
||||
Flux will deploy the app in the current directory, and start routing traffic to it.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeployCommand(ctx models.CommandCtx, args []string) error {
|
||||
if _, err := os.Stat("flux.json"); err != nil {
|
||||
return fmt.Errorf("no flux.json found, please run flux init first")
|
||||
}
|
||||
|
||||
spinnerWriter := models.NewCustomSpinnerWriter()
|
||||
|
||||
loadingSpinner := spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(spinnerWriter))
|
||||
defer func() {
|
||||
if loadingSpinner.Active() {
|
||||
loadingSpinner.Stop()
|
||||
}
|
||||
}()
|
||||
|
||||
signalChannel := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChannel, os.Interrupt)
|
||||
go func() {
|
||||
<-signalChannel
|
||||
if loadingSpinner.Active() {
|
||||
loadingSpinner.Stop()
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
loadingSpinner.Suffix = " Deploying"
|
||||
loadingSpinner.Start()
|
||||
|
||||
buf, err := compressDirectory(info.Compression)
|
||||
buf, err := compressDirectory(ctx.Info.Compression)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to compress directory: %v", err)
|
||||
}
|
||||
@@ -204,7 +217,7 @@ func DeployCommand(seekingHelp bool, config models.Config, info pkg.Info, loadin
|
||||
return fmt.Errorf("failed to close writer: %v", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", config.DeamonURL+"/deploy", body)
|
||||
req, err := http.NewRequest("POST", ctx.Config.DeamonURL+"/deploy", body)
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -7,22 +7,21 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
)
|
||||
|
||||
func InitCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux init [project-name]
|
||||
|
||||
Options:
|
||||
project-name: The name of the project to initialize
|
||||
|
||||
Flux will initialize a new project in the current directory or the specified project.`)
|
||||
return nil
|
||||
}
|
||||
func InitCommand(ctx models.CommandCtx, args []string) error {
|
||||
// if seekingHelp {
|
||||
// fmt.Println(`Usage:
|
||||
// flux init [project-name]
|
||||
|
||||
// Options:
|
||||
// project-name: The name of the project to initialize
|
||||
|
||||
// Flux will initialize a new project in the current directory or the specified project.`)
|
||||
// return nil
|
||||
// }
|
||||
|
||||
var projectConfig pkg.ProjectConfig
|
||||
|
||||
|
||||
@@ -7,21 +7,12 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
)
|
||||
|
||||
func ListCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux list
|
||||
|
||||
Flux will list all the apps in the daemon.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
resp, err := http.Get(config.DeamonURL + "/apps")
|
||||
func ListCommand(ctx models.CommandCtx, args []string) error {
|
||||
resp, err := http.Get(ctx.Config.DeamonURL + "/apps")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get apps: %v", err)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func GetProjectName(command string, args []string) (string, error) {
|
||||
|
||||
if len(args) == 0 {
|
||||
if _, err := os.Stat("flux.json"); err != nil {
|
||||
return "", fmt.Errorf("usage: flux %[1]s <app name>, or run flux %[1]s in the project directory", command)
|
||||
return "", fmt.Errorf("the current directory is not a flux project, please run flux %[1]s in the project directory", command)
|
||||
}
|
||||
|
||||
fluxConfigFile, err := os.Open("flux.json")
|
||||
|
||||
@@ -6,26 +6,16 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
)
|
||||
|
||||
func StartCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux start
|
||||
|
||||
Flux will start the deployment of the app in the current directory.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartCommand(ctx models.CommandCtx, args []string) error {
|
||||
projectName, err := GetProjectName("start", args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.Post(config.DeamonURL+"/start/"+projectName, "application/json", nil)
|
||||
req, err := http.Post(ctx.Config.DeamonURL+"/start/"+projectName, "application/json", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to start app: %v", err)
|
||||
}
|
||||
|
||||
@@ -6,26 +6,16 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
)
|
||||
|
||||
func StopCommand(seekingHelp bool, config models.Config, info pkg.Info, loadingSpinner *spinner.Spinner, spinnerWriter *models.CustomSpinnerWriter, args []string) error {
|
||||
if seekingHelp {
|
||||
fmt.Println(`Usage:
|
||||
flux stop
|
||||
|
||||
Flux will stop the deployment of the app in the current directory.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
func StopCommand(ctx models.CommandCtx, args []string) error {
|
||||
projectName, err := GetProjectName("stop", args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req, err := http.Post(config.DeamonURL+"/stop/"+projectName, "application/json", nil)
|
||||
req, err := http.Post(ctx.Config.DeamonURL+"/stop/"+projectName, "application/json", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to stop app: %v", err)
|
||||
}
|
||||
|
||||
155
cmd/flux/main.go
155
cmd/flux/main.go
@@ -3,16 +3,14 @@ package main
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/agnivade/levenshtein"
|
||||
"github.com/briandowns/spinner"
|
||||
"github.com/juls0730/flux/cmd/flux/commands"
|
||||
"github.com/juls0730/flux/cmd/flux/models"
|
||||
"github.com/juls0730/flux/pkg"
|
||||
@@ -29,62 +27,93 @@ var helpStr = `Usage:
|
||||
flux <command>
|
||||
|
||||
Available Commands:
|
||||
init Initialize a new project
|
||||
deploy Deploy a new version of the app
|
||||
stop Stop a container
|
||||
start Start a container
|
||||
delete Delete a container
|
||||
list List all containers
|
||||
%s
|
||||
|
||||
Flags:
|
||||
-h, --help help for flux
|
||||
Available Flags:
|
||||
--help, -h: Show this help message
|
||||
|
||||
Use "flux <command> --help" for more information about a command.`
|
||||
Use "flux <command> --help" for more information about a command.
|
||||
`
|
||||
|
||||
var maxDistance = 3
|
||||
|
||||
type CommandFunc func(models.CommandCtx, []string) error
|
||||
|
||||
type Command struct {
|
||||
Help string
|
||||
HandlerFunc CommandFunc
|
||||
}
|
||||
|
||||
type CommandHandler struct {
|
||||
commands map[string]func(bool, models.Config, pkg.Info, *spinner.Spinner, *models.CustomSpinnerWriter, []string) error
|
||||
commands map[string]Command
|
||||
aliases map[string]string
|
||||
}
|
||||
|
||||
func (h *CommandHandler) RegisterCmd(name string, handler func(bool, models.Config, pkg.Info, *spinner.Spinner, *models.CustomSpinnerWriter, []string) error) {
|
||||
h.commands[name] = handler
|
||||
func NewCommandHandler() CommandHandler {
|
||||
return CommandHandler{
|
||||
commands: make(map[string]Command),
|
||||
aliases: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func runCommand(command string, args []string, config models.Config, info pkg.Info, cmdHandler CommandHandler, try int) error {
|
||||
if try == 2 {
|
||||
return fmt.Errorf("unknown command: %s", command)
|
||||
func (h *CommandHandler) RegisterCmd(name string, handler CommandFunc, help string) {
|
||||
coomand := Command{
|
||||
Help: help,
|
||||
HandlerFunc: handler,
|
||||
}
|
||||
|
||||
seekingHelp := false
|
||||
if len(args) > 0 && (args[len(args)-1] == "--help" || args[len(args)-1] == "-h") {
|
||||
seekingHelp = true
|
||||
args = args[:len(args)-1]
|
||||
h.commands[name] = coomand
|
||||
}
|
||||
|
||||
func (h *CommandHandler) RegisterAlias(alias string, command string) {
|
||||
h.aliases[alias] = command
|
||||
}
|
||||
|
||||
// returns the command and whether or not it exists
|
||||
func (h *CommandHandler) GetCommand(command string) (Command, bool) {
|
||||
if command, ok := h.aliases[command]; ok {
|
||||
return h.commands[command], true
|
||||
}
|
||||
|
||||
spinnerWriter := models.NewCustomSpinnerWriter()
|
||||
commandStruct, ok := h.commands[command]
|
||||
return commandStruct, ok
|
||||
}
|
||||
|
||||
loadingSpinner := spinner.New(spinner.CharSets[14], 100*time.Millisecond, spinner.WithWriter(spinnerWriter))
|
||||
defer func() {
|
||||
if loadingSpinner.Active() {
|
||||
loadingSpinner.Stop()
|
||||
}
|
||||
}()
|
||||
var helpPadding = 13
|
||||
|
||||
signalChannel := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChannel, os.Interrupt)
|
||||
go func() {
|
||||
<-signalChannel
|
||||
if loadingSpinner.Active() {
|
||||
loadingSpinner.Stop()
|
||||
func (h *CommandHandler) GetHelp() {
|
||||
commandsStr := ""
|
||||
for command := range h.commands {
|
||||
curLine := ""
|
||||
|
||||
curLine += command
|
||||
for alias, aliasCommand := range h.aliases {
|
||||
if aliasCommand == command {
|
||||
curLine += fmt.Sprintf(", %s", alias)
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}()
|
||||
curLine += strings.Repeat(" ", helpPadding-(len(curLine)-2))
|
||||
commandsStr += fmt.Sprintf(" %s %s\n", curLine, h.commands[command].Help)
|
||||
}
|
||||
|
||||
handler, ok := cmdHandler.commands[command]
|
||||
fmt.Printf(helpStr, strings.TrimRight(commandsStr, "\n"))
|
||||
}
|
||||
|
||||
func (h *CommandHandler) GetHelpCmd(models.CommandCtx, []string) error {
|
||||
h.GetHelp()
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(command string, args []string, config models.Config, info pkg.Info, cmdHandler CommandHandler) error {
|
||||
commandCtx := models.CommandCtx{
|
||||
Config: config,
|
||||
Info: info,
|
||||
}
|
||||
|
||||
commandStruct, ok := cmdHandler.commands[command]
|
||||
if ok {
|
||||
return handler(seekingHelp, config, info, loadingSpinner, spinnerWriter, args)
|
||||
return commandStruct.HandlerFunc(commandCtx, args)
|
||||
}
|
||||
|
||||
// diff the command against the list of commands and if we find a command that is more than 80% similar, ask if that's what the user meant
|
||||
@@ -108,7 +137,8 @@ func runCommand(command string, args []string, config models.Config, info pkg.In
|
||||
}
|
||||
|
||||
var response string
|
||||
fmt.Printf("No command found with the name '%s'. Did you mean '%s'?\n", command, closestMatch.name)
|
||||
// new line ommitted because it will be produced when the user presses enter to submit their response
|
||||
fmt.Printf("No command found with the name '%s'. Did you mean '%s'? (y/N)", command, closestMatch.name)
|
||||
fmt.Scanln(&response)
|
||||
|
||||
if strings.ToLower(response) == "y" || strings.ToLower(response) == "yes" {
|
||||
@@ -117,18 +147,34 @@ func runCommand(command string, args []string, config models.Config, info pkg.In
|
||||
return nil
|
||||
}
|
||||
|
||||
return runCommand(command, args, config, info, cmdHandler, try+1)
|
||||
// re-run command after accepting the suggestion
|
||||
return runCommand(command, args, config, info, cmdHandler)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println(helpStr)
|
||||
cmdHandler := NewCommandHandler()
|
||||
|
||||
cmdHandler.RegisterCmd("init", commands.InitCommand, "Initialize a new project")
|
||||
cmdHandler.RegisterCmd("deploy", commands.DeployCommand, "Deploy a new version of the app")
|
||||
cmdHandler.RegisterCmd("start", commands.StartCommand, "Start the app")
|
||||
cmdHandler.RegisterCmd("stop", commands.StopCommand, "Stop the app")
|
||||
cmdHandler.RegisterCmd("list", commands.ListCommand, "List all the apps")
|
||||
cmdHandler.RegisterCmd("delete", commands.DeleteCommand, "Delete the app")
|
||||
|
||||
fs := flag.NewFlagSet("flux", flag.ExitOnError)
|
||||
fs.Usage = func() {
|
||||
cmdHandler.GetHelp()
|
||||
}
|
||||
|
||||
err := fs.Parse(os.Args[1:])
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if os.Args[1] == "--help" || os.Args[1] == "-h" {
|
||||
fmt.Println(helpStr)
|
||||
os.Exit(0)
|
||||
if len(os.Args) < 2 {
|
||||
cmdHandler.GetHelp()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(filepath.Join(configPath, "config.json")); err != nil {
|
||||
@@ -155,9 +201,6 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
command := os.Args[1]
|
||||
args := os.Args[2:]
|
||||
|
||||
resp, err := http.Get(config.DeamonURL + "/heartbeat")
|
||||
if err != nil {
|
||||
fmt.Println("Failed to connect to daemon")
|
||||
@@ -186,19 +229,9 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cmdHandler := CommandHandler{
|
||||
commands: make(map[string]func(bool, models.Config, pkg.Info, *spinner.Spinner, *models.CustomSpinnerWriter, []string) error),
|
||||
}
|
||||
|
||||
cmdHandler.RegisterCmd("deploy", commands.DeployCommand)
|
||||
cmdHandler.RegisterCmd("stop", commands.StopCommand)
|
||||
cmdHandler.RegisterCmd("start", commands.StartCommand)
|
||||
cmdHandler.RegisterCmd("delete", commands.DeleteCommand)
|
||||
cmdHandler.RegisterCmd("init", commands.InitCommand)
|
||||
|
||||
err = runCommand(command, args, config, info, cmdHandler, 0)
|
||||
err = runCommand(os.Args[1], fs.Args()[1:], config, info, cmdHandler)
|
||||
if err != nil {
|
||||
fmt.Printf("%v\n", err)
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
8
cmd/flux/models/cmd.go
Normal file
8
cmd/flux/models/cmd.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package models
|
||||
|
||||
import "github.com/juls0730/flux/pkg"
|
||||
|
||||
type CommandCtx struct {
|
||||
Config Config
|
||||
Info pkg.Info
|
||||
}
|
||||
@@ -44,11 +44,14 @@ func NewCustomStdout(spinner *CustomSpinnerWriter) *CustomStdout {
|
||||
}
|
||||
}
|
||||
|
||||
// We have this custom writer because we want to have a spinner at the bottom of the terminal, but we dont want to have
|
||||
// it interfere with the output of the command
|
||||
func (w *CustomStdout) Write(p []byte) (n int, err error) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
|
||||
n, err = os.Stdout.Write([]byte(fmt.Sprintf("\033[2K\r%s", p)))
|
||||
// clear line and carriage return
|
||||
n, err = os.Stdout.Write(fmt.Appendf(nil, "\033[2K\r%s", p))
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user