Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for User Links add through annotations for Pods and Services #2249

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
666 changes: 334 additions & 332 deletions i18n/messages-en.xtb

Large diffs are not rendered by default.

1,670 changes: 836 additions & 834 deletions i18n/messages-ja.xtb

Large diffs are not rendered by default.

1,444 changes: 723 additions & 721 deletions i18n/messages-zh-tw.xtb

Large diffs are not rendered by default.

1,662 changes: 832 additions & 830 deletions i18n/messages-zh.xtb

Large diffs are not rendered by default.

20 changes: 17 additions & 3 deletions src/app/backend/handler/apihandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie
apiV1Ws.GET("/service/{namespace}").
To(apiHandler.handleGetServiceList).
Writes(resourceService.ServiceList{}))
apiV1Ws.Route(
apiV1Ws.GET("/service/{namespace}/{service}/endpoint").
To(apiHandler.handleGetServiceEndpoints).
Writes(endpoint.EndpointList{}))
apiV1Ws.Route(
apiV1Ws.GET("/service/{namespace}/{service}").
To(apiHandler.handleGetServiceDetail).
Expand Down Expand Up @@ -750,12 +754,17 @@ func (apiHandler *APIHandler) handleGetServiceDetail(request *restful.Request, r
handleInternalError(response, err)
return
}

config, err := apiHandler.cManager.Config(nil)
if err != nil {
handleInternalError(response, err)
return
}
namespace := request.PathParameter("namespace")
name := request.PathParameter("service")
dataSelect := parseDataSelectPathParameter(request)
dataSelect.MetricQuery = dataselect.StandardMetrics
result, err := resourceService.GetServiceDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name, dataSelect)
result, err := resourceService.GetServiceDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name,
config.Host, dataSelect)
if err != nil {
handleInternalError(response, err)
return
Expand Down Expand Up @@ -1391,10 +1400,15 @@ func (apiHandler *APIHandler) handleGetPodDetail(request *restful.Request, respo
handleInternalError(response, err)
return
}
config, err := apiHandler.cManager.Config(nil)
if err != nil {
handleInternalError(response, err)
return
}

namespace := request.PathParameter("namespace")
name := request.PathParameter("pod")
result, err := pod.GetPodDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name)
result, err := pod.GetPodDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name, config.Host)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to test it not on a localhost?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure I understand the question... Are you asking if I was not able to test it on localhost?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant setup different than localhost, i.e. AWS, GCE etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested running master on a vagrant vm. Dashboard did generated correct links.

