-
Notifications
You must be signed in to change notification settings - Fork 214
Create base #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
vendor |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
FROM codercom/ubuntu-dev-go | ||
|
||
LABEL project_root "~/go/src/go.coder.com" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# sshcode | ||
|
||
`sshcode` is a CLI to automatically install and run [code-server](https://github.com/codercom/code-server) over SSH. | ||
|
||
 | ||
|
||
## Install | ||
|
||
Chrome is recommended. | ||
|
||
```bash | ||
go get go.coder.com/sshcode | ||
``` | ||
|
||
## Usage | ||
|
||
```bash | ||
sshcode [email protected] | ||
# Starts code-server on dev.kwc.io and opens in a new browser window. | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module go.coder.com/sshcode | ||
|
||
go 1.12 | ||
|
||
require ( | ||
go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8 | ||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be // indirect | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= | ||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | ||
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= | ||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | ||
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= | ||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | ||
go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8 h1:PtQ3moPi4EAz3cyQhkUs1IGIXa2QgJpP60yMjOdu0kk= | ||
go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8/go.mod h1:83JsYgXYv0EOaXjIMnaZ1Fl6ddNB3fJnDZ/8845mUJ8= | ||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be h1:mI+jhqkn68ybP0ORJqunXn+fq+Eeb4hHKqLQcFICjAc= | ||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"net" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"strconv" | ||
"time" | ||
|
||
"go.coder.com/flog" | ||
) | ||
|
||
func main() { | ||
flag.Usage = func() { | ||
fmt.Printf(`Usage: %v HOST [SSH ARGS...] | ||
Start code-server over SSH. | ||
More info: https://github.com/codercom/sshcode | ||
`, os.Args[0]) | ||
} | ||
|
||
flag.Parse() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a blocker but in the future, you don't need the flag library, you have no flags. You can directly use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nvm, flag automatically gives you a |
||
host := flag.Arg(0) | ||
|
||
if host == "" { | ||
// If no host is specified output the usage. | ||
flag.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
flog.Info("ensuring code-server is updated...") | ||
|
||
// Downloads the latest code-server and allows it to be executed. | ||
sshCmd := exec.Command("ssh", | ||
"-tt", | ||
kylecarbs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
host, | ||
`/bin/bash -c 'set -euxo pipefail || exit 1 | ||
mkdir -p ~/bin | ||
wget -q https://codesrv-ci.cdr.sh/latest-linux -O ~/bin/code-server | ||
chmod +x ~/bin/code-server | ||
'`, | ||
) | ||
output, err := sshCmd.CombinedOutput() | ||
if err != nil { | ||
flog.Fatal("failed to update code-server: %v: %s", err, output) | ||
} | ||
|
||
flog.Info("starting code-server...") | ||
localPort, err := scanAvailablePort() | ||
if err != nil { | ||
flog.Fatal("failed to scan available port: %v", err) | ||
} | ||
|
||
// Starts code-server and forwards the remote port. | ||
sshCmd = exec.Command("ssh", | ||
"-tt", | ||
"-q", | ||
"-L", | ||
localPort+":localhost:"+localPort, | ||
host, | ||
"~/bin/code-server --host 127.0.0.1 --allow-http --no-auth --port="+localPort, | ||
) | ||
sshCmd.Stdout = os.Stdout | ||
sshCmd.Stderr = os.Stderr | ||
err = sshCmd.Start() | ||
if err != nil { | ||
flog.Fatal("failed to start code-server: %v", err) | ||
} | ||
|
||
url := "http://127.0.0.1:" + localPort | ||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) | ||
defer cancel() | ||
for { | ||
kylecarbs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if ctx.Err() != nil { | ||
flog.Fatal("code-server didn't start in time %v", ctx.Err()) | ||
} | ||
// Waits for code-server to be available before opening the browser. | ||
r, _ := http.NewRequest("GET", url, nil) | ||
r = r.WithContext(ctx) | ||
resp, err := http.DefaultClient.Do(r) | ||
if err != nil { | ||
continue | ||
} | ||
resp.Body.Close() | ||
break | ||
} | ||
|
||
openBrowser(url) | ||
sshCmd.Wait() | ||
} | ||
|
||
func openBrowser(url string) { | ||
var openCmd *exec.Cmd | ||
if commandExists("google-chrome") { | ||
openCmd = exec.Command("google-chrome", "--app="+url, "--disable-extensions", "--disable-plugins") | ||
} else if commandExists("firefox") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I take it back. If neither of these exist, this program will panic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
openCmd = exec.Command("firefox", "--url="+url, "-safe-mode") | ||
} else { | ||
flog.Info("unable to find a browser to open: sshcode only supports firefox and chrome") | ||
|
||
return | ||
} | ||
|
||
err := openCmd.Start() | ||
if err != nil { | ||
flog.Fatal("failed to open browser: %v", err) | ||
} | ||
} | ||
|
||
// Checks if a command exists locally. | ||
func commandExists(name string) bool { | ||
_, err := exec.LookPath(name) | ||
return err == nil | ||
} | ||
|
||
// scanAvailablePort scans 1024-4096 until an available port is found. | ||
func scanAvailablePort() (string, error) { | ||
for port := 1024; port < 4096; port++ { | ||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) | ||
if err != nil { | ||
// If we have an error the port is taken. | ||
port++ | ||
continue | ||
} | ||
_ = l.Close() | ||
|
||
return strconv.Itoa(port), nil | ||
} | ||
|
||
return "", errors.New("no ports available") | ||
} |
Uh oh!
There was an error while loading. Please reload this page.