Cleanup Adapter structure to not be used to pass parameters (#5918)

* Do not use receiver to pass DevfileCommands parameters

* Do not use receiver to pass DebugPort parameter

* Do not use receiver to pass deployment parameter

* Do not use receiver to pass pod parameter

* Move randomPorts and errOut as PushParameters
This commit is contained in:
Philippe Martin
2022-07-06 14:42:49 +02:00
committed by GitHub
parent 722020678f
commit 1b303ebfa3
10 changed files with 138 additions and 109 deletions

View File

@@ -60,7 +60,7 @@ func (o *DevClient) Start(
AppName: "app",
Devfile: devfileObj,
},
namespace, randomPorts, errOut)
namespace)
envSpecificInfo, err := envinfo.NewEnvSpecificInfo(path)
if err != nil {
@@ -75,6 +75,8 @@ func (o *DevClient) Start(
Debug: debug,
DevfileBuildCmd: buildCommand,
DevfileRunCmd: runCommand,
RandomPorts: randomPorts,
ErrOut: errOut,
}
klog.V(4).Infoln("Creating inner-loop resources for the component")
@@ -97,6 +99,8 @@ func (o *DevClient) Watch(
buildCommand string,
runCommand string,
variables map[string]string,
randomPorts bool,
errOut io.Writer,
) error {
envSpecificInfo, err := envinfo.NewEnvSpecificInfo(path)
if err != nil {
@@ -116,6 +120,8 @@ func (o *DevClient) Watch(
DevfileRunCmd: runCommand,
DebugPort: envSpecificInfo.GetDebugPort(),
Variables: variables,
RandomPorts: randomPorts,
ErrOut: errOut,
}
return o.watchClient.WatchAndPush(out, watchParameters, ctx)

View File

@@ -44,6 +44,8 @@ type Client interface {
buildCommand string,
runCommand string,
variables map[string]string,
randomPorts bool,
errOut io.Writer,
) error
}

View File

@@ -53,17 +53,17 @@ func (mr *MockClientMockRecorder) Start(devfileObj, namespace, ignorePaths, path
}
// Watch mocks base method.
func (m *MockClient) Watch(devfileObj parser.DevfileObj, path string, ignorePaths []string, out io.Writer, h Handler, ctx context.Context, debug bool, buildCommand, runCommand string, variables map[string]string) error {
func (m *MockClient) Watch(devfileObj parser.DevfileObj, path string, ignorePaths []string, out io.Writer, h Handler, ctx context.Context, debug bool, buildCommand, runCommand string, variables map[string]string, randomPorts bool, errOut io.Writer) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables)
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables, randomPorts, errOut)
ret0, _ := ret[0].(error)
return ret0
}
// Watch indicates an expected call of Watch.
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables interface{}) *gomock.Call {
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables, randomPorts, errOut interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockClient)(nil).Watch), devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockClient)(nil).Watch), devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables, randomPorts, errOut)
}
// MockHandler is a mock of Handler interface.

View File