if err != nil {
handleInternalError(response, err)
return
Expand Down
19 changes: 16 additions & 3 deletions src/app/backend/resource/pod/detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/controller"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/userlinks"
"k8s.io/apimachinery/pkg/api/errors"
res "k8s.io/apimachinery/pkg/api/resource"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -72,6 +73,9 @@ type PodDetail struct {
// Events is list of events associated with a pod.
EventList common.EventList `json:"eventList"`

// Array of composed userlinks that have been derived from pod annotation.
UserLinks []userlinks.UserLink `json:"userLinks"`

// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
Expand Down Expand Up @@ -110,7 +114,7 @@ type EnvVar struct {

// GetPodDetail returns the details (PodDetail) of a named Pod from a particular namespace.
// TODO(maciaszczykm): Owner reference should be used instead of created by annotation.
func GetPodDetail(client kubernetes.Interface, metricClient metricapi.MetricClient, namespace, name string) (*PodDetail, error) {
func GetPodDetail(client kubernetes.Interface, metricClient metricapi.MetricClient, namespace, name, host string) (*PodDetail, error) {
log.Printf("Getting details of %s pod in %s namespace", name, namespace)

channels := &common.ResourceChannels{
Expand Down Expand Up @@ -153,7 +157,14 @@ func GetPodDetail(client kubernetes.Interface, metricClient metricapi.MetricClie
return nil, criticalError
}

podDetail := toPodDetail(pod, metrics, configMapList, secretList, controller, eventList, nonCriticalErrors)
userLinks, err := userlinks.GetUserLinks(client, namespace, name, api.ResourceKindPod, host)
nonCriticalErrors, criticalError = errorHandler.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}

podDetail := toPodDetail(pod, metrics, configMapList, secretList, controller, eventList,
userLinks, nonCriticalErrors)
return &podDetail, nil
}

Expand Down Expand Up @@ -225,7 +236,8 @@ func extractContainerInfo(containerList []v1.Container, pod *v1.Pod, configMaps
}

func toPodDetail(pod *v1.Pod, metrics []metricapi.Metric, configMaps *v1.ConfigMapList, secrets *v1.SecretList,
controller controller.ResourceOwner, events *common.EventList, nonCriticalErrors []error) PodDetail {
controller controller.ResourceOwner, events *common.EventList, userLinks []userlinks.UserLink,
nonCriticalErrors []error) PodDetail {
return PodDetail{
ObjectMeta: api.NewObjectMeta(pod.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindPod),
Expand All @@ -239,6 +251,7 @@ func toPodDetail(pod *v1.Pod, metrics []metricapi.Metric, configMaps *v1.ConfigM
Metrics: metrics,
Conditions: getPodConditions(*pod),
EventList: *events,
UserLinks: userLinks,
Errors: nonCriticalErrors,
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/app/backend/resource/pod/detail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,20 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/controller"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/userlinks"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/pkg/api/v1"
)

func TestGetPodDetail(t *testing.T) {
cases := []struct {
host string
pod *v1.PodList
expected *PodDetail
}{
{
host: "http://localhost:8080",
pod: &v1.PodList{Items: []v1.Pod{{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-pod", Namespace: "test-namespace",
Expand All @@ -51,6 +54,7 @@ func TestGetPodDetail(t *testing.T) {
Containers: []Container{},
InitContainers: []Container{},
EventList: common.EventList{Events: []common.Event{}},
UserLinks: []userlinks.UserLink{},
Metrics: []metricapi.Metric{},
Errors: []error{},
},
Expand All @@ -61,7 +65,7 @@ func TestGetPodDetail(t *testing.T) {
fakeClient := fake.NewSimpleClientset(c.pod)

dataselect.DefaultDataSelectWithMetrics.MetricQuery = dataselect.NoMetrics
actual, err := GetPodDetail(fakeClient, nil, "test-namespace", "test-pod")
actual, err := GetPodDetail(fakeClient, nil, "test-namespace", "test-pod", c.host)

if err != nil {
t.Errorf("GetPodDetail(%#v) == \ngot err %#v", c.pod, err)
Expand Down
3 changes: 3 additions & 0 deletions src/app/backend/resource/service/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/endpoint"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/userlinks"
"k8s.io/client-go/pkg/api/v1"
)

Expand All @@ -38,6 +39,7 @@ func ToService(service *v1.Service) Service {

// ToServiceDetail returns api service object based on kubernetes service object
func ToServiceDetail(service *v1.Service, events common.EventList, pods pod.PodList, endpointList endpoint.EndpointList,
userLinks []userlinks.UserLink,
nonCriticalErrors []error) ServiceDetail {
return ServiceDetail{
ObjectMeta: api.NewObjectMeta(service.ObjectMeta),
Expand All @@ -50,6 +52,7 @@ func ToServiceDetail(service *v1.Service, events common.EventList, pods pod.PodL
Type: service.Spec.Type,
EventList: events,
PodList: pods,
UserLink: userLinks,
SessionAffinity: service.Spec.SessionAffinity,
Errors: nonCriticalErrors,
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/backend/resource/service/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func TestToServiceDetail(t *testing.T) {
}

for _, c := range cases {
actual := ToServiceDetail(c.service, c.eventList, c.podList, c.endpointList, nil)
actual := ToServiceDetail(c.service, c.eventList, c.podList, c.endpointList, nil, nil)

if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("ToServiceDetail(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
Expand Down
14 changes: 12 additions & 2 deletions src/app/backend/resource/service/detail.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/endpoint"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/userlinks"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
Expand Down Expand Up @@ -61,6 +62,9 @@ type ServiceDetail struct {
// PodList represents list of pods targeted by same label selector as this service.
PodList pod.PodList `json:"podList"`

// Array of composed userlinks that have been derived from service annotation.
UserLink []userlinks.UserLink `json:"userLinks"`

// Show the value of the SessionAffinity of the Service.
SessionAffinity v1.ServiceAffinity `json:"sessionAffinity"`

Expand All @@ -69,7 +73,7 @@ type ServiceDetail struct {
}

// GetServiceDetail gets service details.
func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricClient, namespace, name string,
func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricClient, namespace, name, host string,
dsQuery *dataselect.DataSelectQuery) (*ServiceDetail, error) {

log.Printf("Getting details of %s service in %s namespace", name, namespace)
Expand All @@ -84,6 +88,12 @@ func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricC
return nil, criticalError
}

userLinks, err := userlinks.GetUserLinks(client, namespace, name, api.ResourceKindService, host)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}

podList, err := GetServicePods(client, metricClient, namespace, name, dsQuery)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
Expand All @@ -96,6 +106,6 @@ func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricC
return nil, criticalError
}

service := ToServiceDetail(serviceData, *eventList, *podList, *endpointList, nonCriticalErrors)
service := ToServiceDetail(serviceData, *eventList, *podList, *endpointList, userLinks, nonCriticalErrors)
return &service, nil
}
23 changes: 13 additions & 10 deletions src/app/backend/resource/service/detail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,25 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/endpoint"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/userlinks"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/pkg/api/v1"
)

func TestGetServiceDetail(t *testing.T) {
cases := []struct {
service *v1.Service
namespace, name string
expectedActions []string
expected *ServiceDetail
service *v1.Service
namespace, name, host string
expectedActions []string
expected *ServiceDetail
}{
{
service: &v1.Service{ObjectMeta: metaV1.ObjectMeta{
Name: "svc-1", Namespace: "ns-1", Labels: map[string]string{},
}},
namespace: "ns-1", name: "svc-1",
expectedActions: []string{"get", "list", "get", "list"},
namespace: "ns-1", name: "svc-1", host: "http://localhost:8080",
expectedActions: []string{"get", "list", "get", "get", "list"},
expected: &ServiceDetail{
ObjectMeta: api.ObjectMeta{
Name: "svc-1",
Expand All @@ -60,7 +61,8 @@ func TestGetServiceDetail(t *testing.T) {
EndpointList: endpoint.EndpointList{
Endpoints: []endpoint.Endpoint{},
},
Errors: []error{},
UserLink: []userlinks.UserLink{},
Errors: []error{},
},
},
{
Expand All @@ -74,7 +76,7 @@ func TestGetServiceDetail(t *testing.T) {
},
},
namespace: "ns-2", name: "svc-2",
expectedActions: []string{"get", "list", "get", "list", "list", "list"},
expectedActions: []string{"get", "list", "get", "get", "list", "list", "list"},
expected: &ServiceDetail{
ObjectMeta: api.ObjectMeta{
Name: "svc-2",
Expand All @@ -94,14 +96,15 @@ func TestGetServiceDetail(t *testing.T) {
EndpointList: endpoint.EndpointList{
Endpoints: []endpoint.Endpoint{},
},
Errors: []error{},
UserLink: []userlinks.UserLink{},
Errors: []error{},
},
},
}

for _, c := range cases {
fakeClient := fake.NewSimpleClientset(c.service)
actual, _ := GetServiceDetail(fakeClient, nil, c.namespace, c.name, dataselect.NoDataSelect)
actual, _ := GetServiceDetail(fakeClient, nil, c.namespace, c.name, c.host, dataselect.NoDataSelect)
actions := fakeClient.Actions()

if len(actions) != len(c.expectedActions) {
Expand Down
Loading