Skip to content

Commit

Permalink
improve skywire-cli proxy command (#1680)
Browse files Browse the repository at this point in the history
* improve output of skywire-cli proxy status command

* add -addr value to generated config for skysocks-client

* improve skywire-cli proxy stop command with add two flag --all and --name

* fix no flag choosen issue

* add condition on choosen at least one flag for stop command

* implement proxy start command | implement rpc for custom setting arguments

* fix rpc query on customsetting

* fix random app port on adding new app

* add ctrl+c signal to  command
  • Loading branch information
mrpalide authored Dec 10, 2023
1 parent 5dc0aba commit dc8d582
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 36 deletions.
1 change: 1 addition & 0 deletions cmd/skywire-cli/commands/config/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ var genConfigCmd = &cobra.Command{
Binary: visorconfig.SkysocksClientName,
AutoStart: false,
Port: routing.Port(visorconfig.SkysocksClientPort),
Args: []string{"-addr", visorconfig.SkysocksClientAddr},
},
{
Name: visorconfig.VPNServerName,
Expand Down
138 changes: 116 additions & 22 deletions cmd/skywire-cli/commands/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package skysocksc

import (
"bytes"
"context"
"encoding/json"
"fmt"
"math/rand"
Expand All @@ -12,14 +13,17 @@ import (
"text/tabwriter"
"time"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/skycoin/skywire-utilities/pkg/buildinfo"
"github.com/skycoin/skywire-utilities/pkg/cmdutil"
"github.com/skycoin/skywire-utilities/pkg/skyenv"
clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc"
"github.com/skycoin/skywire/cmd/skywire-cli/internal"
"github.com/skycoin/skywire/pkg/app/appserver"
"github.com/skycoin/skywire/pkg/routing"
"github.com/skycoin/skywire/pkg/servicedisc"
)

Expand All @@ -36,6 +40,10 @@ func init() {
version = ""
}
startCmd.Flags().StringVarP(&pk, "pk", "k", "", "server public key")
startCmd.Flags().StringVarP(&addr, "addr", "a", "", "address of proxy for use")
startCmd.Flags().StringVarP(&clientName, "name", "n", "", "name of skysocks client")
stopCmd.Flags().BoolVar(&allClients, "all", false, "stop all skysocks client")
stopCmd.Flags().StringVar(&clientName, "name", "", "specific skysocks client that want stop")
listCmd.Flags().StringVarP(&sdURL, "url", "a", "", "service discovery url default:\n"+skyenv.ServiceDiscAddr)
listCmd.Flags().BoolVarP(&directQuery, "direct", "b", false, "query service discovery directly")
listCmd.Flags().StringVarP(&pk, "pk", "k", "", "check "+serviceType+" service discovery for public key")
Expand All @@ -50,25 +58,81 @@ var startCmd = &cobra.Command{
Use: "start",
Short: "start the " + serviceType + " client",
Run: func(cmd *cobra.Command, args []string) {
//check that a valid public key is provided
err := pubkey.Set(pk)

rpcClient, err := clirpc.Client(cmd.Flags())
if err != nil {
if len(args) > 0 {
err := pubkey.Set(args[0])
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("unable to create RPC client: %w", err))
}

if clientName != "" && pk != "" && addr != "" {
// add new app with -srv and -addr args, and if app was there just change -srv and -addr args and run it
err := pubkey.Set(pk)
if err != nil {
if len(args) > 0 {
err := pubkey.Set(args[0])
if err != nil {
internal.PrintFatalError(cmd.Flags(), err)
}
} else {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key"))
}
}

arguments := map[string]string{}
arguments["srv"] = pubkey.String()
arguments["addr"] = addr

_, err = rpcClient.App(clientName)
if err == nil {
err = rpcClient.DoCustomSetting(clientName, arguments)
if err != nil {
internal.PrintFatalError(cmd.Flags(), err)
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Error occurs during set args to custom skysocks client"))
}
} else {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key"))
err = rpcClient.AddApp(clientName, "skysocks-client")
if err != nil {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Error during add new app"))
}
err = rpcClient.DoCustomSetting(clientName, arguments)
if err != nil {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Error occurs during set args to custom skysocks client"))
}
}
internal.Catch(cmd.Flags(), rpcClient.StartApp(clientName))
internal.PrintOutput(cmd.Flags(), nil, "Starting.")
} else if clientName != "" && pk == "" && addr == "" {
internal.Catch(cmd.Flags(), rpcClient.StartApp(clientName))
internal.PrintOutput(cmd.Flags(), nil, "Starting.")
} else if pk != "" && clientName == "" && addr == "" {
err := pubkey.Set(pk)
if err != nil {
if len(args) > 0 {
err := pubkey.Set(args[0])
if err != nil {
internal.PrintFatalError(cmd.Flags(), err)
}
} else {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key"))
}
}
internal.Catch(cmd.Flags(), rpcClient.StartSkysocksClient(pubkey.String()))
internal.PrintOutput(cmd.Flags(), nil, "Starting.")
clientName = "skysocks-client"
// change defaul skysocks-proxy app -srv arg and run it
} else {
// error
return
}
rpcClient, err := clirpc.Client(cmd.Flags())
if err != nil {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("unable to create RPC client: %w", err))
}
//TODO: implement operational timeout
internal.Catch(cmd.Flags(), rpcClient.StartSkysocksClient(pubkey.String()))
internal.PrintOutput(cmd.Flags(), nil, "Starting.")

ctx, cancel := cmdutil.SignalContext(context.Background(), &logrus.Logger{})
defer cancel()
go func() {
<-ctx.Done()
cancel()
rpcClient.StopApp(clientName) //nolint
os.Exit(1)
}()

startProcess := true
for startProcess {
time.Sleep(time.Second * 1)
Expand Down Expand Up @@ -107,8 +171,19 @@ var stopCmd = &cobra.Command{
if err != nil {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("unable to create RPC client: %w", err))
}
internal.Catch(cmd.Flags(), rpcClient.StopSkysocksClient())
internal.PrintOutput(cmd.Flags(), "OK", fmt.Sprintln("OK"))
if allClients && clientName != "" {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("cannot use both --all and --name flag in together"))
}
if !allClients && clientName == "" {
internal.PrintFatalError(cmd.Flags(), fmt.Errorf("you should use one of flags, --all or --name"))
}
if allClients {
internal.Catch(cmd.Flags(), rpcClient.StopSkysocksClients())
internal.PrintOutput(cmd.Flags(), "all skysocks client stopped", fmt.Sprintln("all skysocks clients stopped"))
return
}
internal.Catch(cmd.Flags(), rpcClient.StopApp(clientName))
internal.PrintOutput(cmd.Flags(), fmt.Sprintf("skysocks client %s stopped", clientName), fmt.Sprintf("skysocks client %s stopped\n", clientName))
},
}

Expand All @@ -128,26 +203,45 @@ var statusCmd = &cobra.Command{
w := tabwriter.NewWriter(&b, 0, 0, 5, ' ', tabwriter.TabIndent)
internal.Catch(cmd.Flags(), err)
type appState struct {
Status string `json:"status"`
Name string `json:"name"`
Status string `json:"status"`
AutoStart bool `json:"autostart"`
Args []string `json:"args"`
AppPort routing.Port `json:"app_port"`
}
var jsonAppStatus appState
var jsonAppStatus []appState
fmt.Fprintf(w, "---- All Proxy List -----------------------------------------------------\n\n")
for _, state := range states {
if state.Name == stateName {

if state.AppConfig.Binary == binaryName {
status := "stopped"
if state.Status == appserver.AppStatusRunning {
status = "running"
}
if state.Status == appserver.AppStatusErrored {
status = "errored"
}
jsonAppStatus = appState{
Status: status,
jsonAppStatus = append(jsonAppStatus, appState{
Name: state.Name,
Status: status,
AutoStart: state.AutoStart,
Args: state.Args,
AppPort: state.Port,
})
var tmpAddr string
var tmpSrv string
for idx, arg := range state.Args {
if arg == "-srv" {
tmpSrv = state.Args[idx+1]
}
if arg == "-addr" {
tmpAddr = "127.0.0.1" + state.Args[idx+1]
}
}
_, err = fmt.Fprintf(w, "%s\n", status)
_, err = fmt.Fprintf(w, "Name: %s\nStatus: %s\nServer: %s\nAddress: %s\nAppPort: %d\nAutoStart: %t\n\n", state.Name, status, tmpSrv, tmpAddr, state.Port, state.AutoStart)
internal.Catch(cmd.Flags(), err)
}
}
fmt.Fprintf(w, "-------------------------------------------------------------------------\n")
internal.Catch(cmd.Flags(), w.Flush())
internal.PrintOutput(cmd.Flags(), jsonAppStatus, b.String())
},
Expand Down
4 changes: 4 additions & 0 deletions cmd/skywire-cli/commands/proxy/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

var (
binaryName = "skysocks-client"
stateName = "skysocks-client"
serviceType = servicedisc.ServiceTypeProxy
servicePort = ":44"
Expand All @@ -22,6 +23,9 @@ var (
sdURL string
directQuery bool
servers []servicedisc.Service
allClients bool
clientName string
addr string
)

// RootCmd contains commands that interact with the skywire-visor
Expand Down
11 changes: 11 additions & 0 deletions cmd/skywire-cli/commands/vpn/vvpn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package clivpn

import (
"bytes"
"context"
"encoding/json"
"fmt"
"math/rand"
Expand All @@ -12,10 +13,12 @@ import (
"text/tabwriter"
"time"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/skycoin/skywire-utilities/pkg/buildinfo"
"github.com/skycoin/skywire-utilities/pkg/cmdutil"
"github.com/skycoin/skywire-utilities/pkg/skyenv"
clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc"
"github.com/skycoin/skywire/cmd/skywire-cli/internal"
Expand Down Expand Up @@ -80,6 +83,14 @@ var startCmd = &cobra.Command{
}
internal.Catch(cmd.Flags(), rpcClient.StartVPNClient(pubkey))
internal.PrintOutput(cmd.Flags(), nil, "Starting.")
ctx, cancel := cmdutil.SignalContext(context.Background(), &logrus.Logger{})
defer cancel()
go func() {
<-ctx.Done()
cancel()
rpcClient.StopVPNClient("vpn-client") //nolint
os.Exit(1)
}()
startProcess := true
for startProcess {
time.Sleep(time.Second * 1)
Expand Down
24 changes: 19 additions & 5 deletions pkg/visor/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type API interface {
App(appName string) (*appserver.AppState, error)
Apps() ([]*appserver.AppState, error)
StartApp(appName string) error
AddApp(appName, binaryName string) error
RegisterApp(procConf appcommon.ProcConfig) (appcommon.ProcKey, error)
DeregisterApp(procKey appcommon.ProcKey) error
StopApp(appName string) error
Expand Down Expand Up @@ -89,7 +90,7 @@ type API interface {

//skysocks-client controls
StartSkysocksClient(pk string) error
StopSkysocksClient() error
StopSkysocksClients() error
ProxyServers(version, country string) ([]servicedisc.Service, error)

//transports
Expand Down Expand Up @@ -462,6 +463,15 @@ func (v *Visor) StartApp(appName string) error {
return ErrProcNotAvailable
}

// AddApp implement API.
func (v *Visor) AddApp(appName, binaryName string) error {
// check process manager and app launcher availability
if v.appL == nil {
return ErrAppLauncherNotAvailable
}
return v.conf.AddAppConfig(v.appL, appName, binaryName)
}

// RegisterApp implements API.
func (v *Visor) RegisterApp(procConf appcommon.ProcConfig) (appcommon.ProcKey, error) {
// check process manager and app launcher availability
Expand Down Expand Up @@ -618,15 +628,19 @@ func (v *Visor) StartSkysocksClient(serverKey string) error {
return errors.New("no skysocks-client app configuration found")
}

// StopSkysocksClient implements API.
func (v *Visor) StopSkysocksClient() error {
// StopSkysocksClients implements API.
func (v *Visor) StopSkysocksClients() error {
// check process manager and app launcher availability
if v.appL == nil {
return ErrAppLauncherNotAvailable
}
if v.procM != nil {
_, err := v.appL.StopApp(visorconfig.SkysocksClientName) //nolint:errcheck
return err
for _, app := range v.conf.Launcher.Apps {
if app.Binary == visorconfig.SkysocksClientName {
v.appL.StopApp(app.Name) //nolint
}
}
return nil
}
return ErrProcNotAvailable
}
Expand Down
27 changes: 23 additions & 4 deletions pkg/visor/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,25 @@ func (r *RPC) StartApp(name *string, _ *struct{}) (err error) {
return r.visor.StartApp(*name)
}

// SetAppAddIn is input for SetAppAdd.
type SetAppAddIn struct {
AppName string
BinaryName string
}

// AddApp add app to config
func (r *RPC) AddApp(in *SetAppAddIn, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "AddApp", in)(nil, &err)

return r.visor.AddApp(in.AppName, in.BinaryName)
}

// DoCustomSetting set custom setting to apps arguments
func (r *RPC) DoCustomSetting(in *SetAppMapIn, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "DoCustomSetting", in)(nil, &err)
return r.visor.DoCustomSetting(in.AppName, in.Val)
}

// RegisterApp registers a App with provided proc config.
func (r *RPC) RegisterApp(procConf *appcommon.ProcConfig, reply *appcommon.ProcKey) (err error) {
defer rpcutil.LogCall(r.log, "RegisterApp", procConf)(reply, &err)
Expand Down Expand Up @@ -298,11 +317,11 @@ func (r *RPC) StartSkysocksClient(pk string, _ *struct{}) (err error) {
return r.visor.StartSkysocksClient(pk)
}

// StopSkysocksClient stops SkysocksClient App
func (r *RPC) StopSkysocksClient(_ *struct{}, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "StopSkysocksClient", nil)(nil, &err)
// StopSkysocksClients stops all SkysocksClient Apps
func (r *RPC) StopSkysocksClients(_ *struct{}, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "StopSkysocksClients", nil)(nil, &err)

return r.visor.StopSkysocksClient()
return r.visor.StopSkysocksClients()
}

// RestartApp restarts App with provided name.
Expand Down
Loading

0 comments on commit dc8d582

Please sign in to comment.