Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Commit

Permalink
Fix panic for standalone pod in applications view
Browse files Browse the repository at this point in the history
Signed-off-by: Sam Foo <foos@vmware.com>
  • Loading branch information
Sam Foo committed Jul 23, 2021
1 parent 0b422da commit 21f3231
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 2 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/2650-GuessWhoSamFoo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed panic when viewing objects with no owner reference in applications view
15 changes: 13 additions & 2 deletions internal/modules/workloads/detail_describer.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,19 @@ _%s_
return objects[i].GetName() < objects[j].GetName()
})

selection := objects[0].GetOwnerReferences()[0]
rv, err := resourceviewer.Create(ctx, options.Dash, options.Queryer, fmt.Sprintf("%s pods", selection.Name), objects...)
var selection string
for _, obj := range objects {
if len(obj.GetOwnerReferences()) > 0 {
for _, ref := range obj.GetOwnerReferences() {
selection = fmt.Sprintf("%s pods", ref.Name)
continue
}
} else {
selection = string(obj.GetUID())
}
}

rv, err := resourceviewer.Create(ctx, options.Dash, options.Queryer, selection, objects...)
if err != nil {
cr := d.createResponse(
component.NewError(component.TitleFromString("Unable to create resource viewer"), err),
Expand Down
106 changes: 106 additions & 0 deletions internal/modules/workloads/detail_describer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package workloads

import (
"context"
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

clusterFake "github.com/vmware-tanzu/octant/internal/cluster/fake"
configFake "github.com/vmware-tanzu/octant/internal/config/fake"
"github.com/vmware-tanzu/octant/internal/describer"
"github.com/vmware-tanzu/octant/internal/queryer"
queryerFake "github.com/vmware-tanzu/octant/internal/queryer/fake"
"github.com/vmware-tanzu/octant/internal/testutil"
"github.com/vmware-tanzu/octant/pkg/plugin"
pluginFake "github.com/vmware-tanzu/octant/pkg/plugin/fake"
"github.com/vmware-tanzu/octant/pkg/store"
objectStoreFake "github.com/vmware-tanzu/octant/pkg/store/fake"
"github.com/vmware-tanzu/octant/pkg/view/component"
)

func TestDetailDescriber_Describe(t *testing.T) {
controller := gomock.NewController(t)
defer controller.Finish()
ctx := context.Background()

dd, err := NewDetailDescriber()
require.NoError(t, err)

tdo := newTestDescriberOptions(t, controller)
describerOptions := tdo.ToOptions()

result, err := dd.Describe(ctx, "namespace", describerOptions)
require.NoError(t, err)

for _, c := range result.Components {
f, ok := c.(*component.FlexLayout)
require.Equal(t, true, ok)
require.Equal(t, component.TitleFromString("Workload layout"), f.Title)
require.Equal(t, 2, len(f.Config.Sections))
}
}

type testDescriberOptions struct {
dashConfig *configFake.MockDash
queryer queryer.Queryer
}

func newTestDescriberOptions(t *testing.T, controller *gomock.Controller) *testDescriberOptions {
dashConfig := configFake.NewMockDash(controller)

clusterClient := clusterFake.NewMockClientInterface(controller)
objectStore := objectStoreFake.NewMockStore(controller)
discoveryInterface := clusterFake.NewMockDiscoveryInterface(controller)
pluginManager := pluginFake.NewMockManagerInterface(controller)

podKey := store.Key{
Namespace: "namespace",
APIVersion: "v1",
Kind: "Pod",
}

pod := testutil.CreatePod("pod")
u := testutil.ToUnstructured(t, pod)
objectStore.EXPECT().List(gomock.Any(), podKey).Return(testutil.ToUnstructuredList(t, pod), false, nil).AnyTimes()

clusterClient.EXPECT().DiscoveryClient().Return(discoveryInterface, nil).AnyTimes()
discoveryInterface.EXPECT().ServerPreferredNamespacedResources().AnyTimes()
dashConfig.EXPECT().ClusterClient().Return(clusterClient).AnyTimes()
dashConfig.EXPECT().ObjectStore().Return(objectStore).AnyTimes()
dashConfig.EXPECT().PluginManager().Return(pluginManager).AnyTimes()

queryer := queryerFake.NewMockQueryer(controller)
queryer.EXPECT().PersistentVolumeClaimsForPod(gomock.Any(), pod)
queryer.EXPECT().ConfigMapsForPod(gomock.Any(), pod)
queryer.EXPECT().SecretsForPod(gomock.Any(), pod)
queryer.EXPECT().ServicesForPod(gomock.Any(), pod)
queryer.EXPECT().OwnerReference(gomock.Any(), u)
queryer.EXPECT().Children(gomock.Any(), u).Return(&unstructured.UnstructuredList{}, nil)

dashConfig.EXPECT().ObjectPath(pod.Namespace, pod.APIVersion, pod.Kind, pod.Name)
dashConfig.EXPECT().ObjectPath(pod.Namespace, "v1", "ServiceAccount", "")
eventKey := store.Key{
Namespace: "namespace",
APIVersion: "v1",
Kind: "Event",
}
objectStore.EXPECT().List(gomock.Any(), eventKey).Return(&unstructured.UnstructuredList{}, false, nil)
pluginManager.EXPECT().ObjectStatus(gomock.Any(), u).Return(&plugin.ObjectStatusResponse{}, nil)

tdo := &testDescriberOptions{
dashConfig: dashConfig,
queryer: queryer,
}
return tdo
}

func (o *testDescriberOptions) ToOptions() describer.Options {
return describer.Options{
Dash: o.dashConfig,
Fields: map[string]string{"name": "pod"},
Queryer: o.queryer,
}
}

0 comments on commit 21f3231

Please sign in to comment.