Skip to content
New issue

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

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

Already on GitHub? # to your account

Add a rpc server #146

Merged
merged 1 commit into from
Dec 15, 2020
Merged
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
27 changes: 7 additions & 20 deletions alias/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ type Alias struct {
SshAgent string `toml:"ssh-agent"`
Timeout string `toml:"timeout"`
SshConfig string `toml:"config"`
Rpc bool `toml:"rpc"`
RpcAddress string `toml:"rpc-address"`
}

// String parses a Alias object to a string representation.
func (a Alias) String() string {
return fmt.Sprintf("[verbose: %t, insecure: %t, detach: %t, source: %s, destination: %s, server: %s, key: %s, keep-alive-interval: %s, connection-retries: %d, wait-and-retry: %s, ssh-agent: %s, timeout: %s, config: %s]",
return fmt.Sprintf("[verbose: %t, insecure: %t, detach: %t, source: %s, destination: %s, server: %s, key: %s, keep-alive-interval: %s, connection-retries: %d, wait-and-retry: %s, ssh-agent: %s, timeout: %s, config: %s, rpc: %t, rpc-address: %s]",
a.Verbose,
a.Insecure,
a.Detach,
Expand All @@ -45,12 +48,14 @@ func (a Alias) String() string {
a.SshAgent,
a.Timeout,
a.SshConfig,
a.Rpc,
a.RpcAddress,
)
}

// Add persists an tunnel alias to the disk
func Add(alias *Alias) error {
mp, err := createDir()
mp, err := fsutils.CreateHomeDir()
if err != nil {
return err
}
Expand Down Expand Up @@ -174,24 +179,6 @@ func Get(aliasName string) (*Alias, error) {
return a, nil
}

func createDir() (string, error) {
mp, err := fsutils.Dir()
if err != nil {
return "", err
}

if _, err := os.Stat(mp); !os.IsNotExist(err) {
return mp, nil
}

err = os.MkdirAll(mp, os.ModePerm)
if err != nil {
return "", err
}

return mp, nil
}

//FIXME terrible struct name. Change it.
type aliases struct {
Aliases map[string]*Alias `toml:"aliases"`
Expand Down
4 changes: 4 additions & 0 deletions alias/alias_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func TestShow(t *testing.T) {
expected := string(expectedBytes)

output, err := alias.Show(id)
if err != nil {
t.Errorf("error showing alias %s: %v", id, err)
}

if output != expected {
t.Errorf("output doesn't match. Failing the test.")
}
Expand Down
2 changes: 2 additions & 0 deletions alias/testdata/example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ wait-and-retry = "3s"
ssh-agent = ""
timeout = "3s"
config = ""
rpc = true
rpc-address = "127.0.0.1:0"
4 changes: 4 additions & 0 deletions alias/testdata/show.alias.fixture
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
ssh-agent = ""
timeout = "3s"
config = ""
rpc = true
rpc-address = "127.0.0.1:0"
[aliases.test-env]
name = "test-env"
type = "local"
Expand All @@ -31,3 +33,5 @@
ssh-agent = ""
timeout = "3s"
config = ""
rpc = true
rpc-address = "127.0.0.1:0"
2 changes: 2 additions & 0 deletions alias/testdata/show.alias.test-env.fixture
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ wait-and-retry = "3s"
ssh-agent = ""
timeout = "3s"
config = ""
rpc = true
rpc-address = "127.0.0.1:0"
2 changes: 2 additions & 0 deletions alias/testdata/test-env.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ wait-and-retry = "3s"
ssh-agent = ""
timeout = "3s"
config = ""
rpc = true
rpc-address = "127.0.0.1:0"
4 changes: 4 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ provide 0 to never give up or a negative number to disable`)
cmd.Flags().DurationVarP(&conf.WaitAndRetry, "retry-wait", "w", 3*time.Second, "time to wait before trying to reconnect to ssh server")
cmd.Flags().StringVarP(&conf.SshAgent, "ssh-agent", "A", "", "unix socket to communicate with a ssh agent")
cmd.Flags().DurationVarP(&conf.Timeout, "timeout", "t", 3*time.Second, "ssh server connection timeout")
cmd.Flags().BoolVarP(&conf.Rpc, "rpc", "", false, "enable the rpc server")
cmd.Flags().StringVarP(&conf.RpcAddress, "rpc-address", "", "127.0.0.1:0", `set the network address of the rpc server.
The default value uses a random free port to listen for requests.
The full address is kept on $HOME/.mole/<id>.`)

err := cmd.MarkFlagRequired("server")
if err != nil {
Expand Down
39 changes: 39 additions & 0 deletions fsutils/fsutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,42 @@ func Dir() (string, error) {

return mp, nil
}

// CreateHomeDir creates then returns the location where all mole related files
// are persisted, including alias configuration and log files.
func CreateHomeDir() (string, error) {

home, err := Dir()
if err != nil {
return "", err
}

if _, err := os.Stat(home); os.IsNotExist(err) {
err := os.MkdirAll(home, 0755)
if err != nil {
return "", err
}
}

return home, err
}

// CreateInstanceDir creates and then returns the location where all files
// related to a specific mole instance are persisted.
func CreateInstanceDir(appId string) (string, error) {
home, err := Dir()
if err != nil {
return "", err
}

d := filepath.Join(home, appId)

if _, err := os.Stat(d); os.IsNotExist(err) {
err := os.MkdirAll(d, 0755)
if err != nil {
return "", err
}
}

return d, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/prometheus/common v0.10.0
github.com/sevlyar/go-daemon v0.1.5
github.com/sirupsen/logrus v1.6.0
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37
github.com/spf13/cobra v0.0.5
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.3.2
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-dap v0.2.0 h1:whjIGQRumwbR40qRU7CEKuFLmePUUc2s4Nt9DoXXxWk=
github.com/google/go-dap v0.2.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
Expand Down Expand Up @@ -98,6 +99,8 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37 h1:marA1XQDC7N870zmSFIoHZpIUduK80USeY0Rkuflgp4=
github.com/sourcegraph/jsonrpc2 v0.0.0-20200429184054-15c2290dcb37/go.mod h1:ZafdZgk/axhT1cvZAPOhw+95nz2I/Ra5qMlU4gTRwIo=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
Expand Down
22 changes: 4 additions & 18 deletions mole/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"strconv"

"github.com/davrodpin/mole/fsutils"
"github.com/gofrs/uuid"
"github.com/hpcloud/tail"
)

Expand All @@ -34,26 +33,13 @@ type DetachedInstance struct {
// NewDetachedInstance returns a new instance of DetachedInstance, making sure
// the application instance directory is created.
func NewDetachedInstance(id string) (*DetachedInstance, error) {
instanceDir, err := fsutils.Dir()
if err != nil {
return nil, err
}

if id == "" {
u, err := uuid.NewV4()
if err != nil {
return nil, fmt.Errorf("could not auto generate app instance id: %v", err)
}
id = u.String()[:8]
return nil, fmt.Errorf("application instance id can't be empty")
}

home := filepath.Join(instanceDir, id)

if _, err := os.Stat(home); os.IsNotExist(err) {
err := os.MkdirAll(home, 0755)
if err != nil {
return nil, err
}
_, err := fsutils.CreateInstanceDir(id)
if err != nil {
return nil, err
}

pfl, err := GetPidFileLocation(id)
Expand Down
12 changes: 0 additions & 12 deletions mole/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,6 @@ func TestDetachedInstanceFileLocations(t *testing.T) {

}

func TestDetachedInstanceGeneratedId(t *testing.T) {

di, err := mole.NewDetachedInstance("")
if err != nil {
t.Errorf("error creating a new detached instance: %v", err)
}

if di.Id == "" {
t.Errorf("detached instance id is empty")
}
}

func TestDetachedInstanceAlreadyRunning(t *testing.T) {
id := "TestDetachedInstanceAlreadyRunning"

Expand Down
61 changes: 59 additions & 2 deletions mole/mole.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ package mole

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"syscall"
"time"

"github.com/davrodpin/mole/alias"
"github.com/davrodpin/mole/fsutils"
"github.com/davrodpin/mole/rpc"
"github.com/davrodpin/mole/tunnel"
"github.com/sevlyar/go-daemon"

"github.com/awnumar/memguard"
"github.com/gofrs/uuid"
"github.com/sevlyar/go-daemon"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"
)
Expand All @@ -31,6 +37,8 @@ type Configuration struct {
SshAgent string
Timeout time.Duration
SshConfig string
Rpc bool
RpcAddress string
}

// ParseAlias translates a Configuration object to an Alias object.
Expand All @@ -51,6 +59,8 @@ func (c Configuration) ParseAlias(name string) *alias.Alias {
SshAgent: c.SshAgent,
Timeout: c.Timeout.String(),
SshConfig: c.SshConfig,
Rpc: c.Rpc,
RpcAddress: c.RpcAddress,
}
}

Expand All @@ -74,6 +84,14 @@ func (c *Client) Start() error {
if c.Conf.Detach {
var err error

if c.Conf.Id == "" {
u, err := uuid.NewV4()
if err != nil {
return fmt.Errorf("could not auto generate app instance id: %v", err)
}
c.Conf.Id = u.String()[:8]
}

ic, err := NewDetachedInstance(c.Conf.Id)
if err != nil {
log.WithError(err).Errorf("error while creating directory to store mole instance related files")
Expand All @@ -90,10 +108,44 @@ func (c *Client) Start() error {
}
}

if c.Conf.Id == "" {
c.Conf.Id = strconv.Itoa(os.Getpid())
}

if c.Conf.Verbose {
log.SetLevel(log.DebugLevel)
}

d, err := fsutils.CreateInstanceDir(c.Conf.Id)
if err != nil {
log.WithFields(log.Fields{
"id": c.Conf.Id,
}).WithError(err).Error("error creating directory for mole instance")

return err
}

log.Infof(">>> %t %s", c.Conf.Rpc, c.Conf.RpcAddress)
if c.Conf.Rpc {
addr, err := rpc.Start(c.Conf.RpcAddress)
if err != nil {
return err
}

rd := filepath.Join(d, "rpc")

err = ioutil.WriteFile(rd, []byte(addr.String()), 0644)
if err != nil {
log.WithFields(log.Fields{
"id": c.Conf.Id,
}).WithError(err).Error("error creating file with rpc address")

return err
}

log.Infof("rpc server address saved on %s", rd)
}

s, err := tunnel.NewServer(c.Conf.Server.User, c.Conf.Server.Address(), c.Conf.Key, c.Conf.SshAgent, c.Conf.SshConfig)
if err != nil {
log.Errorf("error processing server options: %v\n", err)
Expand Down Expand Up @@ -142,7 +194,8 @@ func (c *Client) Start() error {
//TODO need to find a way to require the attributes below to be always set
// since they are not optional (functionality will break if they are not
// set and CLI parsing is the one setting the default values).
// That could be done by make them required in the constructor's signature
// That could be done by make them required in the constructor's signature or
// by creating a configuration struct for a tunnel object.
t.ConnectionRetries = c.Conf.ConnectionRetries
t.WaitAndRetry = c.Conf.WaitAndRetry
t.KeepAliveInterval = c.Conf.KeepAliveInterval
Expand Down Expand Up @@ -267,6 +320,10 @@ func (c *Configuration) Merge(al *alias.Alias, givenFlags []string) error {

c.SshConfig = al.SshConfig

c.Rpc = al.Rpc

c.RpcAddress = al.RpcAddress

return nil
}

Expand Down
2 changes: 0 additions & 2 deletions mole/mole_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
)

func TestAliasMerge(t *testing.T) {
//keepAliveInterval, _ := time.ParseDuration("5s")

tests := []struct {
alias *alias.Alias
givenFlags []string
Expand Down
10 changes: 10 additions & 0 deletions rpc/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Package rpc implements a JSON-RPC 2.0 server that is used to call registered
procedures.

For more information about JSON-RPC 2.0, please visit:

https://www.jsonrpc.org/specification
*/

package rpc
Loading