Skip to content

Commit 728bde4

Browse files
committed
feat: --tty flag & carriage return fix
1 parent 0a35c92 commit 728bde4

8 files changed

Lines changed: 48 additions & 8 deletions

File tree

cmd/enter.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type EnterCmd struct {
3030
Container string
3131
Pod string
3232
Pick bool
33+
TTY bool
3334
Wait bool
3435
Reconnect bool
3536
Screen bool
@@ -78,6 +79,7 @@ devspace enter bash --image-selector "${runtime.images.app.image}:${runtime.imag
7879
enterCmd.Flags().StringVar(&cmd.ImageSelector, "image-selector", "", "The image to search a pod for (e.g. nginx, nginx:latest, ${runtime.images.app}, nginx:${runtime.images.app.tag})")
7980
enterCmd.Flags().StringVar(&cmd.WorkingDirectory, "workdir", "", "The working directory where to open the terminal or execute the command")
8081

82+
enterCmd.Flags().BoolVar(&cmd.TTY, "tty", true, "If to use a tty to start the command")
8183
enterCmd.Flags().BoolVar(&cmd.Pick, "pick", true, "Select a pod / container if multiple are found")
8284
enterCmd.Flags().BoolVar(&cmd.Wait, "wait", false, "Wait for the pod(s) to start if they are not running")
8385
enterCmd.Flags().BoolVar(&cmd.Reconnect, "reconnect", false, "Will reconnect the terminal if an unexpected return code is encountered")
@@ -158,7 +160,7 @@ func (cmd *EnterCmd) Run(f factory.Factory, args []string) error {
158160

159161
// Start terminal
160162
stdout, stderr, stdin := defaultStdStreams(cmd.Stdout, cmd.Stderr, cmd.Stdin)
161-
exitCode, err := terminal.StartTerminalFromCMD(ctx, targetselector.NewTargetSelector(selectorOptions), command, cmd.Wait, cmd.Reconnect, cmd.Screen, cmd.ScreenSession, stdout, stderr, stdin)
163+
exitCode, err := terminal.StartTerminalFromCMD(ctx, targetselector.NewTargetSelector(selectorOptions), command, cmd.Wait, cmd.Reconnect, cmd.TTY, cmd.Screen, cmd.ScreenSession, stdout, stderr, stdin)
162164
if err != nil {
163165
return err
164166
} else if exitCode != 0 {

docs/hack/functions/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ var Functions = []Function{
363363
Return: reflect.String.String(),
364364
Group: groupOther,
365365
},
366+
{
367+
Name: "wait_pod",
368+
Description: "Waits for a pod to become running",
369+
Args: `[command]`,
370+
Handler: commands.WaitPod,
371+
Flags: commands.WaitPodOptions{},
372+
Group: groupOther,
373+
},
366374
{
367375
Name: "exec_container",
368376
Description: `Executes the command provided as argument inside a container`,

pkg/devspace/config/versions/latest/schema.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,6 +1234,9 @@ type Terminal struct {
12341234
// DisableScreen will disable screen which is used by DevSpace by default to preserve
12351235
// sessions if connections interrupt or the session is lost.
12361236
DisableScreen bool `yaml:"disableScreen,omitempty" json:"disableScreen,omitempty"`
1237+
1238+
// DisableTTY will disable a tty shell for terminal command execution
1239+
DisableTTY bool `yaml:"disableTTY,omitempty" json:"disableTTY,omitempty"`
12371240
}
12381241

12391242
// DependencyConfig defines the devspace dependency

pkg/devspace/deploy/deployer/kubectl/kubectl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ func (d *DeployConfig) buildManifests(ctx devspacecontext.Context, manifest stri
281281
return NewKustomizeBuilder(kustomizePath, d.DeploymentConfig, ctx.Log()).Build(ctx.Context(), ctx.Environ(), ctx.WorkingDir(), manifest)
282282
}
283283

284-
raw, err := ctx.KubeClient().KubeConfigLoader().LoadConfig().RawConfig()
284+
raw, err := ctx.KubeClient().KubeConfigLoader().LoadRawConfig()
285285
if err != nil {
286286
return nil, fmt.Errorf("get raw config")
287287
}

pkg/devspace/kubectl/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func NewClientFromContext(context, namespace string, switchContext bool, kubeLoa
108108
return nil, err
109109
}
110110
restConfig.UserAgent = "DevSpace Version " + upgrade.GetVersion()
111+
111112
kubeClient, err := kubernetes.NewForConfig(restConfig)
112113
if err != nil {
113114
return nil, errors.Wrap(err, "new client")

pkg/devspace/server/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ type forward struct {
121121
}
122122

123123
func newHandler(ctx devspacecontext.Context, path string, pipeline types.Pipeline) (*handler, error) { // Get kube config
124-
kubeConfig, err := kubeconfig.NewLoader().LoadConfig().RawConfig()
124+
kubeConfig, err := kubeconfig.NewLoader().LoadRawConfig()
125125
if err != nil {
126126
return nil, errors.Wrap(err, "load kube config")
127127
}

pkg/devspace/services/terminal/terminal.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func StartTerminalFromCMD(
2727
command []string,
2828
wait,
2929
restart,
30+
tty,
3031
screen bool,
3132
screenSession string,
3233
stdout io.Writer,
@@ -41,7 +42,7 @@ func StartTerminalFromCMD(
4142
ctx.Log().Infof("Opening shell to pod:container %s:%s", ansi.Color(container.Pod.Name, "white+b"), ansi.Color(container.Container.Name, "white+b"))
4243
done := make(chan error)
4344
go func() {
44-
done <- startTerminal(ctx, command, !screen, screenSession, stdout, stderr, stdin, container)
45+
done <- startTerminal(ctx, command, tty, !screen, screenSession, stdout, stderr, stdin, container)
4546
}()
4647

4748
// wait until either client has finished or we got interrupted
@@ -62,14 +63,14 @@ func StartTerminalFromCMD(
6263
if restart && IsUnexpectedExitCode(exitError.Code) {
6364
ctx.Log().WriteString(logrus.InfoLevel, "\n")
6465
ctx.Log().Infof("Restarting because: %s", err)
65-
return StartTerminalFromCMD(ctx, selector, command, wait, restart, screen, screenSession, stdout, stderr, stdin)
66+
return StartTerminalFromCMD(ctx, selector, command, wait, restart, tty, screen, screenSession, stdout, stderr, stdin)
6667
}
6768

6869
return exitError.Code, nil
6970
} else if restart {
7071
ctx.Log().WriteString(logrus.InfoLevel, "\n")
7172
ctx.Log().Infof("Restarting because: %s", err)
72-
return StartTerminalFromCMD(ctx, selector, command, wait, restart, screen, screenSession, stdout, stderr, stdin)
73+
return StartTerminalFromCMD(ctx, selector, command, wait, restart, tty, screen, screenSession, stdout, stderr, stdin)
7374
}
7475

7576
return 0, err
@@ -118,7 +119,7 @@ func StartTerminal(
118119
ctx.Log().Infof("Opening shell to %s:%s (pod:container)", ansi.Color(container.Container.Name, "white+b"), ansi.Color(container.Pod.Name, "white+b"))
119120
errChan := make(chan error)
120121
parent.Go(func() error {
121-
errChan <- startTerminal(ctx, command, devContainer.Terminal.DisableScreen, "dev", stdout, stderr, stdin, container)
122+
errChan <- startTerminal(ctx, command, !devContainer.Terminal.DisableTTY, devContainer.Terminal.DisableScreen, "dev", stdout, stderr, stdin, container)
122123
return nil
123124
})
124125

@@ -158,6 +159,7 @@ func StartTerminal(
158159
func startTerminal(
159160
ctx devspacecontext.Context,
160161
command []string,
162+
tty bool,
161163
disableScreen bool,
162164
screenSession string,
163165
stdout io.Writer,
@@ -218,7 +220,7 @@ fi`,
218220
Pod: container.Pod,
219221
Container: container.Container.Name,
220222
Command: command,
221-
TTY: true,
223+
TTY: tty,
222224
Stdin: stdin,
223225
Stdout: stdout,
224226
Stderr: stderr,

pkg/util/scanner/scanner.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,36 @@ package scanner
22

33
import (
44
"bufio"
5+
"bytes"
56
"io"
67
)
78

89
func NewScanner(r io.Reader) *bufio.Scanner {
910
scanner := bufio.NewScanner(r)
1011
buf := make([]byte, 0, 64*1024)
1112
scanner.Buffer(buf, 1024*1024)
13+
scanner.Split(ScanLines)
1214
return scanner
1315
}
16+
17+
// ScanLines is a split function for a Scanner that returns each line of
18+
// text, stripped of any trailing end-of-line marker. The returned line may
19+
// be empty. The end-of-line marker is one optional carriage return followed
20+
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
21+
// The last non-empty line of input will be returned even if it has no
22+
// newline.
23+
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
24+
if atEOF && len(data) == 0 {
25+
return 0, nil, nil
26+
}
27+
if i := bytes.IndexByte(data, '\n'); i >= 0 {
28+
// We have a full newline-terminated line.
29+
return i + 1, data[0:i], nil
30+
}
31+
// If we're at EOF, we have a final, non-terminated line. Return it.
32+
if atEOF {
33+
return len(data), data, nil
34+
}
35+
// Request more data.
36+
return 0, nil, nil
37+
}

0 commit comments

Comments
 (0)