Skip to content

Commit

Permalink
Merge pull request #628 from homeport/rework/exec
Browse files Browse the repository at this point in the history
Rework `pod-exec` and `node-exec`
  • Loading branch information
HeavyWombat committed May 23, 2024
2 parents 405d2b4 + ddb4ed9 commit 2862a5f
Show file tree
Hide file tree
Showing 19 changed files with 366 additions and 264 deletions.
2 changes: 1 addition & 1 deletion .docs/commands/havener.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ See the individual commands to get the complete overview.
### Options

```
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--fatal fatal output - level 1
Expand Down
2 changes: 1 addition & 1 deletion .docs/commands/havener_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ havener events [flags]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
2 changes: 1 addition & 1 deletion .docs/commands/havener_logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ havener logs [flags]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
36 changes: 19 additions & 17 deletions .docs/commands/havener_node-exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ Execute command on Kubernetes node

### Synopsis

Execute a command on a node.
Execute a command on a node

This executes a command directly on the node itself. Therefore, havener creates
a temporary pod which enables the user to access the shell of the node. The pod
Execute a command directly on the node itself. For this, havener creates a
temporary pod, which enables the user to access the shell of the node. The pod
is deleted automatically afterwards.

The command can be omitted which will result in the default command: /bin/sh. For
example 'havener node-exec foo' will search for a node named 'foo' and open a
shell if found.
example havener node-exec foo will search for a node named 'foo' and open a
shell if the node can be found.

Typically, the TTY flag does have to be specified. By definition, if one one
target node is provided, it is assumed that TTY is desired and STDIN is attached
to the remote process. Analog, for the distributed mode with multiple nodes,
no TTY is set, and the STDIN is multiplexed into each remote process.
When more than one node is specified, it will execute the command on all nodes.
In this distributed mode, both passing the StdIn as well as TTY mode are not
available. By default, the number of parallel node executions is limited to 5
in parallel in order to not create to many requests at the same time. This
value can be overwritten. Handle with care.

If you run the 'node-exec' without any additional arguments, it will print a
list of available nodes.
If you run the node-exec without any additional arguments, it will print a
list of available nodes in the cluster.

For convenience, if the target node name all is used, havener will look up
all nodes automatically.
Expand All @@ -34,12 +35,13 @@ havener node-exec [flags] [<node>[,<node>,...]] [<command>]
### Options

```
--block show distributed shell output as block for each node
-i, --stdin Pass stdin to the container
-t, --tty Stdin is a TTY
--image string Container image used for helper pod (from which the root-shell is accessed) (default "docker.io/library/alpine")
--timeout duration Timeout for the setup of the helper pod (default 30s)
--max-parallel int Number of parallel executions (value less or equal than zero means unlimited) (default 5)
--block Show distributed shell output as block for each node
-h, --help help for node-exec
--image string set image for helper pod from which the root-shell is accessed (default "alpine")
--max-parallel int number of parallel executions (defaults to number of nodes)
--no-tty do not allocate pseudo-terminal for command execution
--timeout int set timout in seconds for the setup of the helper pod (default 10)
```

### Options inherited from parent commands
Expand All @@ -48,7 +50,7 @@ havener node-exec [flags] [<node>[,<node>,...]] [<command>]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
33 changes: 17 additions & 16 deletions .docs/commands/havener_pod-exec.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ Execute command on Kubernetes pod

### Synopsis

Execute a shell command on a pod.
Execute a command on a pod

This is similar to the kubectl exec command with just a slightly
different syntax. In contrast to kubectl, you do not have to specify
the namespace of the pod.
This is similar to the kubectl exec command with just a slightly different
syntax. In contrast to kubectl, you do not have to specify the namespace
of the pod.

If no namespace is given, havener will search all namespaces for
a pod that matches the name.
If no namespace is given, havener will search all namespaces for a pod that
matches the name.

Also, you can omit the command which will result in the default
command: /bin/sh. For example 'havener pod-exec api-0' will search
for a pod named 'api-0' in all namespaces and open a shell if found.
Also, you can omit the command which will result in the default command: /bin/sh.
For example havener pod-exec api-0 will search for a pod named api-0 in all
namespaces and open a shell if found.

In case no container name is given, havener will assume you want to
execute the command in the first container found in the pod.
In case no container name is given, havener will assume you want to execute the
command in the first container found in the pod.

If you run the 'pod-exec' without any additional arguments, it will print a
list of available pods.

For convenience, if the target pod name _all_ is used, havener will look up
For convenience, if the target pod name all is used, havener will look up
all pods in all namespaces automatically.


Expand All @@ -34,9 +34,10 @@ havener pod-exec [flags] [[<namespace>/]<pod>[/container]] [<command>]
### Options

```
--block show distributed shell output as block for each pod
-h, --help help for pod-exec
--no-tty do not allocate pseudo-terminal for command execution
-i, --stdin Pass stdin to the container
-t, --tty Stdin is a TTY
--block show distributed shell output as block for each pod
-h, --help help for pod-exec
```

### Options inherited from parent commands
Expand All @@ -45,7 +46,7 @@ havener pod-exec [flags] [[<namespace>/]<pod>[/container]] [<command>]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
2 changes: 1 addition & 1 deletion .docs/commands/havener_top.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ havener top [flags]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
2 changes: 1 addition & 1 deletion .docs/commands/havener_version.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ havener version [flags]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
2 changes: 1 addition & 1 deletion .docs/commands/havener_watch.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ havener watch [flags]
--debug debug output - level 5
--error error output - level 2
--fatal fatal output - level 1
--kubeconfig string Kubernetes configuration file (default "~/.kube/config")
--kubeconfig string Kubernetes configuration (default "~/.kube/config")
--terminal-height int disable autodetection and specify an explicit terminal height (default -1)
--terminal-width int disable autodetection and specify an explicit terminal width (default -1)
--trace trace output - level 6
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/gonvenience/wait v1.0.3
github.com/gonvenience/wrap v1.2.0
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mattn/go-isatty v0.0.18
github.com/onsi/ginkgo/v2 v2.17.3
github.com/onsi/gomega v1.33.1
github.com/spf13/cobra v1.8.0
Expand Down Expand Up @@ -58,7 +59,6 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mitchellh/go-ps v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
Expand Down
37 changes: 7 additions & 30 deletions internal/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,41 +21,14 @@
package cmd

import (
"io"
"os"

"github.com/gonvenience/wrap"
"github.com/mattn/go-isatty"
)

// duplicateReader creates a given number of io.Reader duplicates based on the
// provided input reader. This way it is possible to use one input reader for
// more than one consumer.
func duplicateReader(reader io.Reader, count int) []io.Reader {
writers := []io.Writer{}
readers := []io.Reader{}
for i := 0; i < count; i++ {
r, w := io.Pipe()
writers = append(writers, w)
readers = append(readers, r)
}

writer := io.MultiWriter(writers...)
go func() {
if _, err := io.Copy(writer, reader); err != nil {
panic(err)
}

for i := range writers {
if w, ok := writers[i].(io.Closer); ok {
w.Close()
}
}
}()

return readers
}

func combineErrorsFromChannel(context string, c chan error) error {
errors := []error{}
var errors []error
for err := range c {
if err != nil {
errors = append(errors, err)
Expand All @@ -70,3 +43,7 @@ func combineErrorsFromChannel(context string, c chan error) error {
return wrap.Errors(errors, context)
}
}

func isTerminal(fd uintptr) bool { return isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd) }

func isStdinTerminal() bool { return isTerminal(os.Stdin.Fd()) }
3 changes: 1 addition & 2 deletions internal/cmd/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package cmd

import (
"context"
"fmt"
"strings"
"time"
Expand Down Expand Up @@ -86,7 +85,7 @@ func retrieveClusterEvents(hvnr havener.Havener) error {
continue
}

watcher, err := hvnr.Client().CoreV1().Events(namespace).Watch(context.TODO(), metav1.ListOptions{})
watcher, err := hvnr.Client().CoreV1().Events(namespace).Watch(hvnr.Context(), metav1.ListOptions{})
if err != nil {
return fmt.Errorf("failed to setup event watcher: %w", err)
}
Expand Down
Loading

0 comments on commit 2862a5f

Please sign in to comment.