Skip to content

Commit

Permalink
Update the 'Executing the application' spinner accordingly when the r…
Browse files Browse the repository at this point in the history
…elated command is done
  • Loading branch information
rm3l committed Jun 24, 2022
1 parent 3c14855 commit f3bb6cf
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 12 deletions.
26 changes: 17 additions & 9 deletions pkg/devfile/adapters/kubernetes/component/commandhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,25 @@ func (a *adapterHandler) ApplyKubernetes(_ devfilev1.Component) error {
func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
remoteProcessHandler := remotecmd.NewKubeExecProcessHandler()

startHandler := func(status remotecmd.RemoteProcessStatus, stdout []string, stderr []string, err error) {
switch status {
case remotecmd.Starting:
_ = log.SpinnerNoSpin(fmt.Sprintf("Executing the application (command: %s)", devfileCmd.Id))
case remotecmd.Stopped, remotecmd.Errored:
if err != nil {
klog.V(2).Infof("error while running background command: %v", err)
statusHandlerFunc := func(s *log.Status) remotecmd.CommandOutputHandler {
return func(status remotecmd.RemoteProcessStatus, stdout []string, stderr []string, err error) {
switch status {
case remotecmd.Starting:
// Creating with no spin because the command could be long-running, and we cannot determine when it will end.
s.Start(fmt.Sprintf("Executing the application (command: %s)", devfileCmd.Id), true)
case remotecmd.Stopped, remotecmd.Errored:
s.End(status == remotecmd.Stopped)
if err != nil {
klog.V(2).Infof("error while running background command: %v", err)
}
}
}
}

// Spinner created but not started yet.
// It will be displayed when the statusHandlerFunc function is called with the "Starting" state.
spinner := log.NewStatus(log.GetStdout())

// if we need to restart, issue the remote process handler command to stop all running commands first.
// We do not need to restart Hot reload capable commands.
if a.componentExists {
Expand All @@ -67,7 +75,7 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
return err
}

if err = remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, startHandler); err != nil {
if err = remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
return err
}
} else {
Expand All @@ -79,7 +87,7 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
return err
}

if err := remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, startHandler); err != nil {
if err := remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
return err
}
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/remotecmd/kubeexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,12 @@ func (k *kubeExecProcessHandler) StartProcessForCommand(
}

if outputHandler != nil {
outputHandler(Stopped, stdout, stderr, err)
processInfo, infoErr := k.GetProcessInfoForCommand(def, kclient, podName, containerName)
if infoErr != nil {
outputHandler(Errored, stdout, stderr, err)
return
}
outputHandler(processInfo.Status, stdout, stderr, err)
}
}()

Expand Down
34 changes: 32 additions & 2 deletions pkg/remotecmd/kubexec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ func TestKubeExecProcessHandler_GetProcessInfoForCommand(t *testing.T) {
}

func TestKubeExecProcessHandler_StartProcessForCommand(t *testing.T) {
kill0CmdProvider := func(p int) []string {
return []string{ShellExecutable, "-c", fmt.Sprintf("kill -0 %d; echo $?", p)}
}

execCmdWithoutWorkingDir := CommandDefinition{
Id: "my-exec-cmd",
CmdLine: "echo Hello; sleep 300",
Expand Down Expand Up @@ -202,12 +206,25 @@ func TestKubeExecProcessHandler_StartProcessForCommand(t *testing.T) {
_, err := stdout.Write([]byte("Hello"))
return err
})
kclient.EXPECT().ExecCMDInContainer(gomock.Eq(_containerName), gomock.Eq(_podName),
gomock.Eq([]string{ShellExecutable, "-c", fmt.Sprintf("cat %s || true", getPidFileForCommand(execCmdWithoutWorkingDir))}),
gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(containerName, podName string, cmd []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, tty bool) error {
_, err := stdout.Write([]byte("123"))
return err
})
kclient.EXPECT().ExecCMDInContainer(gomock.Eq(_containerName), gomock.Eq(_podName), gomock.Eq(kill0CmdProvider(123)),
gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(containerName, podName string, cmd []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, tty bool) error {
_, err := stdout.Write([]byte("1"))
return err
})
},
isCmdExpectedToRun: true,
expectedStatuses: []RemoteProcessStatus{Starting, Stopped},
},
{
name: "command with all fields returned no error",
name: "command with all fields returned an error",
cmdDef: fullExecCmd,
kubeClientCustomizer: func(kclient *kclient.MockClientInterface) {
kclient.EXPECT().ExecCMDInContainer(gomock.Eq(_containerName), gomock.Eq(_podName),
Expand All @@ -216,9 +233,22 @@ func TestKubeExecProcessHandler_StartProcessForCommand(t *testing.T) {
getPidFileForCommand(fullExecCmd), fullExecCmd.WorkingDir, fullExecCmd.CmdLine)}),
gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
Return(errors.New("error while running command"))
kclient.EXPECT().ExecCMDInContainer(gomock.Eq(_containerName), gomock.Eq(_podName),
gomock.Eq([]string{ShellExecutable, "-c", fmt.Sprintf("cat %s || true", getPidFileForCommand(fullExecCmd))}),
gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(containerName, podName string, cmd []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, tty bool) error {
_, err := stdout.Write([]byte("123\n1"))
return err
})
kclient.EXPECT().ExecCMDInContainer(gomock.Eq(_containerName), gomock.Eq(_podName), gomock.Eq(kill0CmdProvider(123)),
gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).
DoAndReturn(func(containerName, podName string, cmd []string, stdout io.Writer, stderr io.Writer, stdin io.Reader, tty bool) error {
_, err := stdout.Write([]byte("1"))
return err
})
},
isCmdExpectedToRun: true,
expectedStatuses: []RemoteProcessStatus{Starting, Stopped},
expectedStatuses: []RemoteProcessStatus{Starting, Errored},
},
} {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit f3bb6cf

Please sign in to comment.