...

Source file src/github.com/redhat-developer/odo/pkg/component/describe/describe.go

Documentation: github.com/redhat-developer/odo/pkg/component/describe

     1  package describe
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
     9  	"github.com/devfile/library/v2/pkg/devfile/generator"
    10  	"github.com/devfile/library/v2/pkg/devfile/parser"
    11  	"github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
    12  	"k8s.io/klog"
    13  
    14  	"github.com/redhat-developer/odo/pkg/api"
    15  	"github.com/redhat-developer/odo/pkg/component"
    16  	"github.com/redhat-developer/odo/pkg/kclient"
    17  	"github.com/redhat-developer/odo/pkg/log"
    18  	clierrors "github.com/redhat-developer/odo/pkg/odo/cli/errors"
    19  	"github.com/redhat-developer/odo/pkg/odo/cli/feature"
    20  	"github.com/redhat-developer/odo/pkg/odo/commonflags"
    21  	fcontext "github.com/redhat-developer/odo/pkg/odo/commonflags/context"
    22  	odocontext "github.com/redhat-developer/odo/pkg/odo/context"
    23  	"github.com/redhat-developer/odo/pkg/podman"
    24  	"github.com/redhat-developer/odo/pkg/state"
    25  )
    26  
    27  type platformDependent interface {
    28  	GetPlatform() string
    29  }
    30  
    31  // DescribeDevfileComponent describes the component defined by the devfile in the current directory
    32  func DescribeDevfileComponent(
    33  	ctx context.Context,
    34  	kubeClient kclient.ClientInterface,
    35  	podmanClient podman.Client,
    36  	stateClient state.Client,
    37  ) (result api.Component, devfile *parser.DevfileObj, err error) {
    38  	var (
    39  		devfileObj    = odocontext.GetEffectiveDevfileObj(ctx)
    40  		devfilePath   = odocontext.GetDevfilePath(ctx)
    41  		componentName = odocontext.GetComponentName(ctx)
    42  	)
    43  
    44  	devfileData, err := api.GetDevfileData(*devfileObj)
    45  	if err != nil {
    46  		return api.Component{}, nil, err
    47  	}
    48  
    49  	isPlatformFeatureEnabled := feature.IsEnabled(ctx, feature.GenericPlatformFlag)
    50  	platform := fcontext.GetPlatform(ctx, "")
    51  	switch platform {
    52  	case "":
    53  		if kubeClient == nil {
    54  			log.Warning(kclient.NewNoConnectionError())
    55  		}
    56  		if isPlatformFeatureEnabled && podmanClient == nil {
    57  			log.Warning(podman.NewPodmanNotFoundError(nil))
    58  		}
    59  	case commonflags.PlatformCluster:
    60  		if kubeClient == nil {
    61  			return api.Component{}, nil, kclient.NewNoConnectionError()
    62  		}
    63  		podmanClient = nil
    64  	case commonflags.PlatformPodman:
    65  		if podmanClient == nil {
    66  			return api.Component{}, nil, podman.NewPodmanNotFoundError(nil)
    67  		}
    68  		kubeClient = nil
    69  	}
    70  
    71  	// TODO(feloy) Pass PID with `--pid` flag
    72  	allControlPlaneData, err := stateClient.GetAPIServerPorts(ctx)
    73  	if err != nil {
    74  		return api.Component{}, nil, err
    75  	}
    76  	for i := range allControlPlaneData {
    77  		if allControlPlaneData[i].Platform == "" {
    78  			allControlPlaneData[i].Platform = commonflags.PlatformCluster
    79  		}
    80  	}
    81  
    82  	devControlPlaneData := filterByPlatform(ctx, true, allControlPlaneData)
    83  
    84  	// TODO(feloy) Pass PID with `--pid` flag
    85  	allFwdPorts, err := stateClient.GetForwardedPorts(ctx)
    86  	if err != nil {
    87  		return api.Component{}, nil, err
    88  	}
    89  	if isPlatformFeatureEnabled {
    90  		for i := range allFwdPorts {
    91  			if allFwdPorts[i].Platform == "" {
    92  				allFwdPorts[i].Platform = commonflags.PlatformCluster
    93  			}
    94  		}
    95  	}
    96  	forwardedPorts := filterByPlatform(ctx, isPlatformFeatureEnabled, allFwdPorts)
    97  
    98  	runningOn, err := GetRunningOn(ctx, componentName, kubeClient, podmanClient)
    99  	if err != nil {
   100  		return api.Component{}, nil, err
   101  	}
   102  
   103  	var ingresses []api.ConnectionData
   104  	var routes []api.ConnectionData
   105  	if kubeClient != nil {
   106  		ingresses, routes, err = component.ListRoutesAndIngresses(kubeClient, componentName, odocontext.GetApplication(ctx))
   107  		if err != nil {
   108  			err = clierrors.NewWarning("failed to get ingresses/routes", err)
   109  			// Do not return the error yet, as it is only a warning
   110  		}
   111  	}
   112  
   113  	cmp := api.Component{
   114  		DevfilePath:       devfilePath,
   115  		DevfileData:       devfileData,
   116  		DevControlPlane:   devControlPlaneData,
   117  		DevForwardedPorts: forwardedPorts,
   118  		RunningIn:         api.MergeRunningModes(runningOn),
   119  		RunningOn:         runningOn,
   120  		ManagedBy:         "odo",
   121  		Ingresses:         ingresses,
   122  		Routes:            routes,
   123  	}
   124  	if !isPlatformFeatureEnabled {
   125  		// Display RunningOn field only if the feature is enabled
   126  		cmp.RunningOn = nil
   127  	}
   128  	updateWithRemoteSourceLocation(&cmp)
   129  	return cmp, devfileObj, err
   130  }
   131  
   132  // DescribeNamedComponent describes a component given its name
   133  func DescribeNamedComponent(
   134  	ctx context.Context,
   135  	name string,
   136  	kubeClient kclient.ClientInterface,
   137  	podmanClient podman.Client,
   138  ) (result api.Component, devfileObj *parser.DevfileObj, err error) {
   139  
   140  	isPlatformFeatureEnabled := feature.IsEnabled(ctx, feature.GenericPlatformFlag)
   141  	platform := fcontext.GetPlatform(ctx, "")
   142  	switch platform {
   143  	case "":
   144  		if isPlatformFeatureEnabled {
   145  			//Get info from all platforms
   146  			if kubeClient == nil {
   147  				log.Warning(kclient.NewNoConnectionError())
   148  			}
   149  			if podmanClient == nil {
   150  				log.Warning(podman.NewPodmanNotFoundError(nil))
   151  			}
   152  		} else {
   153  			if kubeClient == nil {
   154  				return api.Component{}, nil, kclient.NewNoConnectionError()
   155  			}
   156  			podmanClient = nil
   157  		}
   158  	case commonflags.PlatformCluster:
   159  		if kubeClient == nil {
   160  			return api.Component{}, nil, kclient.NewNoConnectionError()
   161  		}
   162  		podmanClient = nil
   163  	case commonflags.PlatformPodman:
   164  		if podmanClient == nil {
   165  			return api.Component{}, nil, podman.NewPodmanNotFoundError(nil)
   166  		}
   167  		kubeClient = nil
   168  	}
   169  
   170  	runningOn, err := GetRunningOn(ctx, name, kubeClient, podmanClient)
   171  	if err != nil {
   172  		return api.Component{}, nil, err
   173  	}
   174  
   175  	devfile, err := component.GetDevfileInfo(ctx, kubeClient, podmanClient, name)
   176  	if err != nil {
   177  		return api.Component{}, nil, err
   178  	}
   179  
   180  	var ingresses []api.ConnectionData
   181  	var routes []api.ConnectionData
   182  	if kubeClient != nil {
   183  		ingresses, routes, err = component.ListRoutesAndIngresses(kubeClient, name, odocontext.GetApplication(ctx))
   184  		if err != nil {
   185  			return api.Component{}, nil, fmt.Errorf("failed to get ingresses/routes: %w", err)
   186  		}
   187  	}
   188  
   189  	cmp := api.Component{
   190  		DevfileData: &api.DevfileData{
   191  			Devfile: devfile.Data,
   192  		},
   193  		RunningIn: api.MergeRunningModes(runningOn),
   194  		RunningOn: runningOn,
   195  		ManagedBy: "odo",
   196  		Ingresses: ingresses,
   197  		Routes:    routes,
   198  	}
   199  	if !feature.IsEnabled(ctx, feature.GenericPlatformFlag) {
   200  		// Display RunningOn field only if the feature is enabled
   201  		cmp.RunningOn = nil
   202  	}
   203  
   204  	return cmp, &devfile, nil
   205  }
   206  
   207  func GetRunningOn(ctx context.Context, n string, kubeClient kclient.ClientInterface, podmanClient podman.Client) (map[string]api.RunningModes, error) {
   208  	var runningOn map[string]api.RunningModes
   209  	runningModesMap, err := component.GetRunningModes(ctx, kubeClient, podmanClient, n)
   210  	if err != nil {
   211  		if !errors.As(err, &component.NoComponentFoundError{}) {
   212  			return nil, err
   213  		}
   214  		// it is ok if the component is not deployed
   215  		runningModesMap = nil
   216  	}
   217  	if runningModesMap != nil {
   218  		runningOn = make(map[string]api.RunningModes, len(runningModesMap))
   219  		if kubeClient != nil && runningModesMap[kubeClient] != nil {
   220  			runningOn[commonflags.PlatformCluster] = runningModesMap[kubeClient]
   221  		}
   222  		if podmanClient != nil && runningModesMap[podmanClient] != nil {
   223  			runningOn[commonflags.PlatformPodman] = runningModesMap[podmanClient]
   224  		}
   225  	}
   226  	return runningOn, nil
   227  }
   228  
   229  func filterByPlatform[T platformDependent](ctx context.Context, isFeatEnabled bool, all []T) (result []T) {
   230  	if !isFeatEnabled {
   231  		return nil
   232  	}
   233  
   234  	plt := fcontext.GetPlatform(ctx, "")
   235  	switch plt {
   236  	case "":
   237  		// Read from all platforms
   238  		result = all
   239  	case commonflags.PlatformCluster:
   240  		for _, p := range all {
   241  			if p.GetPlatform() == "" || p.GetPlatform() == commonflags.PlatformCluster {
   242  				result = append(result, p)
   243  			}
   244  		}
   245  	case commonflags.PlatformPodman:
   246  		for _, p := range all {
   247  			if p.GetPlatform() == commonflags.PlatformPodman {
   248  				result = append(result, p)
   249  			}
   250  		}
   251  	}
   252  	return result
   253  }
   254  
   255  func updateWithRemoteSourceLocation(cmp *api.Component) {
   256  	components, err := cmp.DevfileData.Devfile.GetComponents(common.DevfileOptions{
   257  		ComponentOptions: common.ComponentOptions{ComponentType: v1alpha2.ContainerComponentType},
   258  	})
   259  	if err != nil {
   260  		return
   261  	}
   262  	for _, comp := range components {
   263  		if comp.Container.GetMountSources() {
   264  			if comp.Container.SourceMapping == "" {
   265  				comp.Container.SourceMapping = generator.DevfileSourceVolumeMount
   266  				err = cmp.DevfileData.Devfile.UpdateComponent(comp)
   267  				if err != nil {
   268  					klog.V(2).Infof("error occurred while updating the component %s; cause: %s", comp.Name, err)
   269  				}
   270  			}
   271  		}
   272  	}
   273  }
   274  

View as plain text