Skip to content

Commit

Permalink
Update Docker and Kubernetes adapter to use groups (#3206)
Browse files Browse the repository at this point in the history
* Update Docker and Kubernetes adapter to use groups

* Update Some Validation

Incorporate some review comments for commands Map
Update Some Validation logic
  • Loading branch information
Aditi Sharma committed May 28, 2020
1 parent e125119 commit a0f05cf
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 130 deletions.
35 changes: 27 additions & 8 deletions pkg/devfile/adapters/common/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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\"")
}

Expand All @@ -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
}
}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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
}
9 changes: 9 additions & 0 deletions pkg/devfile/adapters/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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)
}
7 changes: 5 additions & 2 deletions pkg/devfile/adapters/common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
104 changes: 44 additions & 60 deletions pkg/devfile/adapters/docker/component/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
108 changes: 48 additions & 60 deletions pkg/devfile/adapters/kubernetes/component/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a0f05cf

Please sign in to comment.