Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an odo run command to manually execute command during odo dev #6857

Merged
1 change: 1 addition & 0 deletions cmd/odo/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Examples:
init Init bootstraps a new project
logs Show logs of all containers of the component
registry List all components from the Devfile registry
run Run a specific command in the Dev mode

`

Expand Down
6 changes: 1 addition & 5 deletions pkg/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,7 @@ func Log(platformClient platform.Client, componentName string, appName string, f

pod, err := platformClient.GetRunningPodFromSelector(odolabels.GetSelector(componentName, appName, odolabels.ComponentDevMode, false))
if err != nil {
return nil, fmt.Errorf("the component %s doesn't exist on the cluster", componentName)
}

if pod.Status.Phase != corev1.PodRunning {
return nil, fmt.Errorf("unable to show logs, component is not in running state. current status=%v", pod.Status.Phase)
return nil, fmt.Errorf("a running component %s doesn't exist on the cluster: %w", componentName, err)
}

containerName := command.Exec.Component
Expand Down
6 changes: 0 additions & 6 deletions pkg/component/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,6 @@ func (do *DeleteComponentClient) ExecutePreStopEvents(ctx context.Context, devfi
return fmt.Errorf("unable to determine if component %s exists; cause: %v", componentName, err.Error())
}

// do not fail Delete operation if if the pod is not running or if the event execution fails
if pod.Status.Phase != corev1.PodRunning {
klog.V(4).Infof("unable to execute preStop events, pod for component %q is not running", componentName)
return nil
}

klog.V(4).Infof("Executing %q event commands for component %q", libdevfile.PreStop, componentName)
// ignore the failures if any; delete should not fail because preStop events failed to execute
handler := component.NewRunHandler(
Expand Down
19 changes: 0 additions & 19 deletions pkg/component/delete/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -700,25 +700,6 @@ func TestDeleteComponentClient_ExecutePreStopEvents(t *testing.T) {
},
wantErr: false,
},
{
name: "did not execute PreStopEvents because the pod is not in the running state",
fields: fields{
kubeClient: func(ctrl *gomock.Controller) kclient.ClientInterface {
client := kclient.NewMockClientInterface(ctrl)

selector := odolabels.GetSelector(componentName, "app", odolabels.ComponentDevMode, false)
pod := odoTestingUtil.CreateFakePod(componentName, "mypod", "runtime")
pod.Status.Phase = corev1.PodFailed
client.EXPECT().GetRunningPodFromSelector(selector).Return(pod, nil)
return client
},
},
args: args{
devfileObj: devfileObjWithPreStopEvents,
appName: appName,
},
wantErr: false,
},
{
name: "failed to execute PreStopEvents because it failed to execute the command inside the container, but no error returned",
fields: fields{
Expand Down
53 changes: 53 additions & 0 deletions pkg/dev/common/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package common

import (
"context"
"fmt"

"github.com/redhat-developer/odo/pkg/component"
"github.com/redhat-developer/odo/pkg/configAutomount"
"github.com/redhat-developer/odo/pkg/devfile/image"
"github.com/redhat-developer/odo/pkg/exec"
"github.com/redhat-developer/odo/pkg/libdevfile"
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
"github.com/redhat-developer/odo/pkg/platform"
"github.com/redhat-developer/odo/pkg/testingutil/filesystem"
)

func Run(
ctx context.Context,
commandName string,
platformClient platform.Client,
execClient exec.Client,
configAutomountClient configAutomount.Client,
filesystem filesystem.Filesystem,
) error {
var (
componentName = odocontext.GetComponentName(ctx)
devfileObj = odocontext.GetEffectiveDevfileObj(ctx)
devfilePath = odocontext.GetDevfilePath(ctx)
)

pod, err := platformClient.GetPodUsingComponentName(componentName)
if err != nil {
return fmt.Errorf("unable to get pod for component %s: %w. Please check the command 'odo dev' is running", componentName, err)
}

handler := component.NewRunHandler(
ctx,
platformClient,
execClient,
configAutomountClient,
pod.Name,
false,
component.GetContainersNames(pod),
"Executing command in container",

filesystem,
image.SelectBackend(ctx),
*devfileObj,
devfilePath,
)

return libdevfile.ExecuteCommandByName(ctx, *devfileObj, commandName, handler, false)
}
5 changes: 5 additions & 0 deletions pkg/dev/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ type Client interface {
options StartOptions,
) error

Run(
ctx context.Context,
commandName string,
) error

// CleanupResources deletes the component created using the context's devfile and writes any outputs to out
CleanupResources(ctx context.Context, out io.Writer) error
}
23 changes: 23 additions & 0 deletions pkg/dev/kubedev/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package kubedev

import (
"context"

"github.com/redhat-developer/odo/pkg/dev/common"
"k8s.io/klog"
)

func (o *DevClient) Run(
ctx context.Context,
commandName string,
) error {
klog.V(4).Infof("running command %q on cluster", commandName)
return common.Run(
ctx,
commandName,
o.kubernetesClient,
o.execClient,
o.configAutomountClient,
o.filesystem,
)
}
14 changes: 14 additions & 0 deletions pkg/dev/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions pkg/dev/podmandev/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package podmandev

import (
"context"

"github.com/redhat-developer/odo/pkg/dev/common"
"k8s.io/klog"
)

func (o *DevClient) Run(
ctx context.Context,
commandName string,
) error {
klog.V(4).Infof("running command %q on podman", commandName)
return common.Run(
ctx,
commandName,
o.podmanClient,
o.execClient,
nil, // TODO(feloy) set when running on new container is supported on podman
o.fs,
)
}
4 changes: 4 additions & 0 deletions pkg/exec/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ func (o fakePlatform) GetRunningPodFromSelector(selector string) (*corev1.Pod, e
panic("not implemented yet")
}

func (o fakePlatform) GetPodUsingComponentName(componentName string) (*corev1.Pod, error) {
panic("not implemented yet")
}

func TestExecuteCommand(t *testing.T) {
for _, tt := range []struct {
name string
Expand Down
3 changes: 3 additions & 0 deletions pkg/libdevfile/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func (e NoCommandFoundError) Error() string {
if e.name == "" {
return fmt.Sprintf("no %s command found in devfile", e.kind)
}
if e.kind == "" {
return fmt.Sprintf("no command named %q found in devfile", e.name)
}
return fmt.Sprintf("no %s command with name %q found in Devfile", e.kind, e.name)
}

Expand Down
19 changes: 19 additions & 0 deletions pkg/libdevfile/libdevfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ func ExecuteCommandByNameAndKind(ctx context.Context, devfileObj parser.DevfileO
return executeCommand(ctx, devfileObj, cmd, handler)
}

// ExecuteCommandByName executes the specified command cmdName in the Devfile.
// If ignoreCommandNotFound is true, nothing is executed if the command is not found and no error is returned.
func ExecuteCommandByName(ctx context.Context, devfileObj parser.DevfileObj, cmdName string, handler Handler, ignoreCommandNotFound bool) error {
commands, err := devfileObj.Data.GetCommands(
common.DevfileOptions{
FilterByName: cmdName,
},
)
if err != nil {
return err
}
if len(commands) != 1 {
return NewNoCommandFoundError("", cmdName)
}

cmd := commands[0]
return executeCommand(ctx, devfileObj, cmd, handler)
}

// executeCommand executes a specific command of a devfile using handler as backend
func executeCommand(ctx context.Context, devfileObj parser.DevfileObj, command v1alpha2.Command, handler Handler) error {
cmd, err := newCommand(devfileObj, command)
Expand Down
2 changes: 2 additions & 0 deletions pkg/odo/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"unicode"

"github.com/redhat-developer/odo/pkg/odo/cli/logs"
"github.com/redhat-developer/odo/pkg/odo/cli/run"
"github.com/redhat-developer/odo/pkg/odo/commonflags"

"github.com/redhat-developer/odo/pkg/log"
Expand Down Expand Up @@ -195,6 +196,7 @@ func odoRootCmd(ctx context.Context, name, fullName string) *cobra.Command {
set.NewCmdSet(set.RecommendedCommandName, util.GetFullName(fullName, set.RecommendedCommandName)),
logs.NewCmdLogs(logs.RecommendedCommandName, util.GetFullName(fullName, logs.RecommendedCommandName)),
completion.NewCmdCompletion(completion.RecommendedCommandName, util.GetFullName(fullName, completion.RecommendedCommandName)),
run.NewCmdRun(run.RecommendedCommandName, util.GetFullName(fullName, run.RecommendedCommandName)),
)

// Add all subcommands to base commands
Expand Down
14 changes: 14 additions & 0 deletions pkg/odo/cli/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ func (o NoCommandInDevfileError) Error() string {
return fmt.Sprintf("no command of kind %q found in the devfile", o.command)
}

type NoCommandNameInDevfileError struct {
name string
}

func NewNoCommandNameInDevfileError(name string) NoCommandNameInDevfileError {
return NoCommandNameInDevfileError{
name: name,
}
}

func (o NoCommandNameInDevfileError) Error() string {
return fmt.Sprintf("no command named %q found in the devfile", o.name)
}

type Warning struct {
msg string
err error
Expand Down
Loading