Skip to content

Commit

Permalink
odo list component shows components running on podman (#6366)
Browse files Browse the repository at this point in the history
* Enable run-on flag

* List all components

* Select specific platform with --run-on flag

* Make podmanClient nil if no podman client is accessible

* integration test

* Delay the display of warnings related to experimental features

* Add logs displaying podman commands executed

* Use None when Running On is empty

* odo list
  • Loading branch information
feloy authored Dec 6, 2022
1 parent 623a145 commit 0c008c6
Show file tree
Hide file tree
Showing 21 changed files with 512 additions and 164 deletions.
13 changes: 8 additions & 5 deletions pkg/api/component-abstract.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package api

// ComponentAbstract represents a component as part of a list of components
type ComponentAbstract struct {
Name string `json:"name"`
ManagedBy string `json:"managedBy"`
ManagedByVersion string `json:"managedByVersion"`
RunningIn RunningModes `json:"runningIn"`
Type string `json:"projectType"`
Name string `json:"name"`
ManagedBy string `json:"managedBy"`
ManagedByVersion string `json:"managedByVersion"`
// RunningIn are the modes the component is running in, among Dev and Deploy
RunningIn RunningModes `json:"runningIn"`
Type string `json:"projectType"`
// RunningOn is the platform the component is running on, either cluster or podman
RunningOn string `json:"runningOn,omitempty"`
}

const (
Expand Down
26 changes: 14 additions & 12 deletions pkg/binding/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,24 @@ func (o *BindingClient) ListAllBindings(devfileObj *parser.DevfileObj, context s
}
}

specs, bindings, err := o.kubernetesClient.ListServiceBindingsFromAllGroups()
if err != nil {
return nil, nil, err
}

for i := range specs {
bindingList, err = o.process(bindingList, &specs[i])
if o.kubernetesClient != nil {
specs, bindings, err := o.kubernetesClient.ListServiceBindingsFromAllGroups()
if err != nil {
return nil, nil, err
}
}

for i := range bindings {
bindingList, err = o.process(bindingList, &bindings[i])
if err != nil {
return nil, nil, err
for i := range specs {
bindingList, err = o.process(bindingList, &specs[i])
if err != nil {
return nil, nil, err
}
}

for i := range bindings {
bindingList, err = o.process(bindingList, &bindings[i])
if err != nil {
return nil, nil, err
}
}
}

Expand Down
29 changes: 22 additions & 7 deletions pkg/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import (
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/kclient"
odolabels "github.com/redhat-developer/odo/pkg/labels"
"github.com/redhat-developer/odo/pkg/odo/commonflags"
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
"github.com/redhat-developer/odo/pkg/platform"
"github.com/redhat-developer/odo/pkg/podman"
"github.com/redhat-developer/odo/pkg/util"

corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -170,6 +172,7 @@ func ListAllClusterComponents(client kclient.ClientInterface, namespace string)
ManagedBy: managedBy,
Type: componentType,
ManagedByVersion: managedByVersion,
RunningOn: commonflags.RunOnCluster,
}
mode := odolabels.GetMode(labels)
componentFound := false
Expand Down Expand Up @@ -204,14 +207,26 @@ func ListAllClusterComponents(client kclient.ClientInterface, namespace string)
return components, nil
}

func ListAllComponents(client kclient.ClientInterface, namespace string, devObj *parser.DevfileObj, componentName string) ([]api.ComponentAbstract, string, error) {
var devfileComponents []api.ComponentAbstract
var err error
func ListAllComponents(client kclient.ClientInterface, podmanClient podman.Client, namespace string, devObj *parser.DevfileObj, componentName string) ([]api.ComponentAbstract, string, error) {
var (
allComponents []api.ComponentAbstract
)

if client != nil {
devfileComponents, err = ListAllClusterComponents(client, namespace)
clusterComponents, err := ListAllClusterComponents(client, namespace)
if err != nil {
return nil, "", err
}
allComponents = append(allComponents, clusterComponents...)
}

// PdomanClient can be nil if experimental mode is not active
if podmanClient != nil {
podmanComponents, err := podmanClient.ListAllComponents()
if err != nil {
return nil, "", err
}
allComponents = append(allComponents, podmanComponents...)
}

localComponent := api.ComponentAbstract{
Expand All @@ -225,12 +240,12 @@ func ListAllComponents(client kclient.ClientInterface, namespace string, devObj

componentInDevfile := ""
if localComponent.Name != "" {
if !Contains(localComponent, devfileComponents) {
devfileComponents = append(devfileComponents, localComponent)
if !Contains(localComponent, allComponents) {
allComponents = append(allComponents, localComponent)
}
componentInDevfile = localComponent.Name
}
return devfileComponents, componentInDevfile, nil
return allComponents, componentInDevfile, nil
}

func getResourcesForComponent(
Expand Down
6 changes: 5 additions & 1 deletion pkg/component/component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func TestListAllClusterComponents(t *testing.T) {
ManagedByVersion: "",
RunningIn: nil,
Type: "Unknown",
RunningOn: "cluster",
}},
wantErr: false,
},
Expand Down Expand Up @@ -125,12 +126,14 @@ func TestListAllClusterComponents(t *testing.T) {
ManagedByVersion: "",
RunningIn: nil,
Type: "Unknown",
RunningOn: "cluster",
}, {
Name: "svc1",
ManagedBy: "odo",
ManagedByVersion: "v3.0.0-beta3",
RunningIn: nil,
Type: "nodejs",
RunningOn: "cluster",
}},
wantErr: false,
},
Expand All @@ -156,7 +159,8 @@ func TestListAllClusterComponents(t *testing.T) {
"dev": true,
"deploy": true,
},
Type: "nodejs",
Type: "nodejs",
RunningOn: "cluster",
}},
wantErr: false,
},
Expand Down
2 changes: 1 addition & 1 deletion pkg/dev/podmandev/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ func createPodFromComponent(
}
}

