mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
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:
@@ -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)
|
||||
|
||||
@@ -44,6 +44,8 @@ type Client interface {
|
||||
buildCommand string,
|
||||
runCommand string,
|
||||
variables map[string]string,
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) error
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,3 +7,9 @@ const (
|
||||
// PreStop is a devfile event
|
||||
PreStop DevfileEventType = "preStop"
|
||||
)
|
||||
|
||||
type DevfileCommands struct {
|
||||
BuildCmd string
|
||||
RunCmd string
|
||||
DebugCmd string
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user