Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
1 result

Target

Select target project
  • ai3/tools/gitlab-review-float-env-dashboard
1 result
Select Git revision
  • master
1 result
Show changes
Commits on Source (2)
FROM golang:1.17.2 as build
FROM golang:1.19 as build
ADD . /src
RUN cd /src && go build -tags netgo -o gitlab-review-float-env-dashboard ./main.go && strip gitlab-review-float-env-dashboard
......
......@@ -14,59 +14,96 @@ import (
var (
addr = flag.String("addr", ":3499", "address to listen on")
hostname = flag.String("hostname", "localhost", "public hostname")
jumpHost = flag.String("jump-host", "localhost", "SSH jump host")
hostname = flag.String("hostname", "", "(deprecated) see --jump-host")
hostConnFmt = flag.String(
"host-ssh-format",
"ssh -o UserKnownHostsFile=/dev/null -i ~/.vagrant.d/insecure_private_key -J {{.JumpHost}} root@{{.Host.IP}}",
"format string for host-specific SSH connections")
enableSOCKS = flag.Bool("enable-socks", false, "show SOCKS5 connection params")
title = flag.String("title", "VMine test cluster", "title string")
)
var (
dashTplSrc = `<!doctype html>
<html lang="en">
<head>
<title>VMine test cluster</title>
<title>{{.Title}}</title>
<style type="text/css">
body { background: white; }
.name { font-size: 120%; }
.attrs { color: #666; font-size: 90%; }
.table { border: 0; width: 100%; }
.host {
padding-left: 40px;
background: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHdpZHRoPSIyNHB4IiBoZWlnaHQ9IjI0cHgiIHN0cm9rZS13aWR0aD0iMS41IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgY29sb3I9IiMwMDAwMDAiPjxwYXRoIGQ9Ik02IDE4LjAxbC4wMS0uMDExTTYgNi4wMWwuMDEtLjAxMSIgc3Ryb2tlPSIjMDAwMDAwIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48L3BhdGg+PHBhdGggZD0iTTIgOS40VjIuNmEuNi42IDAgMDEuNi0uNmgxOC44YS42LjYgMCAwMS42LjZ2Ni44YS42LjYgMCAwMS0uNi42SDIuNmEuNi42IDAgMDEtLjYtLjZ6TTIgMjEuNHYtNi44YS42LjYgMCAwMS42LS42aDE4LjhhLjYuNiAwIDAxLjYuNnY2LjhhLjYuNiAwIDAxLS42LjZIMi42YS42LjYgMCAwMS0uNi0uNnoiIHN0cm9rZT0iIzAwMDAwMCIgc3Ryb2tlLXdpZHRoPSIxLjUiPjwvcGF0aD48L3N2Zz4K") no-repeat left 5px;
}
</style>
</head>
<body>
<h1>VMine test cluster</h1>
<h1>{{.Title}}</h1>
<h4>Hosts</h4>
<p>
You can connect to individual hosts over SSH via the jump host <i>{{.JumpHost}}</i>.<br>
Download the required SSH private key here:
<a href="https://github.com/hashicorp/vagrant/blob/main/keys/vagrant">Vagrant default insecure private key</a>,
if you do not already have it, and save it to <i>~/.vagrant.d/insecure_private_key</i>.
</p>
<table class="table">
<tbody>
{{$hostname := .Hostname}}
{{range $index, $host := .Inventory}}
<tr>
<td>
<div class="host">
<b class="name">{{$host.Name}}</b> {{$host.IP}}<br>
<span class="attrs">
{{$host.CPU}} cores, {{$host.RAM}}M ram
</span>
</div>
</td>
<td>
<pre>ssh -i ~/.vagrant.d/insecure_private_key -J {{$hostname}} vagrant@{{$host.IP}}</pre>
<pre>{{hostConn $host}}</pre>
</td>
</tr>
{{end}}
</tbody>
</table>
<h4>SOCKS proxy connection</h4>
{{if .EnableSOCKS}}
<h4>HTTP connection (via SOCKS5 proxy)</h4>
<pre>ssh -nN -L 9051:{{.SocksIP}}:9051 {{.Hostname}} &
# test-browser from ai3/testbed
test-browser --proxy=localhost:9051 https://...
</pre>
<p>
Forward a local port to the SOCKS5 proxy running on {{.SocksIP}}, and run a
private browser that uses it:
</p>
<pre>ssh -nN -L 9051:{{.SocksIP}}:9051 {{.JumpHost}} &
chromium --user-data-dir=$(mktemp -d) --no-first-run --no-default-browser-check \
--proxy-server=socks5://localhost:9051 https://...
</pre>
{{end}}
</body>
</html>`
dashTpl = template.Must(template.New("").Parse(dashTplSrc))
dashTpl = template.Must(template.New("").Funcs(map[string]interface{}{
"hostConn": hostConnString,
}).Parse(dashTplSrc))
hostConnTpl *template.Template
)
func hostConnString(host *hostinfo) string {
var buf bytes.Buffer
hostConnTpl.Execute(&buf, map[string]interface{}{
"JumpHost": *jumpHost,
"Host": host,
})
return buf.String()
}
type hostinfo struct {
Name string `json:"name"`
Image string `json:"image"`
......@@ -114,11 +151,15 @@ func handleRequest(w http.ResponseWriter, req *http.Request) {
dashTpl.Execute(w, struct {
Inventory []*hostinfo
SocksIP string
Hostname string
JumpHost string
EnableSOCKS bool
Title string
}{
Inventory: inventory,
SocksIP: inventory[0].IP,
Hostname: *hostname,
JumpHost: *jumpHost,
EnableSOCKS: *enableSOCKS,
Title: *title,
})
}
......@@ -126,6 +167,16 @@ func main() {
log.SetFlags(0)
flag.Parse()
if *hostname != "" {
*jumpHost = *hostname
}
var err error
hostConnTpl, err = template.New("hostconn").Parse(*hostConnFmt)
if err != nil {
log.Fatalf("error in host connection template: %v", err)
}
http.Handle("/dash/", http.StripPrefix("/dash/", http.HandlerFunc(handleRequest)))
log.Fatal(http.ListenAndServe(*addr, nil))
......