From 7e6b4d9272495ec794daa9079a02f8ea00d4d712 Mon Sep 17 00:00:00 2001
From: Erik Brakkee
Date: Sun, 21 Jul 2024 22:36:17 +0200
Subject: [PATCH] lots of work to make it actually work. Icluding the server
keep alive interval. Fix where expiry duration was added twice.
---
cmd/agent/agent.go | 25 +++++++++++++++++------
cmd/converge/server.go | 1 -
kubernetes/deployment.yaml | 25 +++++++++++++++++++++++
kubernetes/service.yaml | 13 ++++++++++++
pkg/agent/help.txt | 6 +++++-
pkg/agent/session.go | 2 +-
static/index.html | 42 ++++++++++++++++++++++----------------
7 files changed, 87 insertions(+), 27 deletions(-)
create mode 100644 kubernetes/deployment.yaml
create mode 100644 kubernetes/service.yaml
diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go
index 6cb5c2d..a02b9a0 100755
--- a/cmd/agent/agent.go
+++ b/cmd/agent/agent.go
@@ -58,10 +58,10 @@ func setWinsize(f *os.File, w, h int) {
uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0})))
}
-func sshServer(hostKeyFile string) *ssh.Server {
+func sshServer(hostKeyFile string, shellCommand string) *ssh.Server {
ssh.Handle(func(s ssh.Session) {
- // TODO shell should be made configurable
- cmd := exec.Command("bash")
+
+ cmd := exec.Command(shellCommand)
ptyReq, winCh, isPty := s.Pty()
if isPty {
workingDirectory, _ := os.Getwd()
@@ -154,8 +154,8 @@ func (f ReaderFunc) Read(p []byte) (n int, err error) {
func main() {
wsURL := os.Args[1]
- advanceWarningTime := 10 * time.Minute
- agentExpriryTime := 30 * time.Minute
+ advanceWarningTime := 5 * time.Minute
+ agentExpriryTime := 10 * time.Minute
tickerInterval := 60 * time.Second
agent.ConfigureAgent(advanceWarningTime, agentExpriryTime, tickerInterval)
@@ -176,8 +176,21 @@ func main() {
// Need to create listener implementation that aactually listens for websocket connections.
var service AgentService
+ shells := []string{"bash", "sh", "ash", "ksh", "zsh", "fish", "tcsh", "csh"}
+ shell := ""
+ for _, candidate := range shells {
+ shell, err = exec.LookPath(candidate)
+ if err == nil {
+ break
+ }
+ }
+ if shell == "" {
+ log.Printf("Cannot find a shell in %v", shells)
+ os.Exit(1)
+ }
+ log.Printf("Using shell %s for remote sessions", shell)
service = ListenerServer(func() *ssh.Server {
- return sshServer("hostkey.pem")
+ return sshServer("hostkey.pem", shell)
})
//service = ConnectionServer(netCatServer)
//service = ConnectionServer(echoServer)
diff --git a/cmd/converge/server.go b/cmd/converge/server.go
index fc34ae7..7dd3cb0 100644
--- a/cmd/converge/server.go
+++ b/cmd/converge/server.go
@@ -69,7 +69,6 @@ type FilteredFileSystem struct {
}
func (ffs FilteredFileSystem) Open(name string) (http.File, error) {
- log.Println("Name : " + name)
f, err := ffs.fs.Open(name)
if err != nil {
return nil, err
diff --git a/kubernetes/deployment.yaml b/kubernetes/deployment.yaml
new file mode 100644
index 0000000..aa6d050
--- /dev/null
+++ b/kubernetes/deployment.yaml
@@ -0,0 +1,25 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ labels:
+ app: converge
+ name: converge
+ namespace: wamblee-org
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: converge
+ template:
+ metadata:
+ labels:
+ app: converge
+ spec:
+ containers:
+ - image: your.repo.com/converge:1.0
+ imagePullPolicy: Always
+ name: converge
+ ports:
+ - containerPort: 8000
+
+
diff --git a/kubernetes/service.yaml b/kubernetes/service.yaml
new file mode 100644
index 0000000..c9f09d5
--- /dev/null
+++ b/kubernetes/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: converge
+ name: converge
+spec:
+ ports:
+ - port: 8000
+ protocol: TCP
+ targetPort: 8000
+ selector:
+ app: converge
diff --git a/pkg/agent/help.txt b/pkg/agent/help.txt
index 0fed91e..dcb960e 100644
--- a/pkg/agent/help.txt
+++ b/pkg/agent/help.txt
@@ -1,6 +1,6 @@
Session is set to expire at %v
-The session expires automatically after %d time.
+The session expires automatically after %v.
If there are no more sessions after logging out, the agent
terminates.
@@ -8,6 +8,10 @@ You can extend this time using
touch $agentdir/.hold
+The expiry time is equal to the modification time of the .hold
+file with the expiry duration added.
+
To prevent the agent from exiting after the last session is gone,
also use the above command in any shell.
+
diff --git a/pkg/agent/session.go b/pkg/agent/session.go
index 2c8016d..f1ac5c0 100644
--- a/pkg/agent/session.go
+++ b/pkg/agent/session.go
@@ -161,7 +161,7 @@ func (state *AgentState) expiryTime(filename string) time.Time {
func check() {
now := time.Now()
- expiryTime := state.expiryTime(".hold").Add(state.agentExpriryTime)
+ expiryTime := state.expiryTime(".hold")
if now.After(expiryTime) {
messageUsers("Expiry time was reached logging out")
diff --git a/static/index.html b/static/index.html
index 1b178ba..2684c8c 100644
--- a/static/index.html
+++ b/static/index.html
@@ -17,34 +17,40 @@
About
- Converge is a utility for troubleshooting builds on continuous integration serves.
- It solves a common problem where the cause of job failure is difficult to determine.
- This is complicated furhter by the fact that build jobs are usually run on a build
- farm where there is no access to the build agents or in more modern envrionments when
- jobs are run in ephemeral containers.
+ Converge is a utility for troubleshooting builds on continuous integration serves.
+ It solves a common problem where the cause of job failure is difficult to determine.
+ This is complicated further by the fact that build jobs are usually run on a build
+ farm where there is no access to the build agents or in more modern envrionments when
+ jobs are run in ephemeral containers.
- With Converge it is possible to get remote shell access to such jobs. This works
- by configuring the build job to connect to a Converge server using an agent program.
- The agent program can be downloaded from within the CI job using curl or wget.
- Next, an end-use can connect to the Converge server, a rendez-vous server, that connects
- the client and server together.
+ With Converge it is possible to get remote shell access to such jobs. This works
+ by configuring the build job to connect to a Converge server using an agent program.
+ The agent program can be downloaded from within the CI job using curl or wget.
+ Next, an end-use can connect to the Converge server, a rendez-vous server, that connects
+ the client and server together.
- The setup is such that the connection from client (end-user) to server (agent on CI job)
- is end-to-end encrypted. The Converge server itself is no more than a bitpipe which pumps
- data between client and agent.
+ The setup is such that the connection from client (end-user) to server (agent on CI job)
+ is end-to-end encrypted. The Converge server itself is no more than a bitpipe which pumps
+ data between client and agent.
- Both ssh and sftp are supported. Multiple shells are also allowed.
+ Both ssh and sftp are supported. Multiple shells are also allowed.
- There is a timeout mechanism in the agent such that jobs do not hang indefinetely waiting
- for a connection.
+ There is a timeout mechanism in the agent such that jobs do not hang indefinitely waiting
+ for a connection. This mechanism is useful to make sure build agents do not wait
+ indefinitely for a user session. By default, the agent exits with status 0 when
+ the first client exits after logging in. This behavior as well as general expiry can be
+ controlled from within a shell session by touching a .hold file. After logging in, the
+ user can control expiry of the session as instructed by messages in the ssh session.
+ Then the timeout of a session is near the user is informed about this with messages
+ in the shell.
Usage
@@ -75,7 +81,7 @@
This is a command that can be used as a proxy command for SSH which performs the connection to the remote
- server.
+ server.
Next step is to run a local SSH of SFTP client:
@@ -118,7 +124,7 @@
ssh -oServerAliveInterval=10 -p 10000 abc@localhost
- sftp -oServerAliveInterval=10 -oPort 10000 abc@localhost
+ sftp -oServerAliveInterval=10 -oPort=10000 abc@localhost