// TODO add labels (for GetRunningPodFromSelector)
pod := corev1.Pod{
Spec: corev1.PodSpec{
Containers: containers,
Expand All @@ -97,6 +96,7 @@ func createPodFromComponent(

runtime := component.GetComponentRuntimeFromDevfileMetadata(devfileObj.Data.GetMetadata())
pod.SetLabels(labels.GetLabels(componentName, appName, runtime, labels.ComponentDevMode, true))
labels.SetProjectType(pod.GetLabels(), component.GetComponentTypeFromDevfileMetadata(devfileObj.Data.GetMetadata()))

return &pod, fwPorts, nil
}
Expand Down
1 change: 1 addition & 0 deletions pkg/dev/podmandev/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ var (
"app.kubernetes.io/part-of": appName,
"component": devfileName,
"odo.dev/mode": labels.ComponentDevMode,
"odo.dev/project-type": "Not available",
},
},
Spec: corev1.PodSpec{
Expand Down
2 changes: 1 addition & 1 deletion pkg/odo/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func odoRootCmd(ctx context.Context, name, fullName string) *cobra.Command {
version.NewCmdVersion(version.RecommendedCommandName, util.GetFullName(fullName, version.RecommendedCommandName)),
preference.NewCmdPreference(ctx, preference.RecommendedCommandName, util.GetFullName(fullName, preference.RecommendedCommandName)),
telemetry.NewCmdTelemetry(telemetry.RecommendedCommandName),
list.NewCmdList(list.RecommendedCommandName, util.GetFullName(fullName, list.RecommendedCommandName)),
list.NewCmdList(ctx, list.RecommendedCommandName, util.GetFullName(fullName, list.RecommendedCommandName)),
build_images.NewCmdBuildImages(build_images.RecommendedCommandName, util.GetFullName(fullName, build_images.RecommendedCommandName)),
deploy.NewCmdDeploy(deploy.RecommendedCommandName, util.GetFullName(fullName, deploy.RecommendedCommandName)),
_init.NewCmdInit(_init.RecommendedCommandName, util.GetFullName(fullName, _init.RecommendedCommandName)),
Expand Down
10 changes: 7 additions & 3 deletions pkg/odo/cli/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,16 @@ func (o *DevOptions) Validate(ctx context.Context) error {
return clierrors.NewNoCommandInDevfileError("debug")
}

platform := fcontext.GetRunOn(ctx)
platform := fcontext.GetRunOn(ctx, commonflags.RunOnCluster)
switch platform {
case commonflags.RunOnCluster:
if o.clientset.KubernetesClient == nil {
return errors.New("no connection to cluster defined")
}
case commonflags.RunOnPodman:
if o.clientset.PodmanClient == nil {
return errors.New("unable to access podman. Do you have podman client installed?")
}
}
return nil
}
Expand All @@ -118,7 +122,7 @@ func (o *DevOptions) Run(ctx context.Context) (err error) {
path = filepath.Dir(devfilePath)
componentName = odocontext.GetComponentName(ctx)
variables = fcontext.GetVariables(ctx)
platform = fcontext.GetRunOn(ctx)
platform = fcontext.GetRunOn(ctx, commonflags.RunOnCluster)
)

var dest string
Expand Down Expand Up @@ -226,7 +230,7 @@ It forwards endpoints with any exposure values ('public', 'internal' or 'none')
clientset.FILESYSTEM,
clientset.INIT,
clientset.KUBERNETES_NULLABLE,
clientset.PODMAN,
clientset.PODMAN_NULLABLE,
clientset.PORT_FORWARD,
clientset.PREFERENCE,
clientset.STATE,
Expand Down
55 changes: 46 additions & 9 deletions pkg/odo/cli/list/component/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import (
"github.com/spf13/cobra"

"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/odo/cli/feature"
"github.com/redhat-developer/odo/pkg/odo/cli/ui"
"github.com/redhat-developer/odo/pkg/odo/commonflags"

"github.com/redhat-developer/odo/pkg/component"

"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/odo/cmdline"
fcontext "github.com/redhat-developer/odo/pkg/odo/commonflags/context"
odocontext "github.com/redhat-developer/odo/pkg/odo/context"
"github.com/redhat-developer/odo/pkg/odo/genericclioptions"
"github.com/redhat-developer/odo/pkg/odo/genericclioptions/clientset"
Expand Down Expand Up @@ -91,7 +93,7 @@ func (lo *ListOptions) Run(ctx context.Context) error {

listSpinner.End(true)

HumanReadableOutput(list)
HumanReadableOutput(ctx, list)
return nil
}

Expand All @@ -104,20 +106,38 @@ func (lo *ListOptions) run(ctx context.Context) (api.ResourcesList, error) {
var (
devfileObj = odocontext.GetDevfileObj(ctx)
componentName = odocontext.GetComponentName(ctx)

kubeClient = lo.clientset.KubernetesClient
podmanClient = lo.clientset.PodmanClient
)
devfileComponents, componentInDevfile, err := component.ListAllComponents(
lo.clientset.KubernetesClient, lo.namespaceFilter, devfileObj, componentName)

switch fcontext.GetRunOn(ctx, "") {
case commonflags.RunOnCluster:
podmanClient = nil
case commonflags.RunOnPodman:
kubeClient = nil
}

allComponents, componentInDevfile, err := component.ListAllComponents(
kubeClient, podmanClient, lo.namespaceFilter, devfileObj, componentName)
if err != nil {
return api.ResourcesList{}, err
}

// RunningOn is displayed only when RunOn is active
if !feature.IsEnabled(ctx, feature.GenericRunOnFlag) {
for i := range allComponents {
allComponents[i].RunningOn = ""
}
}
return api.ResourcesList{
ComponentInDevfile: componentInDevfile,
Components: devfileComponents,
Components: allComponents,
}, nil
}

// NewCmdList implements the list odo command
func NewCmdComponentList(name, fullName string) *cobra.Command {
func NewCmdComponentList(ctx context.Context, name, fullName string) *cobra.Command {
o := NewListOptions()

var listCmd = &cobra.Command{
Expand All @@ -133,15 +153,18 @@ func NewCmdComponentList(name, fullName string) *cobra.Command {
Aliases: []string{"components"},
}
clientset.Add(listCmd, clientset.KUBERNETES_NULLABLE, clientset.FILESYSTEM)

if feature.IsEnabled(ctx, feature.GenericRunOnFlag) {
clientset.Add(listCmd, clientset.PODMAN_NULLABLE)
}
listCmd.Flags().StringVar(&o.namespaceFlag, "namespace", "", "Namespace for odo to scan for components")

commonflags.UseOutputFlag(listCmd)
commonflags.UseRunOnFlag(listCmd)

return listCmd
}

func HumanReadableOutput(list api.ResourcesList) {
func HumanReadableOutput(ctx context.Context, list api.ResourcesList) {
components := list.Components
if len(components) == 0 {
log.Error("There are no components deployed.")
Expand All @@ -151,7 +174,11 @@ func HumanReadableOutput(list api.ResourcesList) {
t := ui.NewTable()

// Create the header and then sort accordingly
t.AppendHeader(table.Row{"NAME", "PROJECT TYPE", "RUNNING IN", "MANAGED"})
headers := table.Row{"NAME", "PROJECT TYPE", "RUNNING IN", "MANAGED"}
if feature.IsEnabled(ctx, feature.GenericRunOnFlag) {
headers = append(headers, "RUNNING ON")
}
t.AppendHeader(headers)
t.SortBy([]table.SortBy{
{Name: "MANAGED", Mode: table.Asc},
{Name: "NAME", Mode: table.Dsc},
Expand Down Expand Up @@ -190,7 +217,17 @@ func HumanReadableOutput(list api.ResourcesList) {
managedBy = text.Colors{text.FgBlue}.Sprintf(managedBy)
}

t.AppendRow(table.Row{name, componentType, mode, managedBy})
row := table.Row{name, componentType, mode, managedBy}

if feature.IsEnabled(ctx, feature.GenericRunOnFlag) {
runningOn := comp.RunningOn
if runningOn == "" {
runningOn = "None"
}
row = append(row, runningOn)
}

t.AppendRow(row)
}
t.Render()

Expand Down
Loading

0 comments on commit 0c008c6

Please sign in to comment.