Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.

Commit

Permalink
Support sshctx [DisplayName] (#7)
Browse files Browse the repository at this point in the history
* Support `sshctx [DisplayName]`

Signed-off-by: spencercjh <shouspencercjh@foxmail.com>

* Add docs

Signed-off-by: spencercjh <shouspencercjh@foxmail.com>
  • Loading branch information
spencercjh authored Nov 11, 2021
1 parent 35f43ca commit f45996d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 13 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ USAGE:

```sh
$ sshctx
List hosts in `~/.ssh/config`
List hosts in `~/.ssh/config`.

$ sshctx 192.168.1.2
Connect to context `192.168.1.2`.
$ sshctx test
Connect to host `test` in your `~/.ssh/config`.

$ sshctx -
Connect to context `192.168.1.2`.
Connect to context `test`.

$ sshctx -p
Show the latest connected host
```

-----
48 changes: 39 additions & 9 deletions cmd/sshctx/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (

// SwitchOp indicates intention to switch contexts.
type SwitchOp struct {
Target string // '-' for back and forth, or NAME
Target string // - or DisplayName or `💻: DisplayName#user@host`
}

func (op SwitchOp) Run(stdout, stderr io.Writer) error {
Expand Down Expand Up @@ -84,35 +84,65 @@ func savePreviousHost(stdin io.Writer, displayName, sshPara string) error {
}

sshCtxDataPath, _ := sshconfig.GetSSHCtxDataPath()
if err := ioutil.WriteFile(sshCtxDataPath, data, 0666); err != nil {
if err := ioutil.WriteFile(sshCtxDataPath, data, 0600); err != nil {
return errors.Wrap(err, "failed to write host to sshctxData file")
}
_ = printer.Success(stdin, "Saved previous host successfully: %v", host)
return nil
}

// extract
// extract displayName and sshPara from `💻: DisplayName#SSHPara`
func extract(target string) (string, string, error) {
sshParaBeginIndex := strings.IndexAny(target, "#")
if sshParaBeginIndex == -1 {
return "", "", errors.New("invalid target")
}
displayName := target[:sshParaBeginIndex]
var displayName = target[:sshParaBeginIndex]
displayName = target[strings.IndexAny(displayName, ": ")+2 : sshParaBeginIndex]
sshPara := target[sshParaBeginIndex+1:]
return displayName, sshPara, nil
}

// connectTarget
func connectTarget(target string, stderr io.Writer) (string, string, error) {
// sshctx DisplayName
if !strings.HasPrefix(target, "💻") {
return connectTargetWithDisplayNameOnly(target, stderr)
}

// sshctx 💻: DisplayName#user@host from LIST op
displayName, sshPara, err := extract(target)
if err != nil {
return "", "", err
}
return connectTargetWithDisplayName(displayName, sshPara, stderr)
return connectTargetWithDisplayNameAndSSHParameter(displayName, sshPara, stderr)
}

// connectTargetWithDisplayNameOnly
func connectTargetWithDisplayNameOnly(displayName string, stderr io.Writer) (string, string, error) {
sc := new(sshconfig.SSHConfig).WithLoader(sshconfig.DefaultLoader)

defer func(sshConfig *sshconfig.SSHConfig) {
_ = sshConfig.Close()
}(sc)

if err := sc.Parse(); err != nil {
return "", "", errors.Wrap(err, "sshconfig error")
}
var targetHost = sshconfig.EmptyHost
for _, h := range sc.Hosts {
if displayName == h.DisplayName {
targetHost = h
}
}
if targetHost == sshconfig.EmptyHost {
return "", "", fmt.Errorf("no config for host: %s", displayName)
}
return connectTargetWithDisplayNameAndSSHParameter(targetHost.DisplayName, targetHost.ToSSHParameter(), stderr)
}

// connectTargetWithDisplayName
func connectTargetWithDisplayName(displayName string, sshPara string, stderr io.Writer) (string, string, error) {
// connectTargetWithDisplayNameAndSSHParameter actual ssh cmd
func connectTargetWithDisplayNameAndSSHParameter(displayName string, sshPara string, stderr io.Writer) (string, string, error) {
_ = printer.Success(stderr, "Switched to target %s.", printer.SuccessColor.Sprint(displayName))

var waitGroup sync.WaitGroup
Expand All @@ -131,7 +161,7 @@ func connectTargetWithDisplayName(displayName string, sshPara string, stderr io.
return displayName, sshPara, nil
}

// connectPrevious switches to previously switch context.
// connectPrevious switches to previously connected host.
func connectPrevious(stderr io.Writer) (string, string, error) {
sc := new(sshconfig.SSHConfig).WithLoader(sshconfig.DefaultLoader)

Expand All @@ -147,5 +177,5 @@ func connectPrevious(stderr io.Writer) (string, string, error) {
return "", "", errors.New("No previous host")
}

return connectTargetWithDisplayName(sc.PreviousHost.DisplayName, sc.PreviousHost.ToSSHParameter(), stderr)
return connectTargetWithDisplayNameAndSSHParameter(sc.PreviousHost.DisplayName, sc.PreviousHost.ToSSHParameter(), stderr)
}

0 comments on commit f45996d

Please sign in to comment.