mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
Simplify pkg/devfile/adapters/... packages (#5914)
* Remove dependency on common.AdapterContext for sync.Adapter
* Simplify adapters.NewComponentAdapter
* NewComponentAdapter accepts kubernetes.KubernetesContext instead of interface{}
* Replace KubernetesContext with its only field Namespace
* Move the Push Interface and builders to the kubernetes.component package
* Move AdapterContext to kubernetes.component package
* Embeds component.New into NewKubernetesAdapter
* Move GetCommandsMap where it is used
* Move GetSyncFilesFromAttributes where it is used
* Move constants where they are used
* Move types to adapters package
* Update pkg/devfile/adapters/kubernetes/component/adapter.go
Co-authored-by: Armel Soro <armel@rm3l.org>
Co-authored-by: Armel Soro <armel@rm3l.org>
This commit is contained in:
@@ -13,8 +13,7 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/component"
|
||||
"github.com/redhat-developer/odo/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -43,7 +42,7 @@ func NewDevClient(
|
||||
|
||||
func (o *DevClient) Start(
|
||||
devfileObj parser.DevfileObj,
|
||||
platformContext kubernetes.KubernetesContext,
|
||||
namespace string,
|
||||
ignorePaths []string,
|
||||
path string,
|
||||
debug bool,
|
||||
@@ -53,19 +52,22 @@ func (o *DevClient) Start(
|
||||
errOut io.Writer,
|
||||
) error {
|
||||
klog.V(4).Infoln("Creating new adapter")
|
||||
adapter, err := adapters.NewComponentAdapter(
|
||||
adapter := component.NewKubernetesAdapter(
|
||||
o.kubernetesClient, o.prefClient, o.portForwardClient,
|
||||
devfileObj.GetMetadataName(), path, "app", devfileObj, platformContext, randomPorts, errOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
component.AdapterContext{
|
||||
ComponentName: devfileObj.GetMetadataName(),
|
||||
Context: path,
|
||||
AppName: "app",
|
||||
Devfile: devfileObj,
|
||||
},
|
||||
namespace, randomPorts, errOut)
|
||||
|
||||
envSpecificInfo, err := envinfo.NewEnvSpecificInfo(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pushParameters := common.PushParameters{
|
||||
pushParameters := adapters.PushParameters{
|
||||
EnvSpecificInfo: *envSpecificInfo,
|
||||
DebugPort: envSpecificInfo.GetDebugPort(),
|
||||
Path: path,
|
||||
|
||||
@@ -4,22 +4,20 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
|
||||
"github.com/devfile/library/pkg/devfile/parser"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/watch"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
// Start the resources in devfileObj on the platformContext. It then pushes the files in path to the container.
|
||||
// Start the resources in devfileObj on the namespace. It then pushes the files in path to the container.
|
||||
// If debug is true, executes the debug command, or the run command by default.
|
||||
// If buildCommand is set, this will look up the specified build command in the Devfile. Otherwise, it uses the default one.
|
||||
// If runCommand is set, this will look up the specified run command in the Devfile and execute it. Otherwise, it uses the default one.
|
||||
Start(
|
||||
devfileObj parser.DevfileObj,
|
||||
platformContext kubernetes.KubernetesContext,
|
||||
namespace string,
|
||||
ignorePaths []string,
|
||||
path string,
|
||||
debug bool,
|
||||
@@ -50,5 +48,5 @@ type Client interface {
|
||||
}
|
||||
|
||||
type Handler interface {
|
||||
RegenerateAdapterAndPush(common.PushParameters, watch.WatchParameters) error
|
||||
RegenerateAdapterAndPush(adapters.PushParameters, watch.WatchParameters) error
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
|
||||
parser "github.com/devfile/library/pkg/devfile/parser"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
common "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
kubernetes "github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes"
|
||||
adapters "github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
watch "github.com/redhat-developer/odo/pkg/watch"
|
||||
)
|
||||
|
||||
@@ -40,31 +39,31 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder {
|
||||
}
|
||||
|
||||
// Start mocks base method.
|
||||
func (m *MockClient) Start(devfileObj parser.DevfileObj, platformContext kubernetes.KubernetesContext, ignorePaths []string, path string, debug, randomPorts bool, errOut io.Writer) error {
|
||||
func (m *MockClient) Start(devfileObj parser.DevfileObj, namespace string, ignorePaths []string, path string, debug bool, buildCommand, runCommand string, randomPorts bool, errOut io.Writer) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Start", devfileObj, platformContext, ignorePaths, path, debug, randomPorts, errOut)
|
||||
ret := m.ctrl.Call(m, "Start", devfileObj, namespace, ignorePaths, path, debug, buildCommand, runCommand, randomPorts, errOut)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Start indicates an expected call of Start.
|
||||
func (mr *MockClientMockRecorder) Start(devfileObj, platformContext, ignorePaths, path, debug, randomPorts, errOut interface{}) *gomock.Call {
|
||||
func (mr *MockClientMockRecorder) Start(devfileObj, namespace, ignorePaths, path, debug, buildCommand, runCommand, randomPorts, errOut interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockClient)(nil).Start), devfileObj, platformContext, ignorePaths, path, debug, randomPorts, errOut)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockClient)(nil).Start), devfileObj, namespace, ignorePaths, path, debug, buildCommand, runCommand, randomPorts, errOut)
|
||||
}
|
||||
|
||||
// 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, 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) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx, debug, variables)
|
||||
ret := m.ctrl.Call(m, "Watch", devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Watch indicates an expected call of Watch.
|
||||
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx, debug, variables interface{}) *gomock.Call {
|
||||
func (mr *MockClientMockRecorder) Watch(devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables 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, variables)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockClient)(nil).Watch), devfileObj, path, ignorePaths, out, h, ctx, debug, buildCommand, runCommand, variables)
|
||||
}
|
||||
|
||||
// MockHandler is a mock of Handler interface.
|
||||
@@ -91,7 +90,7 @@ func (m *MockHandler) EXPECT() *MockHandlerMockRecorder {
|
||||
}
|
||||
|
||||
// RegenerateAdapterAndPush mocks base method.
|
||||
func (m *MockHandler) RegenerateAdapterAndPush(arg0 common.PushParameters, arg1 watch.WatchParameters) error {
|
||||
func (m *MockHandler) RegenerateAdapterAndPush(arg0 adapters.PushParameters, arg1 watch.WatchParameters) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RegenerateAdapterAndPush", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package common
|
||||
|
||||
// ComponentAdapter defines the functions that platform-specific adapters must implement
|
||||
type ComponentAdapter interface {
|
||||
Push(parameters PushParameters) error
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
)
|
||||
|
||||
const (
|
||||
// EnvProjectsRoot is the env defined for project mount in a component container when component's mountSources=true
|
||||
EnvProjectsRoot = "PROJECTS_ROOT"
|
||||
|
||||
// EnvDebugPort is the env defined in the runtime component container which holds the debug port for remote debugging
|
||||
EnvDebugPort = "DEBUG_PORT"
|
||||
)
|
||||
|
||||
// GetCommandsMap returns a map of the command Id to the command
|
||||
func GetCommandsMap(commands []devfilev1.Command) map[string]devfilev1.Command {
|
||||
commandMap := make(map[string]devfilev1.Command, len(commands))
|
||||
for _, command := range commands {
|
||||
command.Id = strings.ToLower(command.Id)
|
||||
commandMap[command.Id] = command
|
||||
}
|
||||
return commandMap
|
||||
}
|
||||
|
||||
// GetSyncFilesFromAttributes gets the target files and folders along with their respective remote destination from the devfile
|
||||
// it uses the "dev.odo.push.path" attribute in the run command
|
||||
func GetSyncFilesFromAttributes(commandsMap PushCommandsMap) map[string]string {
|
||||
syncMap := make(map[string]string)
|
||||
if value, ok := commandsMap[devfilev1.RunCommandGroupKind]; ok {
|
||||
for key, value := range value.Attributes.Strings(nil) {
|
||||
if strings.HasPrefix(key, "dev.odo.push.path:") {
|
||||
localValue := strings.ReplaceAll(key, "dev.odo.push.path:", "")
|
||||
syncMap[filepath.Clean(localValue)] = filepath.ToSlash(filepath.Clean(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
return syncMap
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
devfileParser "github.com/devfile/library/pkg/devfile/parser"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/portForward"
|
||||
"github.com/redhat-developer/odo/pkg/preference"
|
||||
)
|
||||
|
||||
// NewComponentAdapter returns a Devfile adapter for the targeted platform
|
||||
func NewComponentAdapter(
|
||||
kubernetesClient kclient.ClientInterface,
|
||||
prefClient preference.Client,
|
||||
portForwardClient portForward.Client,
|
||||
componentName string,
|
||||
context string,
|
||||
appName string,
|
||||
devObj devfileParser.DevfileObj,
|
||||
platformContext interface{},
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) (common.ComponentAdapter, error) {
|
||||
|
||||
adapterContext := common.AdapterContext{
|
||||
ComponentName: componentName,
|
||||
Context: context,
|
||||
AppName: appName,
|
||||
Devfile: devObj,
|
||||
}
|
||||
|
||||
kc, ok := platformContext.(kubernetes.KubernetesContext)
|
||||
if !ok {
|
||||
return nil, errors.New("error retrieving context for Kubernetes")
|
||||
}
|
||||
return createKubernetesAdapter(adapterContext, kubernetesClient, prefClient, portForwardClient, kc.Namespace, randomPorts, errOut)
|
||||
|
||||
}
|
||||
|
||||
func createKubernetesAdapter(
|
||||
adapterContext common.AdapterContext,
|
||||
kubernetesClient kclient.ClientInterface,
|
||||
prefClient preference.Client,
|
||||
portForwardClient portForward.Client,
|
||||
namespace string,
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) (common.ComponentAdapter, error) {
|
||||
if namespace != "" {
|
||||
kubernetesClient.SetNamespace(namespace)
|
||||
}
|
||||
return newKubernetesAdapter(adapterContext, kubernetesClient, prefClient, portForwardClient, randomPorts, errOut)
|
||||
}
|
||||
|
||||
func newKubernetesAdapter(
|
||||
adapterContext common.AdapterContext,
|
||||
client kclient.ClientInterface,
|
||||
prefClient preference.Client,
|
||||
portForwardClient portForward.Client,
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) (common.ComponentAdapter, error) {
|
||||
// Feed the common metadata to the platform-specific adapter
|
||||
kubernetesAdapter := kubernetes.New(adapterContext, client, prefClient, portForwardClient, randomPorts, errOut)
|
||||
|
||||
return kubernetesAdapter, nil
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package adapters
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/devfile/library/pkg/devfile/parser/data"
|
||||
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
devfileParser "github.com/devfile/library/pkg/devfile/parser"
|
||||
adaptersCommon "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
)
|
||||
|
||||
func TestNewPlatformAdapter(t *testing.T) {
|
||||
tests := []struct {
|
||||
adapterType string
|
||||
name string
|
||||
componentName string
|
||||
componentType devfilev1.ComponentType
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
adapterType: "kubernetes.Adapter",
|
||||
name: "get platform adapter",
|
||||
componentName: "test",
|
||||
componentType: devfilev1.ContainerComponentType,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run("get platform adapter", func(t *testing.T) {
|
||||
devObj := devfileParser.DevfileObj{
|
||||
Data: func() data.DevfileData {
|
||||
devfileData, err := data.NewDevfileData(string(data.APISchemaVersion200))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = devfileData.AddComponents([]devfilev1.Component{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return devfileData
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterContext := adaptersCommon.AdapterContext{
|
||||
ComponentName: tt.componentName,
|
||||
Devfile: devObj,
|
||||
}
|
||||
fkclient, _ := kclient.FakeNew()
|
||||
adapter, err := newKubernetesAdapter(adapterContext, fkclient, nil, nil, false, os.Stdout)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: '%v'", err)
|
||||
}
|
||||
|
||||
// test that the returned adapter is of the right type
|
||||
if !tt.wantErr == (reflect.TypeOf(adapter).String() != tt.adapterType) {
|
||||
t.Errorf("incorrect adapter type: '%v'", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/portForward"
|
||||
"github.com/redhat-developer/odo/pkg/preference"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/component"
|
||||
)
|
||||
|
||||
// Adapter maps Devfiles to Kubernetes resources and actions
|
||||
type Adapter struct {
|
||||
componentAdapter common.ComponentAdapter
|
||||
}
|
||||
|
||||
var _ common.ComponentAdapter = (*Adapter)(nil)
|
||||
|
||||
type KubernetesContext struct {
|
||||
Namespace string
|
||||
}
|
||||
|
||||
// New instantiates a kubernetes adapter
|
||||
func New(
|
||||
adapterContext common.AdapterContext,
|
||||
client kclient.ClientInterface,
|
||||
prefClient preference.Client,
|
||||
portForwardClient portForward.Client,
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) Adapter {
|
||||
|
||||
compAdapter := component.New(adapterContext, client, prefClient, portForwardClient, randomPorts, errOut)
|
||||
|
||||
return Adapter{
|
||||
componentAdapter: &compAdapter,
|
||||
}
|
||||
}
|
||||
|
||||
// Push creates Kubernetes resources that correspond to the devfile if they don't already exist
|
||||
func (k Adapter) Push(parameters common.PushParameters) error {
|
||||
|
||||
err := k.componentAdapter.Push(parameters)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create the component: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -3,15 +3,14 @@ package component
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/devfile/library/pkg/devfile/generator"
|
||||
devfileCommon "github.com/devfile/library/pkg/devfile/parser/data/v2/common"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/component"
|
||||
"github.com/redhat-developer/odo/pkg/devfile"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/storage"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/utils"
|
||||
"github.com/redhat-developer/odo/pkg/envinfo"
|
||||
@@ -28,6 +27,8 @@ import (
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
"github.com/devfile/library/pkg/devfile/generator"
|
||||
"github.com/devfile/library/pkg/devfile/parser"
|
||||
parsercommon "github.com/devfile/library/pkg/devfile/parser/data/v2/common"
|
||||
dfutil "github.com/devfile/library/pkg/util"
|
||||
|
||||
@@ -37,20 +38,57 @@ import (
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// New instantiates a component adapter
|
||||
func New(
|
||||
adapterContext common.AdapterContext,
|
||||
kubeClient kclient.ClientInterface,
|
||||
// Adapter is a component adapter implementation for Kubernetes
|
||||
type Adapter struct {
|
||||
kubeClient kclient.ClientInterface
|
||||
prefClient preference.Client
|
||||
portForwardClient portForward.Client
|
||||
|
||||
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
|
||||
type AdapterContext struct {
|
||||
ComponentName string // ComponentName is the odo component name, it is NOT related to any devfile components
|
||||
Context string // Context is the given directory containing the source code and configs
|
||||
AppName string // the application name associated to a component
|
||||
Devfile parser.DevfileObj // Devfile is the object returned by the Devfile parser
|
||||
}
|
||||
|
||||
var _ sync.SyncClient = (*Adapter)(nil)
|
||||
var _ ComponentAdapter = (*Adapter)(nil)
|
||||
|
||||
// NewKubernetesAdapter returns a Devfile adapter for the targeted platform
|
||||
func NewKubernetesAdapter(
|
||||
kubernetesClient kclient.ClientInterface,
|
||||
prefClient preference.Client,
|
||||
portForwardClient portForward.Client,
|
||||
context AdapterContext,
|
||||
namespace string,
|
||||
randomPorts bool,
|
||||
errOut io.Writer,
|
||||
) Adapter {
|
||||
|
||||
if namespace != "" {
|
||||
kubernetesClient.SetNamespace(namespace)
|
||||
}
|
||||
|
||||
return Adapter{
|
||||
kubeClient: kubeClient,
|
||||
kubeClient: kubernetesClient,
|
||||
prefClient: prefClient,
|
||||
portForwardClient: portForwardClient,
|
||||
AdapterContext: adapterContext,
|
||||
AdapterContext: context,
|
||||
logger: machineoutput.NewMachineEventLoggingClient(),
|
||||
randomPorts: randomPorts,
|
||||
errOut: errOut,
|
||||
@@ -73,43 +111,20 @@ func (a *Adapter) getPod(refresh bool) (*corev1.Pod, error) {
|
||||
return a.pod, nil
|
||||
}
|
||||
|
||||
func (a *Adapter) ComponentInfo(command devfilev1.Command) (common.ComponentInfo, error) {
|
||||
func (a *Adapter) ComponentInfo(command devfilev1.Command) (adapters.ComponentInfo, error) {
|
||||
pod, err := a.getPod(false)
|
||||
if err != nil {
|
||||
return common.ComponentInfo{}, err
|
||||
return adapters.ComponentInfo{}, err
|
||||
}
|
||||
return common.ComponentInfo{
|
||||
return adapters.ComponentInfo{
|
||||
PodName: pod.Name,
|
||||
ContainerName: command.Exec.Component,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Adapter is a component adapter implementation for Kubernetes
|
||||
type Adapter struct {
|
||||
kubeClient kclient.ClientInterface
|
||||
prefClient preference.Client
|
||||
portForwardClient portForward.Client
|
||||
|
||||
common.AdapterContext
|
||||
logger machineoutput.MachineEventLoggingClient
|
||||
|
||||
devfileBuildCmd string
|
||||
devfileRunCmd string
|
||||
devfileDebugCmd string
|
||||
devfileDebugPort int
|
||||
pod *corev1.Pod
|
||||
deployment *appsv1.Deployment
|
||||
|
||||
randomPorts bool
|
||||
errOut io.Writer
|
||||
}
|
||||
|
||||
var _ sync.SyncClient = (*Adapter)(nil)
|
||||
var _ common.ComponentAdapter = (*Adapter)(nil)
|
||||
|
||||
// Push updates the component if a matching component exists or creates one if it doesn't exist
|
||||
// Once the component has started, it will sync the source code to it.
|
||||
func (a Adapter) Push(parameters common.PushParameters) (err error) {
|
||||
func (a Adapter) Push(parameters adapters.PushParameters) (err error) {
|
||||
|
||||
// Get the Dev deployment:
|
||||
// Since `odo deploy` can theoretically deploy a deployment as well with the same instance name
|
||||
@@ -293,18 +308,18 @@ func (a Adapter) Push(parameters common.PushParameters) (err error) {
|
||||
s = log.Spinner("Syncing files into the container")
|
||||
defer s.End(false)
|
||||
// Get a sync adapter. Check if project files have changed and sync accordingly
|
||||
syncAdapter := sync.New(a.AdapterContext, &a, a.kubeClient)
|
||||
compInfo := common.ComponentInfo{
|
||||
syncAdapter := sync.New(&a, a.kubeClient, a.ComponentName)
|
||||
compInfo := adapters.ComponentInfo{
|
||||
ContainerName: containerName,
|
||||
PodName: pod.GetName(),
|
||||
SyncFolder: syncFolder,
|
||||
}
|
||||
syncParams := common.SyncParameters{
|
||||
syncParams := adapters.SyncParameters{
|
||||
PushParams: parameters,
|
||||
CompInfo: compInfo,
|
||||
ComponentExists: componentExists,
|
||||
PodChanged: podChanged,
|
||||
Files: common.GetSyncFilesFromAttributes(pushDevfileCommands),
|
||||
Files: getSyncFilesFromAttributes(pushDevfileCommands),
|
||||
}
|
||||
|
||||
execRequired, err := syncAdapter.SyncFiles(syncParams)
|
||||
@@ -335,7 +350,7 @@ func (a Adapter) Push(parameters common.PushParameters) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
commandType, err := devfileCommon.GetCommandType(cmd)
|
||||
commandType, err := parsercommon.GetCommandType(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -656,6 +671,24 @@ func getFirstContainerWithSourceVolume(containers []corev1.Container) (string, s
|
||||
}
|
||||
|
||||
// ExtractProjectToComponent extracts the project archive(tar) to the target path from the reader stdin
|
||||
func (a Adapter) ExtractProjectToComponent(componentInfo common.ComponentInfo, targetPath string, stdin io.Reader) error {
|
||||
func (a Adapter) ExtractProjectToComponent(componentInfo adapters.ComponentInfo, targetPath string, stdin io.Reader) error {
|
||||
return a.kubeClient.ExtractProjectToComponent(componentInfo.ContainerName, componentInfo.PodName, targetPath, stdin)
|
||||
}
|
||||
|
||||
// PushCommandsMap stores the commands to be executed as per their types.
|
||||
type PushCommandsMap map[devfilev1.CommandGroupKind]devfilev1.Command
|
||||
|
||||
// getSyncFilesFromAttributes gets the target files and folders along with their respective remote destination from the devfile
|
||||
// it uses the "dev.odo.push.path" attribute in the run command
|
||||
func getSyncFilesFromAttributes(commandsMap PushCommandsMap) map[string]string {
|
||||
syncMap := make(map[string]string)
|
||||
if value, ok := commandsMap[devfilev1.RunCommandGroupKind]; ok {
|
||||
for key, value := range value.Attributes.Strings(nil) {
|
||||
if strings.HasPrefix(key, "dev.odo.push.path:") {
|
||||
localValue := strings.ReplaceAll(key, "dev.odo.push.path:", "")
|
||||
syncMap[filepath.Clean(localValue)] = filepath.ToSlash(filepath.Clean(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
return syncMap
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
devfileParser "github.com/devfile/library/pkg/devfile/parser"
|
||||
"github.com/devfile/library/pkg/testingutil"
|
||||
|
||||
adaptersCommon "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
odolabels "github.com/redhat-developer/odo/pkg/labels"
|
||||
odoTestingUtil "github.com/redhat-developer/odo/pkg/testingutil"
|
||||
@@ -114,7 +113,7 @@ func TestCreateOrUpdateComponent(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterCtx := adaptersCommon.AdapterContext{
|
||||
adapterCtx := AdapterContext{
|
||||
ComponentName: testComponentName,
|
||||
AppName: testAppName,
|
||||
Devfile: devObj,
|
||||
@@ -135,7 +134,7 @@ func TestCreateOrUpdateComponent(t *testing.T) {
|
||||
Name: testComponentName,
|
||||
AppName: testAppName,
|
||||
})
|
||||
componentAdapter := New(adapterCtx, fkclient, nil, nil, false, os.Stdout)
|
||||
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "", false, os.Stdout)
|
||||
err := componentAdapter.createOrUpdateComponent(tt.running, tt.envInfo, false)
|
||||
|
||||
// Checks for unexpected error cases
|
||||
@@ -310,7 +309,7 @@ func TestDoesComponentExist(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterCtx := adaptersCommon.AdapterContext{
|
||||
adapterCtx := AdapterContext{
|
||||
ComponentName: tt.componentName,
|
||||
AppName: tt.appName,
|
||||
Devfile: devObj,
|
||||
@@ -348,7 +347,7 @@ func TestDoesComponentExist(t *testing.T) {
|
||||
})
|
||||
|
||||
// DoesComponentExist requires an already started component, so start it.
|
||||
componentAdapter := New(adapterCtx, fkclient, nil, nil, false, os.Stdout)
|
||||
componentAdapter := NewKubernetesAdapter(fkclient, nil, nil, adapterCtx, "", false, os.Stdout)
|
||||
err := componentAdapter.createOrUpdateComponent(false, tt.envInfo, false)
|
||||
|
||||
// Checks for unexpected error cases
|
||||
@@ -424,7 +423,7 @@ func TestWaitAndGetComponentPod(t *testing.T) {
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterCtx := adaptersCommon.AdapterContext{
|
||||
adapterCtx := AdapterContext{
|
||||
ComponentName: testComponentName,
|
||||
Devfile: devObj,
|
||||
}
|
||||
@@ -444,7 +443,7 @@ func TestWaitAndGetComponentPod(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
prefClient := preference.NewMockClient(ctrl)
|
||||
prefClient.EXPECT().GetPushTimeout().Return(100 * time.Second)
|
||||
componentAdapter := New(adapterCtx, fkclient, prefClient, nil, false, os.Stdout)
|
||||
componentAdapter := NewKubernetesAdapter(fkclient, prefClient, nil, adapterCtx, "", false, os.Stdout)
|
||||
_, err := componentAdapter.getPod(false)
|
||||
|
||||
// Checks for unexpected error cases
|
||||
@@ -552,7 +551,7 @@ func TestAdapter_generateDeploymentObjectMeta(t *testing.T) {
|
||||
|
||||
a := Adapter{
|
||||
kubeClient: fakeClient,
|
||||
AdapterContext: adaptersCommon.AdapterContext{
|
||||
AdapterContext: AdapterContext{
|
||||
ComponentName: tt.fields.componentName,
|
||||
AppName: tt.fields.appName,
|
||||
},
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/component"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/libdevfile"
|
||||
"github.com/redhat-developer/odo/pkg/log"
|
||||
"github.com/redhat-developer/odo/pkg/remotecmd"
|
||||
@@ -22,12 +22,12 @@ const numberOfLinesToOutputLog = 100
|
||||
|
||||
type adapterHandler struct {
|
||||
Adapter
|
||||
parameters common.PushParameters
|
||||
parameters adapters.PushParameters
|
||||
componentExists bool
|
||||
}
|
||||
|
||||
var _ libdevfile.Handler = (*adapterHandler)(nil)
|
||||
var _ common.ComponentAdapter = (*adapterHandler)(nil)
|
||||
var _ ComponentAdapter = (*adapterHandler)(nil)
|
||||
var _ sync.SyncClient = (*adapterHandler)(nil)
|
||||
|
||||
func (a *adapterHandler) ApplyImage(_ devfilev1.Component) error {
|
||||
|
||||
8
pkg/devfile/adapters/kubernetes/component/interface.go
Normal file
8
pkg/devfile/adapters/kubernetes/component/interface.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package component
|
||||
|
||||
import "github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
|
||||
// ComponentAdapter defines the functions that platform-specific adapters must implement
|
||||
type ComponentAdapter interface {
|
||||
Push(parameters adapters.PushParameters) error
|
||||
}
|
||||
@@ -9,11 +9,18 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/klog"
|
||||
|
||||
adaptersCommon "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/libdevfile"
|
||||
"github.com/redhat-developer/odo/pkg/storage"
|
||||
)
|
||||
|
||||
const (
|
||||
// _envProjectsRoot is the env defined for project mount in a component container when component's mountSources=true
|
||||
_envProjectsRoot = "PROJECTS_ROOT"
|
||||
|
||||
// _envDebugPort is the env defined in the runtime component container which holds the debug port for remote debugging
|
||||
_envDebugPort = "DEBUG_PORT"
|
||||
)
|
||||
|
||||
// GetOdoContainerVolumes returns the mandatory Kube volumes for an Odo component
|
||||
func GetOdoContainerVolumes(sourcePVCName string) []corev1.Volume {
|
||||
var sourceVolume corev1.Volume
|
||||
@@ -64,7 +71,7 @@ func AddOdoProjectVolume(containers *[]corev1.Container) {
|
||||
}
|
||||
for i, container := range *containers {
|
||||
for _, env := range container.Env {
|
||||
if env.Name == adaptersCommon.EnvProjectsRoot {
|
||||
if env.Name == _envProjectsRoot {
|
||||
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
|
||||
Name: storage.OdoSourceVolume,
|
||||
MountPath: env.Value,
|
||||
@@ -172,11 +179,11 @@ func UpdateContainerEnvVars(
|
||||
|
||||
// Check if the container belongs to a debug command component
|
||||
for _, c := range debugContainers {
|
||||
if container.Name == c && !isEnvPresent(container.Env, adaptersCommon.EnvDebugPort) {
|
||||
if container.Name == c && !isEnvPresent(container.Env, _envDebugPort) {
|
||||
klog.V(2).Infof("Updating container %v env with debug command's debugPort", container.Name)
|
||||
container.Env = append(container.Env,
|
||||
corev1.EnvVar{
|
||||
Name: adaptersCommon.EnvDebugPort,
|
||||
Name: _envDebugPort,
|
||||
Value: strconv.Itoa(devfileDebugPort),
|
||||
})
|
||||
break
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
devfileParser "github.com/devfile/library/pkg/devfile/parser"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
|
||||
adaptersCommon "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
odoTestingUtil "github.com/redhat-developer/odo/pkg/testingutil"
|
||||
|
||||
@@ -120,7 +119,7 @@ func TestAddOdoProjectVolume(t *testing.T) {
|
||||
Name: "container1",
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: adaptersCommon.EnvProjectsRoot,
|
||||
Name: _envProjectsRoot,
|
||||
Value: "/path1",
|
||||
},
|
||||
},
|
||||
@@ -129,7 +128,7 @@ func TestAddOdoProjectVolume(t *testing.T) {
|
||||
Name: "container2",
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: adaptersCommon.EnvProjectsRoot,
|
||||
Name: _envProjectsRoot,
|
||||
Value: "/path2",
|
||||
},
|
||||
},
|
||||
@@ -860,7 +859,7 @@ func TestUpdateContainerEnvVars(t *testing.T) {
|
||||
for _, envVar := range container.Env {
|
||||
// if the debug command is also present
|
||||
if len(tt.execCommands) >= 2 {
|
||||
if envVar.Name == adaptersCommon.EnvDebugPort {
|
||||
if envVar.Name == _envDebugPort {
|
||||
// check if the debug command's debugPort env was set properly
|
||||
envDebugPortMatched = true
|
||||
}
|
||||
@@ -876,7 +875,7 @@ func TestUpdateContainerEnvVars(t *testing.T) {
|
||||
|
||||
if len(tt.execCommands) >= 2 && !envDebugPortMatched {
|
||||
t.Errorf("TestUpdateContainerEnvVars error: missing env var %s in container %q",
|
||||
adaptersCommon.EnvDebugPort, cmp)
|
||||
_envDebugPort, cmp)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
package common
|
||||
package adapters
|
||||
|
||||
import (
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
devfileParser "github.com/devfile/library/pkg/devfile/parser"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/envinfo"
|
||||
)
|
||||
|
||||
// AdapterContext is a construct that is common to all adapters
|
||||
type AdapterContext struct {
|
||||
ComponentName string // ComponentName is the odo component name, it is NOT related to any devfile components
|
||||
Context string // Context is the given directory containing the source code and configs
|
||||
AppName string // the application name associated to a component
|
||||
Devfile devfileParser.DevfileObj // Devfile is the object returned by the Devfile parser
|
||||
}
|
||||
|
||||
// PushParameters is a struct containing the parameters to be used when pushing to a devfile component
|
||||
type PushParameters struct {
|
||||
Path string // Path refers to the parent folder containing the source code to push up to a component
|
||||
@@ -52,11 +41,3 @@ type ComponentInfo struct {
|
||||
func (ci ComponentInfo) IsEmpty() bool {
|
||||
return len(ci.ContainerName) == 0
|
||||
}
|
||||
|
||||
// PushCommandsMap stores the commands to be executed as per their types.
|
||||
type PushCommandsMap map[devfilev1.CommandGroupKind]devfilev1.Command
|
||||
|
||||
// NewPushCommandMap returns the instance of PushCommandsMap
|
||||
func NewPushCommandMap() PushCommandsMap {
|
||||
return make(map[devfilev1.CommandGroupKind]devfilev1.Command)
|
||||
}
|
||||
@@ -2,9 +2,9 @@ package validate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
v2 "github.com/devfile/library/pkg/devfile/parser/data/v2"
|
||||
parsercommon "github.com/devfile/library/pkg/devfile/parser/data/v2/common"
|
||||
"k8s.io/klog"
|
||||
@@ -25,7 +25,7 @@ func ValidateDevfileData(data interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
commandsMap := common.GetCommandsMap(commands)
|
||||
commandsMap := getCommandsMap(commands)
|
||||
|
||||
// Validate all the devfile components before validating commands
|
||||
if err := validateComponents(components); err != nil {
|
||||
@@ -46,3 +46,13 @@ func ValidateDevfileData(data interface{}) error {
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// getCommandsMap returns a map of the command Id to the command
|
||||
func getCommandsMap(commands []devfilev1.Command) map[string]devfilev1.Command {
|
||||
commandMap := make(map[string]devfilev1.Command, len(commands))
|
||||
for _, command := range commands {
|
||||
command.Id = strings.ToLower(command.Id)
|
||||
commandMap[command.Id] = command
|
||||
}
|
||||
return commandMap
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package common
|
||||
package validate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
)
|
||||
|
||||
func TestGetCommands(t *testing.T) {
|
||||
func Test_getCommands(t *testing.T) {
|
||||
|
||||
component := []devfilev1.Component{
|
||||
testingutil.GetFakeContainerComponent("alias1"),
|
||||
@@ -135,7 +135,7 @@ func TestGetCommands(t *testing.T) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
commandsMap := GetCommandsMap(commands)
|
||||
commandsMap := getCommandsMap(commands)
|
||||
if len(commandsMap) != len(tt.expectedCommands) {
|
||||
t.Errorf("TestGetCommands error: number of returned commands don't match: %v got: %v", len(tt.expectedCommands), len(commandsMap))
|
||||
}
|
||||
@@ -17,8 +17,7 @@ import (
|
||||
"github.com/redhat-developer/odo/pkg/dev"
|
||||
ododevfile "github.com/redhat-developer/odo/pkg/devfile"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes"
|
||||
kcomponent "github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/component"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/location"
|
||||
"github.com/redhat-developer/odo/pkg/envinfo"
|
||||
"github.com/redhat-developer/odo/pkg/libdevfile"
|
||||
@@ -202,10 +201,7 @@ func (o *DevOptions) Validate() error {
|
||||
|
||||
func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
var (
|
||||
devFileObj = o.Context.EnvSpecificInfo.GetDevfileObj()
|
||||
platformContext = kubernetes.KubernetesContext{
|
||||
Namespace: o.Context.GetProject(),
|
||||
}
|
||||
devFileObj = o.Context.EnvSpecificInfo.GetDevfileObj()
|
||||
path = filepath.Dir(o.Context.EnvSpecificInfo.GetDevfilePath())
|
||||
devfileName = devFileObj.GetMetadataName()
|
||||
namespace = o.GetProject()
|
||||
@@ -223,7 +219,7 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
"odo version: "+version.VERSION)
|
||||
|
||||
log.Section("Deploying to the cluster in developer mode")
|
||||
err = o.clientset.DevClient.Start(devFileObj, platformContext, o.ignorePaths, path, o.debugFlag, o.buildCommandFlag, o.runCommandFlag, o.randomPortsFlag, o.errOut)
|
||||
err = o.clientset.DevClient.Start(devFileObj, namespace, o.ignorePaths, path, o.debugFlag, o.buildCommandFlag, o.runCommandFlag, o.randomPortsFlag, o.errOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -251,8 +247,8 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
// RegenerateAdapterAndPush regenerates the adapter and pushes the files to remote pod
|
||||
func (o *Handler) RegenerateAdapterAndPush(pushParams common.PushParameters, watchParams watch.WatchParameters) error {
|
||||
var adapter common.ComponentAdapter
|
||||
func (o *Handler) RegenerateAdapterAndPush(pushParams adapters.PushParameters, watchParams watch.WatchParameters) error {
|
||||
var adapter kcomponent.ComponentAdapter
|
||||
|
||||
adapter, err := o.regenerateComponentAdapterFromWatchParams(watchParams)
|
||||
if err != nil {
|
||||
@@ -267,28 +263,26 @@ func (o *Handler) RegenerateAdapterAndPush(pushParams common.PushParameters, wat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Handler) regenerateComponentAdapterFromWatchParams(parameters watch.WatchParameters) (common.ComponentAdapter, error) {
|
||||
func (o *Handler) regenerateComponentAdapterFromWatchParams(parameters watch.WatchParameters) (kcomponent.ComponentAdapter, error) {
|
||||
devObj, err := ododevfile.ParseAndValidateFromFileWithVariables(location.DevfileLocation(""), parameters.Variables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
platformContext := kubernetes.KubernetesContext{
|
||||
Namespace: parameters.EnvSpecificInfo.GetNamespace(),
|
||||
}
|
||||
|
||||
return adapters.NewComponentAdapter(
|
||||
return kcomponent.NewKubernetesAdapter(
|
||||
o.clientset.KubernetesClient,
|
||||
o.clientset.PreferenceClient,
|
||||
o.clientset.PortForwardClient,
|
||||
parameters.ComponentName,
|
||||
parameters.Path,
|
||||
parameters.ApplicationName,
|
||||
devObj,
|
||||
platformContext,
|
||||
kcomponent.AdapterContext{
|
||||
ComponentName: parameters.ComponentName,
|
||||
Context: parameters.Path,
|
||||
AppName: parameters.ApplicationName,
|
||||
Devfile: devObj,
|
||||
},
|
||||
parameters.EnvSpecificInfo.GetNamespace(),
|
||||
o.randomPorts,
|
||||
o.errOut,
|
||||
)
|
||||
), nil
|
||||
}
|
||||
|
||||
func (o *DevOptions) HandleSignal() error {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/devfile/library/pkg/devfile/generator"
|
||||
dfutil "github.com/devfile/library/pkg/util"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/remotecmd"
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
@@ -18,19 +18,19 @@ import (
|
||||
)
|
||||
|
||||
// New instantiates a component adapter
|
||||
func New(adapterContext common.AdapterContext, syncClient SyncClient, kubeClient kclient.ClientInterface) Adapter {
|
||||
func New(syncClient SyncClient, kubeClient kclient.ClientInterface, componentName string) Adapter {
|
||||
return Adapter{
|
||||
kubeClient: kubeClient,
|
||||
SyncClient: syncClient,
|
||||
AdapterContext: adapterContext,
|
||||
kubeClient: kubeClient,
|
||||
SyncClient: syncClient,
|
||||
ComponentName: componentName,
|
||||
}
|
||||
}
|
||||
|
||||
// Adapter is a component adapter implementation for sync
|
||||
type Adapter struct {
|
||||
kubeClient kclient.ClientInterface
|
||||
SyncClient SyncClient
|
||||
common.AdapterContext
|
||||
kubeClient kclient.ClientInterface
|
||||
SyncClient SyncClient
|
||||
ComponentName string
|
||||
}
|
||||
|
||||
// SyncFiles does a couple of things:
|
||||
@@ -38,7 +38,7 @@ type Adapter struct {
|
||||
// otherwise, it checks which files have changed and syncs the delta
|
||||
// it returns a boolean execRequired and an error. execRequired tells us if files have
|
||||
// changed and devfile execution is required
|
||||
func (a Adapter) SyncFiles(syncParameters common.SyncParameters) (bool, error) {
|
||||
func (a Adapter) SyncFiles(syncParameters adapters.SyncParameters) (bool, error) {
|
||||
|
||||
// Whether to write the indexer content to the index file path (resolvePath)
|
||||
forceWrite := false
|
||||
@@ -169,7 +169,7 @@ func (a Adapter) SyncFiles(syncParameters common.SyncParameters) (bool, error) {
|
||||
}
|
||||
|
||||
// pushLocal syncs source code from the user's disk to the component
|
||||
func (a Adapter) pushLocal(path string, files []string, delFiles []string, isForcePush bool, globExps []string, compInfo common.ComponentInfo, ret util.IndexerRet) error {
|
||||
func (a Adapter) pushLocal(path string, files []string, delFiles []string, isForcePush bool, globExps []string, compInfo adapters.ComponentInfo, ret util.IndexerRet) error {
|
||||
klog.V(4).Infof("Push: componentName: %s, path: %s, files: %s, delFiles: %s, isForcePush: %+v", a.ComponentName, path, files, delFiles, isForcePush)
|
||||
|
||||
// Edge case: check to see that the path is NOT empty.
|
||||
@@ -222,7 +222,7 @@ func (a Adapter) pushLocal(path string, files []string, delFiles []string, isFor
|
||||
|
||||
// updateIndexWithWatchChanges uses the pushParameters.WatchDeletedFiles and pushParamters.WatchFiles to update
|
||||
// the existing index file; the index file is required to exist when this function is called.
|
||||
func updateIndexWithWatchChanges(pushParameters common.PushParameters) error {
|
||||
func updateIndexWithWatchChanges(pushParameters adapters.PushParameters) error {
|
||||
indexFilePath, err := util.ResolveIndexFilePath(pushParameters.Path)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -8,14 +8,10 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/devfile/library/pkg/devfile/parser/data"
|
||||
|
||||
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
|
||||
"github.com/devfile/library/pkg/devfile/generator"
|
||||
"github.com/devfile/library/pkg/devfile/parser"
|
||||
"github.com/golang/mock/gomock"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/kclient"
|
||||
"github.com/redhat-developer/odo/pkg/sync/mock"
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
@@ -115,22 +111,22 @@ func TestSyncFiles(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
client SyncClient
|
||||
syncParameters common.SyncParameters
|
||||
syncParameters adapters.SyncParameters
|
||||
wantErr bool
|
||||
wantIsPushRequired bool
|
||||
}{
|
||||
{
|
||||
name: "Case 1: Component does not exist",
|
||||
client: syncClient,
|
||||
syncParameters: common.SyncParameters{
|
||||
PushParams: common.PushParameters{
|
||||
syncParameters: adapters.SyncParameters{
|
||||
PushParams: adapters.PushParameters{
|
||||
Path: directory,
|
||||
WatchFiles: []string{},
|
||||
WatchDeletedFiles: []string{},
|
||||
IgnoredFiles: []string{},
|
||||
ForceBuild: false,
|
||||
},
|
||||
CompInfo: common.ComponentInfo{
|
||||
CompInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
ComponentExists: false,
|
||||
@@ -141,15 +137,15 @@ func TestSyncFiles(t *testing.T) {
|
||||
{
|
||||
name: "Case 2: Component does exist",
|
||||
client: syncClient,
|
||||
syncParameters: common.SyncParameters{
|
||||
PushParams: common.PushParameters{
|
||||
syncParameters: adapters.SyncParameters{
|
||||
PushParams: adapters.PushParameters{
|
||||
Path: directory,
|
||||
WatchFiles: []string{},
|
||||
WatchDeletedFiles: []string{},
|
||||
IgnoredFiles: []string{},
|
||||
ForceBuild: false,
|
||||
},
|
||||
CompInfo: common.ComponentInfo{
|
||||
CompInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
ComponentExists: true,
|
||||
@@ -160,15 +156,15 @@ func TestSyncFiles(t *testing.T) {
|
||||
{
|
||||
name: "Case 3: FakeErrorClient error",
|
||||
client: errorSyncClient,
|
||||
syncParameters: common.SyncParameters{
|
||||
PushParams: common.PushParameters{
|
||||
syncParameters: adapters.SyncParameters{
|
||||
PushParams: adapters.PushParameters{
|
||||
Path: directory,
|
||||
WatchFiles: []string{},
|
||||
WatchDeletedFiles: []string{},
|
||||
IgnoredFiles: []string{},
|
||||
ForceBuild: true,
|
||||
},
|
||||
CompInfo: common.ComponentInfo{
|
||||
CompInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
ComponentExists: true,
|
||||
@@ -179,15 +175,15 @@ func TestSyncFiles(t *testing.T) {
|
||||
{
|
||||
name: "Case 4: File change",
|
||||
client: syncClient,
|
||||
syncParameters: common.SyncParameters{
|
||||
PushParams: common.PushParameters{
|
||||
syncParameters: adapters.SyncParameters{
|
||||
PushParams: adapters.PushParameters{
|
||||
Path: directory,
|
||||
WatchFiles: []string{path.Join(directory, "test.log")},
|
||||
WatchDeletedFiles: []string{},
|
||||
IgnoredFiles: []string{},
|
||||
ForceBuild: false,
|
||||
},
|
||||
CompInfo: common.ComponentInfo{
|
||||
CompInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
ComponentExists: true,
|
||||
@@ -198,26 +194,7 @@ func TestSyncFiles(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
devObj := parser.DevfileObj{
|
||||
Data: func() data.DevfileData {
|
||||
devfileData, err := data.NewDevfileData(string(data.APISchemaVersion200))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = devfileData.AddComponents([]devfilev1.Component{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return devfileData
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterCtx := common.AdapterContext{
|
||||
ComponentName: testComponentName,
|
||||
Devfile: devObj,
|
||||
}
|
||||
|
||||
syncAdapter := New(adapterCtx, tt.client, kc)
|
||||
syncAdapter := New(tt.client, kc, testComponentName)
|
||||
isPushRequired, err := syncAdapter.SyncFiles(tt.syncParameters)
|
||||
if !tt.wantErr && err != nil {
|
||||
t.Errorf("TestSyncFiles error: unexpected error when syncing files %v", err)
|
||||
@@ -274,7 +251,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files []string
|
||||
delFiles []string
|
||||
isForcePush bool
|
||||
compInfo common.ComponentInfo
|
||||
compInfo adapters.ComponentInfo
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -284,7 +261,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{path.Join(directory, "test.log")},
|
||||
delFiles: []string{},
|
||||
isForcePush: false,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -296,7 +273,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{path.Join(directory, "test.log")},
|
||||
delFiles: []string{},
|
||||
isForcePush: false,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
wantErr: true,
|
||||
@@ -308,7 +285,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{},
|
||||
delFiles: []string{},
|
||||
isForcePush: false,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -320,7 +297,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{},
|
||||
delFiles: []string{path.Join(directory, "test.log")},
|
||||
isForcePush: false,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -332,7 +309,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{},
|
||||
delFiles: []string{},
|
||||
isForcePush: true,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -344,7 +321,7 @@ func TestPushLocal(t *testing.T) {
|
||||
files: []string{},
|
||||
delFiles: []string{},
|
||||
isForcePush: false,
|
||||
compInfo: common.ComponentInfo{
|
||||
compInfo: adapters.ComponentInfo{
|
||||
ContainerName: "abcd",
|
||||
SyncFolder: "/some/path",
|
||||
},
|
||||
@@ -353,26 +330,7 @@ func TestPushLocal(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
devObj := parser.DevfileObj{
|
||||
Data: func() data.DevfileData {
|
||||
devfileData, err := data.NewDevfileData(string(data.APISchemaVersion200))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = devfileData.AddComponents([]devfilev1.Component{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return devfileData
|
||||
}(),
|
||||
}
|
||||
|
||||
adapterCtx := common.AdapterContext{
|
||||
ComponentName: testComponentName,
|
||||
Devfile: devObj,
|
||||
}
|
||||
|
||||
syncAdapter := New(adapterCtx, syncClient, kc)
|
||||
syncAdapter := New(syncClient, kc, testComponentName)
|
||||
err := syncAdapter.pushLocal(tt.path, tt.files, tt.delFiles, tt.isForcePush, []string{}, tt.compInfo, util.IndexerRet{})
|
||||
if !tt.wantErr && err != nil {
|
||||
t.Errorf("TestPushLocal error: error pushing files: %v", err)
|
||||
@@ -456,7 +414,7 @@ func TestUpdateIndexWithWatchChanges(t *testing.T) {
|
||||
t.Fatalf("TestUpdateIndexWithWatchChangesLocal error: unable to write index file: %v", err)
|
||||
}
|
||||
|
||||
pushParams := common.PushParameters{
|
||||
pushParams := adapters.PushParameters{
|
||||
Path: directory,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: sync.go
|
||||
// Source: pkg/sync/sync.go
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
@@ -9,41 +9,41 @@ import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
common "github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
adapters "github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
)
|
||||
|
||||
// MockSyncClient is a mock of SyncClient interface
|
||||
// MockSyncClient is a mock of SyncClient interface.
|
||||
type MockSyncClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockSyncClientMockRecorder
|
||||
}
|
||||
|
||||
// MockSyncClientMockRecorder is the mock recorder for MockSyncClient
|
||||
// MockSyncClientMockRecorder is the mock recorder for MockSyncClient.
|
||||
type MockSyncClientMockRecorder struct {
|
||||
mock *MockSyncClient
|
||||
}
|
||||
|
||||
// NewMockSyncClient creates a new mock instance
|
||||
// NewMockSyncClient creates a new mock instance.
|
||||
func NewMockSyncClient(ctrl *gomock.Controller) *MockSyncClient {
|
||||
mock := &MockSyncClient{ctrl: ctrl}
|
||||
mock.recorder = &MockSyncClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockSyncClient) EXPECT() *MockSyncClientMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ExtractProjectToComponent mocks base method
|
||||
func (m *MockSyncClient) ExtractProjectToComponent(arg0 common.ComponentInfo, arg1 string, arg2 io.Reader) error {
|
||||
// ExtractProjectToComponent mocks base method.
|
||||
func (m *MockSyncClient) ExtractProjectToComponent(arg0 adapters.ComponentInfo, arg1 string, arg2 io.Reader) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ExtractProjectToComponent", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ExtractProjectToComponent indicates an expected call of ExtractProjectToComponent
|
||||
// ExtractProjectToComponent indicates an expected call of ExtractProjectToComponent.
|
||||
func (mr *MockSyncClientMockRecorder) ExtractProjectToComponent(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExtractProjectToComponent", reflect.TypeOf((*MockSyncClient)(nil).ExtractProjectToComponent), arg0, arg1, arg2)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/log"
|
||||
"github.com/redhat-developer/odo/pkg/testingutil/filesystem"
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
)
|
||||
|
||||
type SyncClient interface {
|
||||
ExtractProjectToComponent(common.ComponentInfo, string, io.Reader) error
|
||||
ExtractProjectToComponent(adapters.ComponentInfo, string, io.Reader) error
|
||||
}
|
||||
|
||||
// CopyFile copies localPath directory or list of files in copyFiles list to the directory in running Pod.
|
||||
@@ -27,7 +27,7 @@ type SyncClient interface {
|
||||
// During copying binary components, localPath represent base directory path to binary and copyFiles contains path of binary
|
||||
// During copying local source components, localPath represent base directory path whereas copyFiles is empty
|
||||
// During `odo watch`, localPath represent base directory path whereas copyFiles contains list of changed Files
|
||||
func CopyFile(client SyncClient, localPath string, compInfo common.ComponentInfo, targetPath string, copyFiles []string, globExps []string, ret util.IndexerRet) error {
|
||||
func CopyFile(client SyncClient, localPath string, compInfo adapters.ComponentInfo, targetPath string, copyFiles []string, globExps []string, ret util.IndexerRet) error {
|
||||
|
||||
// Destination is set to "ToSlash" as all containers being ran within OpenShift / S2I are all
|
||||
// Linux based and thus: "\opt\app-root\src" would not work correctly.
|
||||
|
||||
@@ -10,13 +10,13 @@ import (
|
||||
|
||||
"github.com/devfile/library/pkg/devfile/parser"
|
||||
_delete "github.com/redhat-developer/odo/pkg/component/delete"
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters"
|
||||
"github.com/redhat-developer/odo/pkg/labels"
|
||||
"github.com/redhat-developer/odo/pkg/state"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
gitignore "github.com/sabhiram/go-gitignore"
|
||||
|
||||
"github.com/redhat-developer/odo/pkg/devfile/adapters/common"
|
||||
"github.com/redhat-developer/odo/pkg/envinfo"
|
||||
"github.com/redhat-developer/odo/pkg/log"
|
||||
"github.com/redhat-developer/odo/pkg/util"
|
||||
@@ -59,7 +59,7 @@ type WatchParameters struct {
|
||||
// Custom function that can be used to push detected changes to remote pod. For more info about what each of the parameters to this function, please refer, pkg/component/component.go#PushLocal
|
||||
// WatchHandler func(kclient.ClientInterface, string, string, string, io.Writer, []string, []string, bool, []string, bool) error
|
||||
// Custom function that can be used to push detected changes to remote devfile pod. For more info about what each of the parameters to this function, please refer, pkg/devfile/adapters/interface.go#PlatformAdapter
|
||||
DevfileWatchHandler func(common.PushParameters, WatchParameters) error
|
||||
DevfileWatchHandler func(adapters.PushParameters, WatchParameters) error
|
||||
// Parameter whether or not to show build logs
|
||||
Show bool
|
||||
// EnvSpecificInfo contains information of env.yaml file
|
||||
@@ -338,7 +338,7 @@ func processEvents(changedFiles, deletedPaths []string, parameters WatchParamete
|
||||
fmt.Fprintf(out, "Pushing files...\n\n")
|
||||
klog.V(4).Infof("Copying files %s to pod", changedFiles)
|
||||
|
||||
pushParams := common.PushParameters{
|
||||
pushParams := adapters.PushParameters{
|
||||
Path: parameters.Path,
|
||||
WatchFiles: changedFiles,
|
||||
WatchDeletedFiles: deletedPaths,
|
||||
|
||||
@@ -82,3 +82,8 @@ mockgen -source=pkg/binding/interface.go \
|
||||
mockgen -source=pkg/binding/backend/interface.go \
|
||||
-package backend \
|
||||
-destination pkg/binding/backend/mock.go
|
||||
|
||||
|
||||
mockgen -source=pkg/sync/sync.go \
|
||||
-package mock \
|
||||
-destination pkg/sync/mock/sync.go
|
||||
|
||||
Reference in New Issue
Block a user