From 2833b52d46a01a849f112c781711097e941933e3 Mon Sep 17 00:00:00 2001 From: mik-dass Date: Mon, 18 May 2020 17:30:32 +0530 Subject: [PATCH] Fixes utils of docker docker adapter Signed-off-by: mik-dass --- pkg/devfile/adapters/common/utils.go | 4 +- .../adapters/docker/component/utils.go | 116 +++++++++--------- pkg/devfile/adapters/docker/utils/utils.go | 67 +++++----- 3 files changed, 89 insertions(+), 98 deletions(-) diff --git a/pkg/devfile/adapters/common/utils.go b/pkg/devfile/adapters/common/utils.go index db487b78b55..c286c459f1f 100644 --- a/pkg/devfile/adapters/common/utils.go +++ b/pkg/devfile/adapters/common/utils.go @@ -127,7 +127,7 @@ func GetVolumes(devfileObj devfileParser.DevfileObj) map[string][]DevfileVolume } // IsEnvPresent checks if the env variable is present in an array of env variables -func IsEnvPresent(envVars []common.Container, envVarName string) bool { +func IsEnvPresent(envVars []*common.Env, envVarName string) bool { for _, envVar := range envVars { if envVar.Name == envVarName { return true @@ -138,7 +138,7 @@ func IsEnvPresent(envVars []common.Container, envVarName string) bool { } // IsPortPresent checks if the port is present in the endpoints array -func IsPortPresent(endpoints []common.Endpoint, port int) bool { +func IsPortPresent(endpoints []*common.Endpoint, port int) bool { for _, endpoint := range endpoints { if endpoint.TargetPort == int32(port) { return true diff --git a/pkg/devfile/adapters/docker/component/utils.go b/pkg/devfile/adapters/docker/component/utils.go index f250ec3b564..d32594b4b6e 100644 --- a/pkg/devfile/adapters/docker/component/utils.go +++ b/pkg/devfile/adapters/docker/component/utils.go @@ -72,7 +72,7 @@ func (a Adapter) createComponent() (err error) { // Loop over each component and start a container for it for _, comp := range supportedComponents { var dockerVolumeMounts []mount.Mount - for _, vol := range a.componentAliasToVolumes[*comp.Alias] { + for _, vol := range a.componentAliasToVolumes[comp.Container.Name] { volMount := mount.Mount{ Type: mount.TypeVolume, Source: a.volumeNameToDockerVolName[*vol.Name], @@ -82,7 +82,7 @@ func (a Adapter) createComponent() (err error) { } err = a.pullAndStartContainer(dockerVolumeMounts, projectVolumeName, comp) if err != nil { - return errors.Wrapf(err, "unable to pull and start container %s for component %s", *comp.Alias, componentName) + return errors.Wrapf(err, "unable to pull and start container %s for component %s", comp.Container.Name, componentName) } } klog.V(3).Infof("Successfully created all containers for component %s", componentName) @@ -120,13 +120,13 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { for _, comp := range supportedComponents { // Check to see if this component is already running and if so, update it // If component isn't running, re-create it, as it either may be new, or crashed. - containers, err := a.Client.GetContainersByComponentAndAlias(componentName, *comp.Alias) + containers, err := a.Client.GetContainersByComponentAndAlias(componentName, comp.Container.Name) if err != nil { return false, errors.Wrapf(err, "unable to list containers for component %s", componentName) } var dockerVolumeMounts []mount.Mount - for _, vol := range a.componentAliasToVolumes[*comp.Alias] { + for _, vol := range a.componentAliasToVolumes[comp.Container.Name] { volMount := mount.Mount{ Type: mount.TypeVolume, Source: a.volumeNameToDockerVolName[*vol.Name], @@ -140,7 +140,7 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { // Container doesn't exist, so need to pull its image (to be safe) and start a new container err = a.pullAndStartContainer(dockerVolumeMounts, projectVolumeName, comp) if err != nil { - return false, errors.Wrapf(err, "unable to pull and start container %s for component %s", *comp.Alias, componentName) + return false, errors.Wrapf(err, "unable to pull and start container %s for component %s", comp.Container.Name, componentName) } // Update componentExists so that we re-sync project and initialize supervisord if required @@ -155,7 +155,7 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { return componentExists, errors.Wrapf(err, "unable to get the container config for component %s", componentName) } - portMap, namePortMapping, err := getPortMap(a.Context, comp.Endpoints, false) + portMap, namePortMapping, err := getPortMap(a.Context, comp.Container.Endpoints, false) if err != nil { return componentExists, errors.Wrapf(err, "unable to get the port map from env.yaml file for component %s", componentName) } @@ -167,22 +167,22 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { if utils.DoesContainerNeedUpdating(comp, containerConfig, hostConfig, dockerVolumeMounts, mounts, portMap) { log.Infof("\nCreating Docker resources for component %s", a.ComponentName) - s := log.SpinnerNoSpin("Updating the component " + *comp.Alias) + s := log.SpinnerNoSpin("Updating the component " + comp.Container.Name) defer s.End(false) // Remove the container err := a.Client.RemoveContainer(containerID) if err != nil { - return componentExists, errors.Wrapf(err, "Unable to remove container %s for component %s", containerID, *comp.Alias) + return componentExists, errors.Wrapf(err, "Unable to remove container %s for component %s", containerID, comp.Container.Name) } // Start the container err = a.startComponent(dockerVolumeMounts, projectVolumeName, comp) if err != nil { - return false, errors.Wrapf(err, "Unable to start container for devfile component %s", *comp.Alias) + return false, errors.Wrapf(err, "Unable to start container for devfile component %s", comp.Container.Name) } - klog.V(3).Infof("Successfully created container %s for component %s", *comp.Image, componentName) + klog.V(3).Infof("Successfully created container %s for component %s", comp.Container.Image, componentName) s.End(true) // Update componentExists so that we re-sync project and initialize supervisord if required @@ -191,7 +191,7 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { } else { // Multiple containers were returned with the specified label (which should be unique) // Error out, as this isn't expected - return true, fmt.Errorf("Found multiple running containers for devfile component %s and cannot push changes", *comp.Alias) + return true, fmt.Errorf("Found multiple running containers for devfile component %s and cannot push changes", comp.Container.Name) } } @@ -200,27 +200,27 @@ func (a Adapter) updateComponent() (componentExists bool, err error) { func (a Adapter) pullAndStartContainer(mounts []mount.Mount, projectVolumeName string, comp versionsCommon.DevfileComponent) error { // Container doesn't exist, so need to pull its image (to be safe) and start a new container - s := log.Spinnerf("Pulling image %s", *comp.Image) + s := log.Spinnerf("Pulling image %s", comp.Container.Image) - err := a.Client.PullImage(*comp.Image) + err := a.Client.PullImage(comp.Container.Image) if err != nil { s.End(false) - return errors.Wrapf(err, "Unable to pull %s image", *comp.Image) + return errors.Wrapf(err, "Unable to pull %s image", comp.Container.Image) } s.End(true) // Start the component container err = a.startComponent(mounts, projectVolumeName, comp) if err != nil { - return errors.Wrapf(err, "Unable to start container for devfile component %s", *comp.Alias) + return errors.Wrapf(err, "Unable to start container for devfile component %s", comp.Container.Name) } - klog.V(3).Infof("Successfully created container %s for component %s", *comp.Image, a.ComponentName) + klog.V(3).Infof("Successfully created container %s for component %s", comp.Container.Image, a.ComponentName) return nil } func (a Adapter) startComponent(mounts []mount.Mount, projectVolumeName string, comp versionsCommon.DevfileComponent) error { - hostConfig, namePortMapping, err := a.generateAndGetHostConfig(comp.Endpoints) + hostConfig, namePortMapping, err := a.generateAndGetHostConfig(comp.Container.Endpoints) hostConfig.Mounts = mounts if err != nil { return err @@ -234,15 +234,15 @@ func (a Adapter) startComponent(mounts []mount.Mount, projectVolumeName string, utils.UpdateComponentWithSupervisord(&comp, runCommand, a.supervisordVolumeName, &hostConfig) // If the component set `mountSources` to true, add the source volume and env CHE_PROJECTS_ROOT to it - if comp.MountSources { + if comp.Container.MountSources { utils.AddVolumeToContainer(projectVolumeName, lclient.OdoSourceVolumeMount, &hostConfig) - if !common.IsEnvPresent(comp.Env, common.EnvCheProjectsRoot) { + if !common.IsEnvPresent(comp.Container.Env, common.EnvCheProjectsRoot) { envName := common.EnvCheProjectsRoot envValue := lclient.OdoSourceVolumeMount - comp.Env = append(comp.Env, versionsCommon.DockerimageEnv{ - Name: &envName, - Value: &envValue, + comp.Container.Env = append(comp.Container.Env, &versionsCommon.Env{ + Name: envName, + Value: envValue, }) } } @@ -254,7 +254,7 @@ func (a Adapter) startComponent(mounts []mount.Mount, projectVolumeName string, } // Create the docker container - s := log.Spinner("Starting container for " + *comp.Image) + s := log.Spinner("Starting container for " + comp.Container.Image) defer s.End(false) err = a.Client.StartContainer(&containerConfig, &hostConfig, nil) if err != nil { @@ -267,16 +267,16 @@ func (a Adapter) startComponent(mounts []mount.Mount, projectVolumeName string, func (a Adapter) generateAndGetContainerConfig(componentName string, comp versionsCommon.DevfileComponent) container.Config { // Convert the env vars in the Devfile to the format expected by Docker - envVars := utils.ConvertEnvs(comp.Env) - ports := utils.ConvertPorts(comp.Endpoints) - containerLabels := utils.GetContainerLabels(componentName, *comp.Alias) + envVars := utils.ConvertEnvs(comp.Container.Env) + ports := utils.ConvertPorts(comp.Container.Endpoints) + containerLabels := utils.GetContainerLabels(componentName, comp.Container.Name) - containerConfig := a.Client.GenerateContainerConfig(*comp.Image, comp.Command, comp.Args, envVars, containerLabels, ports) + containerConfig := a.Client.GenerateContainerConfig(comp.Container.Image, []string{}, []string{}, envVars, containerLabels, ports) return containerConfig } -func (a Adapter) generateAndGetHostConfig(endpoints []versionsCommon.DockerimageEndpoint) (container.HostConfig, map[nat.Port]string, error) { +func (a Adapter) generateAndGetHostConfig(endpoints []*versionsCommon.Endpoint) (container.HostConfig, map[nat.Port]string, error) { // Convert the port bindings from env.yaml and generate docker host config portMap, namePortMapping, err := getPortMap(a.Context, endpoints, true) if err != nil { @@ -291,7 +291,7 @@ func (a Adapter) generateAndGetHostConfig(endpoints []versionsCommon.Dockerimage return hostConfig, namePortMapping, nil } -func getPortMap(context string, endpoints []versionsCommon.DockerimageEndpoint, show bool) (nat.PortMap, map[nat.Port]string, error) { +func getPortMap(context string, endpoints []*versionsCommon.Endpoint, show bool) (nat.PortMap, map[nat.Port]string, error) { // Convert the exposed and internal port pairs saved in env.yaml file to PortMap // Todo: Use context to get the approraite envinfo after context is supported in experimental mode portmap := nat.PortMap{} @@ -368,57 +368,51 @@ func (a Adapter) execDevfile(pushDevfileCommands []versionsCommon.DevfileCommand // 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.Name == currentCommand.DefaultName || command.Name == currentCommand.AdapterName { + 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" - for _, action := range command.Actions { - containerID := utils.GetContainerIDForAlias(containers, *action.Component) - compInfo := common.ComponentInfo{ - ContainerName: containerID, - } + containerID := utils.GetContainerIDForAlias(containers, command.Exec.Component) + compInfo := common.ComponentInfo{ + ContainerName: containerID, + } - err = exec.ExecuteDevfileBuildAction(&a.Client, action, command.Name, compInfo, show) - if err != nil { - return err - } + 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.Name) + klog.V(4).Infof("Executing devfile command %v", command.Exec.Id) - for _, action := range command.Actions { - - // 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(*action.Component, containers) - if err != nil { - return - } - } - - containerID := utils.GetContainerIDForAlias(containers, *action.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, action, command.Name, compInfo, show) + // 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 } + } - err = exec.ExecuteDevfileRunAction(&a.Client, action, command.Name, compInfo, show) + 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) + + } } } } diff --git a/pkg/devfile/adapters/docker/utils/utils.go b/pkg/devfile/adapters/docker/utils/utils.go index 6824e56a188..bccb551a2c2 100644 --- a/pkg/devfile/adapters/docker/utils/utils.go +++ b/pkg/devfile/adapters/docker/utils/utils.go @@ -18,7 +18,6 @@ import ( "github.com/openshift/odo/pkg/util" "github.com/pkg/errors" - "k8s.io/klog" ) const ( @@ -61,20 +60,20 @@ func GetContainerIDForAlias(containers []types.Container, alias string) string { } // ConvertEnvs converts environment variables from the devfile structure to an array of strings, as expected by Docker -func ConvertEnvs(vars []common.DockerimageEnv) []string { +func ConvertEnvs(vars []*common.Env) []string { dockerVars := []string{} for _, env := range vars { - envString := fmt.Sprintf("%s=%s", *env.Name, *env.Value) + envString := fmt.Sprintf("%s=%s", env.Name, env.Value) dockerVars = append(dockerVars, envString) } return dockerVars } // ConvertPorts converts endpoints from the devfile structure to PortSet, which is expected by Docker -func ConvertPorts(endpoints []common.DockerimageEndpoint) nat.PortSet { +func ConvertPorts(endpoints []*common.Endpoint) nat.PortSet { portSet := nat.PortSet{} for _, endpoint := range endpoints { - port := nat.Port(strconv.Itoa(int(*endpoint.Port)) + "/tcp") + port := nat.Port(strconv.Itoa(int(endpoint.TargetPort)) + "/tcp") portSet[port] = struct{}{} } return portSet @@ -87,7 +86,7 @@ func ConvertPorts(endpoints []common.DockerimageEndpoint) nat.PortSet { // so this function is necessary to prevent having to restart the container on every odo pushs func DoesContainerNeedUpdating(component common.DevfileComponent, containerConfig *container.Config, hostConfig *container.HostConfig, devfileMounts []mount.Mount, containerMounts []types.MountPoint, portMap nat.PortMap) bool { // If the image was changed in the devfile, the container needs to be updated - if *component.Image != containerConfig.Image { + if component.Container.Image != containerConfig.Image { return true } @@ -100,14 +99,14 @@ func DoesContainerNeedUpdating(component common.DevfileComponent, containerConfi // Update the container if the env vars were updated in the devfile // Need to convert the devfile envvars to the format expected by Docker - devfileEnvVars := ConvertEnvs(component.Env) + devfileEnvVars := ConvertEnvs(component.Container.Env) for _, envVar := range devfileEnvVars { if !containerHasEnvVar(envVar, containerConfig.Env) { return true } } - devfilePorts := ConvertPorts(component.Endpoints) + devfilePorts := ConvertPorts(component.Container.Endpoints) for port := range devfilePorts { if !containerHasPort(port, containerConfig.ExposedPorts) { return true @@ -209,33 +208,31 @@ func containerHasPort(devfilePort nat.Port, exposedPorts nat.PortSet) bool { func UpdateComponentWithSupervisord(comp *common.DevfileComponent, runCommand common.DevfileCommand, supervisordVolumeName string, hostConfig *container.HostConfig) { // Mount the supervisord volume for the run command container - for _, action := range runCommand.Actions { - if *action.Component == *comp.Alias { - AddVolumeToContainer(supervisordVolumeName, adaptersCommon.SupervisordMountPath, hostConfig) - - if len(comp.Command) == 0 && len(comp.Args) == 0 { - klog.V(4).Infof("Updating container %v entrypoint with supervisord", *comp.Alias) - comp.Command = append(comp.Command, adaptersCommon.SupervisordBinaryPath) - comp.Args = append(comp.Args, "-c", adaptersCommon.SupervisordConfFile) - } - - if !adaptersCommon.IsEnvPresent(comp.Env, adaptersCommon.EnvOdoCommandRun) { - envName := adaptersCommon.EnvOdoCommandRun - envValue := *action.Command - comp.Env = append(comp.Env, common.DockerimageEnv{ - Name: &envName, - Value: &envValue, - }) - } - - if !adaptersCommon.IsEnvPresent(comp.Env, adaptersCommon.EnvOdoCommandRunWorkingDir) && action.Workdir != nil { - envName := adaptersCommon.EnvOdoCommandRunWorkingDir - envValue := *action.Workdir - comp.Env = append(comp.Env, common.DockerimageEnv{ - Name: &envName, - Value: &envValue, - }) - } + if runCommand.Exec.Component == comp.Container.Name { + AddVolumeToContainer(supervisordVolumeName, adaptersCommon.SupervisordMountPath, hostConfig) + + //if len(comp.Command) == 0 && len(comp.Args) == 0 { + // klog.V(4).Infof("Updating container %v entrypoint with supervisord", *comp.Alias) + // comp.Command = append(comp.Command, adaptersCommon.SupervisordBinaryPath) + // comp.Args = append(comp.Args, "-c", adaptersCommon.SupervisordConfFile) + //} + + if !adaptersCommon.IsEnvPresent(comp.Container.Env, adaptersCommon.EnvOdoCommandRun) { + envName := adaptersCommon.EnvOdoCommandRun + envValue := runCommand.Exec.CommandLine + comp.Container.Env = append(comp.Container.Env, &common.Env{ + Name: envName, + Value: envValue, + }) + } + + if !adaptersCommon.IsEnvPresent(comp.Container.Env, adaptersCommon.EnvOdoCommandRunWorkingDir) && runCommand.Exec.WorkingDir != nil { + envName := adaptersCommon.EnvOdoCommandRunWorkingDir + envValue := runCommand.Exec.WorkingDir + comp.Container.Env = append(comp.Container.Env, &common.Env{ + Name: envName, + Value: *envValue, + }) } } }