@@ -46,16 +46,6 @@ type Adapter struct {
AdapterContext
logger machineoutput.MachineEventLoggingClient
devfileBuildCmd string
devfileRunCmd string
devfileDebugCmd string
devfileDebugPort int
pod *corev1.Pod
deployment *appsv1.Deployment
randomPorts bool
errOut io.Writer
}
// AdapterContext is a construct that is common to all adapters
@@ -76,8 +66,6 @@ func NewKubernetesAdapter(
portForwardClient portForward.Client,
context AdapterContext,
namespace string,
randomPorts bool,
errOut io.Writer,
) Adapter {
if namespace != "" {
@@ -90,29 +78,28 @@ func NewKubernetesAdapter(
portForwardClient: portForwardClient,
AdapterContext: context,
logger: machineoutput.NewMachineEventLoggingClient(),
randomPorts: randomPorts,
errOut: errOut,
}
}
// getPod lazily records and retrieves the pod associated with the component associated with this adapter. If refresh parameter
// is true, then the pod is refreshed from the cluster regardless of its current local state
func (a *Adapter) getPod(refresh bool) (*corev1.Pod, error) {
if refresh || a.pod == nil {
func (a *Adapter) getPod(pod *corev1.Pod, refresh bool) (*corev1.Pod, error) {
result := pod
if refresh || result == nil {
podSelector := fmt.Sprintf("component=%s", a.ComponentName)
// Wait for Pod to be in running state otherwise we can't sync data to it.
pod, err := a.kubeClient.WaitAndGetPodWithEvents(podSelector, corev1.PodRunning, a.prefClient.GetPushTimeout())
var err error
result, err = a.kubeClient.WaitAndGetPodWithEvents(podSelector, corev1.PodRunning, a.prefClient.GetPushTimeout())
if err != nil {
return nil, fmt.Errorf("error while waiting for pod %s: %w", podSelector, err)
}
a.pod = pod
}
return a.pod, nil
return result, nil
}
func (a *Adapter) ComponentInfo(command devfilev1.Command) (adapters.ComponentInfo, error) {
pod, err := a.getPod(false)
func (a *Adapter) ComponentInfo(pod *corev1.Pod, command devfilev1.Command) (adapters.ComponentInfo, error) {
pod, err := a.getPod(pod, false)
if err != nil {
return adapters.ComponentInfo{}, err
}
@@ -130,19 +117,14 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
// Since `odo deploy` can theoretically deploy a deployment as well with the same instance name
// we make sure that we are retrieving the deployment with the Dev mode, NOT Deploy.
selectorLabels := odolabels.GetSelector(a.ComponentName, a.AppName, odolabels.ComponentDevMode)
a.deployment, err = a.kubeClient.GetOneDeploymentFromSelector(selectorLabels)
deployment, err := a.kubeClient.GetOneDeploymentFromSelector(selectorLabels)
if err != nil {
if _, ok := err.(*kclient.DeploymentNotFoundError); !ok {
return fmt.Errorf("unable to determine if component %s exists: %w", a.ComponentName, err)
}
}
componentExists := a.deployment != nil
a.devfileBuildCmd = parameters.DevfileBuildCmd
a.devfileRunCmd = parameters.DevfileRunCmd
a.devfileDebugCmd = parameters.DevfileDebugCmd
a.devfileDebugPort = parameters.DebugPort
componentExists := deployment != nil
podChanged := false
var podName string
@@ -154,7 +136,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
// If an error occurs, we don't call a.getPod (a blocking function that waits till it finds a pod in "Running" state.)
// We would rely on a call to a.createOrUpdateComponent to reset the pod count for the component to one.
if err == nil {
pod, podErr := a.getPod(true)
pod, podErr := a.getPod(nil, true)
if podErr != nil {
return fmt.Errorf("unable to get pod for component %s: %w", a.ComponentName, podErr)
}
@@ -175,7 +157,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
return err
}
pushDevfileCommands, err := libdevfile.ValidateAndGetPushCommands(a.Devfile, a.devfileBuildCmd, a.devfileRunCmd)
pushDevfileCommands, err := libdevfile.ValidateAndGetPushCommands(a.Devfile, parameters.DevfileBuildCmd, parameters.DevfileRunCmd)
if err != nil {
return fmt.Errorf("failed to validate devfile build and run commands: %w", err)
}
@@ -191,7 +173,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
currentMode := envinfo.Run
if parameters.Debug {
pushDevfileDebugCommands, e := libdevfile.ValidateAndGetCommand(a.Devfile, a.devfileDebugCmd, devfilev1.DebugCommandGroupKind)
pushDevfileDebugCommands, e := libdevfile.ValidateAndGetCommand(a.Devfile, parameters.DevfileDebugCmd, devfilev1.DebugCommandGroupKind)
if e != nil {
return fmt.Errorf("debug command is not valid: %w", e)
}
@@ -223,18 +205,22 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
}
isMainStorageEphemeral := a.prefClient.GetEphemeralSourceVolume()
err = a.createOrUpdateComponent(componentExists, parameters.EnvSpecificInfo, isMainStorageEphemeral)
deployment, err = a.createOrUpdateComponent(componentExists, parameters.EnvSpecificInfo, isMainStorageEphemeral, libdevfile.DevfileCommands{
BuildCmd: parameters.DevfileBuildCmd,
RunCmd: parameters.DevfileRunCmd,
DebugCmd: parameters.DevfileDebugCmd,
}, parameters.DebugPort, deployment)
if err != nil {
return fmt.Errorf("unable to create or update component: %w", err)
}
a.deployment, err = a.kubeClient.WaitForDeploymentRollout(a.deployment.Name)
deployment, err = a.kubeClient.WaitForDeploymentRollout(deployment.Name)
if err != nil {
return fmt.Errorf("error while waiting for deployment rollout: %w", err)
}
// Wait for Pod to be in running state otherwise we can't sync data or exec commands to it.
pod, err := a.getPod(true)
pod, err := a.getPod(nil, true)
if err != nil {
return fmt.Errorf("unable to get pod for component %s: %w", a.ComponentName, err)
}
@@ -245,7 +231,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
return err
}
ownerReference := generator.GetOwnerReference(a.deployment)
ownerReference := generator.GetOwnerReference(deployment)
// update the owner reference of the PVCs with the deployment
for i := range pvcs {
if pvcs[i].OwnerReferences != nil || pvcs[i].DeletionTimestamp != nil {
@@ -268,7 +254,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
}
// create the Kubernetes objects from the manifest and delete the ones not in the devfile
needRestart, err := service.PushLinks(a.kubeClient, a.Devfile, k8sComponents, labels, a.deployment, a.Context)
needRestart, err := service.PushLinks(a.kubeClient, a.Devfile, k8sComponents, labels, deployment, a.Context)
if err != nil {
return fmt.Errorf("failed to create service(s) associated with the component: %w", err)
}
@@ -280,13 +266,13 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
}
}
a.deployment, err = a.kubeClient.WaitForDeploymentRollout(a.deployment.Name)
_, err = a.kubeClient.WaitForDeploymentRollout(deployment.Name)
if err != nil {
return fmt.Errorf("failed to update config to component deployed: %w", err)
}
// Wait for Pod to be in running state otherwise we can't sync data or exec commands to it.
pod, err = a.getPod(true)
pod, err = a.getPod(pod, true)
if err != nil {
return fmt.Errorf("unable to get pod for component %s: %w", a.ComponentName, err)
}
@@ -332,17 +318,17 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
// didn't previously exist
if !componentExists && libdevfile.HasPostStartEvents(a.Devfile) {
err = libdevfile.ExecPostStartEvents(a.Devfile,
component.NewExecHandler(a.kubeClient, a.AppName, a.ComponentName, a.pod.Name, "", parameters.Show))
component.NewExecHandler(a.kubeClient, a.AppName, a.ComponentName, pod.Name, "", parameters.Show))
if err != nil {
return err
}
}
cmdKind := devfilev1.RunCommandGroupKind
cmdName := a.devfileRunCmd
cmdName := parameters.DevfileRunCmd
if parameters.Debug {
cmdKind = devfilev1.DebugCommandGroupKind
cmdName = a.devfileDebugCmd
cmdName = parameters.DevfileDebugCmd
}
cmd, err := libdevfile.ValidateAndGetCommand(a.Devfile, cmdName, cmdKind)
@@ -360,10 +346,11 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
Adapter: a,
parameters: parameters,
componentExists: componentExists,
podName: pod.GetName(),
}
if commandType == devfilev1.ExecCommandType {
running, err = cmdHandler.isRemoteProcessForCommandRunning(cmd)
running, err = cmdHandler.isRemoteProcessForCommandRunning(cmd, pod.Name)
if err != nil {
return err
}
@@ -383,9 +370,9 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
// Invoke the build command once (before calling libdevfile.ExecuteCommandByNameAndKind), as, if cmd is a composite command,
// the handler we pass will be called for each command in that composite command.
doExecuteBuildCommand := func() error {
execHandler := component.NewExecHandler(a.kubeClient, a.AppName, a.ComponentName, a.pod.Name,
execHandler := component.NewExecHandler(a.kubeClient, a.AppName, a.ComponentName, pod.Name,
"Building your application in container on cluster", parameters.Show)
return libdevfile.Build(a.Devfile, a.devfileBuildCmd, execHandler)
return libdevfile.Build(a.Devfile, parameters.DevfileBuildCmd, execHandler)
}
if componentExists {
if parameters.RunModeChanged || cmd.Exec == nil || !util.SafeGetBool(cmd.Exec.HotReloadCapable) {
@@ -408,7 +395,7 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
a.portForwardClient.StopPortForwarding()
}
err = a.portForwardClient.StartPortForwarding(a.Devfile, a.ComponentName, a.randomPorts, a.errOut)
err = a.portForwardClient.StartPortForwarding(a.Devfile, a.ComponentName, parameters.RandomPorts, parameters.ErrOut)
if err != nil {
return fmt.Errorf("fail starting the port forwarding: %w", err)
}
@@ -416,7 +403,14 @@ func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
return nil
}
func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSpecificInfo, isMainStorageEphemeral bool) (err error) {
func (a *Adapter) createOrUpdateComponent(
componentExists bool,
ei envinfo.EnvSpecificInfo,
isMainStorageEphemeral bool,
commands libdevfile.DevfileCommands,
devfileDebugPort int,
deployment *appsv1.Deployment,
) (*appsv1.Deployment, error) {
ei.SetDevfileObj(a.Devfile)
componentName := a.ComponentName
@@ -426,15 +420,15 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
})
// handle the ephemeral storage
err = storage.HandleEphemeralStorage(a.kubeClient, storageClient, componentName, isMainStorageEphemeral)
err := storage.HandleEphemeralStorage(a.kubeClient, storageClient, componentName, isMainStorageEphemeral)
if err != nil {
return err
return nil, err
}
// From devfile info, create PVCs and return ephemeral storages
ephemerals, err := storagepkg.Push(storageClient, &ei)
if err != nil {
return err
return nil, err
}
// Set the labels
@@ -447,40 +441,40 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
containers, err := generator.GetContainers(a.Devfile, parsercommon.DevfileOptions{})
if err != nil {
return err
return nil, err
}
if len(containers) == 0 {
return fmt.Errorf("no valid components found in the devfile")
return nil, fmt.Errorf("no valid components found in the devfile")
}
// Add the project volume before generating init containers
utils.AddOdoProjectVolume(&containers)
utils.AddOdoMandatoryVolume(&containers)
containers, err = utils.UpdateContainerEnvVars(a.Devfile, containers, a.devfileDebugCmd, a.devfileDebugPort)
containers, err = utils.UpdateContainerEnvVars(a.Devfile, containers, commands.DebugCmd, devfileDebugPort)
if err != nil {
return err
return nil, err
}
containers, err = utils.UpdateContainersEntrypointsIfNeeded(a.Devfile, containers, a.devfileBuildCmd, a.devfileRunCmd, a.devfileDebugCmd)
containers, err = utils.UpdateContainersEntrypointsIfNeeded(a.Devfile, containers, commands.BuildCmd, commands.RunCmd, commands.DebugCmd)
if err != nil {
return err
return nil, err
}
initContainers, err := generator.GetInitContainers(a.Devfile)
if err != nil {
return err
return nil, err
}
// list all the pvcs for the component
pvcs, err := a.kubeClient.ListPVCs(fmt.Sprintf("%v=%v", "component", componentName))
if err != nil {
return err
return nil, err
}
odoSourcePVCName, volumeNameToVolInfo, err := storage.GetVolumeInfos(pvcs)
if err != nil {
return err
return nil, err
}
var allVolumes []corev1.Volume
@@ -488,13 +482,13 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
// Get PVC volumes and Volume Mounts
pvcVolumes, err := storage.GetPersistentVolumesAndVolumeMounts(a.Devfile, containers, initContainers, volumeNameToVolInfo, parsercommon.DevfileOptions{})
if err != nil {
return err
return nil, err
}
allVolumes = append(allVolumes, pvcVolumes...)
ephemeralVolumes, err := storage.GetEphemeralVolumesAndVolumeMounts(a.Devfile, containers, initContainers, ephemerals, parsercommon.DevfileOptions{})
if err != nil {
return err
return nil, err
}
allVolumes = append(allVolumes, ephemeralVolumes...)
@@ -505,9 +499,9 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
"component": componentName,
}
deploymentObjectMeta, err := a.generateDeploymentObjectMeta(labels, annotations)
deploymentObjectMeta, err := a.generateDeploymentObjectMeta(deployment, labels, annotations)
if err != nil {
return err
return nil, err
}
deployParams := generator.DeploymentParams{
@@ -520,9 +514,9 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
Replicas: pointer.Int32Ptr(1),
}
deployment, err := generator.GetDeployment(a.Devfile, deployParams)
deployment, err = generator.GetDeployment(a.Devfile, deployParams)
if err != nil {
return err
return nil, err
}
if deployment.Annotations == nil {
deployment.Annotations = make(map[string]string)
@@ -539,7 +533,7 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
serviceName, err := util.NamespaceKubernetesObjectWithTrim(componentName, a.AppName)
if err != nil {
return err
return nil, err
}
serviceObjectMeta := generator.GetObjectMeta(serviceName, a.kubeClient.GetCurrentNamespace(), labels, serviceAnnotations)
serviceParams := generator.ServiceParams{
@@ -549,7 +543,7 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
svc, err := generator.GetService(a.Devfile, serviceParams, parsercommon.DevfileOptions{})
if err != nil {
return err
return nil, err
}
klog.V(2).Infof("Creating deployment %v", deployment.Spec.Template.GetName())
klog.V(2).Infof("The component name is %v", componentName)
@@ -558,33 +552,34 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
klog.V(2).Info("The component already exists, attempting to update it")
if a.kubeClient.IsSSASupported() {
klog.V(4).Info("Applying deployment")
a.deployment, err = a.kubeClient.ApplyDeployment(*deployment)
deployment, err = a.kubeClient.ApplyDeployment(*deployment)
} else {
klog.V(4).Info("Updating deployment")
a.deployment, err = a.kubeClient.UpdateDeployment(*deployment)
deployment, err = a.kubeClient.UpdateDeployment(*deployment)
}
if err != nil {
return err
return nil, err
}
klog.V(2).Infof("Successfully updated component %v", componentName)
err = a.createOrUpdateServiceForComponent(svc, componentName)
ownerReference := generator.GetOwnerReference(deployment)
err = a.createOrUpdateServiceForComponent(svc, componentName, ownerReference)
if err != nil {
return err
return nil, err
}
} else {
if a.kubeClient.IsSSASupported() {
a.deployment, err = a.kubeClient.ApplyDeployment(*deployment)
deployment, err = a.kubeClient.ApplyDeployment(*deployment)
} else {
a.deployment, err = a.kubeClient.CreateDeployment(*deployment)
deployment, err = a.kubeClient.CreateDeployment(*deployment)
}
if err != nil {
return err
return nil, err
}
klog.V(2).Infof("Successfully created component %v", componentName)
if len(svc.Spec.Ports) > 0 {
ownerReference := generator.GetOwnerReference(a.deployment)
ownerReference := generator.GetOwnerReference(deployment)
originOwnerRefs := svc.OwnerReferences
err = a.kubeClient.TryWithBlockOwnerDeletion(ownerReference, func(ownerRef metav1.OwnerReference) error {
svc.OwnerReferences = append(originOwnerRefs, ownerRef)
@@ -592,25 +587,24 @@ func (a *Adapter) createOrUpdateComponent(componentExists bool, ei envinfo.EnvSp
return err
})
if err != nil {
return err
return nil, err
}
klog.V(2).Infof("Successfully created Service for component %s", componentName)
}
}
return nil
return deployment, nil
}
func (a *Adapter) createOrUpdateServiceForComponent(svc *corev1.Service, componentName string) error {
func (a *Adapter) createOrUpdateServiceForComponent(svc *corev1.Service, componentName string, ownerReference metav1.OwnerReference) error {
oldSvc, err := a.kubeClient.GetOneService(a.ComponentName, a.AppName)
originOwnerReferences := svc.OwnerReferences
ownerReference := generator.GetOwnerReference(a.deployment)
if err != nil {
// no old service was found, create a new one
if len(svc.Spec.Ports) > 0 {
err = a.kubeClient.TryWithBlockOwnerDeletion(ownerReference, func(ownerRef metav1.OwnerReference) error {
svc.OwnerReferences = append(originOwnerReferences, ownerRef)
svc.OwnerReferences = append(originOwnerReferences, ownerReference)
_, err = a.kubeClient.CreateService(*svc)
return err
})
@@ -641,9 +635,9 @@ func (a *Adapter) createOrUpdateServiceForComponent(svc *corev1.Service, compone
// generateDeploymentObjectMeta generates a ObjectMeta object for the given deployment's name, labels and annotations
// if no deployment exists, it creates a new deployment name
func (a Adapter) generateDeploymentObjectMeta(labels map[string]string, annotations map[string]string) (metav1.ObjectMeta, error) {
if a.deployment != nil {
return generator.GetObjectMeta(a.deployment.Name, a.kubeClient.GetCurrentNamespace(), labels, annotations), nil
func (a Adapter) generateDeploymentObjectMeta(deployment *appsv1.Deployment, labels map[string]string, annotations map[string]string) (metav1.ObjectMeta, error) {
if deployment != nil {
return generator.GetObjectMeta(deployment.Name, a.kubeClient.GetCurrentNamespace(), labels, annotations), nil
} else {
deploymentName, err := util.NamespaceKubernetesObject(a.ComponentName, a.AppName)
if err != nil {

View File

@@ -3,7 +3,6 @@ package component
import (
"encoding/json"
"errors"
"os"
"reflect"
"testing"
"time"
@@ -15,6 +14,7 @@ import (
"github.com/redhat-developer/odo/pkg/component"
"github.com/redhat-developer/odo/pkg/envinfo"
"github.com/redhat-developer/odo/pkg/libdevfile"
"github.com/redhat-developer/odo/pkg/preference"
"github.com/redhat-developer/odo/pkg/util"
@@ -134,8 +134,8 @@ func TestCreateOrUpdateComponent(t *testing.T) {
Name: testComponentName,
AppName: testAppName,
})
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "", false, os.Stdout)
err := componentAdapter.createOrUpdateComponent(tt.running, tt.envInfo, false)
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "")
_, err := componentAdapter.createOrUpdateComponent(tt.running, tt.envInfo, false, libdevfile.DevfileCommands{}, 0, nil)
// Checks for unexpected error cases
if !tt.wantErr == (err != nil) {
@@ -347,8 +347,8 @@ func TestDoesComponentExist(t *testing.T) {
})
// DoesComponentExist requires an already started component, so start it.
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "", false, os.Stdout)
err := componentAdapter.createOrUpdateComponent(false, tt.envInfo, false)
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "")
_, err := componentAdapter.createOrUpdateComponent(false, tt.envInfo, false, libdevfile.DevfileCommands{}, 0, nil)
// Checks for unexpected error cases
if err != nil {
@@ -443,8 +443,8 @@ func TestWaitAndGetComponentPod(t *testing.T) {
ctrl := gomock.NewController(t)
prefClient := preference.NewMockClient(ctrl)
prefClient.EXPECT().GetPushTimeout().Return(100 * time.Second)
componentAdapter := NewKubernetesAdapter(fkclient, prefClient, nil, adapterCtx, "", false, os.Stdout)
_, err := componentAdapter.getPod(false)
componentAdapter := NewKubernetesAdapter(fkclient, prefClient, nil, adapterCtx, "")
_, err := componentAdapter.getPod(nil, false)
// Checks for unexpected error cases
if !tt.wantErr == (err != nil) {
@@ -555,9 +555,8 @@ func TestAdapter_generateDeploymentObjectMeta(t *testing.T) {
ComponentName: tt.fields.componentName,
AppName: tt.fields.appName,
},
deployment: tt.fields.deployment,
}
got, err := a.generateDeploymentObjectMeta(tt.args.labels, tt.args.annotations)
got, err := a.generateDeploymentObjectMeta(tt.fields.deployment, tt.args.labels, tt.args.annotations)
if (err != nil) != tt.wantErr {
t.Errorf("generateDeploymentObjectMeta() error = %v, wantErr %v", err, tt.wantErr)
return

View File

@@ -24,6 +24,7 @@ type adapterHandler struct {
Adapter
parameters adapters.PushParameters
componentExists bool
podName string
}
var _ libdevfile.Handler = (*adapterHandler)(nil)
@@ -73,12 +74,12 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
return err
}
err = remoteProcessHandler.StopProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component)
err = remoteProcessHandler.StopProcessForCommand(cmdDef, a.kubeClient, a.podName, devfileCmd.Exec.Component)
if err != nil {
return err
}
if err = remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
if err = remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.podName, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
return err
}
} else {
@@ -90,7 +91,7 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
return err
}
if err := remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
if err := remoteProcessHandler.StartProcessForCommand(cmdDef, a.kubeClient, a.podName, devfileCmd.Exec.Component, statusHandlerFunc(spinner)); err != nil {
return err
}
}
@@ -108,7 +109,7 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
_, err := task.NewRetryable(fmt.Sprintf("process for command %q", devfileCmd.Id), func() (bool, interface{}, error) {
klog.V(4).Infof("checking if process for command %q is running", devfileCmd.Id)
remoteProcess, err := remoteProcessHandler.GetProcessInfoForCommand(
remotecmd.CommandDefinition{Id: devfileCmd.Id}, a.kubeClient, a.pod.Name, devfileCmd.Exec.Component)
remotecmd.CommandDefinition{Id: devfileCmd.Id}, a.kubeClient, a.podName, devfileCmd.Exec.Component)
if err != nil {
return false, nil, err
}
@@ -121,7 +122,7 @@ func (a *adapterHandler) Execute(devfileCmd devfilev1.Command) error {
return err
}
return a.checkRemoteCommandStatus(devfileCmd,
return a.checkRemoteCommandStatus(devfileCmd, a.podName,
fmt.Sprintf("Devfile command %q exited with an error status in %.0f second(s)", devfileCmd.Id, totalWaitTime))
}
@@ -146,9 +147,9 @@ func devfileCommandToRemoteCmdDefinition(devfileCmd devfilev1.Command) (remotecm
}
// isRemoteProcessForCommandRunning returns true if the command is running
func (a *adapterHandler) isRemoteProcessForCommandRunning(command devfilev1.Command) (bool, error) {
func (a *adapterHandler) isRemoteProcessForCommandRunning(command devfilev1.Command, podName string) (bool, error) {
remoteProcess, err := remotecmd.NewKubeExecProcessHandler().GetProcessInfoForCommand(
remotecmd.CommandDefinition{Id: command.Id}, a.kubeClient, a.pod.Name, command.Exec.Component)
remotecmd.CommandDefinition{Id: command.Id}, a.kubeClient, podName, command.Exec.Component)
if err != nil {
return false, err
}
@@ -158,9 +159,9 @@ func (a *adapterHandler) isRemoteProcessForCommandRunning(command devfilev1.Comm
// checkRemoteCommandStatus checks if the command is running .
// if the command is not in a running state, we fetch the last 20 lines of the component's log and display it
func (a *adapterHandler) checkRemoteCommandStatus(command devfilev1.Command, notRunningMessage string) error {
func (a *adapterHandler) checkRemoteCommandStatus(command devfilev1.Command, podName string, notRunningMessage string) error {
remoteProcessHandler := remotecmd.NewKubeExecProcessHandler()
remoteProcess, err := remoteProcessHandler.GetProcessInfoForCommand(remotecmd.CommandDefinition{Id: command.Id}, a.kubeClient, a.pod.Name, command.Exec.Component)
remoteProcess, err := remoteProcessHandler.GetProcessInfoForCommand(remotecmd.CommandDefinition{Id: command.Id}, a.kubeClient, podName, command.Exec.Component)
if err != nil {
return err
}

View File

@@ -1,6 +1,8 @@
package adapters
import (
"io"
"github.com/redhat-developer/odo/pkg/envinfo"
)
@@ -20,6 +22,8 @@ type PushParameters struct {
Debug bool // Runs the component in debug mode
DebugPort int // Port used for remote debugging
RunModeChanged bool // It determines if run mode is changed from run to debug or vice versa
RandomPorts bool // True to forward containers ports on local random ports
ErrOut io.Writer // Writer to output forwarded port information
}
// SyncParameters is a struct containing the parameters to be used when syncing a devfile component

View File

@@ -7,3 +7,9 @@ const (
// PreStop is a devfile event
PreStop DevfileEventType = "preStop"
)
type DevfileCommands struct {
BuildCmd string
RunCmd string
DebugCmd string
}

View File

@@ -241,7 +241,20 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
randomPorts: o.randomPortsFlag,
errOut: o.errOut,
}
err = o.clientset.DevClient.Watch(devFileObj, path, o.ignorePaths, o.out, &d, o.ctx, o.debugFlag, o.buildCommandFlag, o.runCommandFlag, o.variables)
err = o.clientset.DevClient.Watch(
devFileObj,
path,
o.ignorePaths,
o.out,
&d,
o.ctx,
o.debugFlag,
o.buildCommandFlag,
o.runCommandFlag,
o.variables,
o.randomPortsFlag,
o.errOut,
)
}
return err
}
@@ -280,8 +293,6 @@ func (o *Handler) regenerateComponentAdapterFromWatchParams(parameters watch.Wat
Devfile: devObj,
},
parameters.EnvSpecificInfo.GetNamespace(),
o.randomPorts,
o.errOut,
), nil
}

View File

@@ -78,6 +78,10 @@ type WatchParameters struct {
DebugPort int
// Variables override Devfile variables
Variables map[string]string
// RandomPorts is true to forward containers ports on local random ports
RandomPorts bool
// ErrOut is a Writer to output forwarded port information
ErrOut io.Writer
}
// evaluateChangesFunc evaluates any file changes for the events by ignoring the files in fileIgnores slice and removes
@@ -351,6 +355,8 @@ func processEvents(changedFiles, deletedPaths []string, parameters WatchParamete
EnvSpecificInfo: *parameters.EnvSpecificInfo,
Debug: parameters.Debug,
DebugPort: parameters.DebugPort,
RandomPorts: parameters.RandomPorts,
ErrOut: parameters.ErrOut,
}
err := parameters.DevfileWatchHandler(pushParams, parameters)
if err != nil {