diff --git a/pkg/devfile/adapters/common/command.go b/pkg/devfile/adapters/common/command.go index 18f27786790..7e0c5980f8d 100644 --- a/pkg/devfile/adapters/common/command.go +++ b/pkg/devfile/adapters/common/command.go @@ -26,6 +26,23 @@ func getCommand(data data.DevfileData, commandName string, groupType common.Devf if commandName != "" { if command.Exec.Id == commandName { + + if supportedCommand.Exec.Group.Kind == "" { + // Devfile V1 for commands passed from flags + // Group type is not updated during conversion + command.Exec.Group.Kind = groupType + } + + // we have found the command with name, its groupType Should match to the flag + // e.g --build-command "mybuild" + // exec: + // id: mybuild + // group: + // kind: build + if command.Exec.Group.Kind != groupType { + return supportedCommand, fmt.Errorf("mismatched type, command %s is of type %v groupType in devfile", commandName, groupType) + + } supportedCommand = command return supportedCommand, nil } @@ -65,7 +82,7 @@ func getCommand(data data.DevfileData, commandName string, groupType common.Devf func validateCommand(data data.DevfileData, command common.DevfileCommand) (err error) { // type must be exec - if command.Type != common.ExecCommandType { + if command.Exec == nil { return fmt.Errorf("Command must be of type \"exec\"") } @@ -84,7 +101,7 @@ func validateCommand(data data.DevfileData, command common.DevfileCommand) (err isActionValid := false for _, component := range components { - if command.Exec.Component == component.Container.Name && isComponentSupported(component) { + if command.Exec.Component == component.Container.Name { isActionValid = true } } @@ -127,8 +144,10 @@ func GetRunCommand(data data.DevfileData, devfileRunCmd string) (runCommand comm // ValidateAndGetPushDevfileCommands validates the build and the run command, // if provided through odo push or else checks the devfile for devBuild and devRun. // It returns the build and run commands if its validated successfully, error otherwise. -func ValidateAndGetPushDevfileCommands(data data.DevfileData, devfileInitCmd, devfileBuildCmd, devfileRunCmd string) (pushDevfileCommands []common.DevfileCommand, err error) { +func ValidateAndGetPushDevfileCommands(data data.DevfileData, devfileInitCmd, devfileBuildCmd, devfileRunCmd string) (commandMap PushCommandsMap, err error) { var emptyCommand common.DevfileCommand + commandMap = NewPushCommandMap() + isInitCommandValid, isBuildCommandValid, isRunCommandValid := false, false, false initCommand, initCmdErr := GetInitCommand(data, devfileInitCmd) @@ -140,7 +159,7 @@ func ValidateAndGetPushDevfileCommands(data data.DevfileData, devfileInitCmd, de klog.V(3).Infof("No init command was provided") } else if !isInitCmdEmpty && initCmdErr == nil { isInitCommandValid = true - pushDevfileCommands = append(pushDevfileCommands, initCommand) + commandMap[common.InitCommandGroupType] = initCommand klog.V(3).Infof("Init command: %v", initCommand.Exec.Id) } @@ -153,14 +172,14 @@ func ValidateAndGetPushDevfileCommands(data data.DevfileData, devfileInitCmd, de klog.V(3).Infof("No build command was provided") } else if !reflect.DeepEqual(emptyCommand, buildCommand) && buildCmdErr == nil { isBuildCommandValid = true - pushDevfileCommands = append(pushDevfileCommands, buildCommand) + commandMap[common.BuildCommandGroupType] = buildCommand klog.V(3).Infof("Build command: %v", buildCommand.Exec.Id) } runCommand, runCmdErr := GetRunCommand(data, devfileRunCmd) if runCmdErr == nil && !reflect.DeepEqual(emptyCommand, runCommand) { - pushDevfileCommands = append(pushDevfileCommands, runCommand) isRunCommandValid = true + commandMap[common.RunCommandGroupType] = runCommand klog.V(3).Infof("Run command: %v", runCommand.Exec.Id) } @@ -176,8 +195,8 @@ func ValidateAndGetPushDevfileCommands(data data.DevfileData, devfileInitCmd, de if runCmdErr != nil { commandErrors += fmt.Sprintf(runCmdErr.Error(), "\n") } - return []common.DevfileCommand{}, fmt.Errorf(commandErrors) + return commandMap, fmt.Errorf(commandErrors) } - return pushDevfileCommands, nil + return commandMap, nil } diff --git a/pkg/devfile/adapters/common/types.go b/pkg/devfile/adapters/common/types.go index 3a4cb3882fb..9b03333f643 100644 --- a/pkg/devfile/adapters/common/types.go +++ b/pkg/devfile/adapters/common/types.go @@ -2,6 +2,7 @@ package common import ( devfileParser "github.com/openshift/odo/pkg/devfile/parser" + "github.com/openshift/odo/pkg/devfile/parser/data/common" "github.com/openshift/odo/pkg/envinfo" ) @@ -52,3 +53,11 @@ type ComponentInfo struct { PodName string ContainerName string } + +// PushCommandsMap stores the commands to be executed as per there types. +type PushCommandsMap map[common.DevfileCommandGroupType]common.DevfileCommand + +// NewPushCommandMap returns the instance of PushCommandsMap +func NewPushCommandMap() PushCommandsMap { + return make(map[common.DevfileCommandGroupType]common.DevfileCommand) +} diff --git a/pkg/devfile/adapters/common/utils.go b/pkg/devfile/adapters/common/utils.go index c286c459f1f..f570e25fc33 100644 --- a/pkg/devfile/adapters/common/utils.go +++ b/pkg/devfile/adapters/common/utils.go @@ -81,8 +81,11 @@ type CommandNames struct { } func isComponentSupported(component common.DevfileComponent) bool { - // Currently odo only uses devfile components of type dockerimage, since most of the Che registry devfiles use it - return component.Type == common.ContainerComponentType + // Currently odo only uses devfile components of type container, since most of the Che registry devfiles use it + if component.Container != nil { + return true + } + return false } // GetBootstrapperImage returns the odo-init bootstrapper image diff --git a/pkg/devfile/adapters/docker/component/utils.go b/pkg/devfile/adapters/docker/component/utils.go index d32594b4b6e..5e1974edda1 100644 --- a/pkg/devfile/adapters/docker/component/utils.go +++ b/pkg/devfile/adapters/docker/component/utils.go @@ -344,77 +344,61 @@ func getPortMap(context string, endpoints []*versionsCommon.Endpoint, show bool) // Executes all the commands from the devfile in order: init and build - which are both optional, and a compulsary run. // Init only runs once when the component is created. -func (a Adapter) execDevfile(pushDevfileCommands []versionsCommon.DevfileCommand, componentExists, show bool, containers []types.Container) (err error) { +func (a Adapter) execDevfile(commandsMap common.PushCommandsMap, componentExists, show bool, containers []types.Container) (err error) { // If nothing has been passed, then the devfile is missing the required run command - if len(pushDevfileCommands) == 0 { + if len(commandsMap) == 0 { return errors.New(fmt.Sprint("error executing devfile commands - there should be at least 1 command")) } - commandOrder := []common.CommandNames{} - // Only add runinit to the expected commands if the component doesn't already exist // This would be the case when first running the container if !componentExists { - commandOrder = append(commandOrder, common.CommandNames{DefaultName: string(common.DefaultDevfileInitCommand), AdapterName: a.devfileInitCmd}) + // Get Init Command + command, ok := commandsMap[versionsCommon.InitCommandGroupType] + if ok { + + containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) + compInfo := common.ComponentInfo{ContainerName: containerID} + err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + if err != nil { + return err + } + } } - commandOrder = append( - commandOrder, - common.CommandNames{DefaultName: string(common.DefaultDevfileBuildCommand), AdapterName: a.devfileBuildCmd}, - common.CommandNames{DefaultName: string(common.DefaultDevfileRunCommand), AdapterName: a.devfileRunCmd}, - ) - - // Loop through each of the expected commands in the devfile - for i, currentCommand := range commandOrder { - // Loop through each of the command given from the devfile - for _, command := range pushDevfileCommands { - // If the current command from the devfile is the currently expected command from the devfile - if command.Exec.Id == currentCommand.DefaultName || command.Exec.Id == currentCommand.AdapterName { - // If the current command is not the last command in the slice - // it is not expected to be the run command - if i < len(commandOrder)-1 { - // Any exec command such as "Init" and "Build" - - containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) - compInfo := common.ComponentInfo{ - ContainerName: containerID, - } - - err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - if err != nil { - return err - } - - // If the current command is the last command in the slice - // it is expected to be the run command - } else { - // Last command is "Run" - klog.V(4).Infof("Executing devfile command %v", command.Exec.Id) - - // Check if the devfile run component containers have supervisord as the entrypoint. - // Start the supervisord if the odo component does not exist - if !componentExists { - err = a.InitRunContainerSupervisord(command.Exec.Component, containers) - if err != nil { - return - } - } - - containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) - compInfo := common.ComponentInfo{ - ContainerName: containerID, - } - - if componentExists && !common.IsRestartRequired(command) { - klog.V(4).Info("restart:false, Not restarting DevRun Command") - err = exec.ExecuteDevfileRunActionWithoutRestart(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - return - } - - err = exec.ExecuteDevfileRunAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - } + // Get Build Command + command, ok := commandsMap[versionsCommon.BuildCommandGroupType] + if ok { + containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) + compInfo := common.ComponentInfo{ContainerName: containerID} + err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + if err != nil { + return err + } + } + + // Get Run command + command, ok = commandsMap[versionsCommon.RunCommandGroupType] + if ok { + klog.V(4).Infof("Executing devfile command %v", command.Exec.Id) + + // Check if the devfile run component containers have supervisord as the entrypoint. + // Start the supervisord if the odo component does not exist + if !componentExists { + err = a.InitRunContainerSupervisord(command.Exec.Component, containers) + if err != nil { + return } } + + containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) + compInfo := common.ComponentInfo{ContainerName: containerID} + if componentExists && !common.IsRestartRequired(command) { + klog.V(4).Info("restart:false, Not restarting DevRun Command") + err = exec.ExecuteDevfileRunActionWithoutRestart(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + return + } + err = exec.ExecuteDevfileRunAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) } return diff --git a/pkg/devfile/adapters/kubernetes/component/adapter.go b/pkg/devfile/adapters/kubernetes/component/adapter.go index 4515ee6d322..8835e4d2665 100644 --- a/pkg/devfile/adapters/kubernetes/component/adapter.go +++ b/pkg/devfile/adapters/kubernetes/component/adapter.go @@ -305,76 +305,64 @@ func (a Adapter) waitAndGetComponentPod(hideSpinner bool) (*corev1.Pod, error) { // Executes all the commands from the devfile in order: init and build - which are both optional, and a compulsary run. // Init only runs once when the component is created. -func (a Adapter) execDevfile(pushDevfileCommands []versionsCommon.DevfileCommand, componentExists, show bool, podName string, containers []corev1.Container) (err error) { +func (a Adapter) execDevfile(commandsMap common.PushCommandsMap, componentExists, show bool, podName string, containers []corev1.Container) (err error) { // If nothing has been passed, then the devfile is missing the required run command - if len(pushDevfileCommands) == 0 { + if len(commandsMap) == 0 { return errors.New(fmt.Sprint("error executing devfile commands - there should be at least 1 command")) } - commandOrder := []common.CommandNames{} + compInfo := common.ComponentInfo{ + PodName: podName, + } // Only add runinit to the expected commands if the component doesn't already exist // This would be the case when first running the container if !componentExists { - commandOrder = append(commandOrder, common.CommandNames{DefaultName: string(common.DefaultDevfileInitCommand), AdapterName: a.devfileInitCmd}) - } - commandOrder = append( - commandOrder, - common.CommandNames{DefaultName: string(common.DefaultDevfileBuildCommand), AdapterName: a.devfileBuildCmd}, - common.CommandNames{DefaultName: string(common.DefaultDevfileRunCommand), AdapterName: a.devfileRunCmd}, - ) - - // Loop through each of the expected commands in the devfile - for i, currentCommand := range commandOrder { - // Loop through each of the command given from the devfile - for _, command := range pushDevfileCommands { - // If the current command from the devfile is the currently expected command from the devfile - if command.Exec.Id == currentCommand.DefaultName || command.Exec.Id == currentCommand.AdapterName { - // If the current command is not the last command in the slice - // it is not expected to be the run command - if i < len(commandOrder)-1 { - // Any exec command such as "Init" and "Build" - - compInfo := common.ComponentInfo{ - ContainerName: command.Exec.Component, - PodName: podName, - } - - err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - if err != nil { - return err - } - - // If the current command is the last command in the slice - // it is expected to be the run command - } else { - // Last command is "Run" - klog.V(4).Infof("Executing devfile command %v", command.Exec.Id) - - // Check if the devfile run component containers have supervisord as the entrypoint. - // Start the supervisord if the odo component does not exist - if !componentExists { - err = a.InitRunContainerSupervisord(command.Exec.Component, podName, containers) - if err != nil { - return - } - } - - compInfo := common.ComponentInfo{ - ContainerName: command.Exec.Component, - PodName: podName, - } - - if componentExists && !common.IsRestartRequired(command) { - klog.V(4).Infof("restart:false, Not restarting DevRun Command") - err = exec.ExecuteDevfileRunActionWithoutRestart(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - return - } - - err = exec.ExecuteDevfileRunAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) - } + // Get Init Command + command, ok := commandsMap[versionsCommon.InitCommandGroupType] + if ok { + compInfo.ContainerName = command.Exec.Component + err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + if err != nil { + return err } + } + + } + + // Get Build Command + command, ok := commandsMap[versionsCommon.BuildCommandGroupType] + if ok { + compInfo.ContainerName = command.Exec.Component + err = exec.ExecuteDevfileBuildAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + if err != nil { + return err + } + } + + // Get Run Command + command, ok = commandsMap[versionsCommon.RunCommandGroupType] + if ok { + klog.V(4).Infof("Executing devfile command %v", command.Exec.Id) + compInfo.ContainerName = command.Exec.Component + + // Check if the devfile run component containers have supervisord as the entrypoint. + // Start the supervisord if the odo component does not exist + if !componentExists { + err = a.InitRunContainerSupervisord(command.Exec.Component, podName, containers) + if err != nil { + return + } + } + + if componentExists && !common.IsRestartRequired(command) { + klog.V(4).Infof("restart:false, Not restarting DevRun Command") + err = exec.ExecuteDevfileRunActionWithoutRestart(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + return + } + err = exec.ExecuteDevfileRunAction(&a.Client, *command.Exec, command.Exec.Id, compInfo, show) + } return