提交 d7b849ef 编写于 作者: M Marcin Maciaszczyk 提交者: Kubernetes Prow Robot

Simplify backend code (#3617)

* Simplify config maps

* Simplify cluster roles

* Simplify cron jobs

* Simplify daemon sets

* Switch to apps/v1
Simplify deployments

* Simplify storage class

* Simplify stateful set

* Simplify service

* Simplify secret

* Simplify replication controller

* Simplify horizontal pod autoscaler

* Simplify ingress
Simplify job

* Simplify namespace

* Finish simplifying packages

* Fix most of the tests

* Format files

* Fix tests

* Fix tests

* Finish fixing tests

* Revert changes in package.json
上级 587f96a3
......@@ -196,7 +196,7 @@ func (self *clientManager) VerberClient(req *restful.Request) (clientapi.Resourc
}
return NewResourceVerber(client.CoreV1().RESTClient(),
client.ExtensionsV1beta1().RESTClient(), client.AppsV1beta2().RESTClient(),
client.ExtensionsV1beta1().RESTClient(), client.AppsV1().RESTClient(),
client.BatchV1().RESTClient(), client.BatchV1beta1().RESTClient(), client.AutoscalingV1().RESTClient(),
client.StorageV1().RESTClient(), client.RbacV1().RESTClient()), nil
}
......
......@@ -729,9 +729,7 @@ func (apiHandler *APIHandler) handleGetServiceDetail(request *restful.Request, r
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, namespace, name)
if err != nil {
kdErrors.HandleInternalError(response, err)
return
......@@ -1210,7 +1208,7 @@ func (apiHandler *APIHandler) handleGetDeploymentDetail(request *restful.Request
namespace := request.PathParameter("namespace")
name := request.PathParameter("deployment")
result, err := deployment.GetDeploymentDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name)
result, err := deployment.GetDeploymentDetail(k8sClient, namespace, name)
if err != nil {
kdErrors.HandleInternalError(response, err)
return
......@@ -1300,7 +1298,7 @@ func (apiHandler *APIHandler) handleGetReplicationControllerDetail(request *rest
namespace := request.PathParameter("namespace")
name := request.PathParameter("replicationController")
result, err := replicationcontroller.GetReplicationControllerDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name)
result, err := replicationcontroller.GetReplicationControllerDetail(k8sClient, namespace, name)
if err != nil {
kdErrors.HandleInternalError(response, err)
return
......@@ -1845,7 +1843,7 @@ func (apiHandler *APIHandler) handleGetJobDetail(request *restful.Request, respo
name := request.PathParameter("name")
dataSelect := parseDataSelectPathParameter(request)
dataSelect.MetricQuery = dataselect.StandardMetrics
result, err := job.GetJobDetail(k8sClient, apiHandler.iManager.Metric().Client(), namespace, name)
result, err := job.GetJobDetail(k8sClient, namespace, name)
if err != nil {
kdErrors.HandleInternalError(response, err)
return
......
......@@ -22,11 +22,11 @@ import (
// ClusterRoleDetail contains Cron Job details.
type ClusterRoleDetail struct {
Rules []rbac.PolicyRule `json:"rules"`
// Extends list item structure.
ClusterRole `json:",inline"`
Rules []rbac.PolicyRule `json:"rules"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
......
......@@ -15,7 +15,7 @@
package common
import (
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
batch "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
......
......@@ -16,7 +16,7 @@ package common
import (
"github.com/kubernetes/dashboard/src/app/backend/api"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
autoscaling "k8s.io/api/autoscaling/v1"
batch "k8s.io/api/batch/v1"
batch2 "k8s.io/api/batch/v1beta1"
......@@ -425,7 +425,7 @@ func GetDeploymentListChannel(client client.Interface,
}
go func() {
list, err := client.AppsV1beta2().Deployments(nsQuery.ToRequestParam()).
list, err := client.AppsV1().Deployments(nsQuery.ToRequestParam()).
List(api.ListEverything)
var filteredItems []apps.Deployment
for _, item := range list.Items {
......@@ -466,7 +466,7 @@ func GetReplicaSetListChannelWithOptions(client client.Interface, nsQuery *Names
}
go func() {
list, err := client.AppsV1beta2().ReplicaSets(nsQuery.ToRequestParam()).
list, err := client.AppsV1().ReplicaSets(nsQuery.ToRequestParam()).
List(options)
var filteredItems []apps.ReplicaSet
for _, item := range list.Items {
......@@ -499,7 +499,7 @@ func GetDaemonSetListChannel(client client.Interface, nsQuery *NamespaceQuery, n
}
go func() {
list, err := client.AppsV1beta2().DaemonSets(nsQuery.ToRequestParam()).List(api.ListEverything)
list, err := client.AppsV1().DaemonSets(nsQuery.ToRequestParam()).List(api.ListEverything)
var filteredItems []apps.DaemonSet
for _, item := range list.Items {
if nsQuery.Matches(item.ObjectMeta.Namespace) {
......@@ -595,7 +595,7 @@ func GetStatefulSetListChannel(client client.Interface,
}
go func() {
statefulSets, err := client.AppsV1beta2().StatefulSets(nsQuery.ToRequestParam()).List(api.ListEverything)
statefulSets, err := client.AppsV1().StatefulSets(nsQuery.ToRequestParam()).List(api.ListEverything)
var filteredItems []apps.StatefulSet
for _, item := range statefulSets.Items {
if nsQuery.Matches(item.ObjectMeta.Namespace) {
......
......@@ -17,7 +17,6 @@ package configmap
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
......@@ -26,8 +25,8 @@ import (
// ConfigMapDetail API resource provides mechanisms to inject containers with configuration data while keeping
// containers agnostic of Kubernetes
type ConfigMapDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
ConfigMap `json:",inline"`
// Data contains the configuration data.
// Each key must be a valid DNS_SUBDOMAIN with an optional leading dot.
......@@ -49,8 +48,7 @@ func GetConfigMapDetail(client kubernetes.Interface, namespace, name string) (*C
func getConfigMapDetail(rawConfigMap *v1.ConfigMap) *ConfigMapDetail {
return &ConfigMapDetail{
ObjectMeta: api.NewObjectMeta(rawConfigMap.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindConfigMap),
Data: rawConfigMap.Data,
ConfigMap: toConfigMap(rawConfigMap.ObjectMeta),
Data: rawConfigMap.Data,
}
}
......@@ -33,9 +33,11 @@ func TestGetConfigMapDetail(t *testing.T) {
Data: map[string]string{"app": "my-name"}, ObjectMeta: metaV1.ObjectMeta{Name: "foo"},
},
&ConfigMapDetail{
TypeMeta: api.TypeMeta{Kind: "configmap"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
Data: map[string]string{"app": "my-name"},
ConfigMap: ConfigMap{
TypeMeta: api.TypeMeta{Kind: "configmap"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
},
Data: map[string]string{"app": "my-name"},
},
},
}
......
......@@ -21,7 +21,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
batch "k8s.io/api/batch/v1"
v1 "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
......@@ -77,7 +77,7 @@ func NewResourceController(ref meta.OwnerReference, namespace string, client cli
}
return PodController(*pod), nil
case api.ResourceKindReplicaSet:
rs, err := client.AppsV1beta2().ReplicaSets(namespace).Get(ref.Name, meta.GetOptions{})
rs, err := client.AppsV1().ReplicaSets(namespace).Get(ref.Name, meta.GetOptions{})
if err != nil {
return nil, err
}
......@@ -89,13 +89,13 @@ func NewResourceController(ref meta.OwnerReference, namespace string, client cli
}
return ReplicationControllerController(*rc), nil
case api.ResourceKindDaemonSet:
ds, err := client.AppsV1beta2().DaemonSets(namespace).Get(ref.Name, meta.GetOptions{})
ds, err := client.AppsV1().DaemonSets(namespace).Get(ref.Name, meta.GetOptions{})
if err != nil {
return nil, err
}
return DaemonSetController(*ds), nil
case api.ResourceKindStatefulSet:
ss, err := client.AppsV1beta2().StatefulSets(namespace).Get(ref.Name, meta.GetOptions{})
ss, err := client.AppsV1().StatefulSets(namespace).Get(ref.Name, meta.GetOptions{})
if err != nil {
return nil, err
}
......
......@@ -22,12 +22,12 @@ import (
// CronJobDetail contains Cron Job details.
type CronJobDetail struct {
ConcurrencyPolicy string `json:"concurrencyPolicy"`
StartingDeadLineSeconds *int64 `json:"startingDeadlineSeconds"`
// Extends list item structure.
CronJob `json:",inline"`
ConcurrencyPolicy string `json:"concurrencyPolicy"`
StartingDeadLineSeconds *int64 `json:"startingDeadlineSeconds"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
......
......@@ -20,7 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
......@@ -34,7 +34,7 @@ import (
func GetServicesForDSDeletion(client client.Interface, labelSelector labels.Selector,
namespace string) ([]v1.Service, error) {
daemonSet, err := client.AppsV1beta2().DaemonSets(namespace).List(metaV1.ListOptions{
daemonSet, err := client.AppsV1().DaemonSets(namespace).List(metaV1.ListOptions{
LabelSelector: labelSelector.String(),
FieldSelector: fields.Everything().String(),
})
......
......@@ -17,7 +17,7 @@ package daemonset
import (
"testing"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
api "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
......
......@@ -17,14 +17,8 @@ package daemonset
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
ds "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
resourceService "github.com/kubernetes/dashboard/src/app/backend/resource/service"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
......@@ -32,33 +26,11 @@ import (
// DaemonSeDetail represents detailed information about a Daemon Set.
type DaemonSetDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
DaemonSet `json:",inline"`
// Label selector of the Daemon Set.
LabelSelector *v1.LabelSelector `json:"labelSelector,omitempty"`
// Container image list of the pod template specified by this Daemon Set.
ContainerImages []string `json:"containerImages"`
// Init Container image list of the pod template specified by this Daemon Set.
InitContainerImages []string `json:"initContainerImages"`
// Aggregate information about pods of this daemon set.
PodInfo common.PodInfo `json:"podInfo"`
// Detailed information about Pods belonging to this Daemon Set.
PodList pod.PodList `json:"podList"`
// Detailed information about service related to Daemon Set.
ServiceList resourceService.ServiceList `json:"serviceList"`
// True when the data contains at least one pod with metrics information, false otherwise.
HasMetrics bool `json:"hasMetrics"`
// List of events related to this daemon set
EventList common.EventList `json:"eventList"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
......@@ -68,53 +40,29 @@ func GetDaemonSetDetail(client k8sClient.Interface, metricClient metricapi.Metri
namespace, name string) (*DaemonSetDetail, error) {
log.Printf("Getting details of %s daemon set in %s namespace", name, namespace)
daemonSet, err := client.AppsV1beta2().DaemonSets(namespace).Get(name, metaV1.GetOptions{})
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
podList, err := GetDaemonSetPods(client, metricClient, ds.DefaultDataSelectWithMetrics, name, namespace)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
podInfo, err := getDaemonSetPodInfo(client, daemonSet)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
channels := &common.ResourceChannels{
EventList: common.GetEventListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
PodList: common.GetPodListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
}
serviceList, err := GetDaemonSetServices(client, ds.DefaultDataSelect, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
eventList := <-channels.EventList.List
if err := <-channels.EventList.Error; err != nil {
return nil, err
}
eventList, err := event.GetResourceEvents(client, ds.DefaultDataSelect, daemonSet.Namespace, daemonSet.Name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
podList := <-channels.PodList.List
if err := <-channels.PodList.Error; err != nil {
return nil, err
}
daemonSetDetail := &DaemonSetDetail{
ObjectMeta: api.NewObjectMeta(daemonSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDaemonSet),
return &DaemonSetDetail{
DaemonSet: toDaemonSet(*daemonSet, podList.Items, eventList.Items),
LabelSelector: daemonSet.Spec.Selector,
PodInfo: *podInfo,
PodList: *podList,
ServiceList: *serviceList,
EventList: *eventList,
Errors: nonCriticalErrors,
}
for _, container := range daemonSet.Spec.Template.Spec.Containers {
daemonSetDetail.ContainerImages = append(daemonSetDetail.ContainerImages, container.Image)
}
for _, initContainer := range daemonSet.Spec.Template.Spec.InitContainers {
daemonSetDetail.InitContainerImages = append(daemonSetDetail.InitContainerImages, initContainer.Image)
}
return daemonSetDetail, nil
Errors: []error{},
}, nil
}
......@@ -21,19 +21,17 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)
// DaemonSetList contains a list of Daemon Sets in the cluster.
type DaemonSetList struct {
ListMeta api.ListMeta `json:"listMeta"`
DaemonSets []DaemonSet `json:"daemonSets"`
CumulativeMetrics []metricapi.Metric `json:"cumulativeMetrics"`
// Basic information about resources status on the list.
Status common.ResourceStatus `json:"status"`
ListMeta api.ListMeta `json:"listMeta"`
DaemonSets []DaemonSet `json:"daemonSets"`
CumulativeMetrics []metricapi.Metric `json:"cumulativeMetrics"`
Status common.ResourceStatus `json:"status"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
......@@ -41,17 +39,11 @@ type DaemonSetList struct {
// DaemonSet plus zero or more Kubernetes services that target the Daemon Set.
type DaemonSet struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Daemon Set.
Pods common.PodInfo `json:"pods"`
// Container images of the Daemon Set.
ContainerImages []string `json:"containerImages"`
// InitContainer images of the Daemon Set.
InitContainerImages []string `json:"initContainerImages"`
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Pods common.PodInfo `json:"podInfo"`
ContainerImages []string `json:"containerImages"`
InitContainerImages []string `json:"initContainerImages"`
}
// GetDaemonSetList returns a list of all Daemon Set in the cluster.
......@@ -116,19 +108,8 @@ func toDaemonSetList(daemonSets []apps.DaemonSet, pods []v1.Pod, events []v1.Eve
daemonSets = FromCells(dsCells)
daemonSetList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for i, daemonSet := range daemonSets {
matchingPods := common.FilterPodsByControllerRef(&daemonSet, pods)
podInfo := common.GetPodInfo(daemonSet.Status.CurrentNumberScheduled,
&daemonSets[i].Status.DesiredNumberScheduled, matchingPods)
podInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods)
daemonSetList.DaemonSets = append(daemonSetList.DaemonSets, DaemonSet{
ObjectMeta: api.NewObjectMeta(daemonSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDaemonSet),
Pods: podInfo,
ContainerImages: common.GetContainerImages(&daemonSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&daemonSet.Spec.Template.Spec),
})
for _, daemonSet := range daemonSets {
daemonSetList.DaemonSets = append(daemonSetList.DaemonSets, toDaemonSet(daemonSet, pods, events))
}
cumulativeMetrics, err := metricPromises.GetMetrics()
......@@ -139,3 +120,17 @@ func toDaemonSetList(daemonSets []apps.DaemonSet, pods []v1.Pod, events []v1.Eve
return daemonSetList
}
func toDaemonSet(daemonSet apps.DaemonSet, pods []v1.Pod, events []v1.Event) DaemonSet {
matchingPods := common.FilterPodsByControllerRef(&daemonSet, pods)
podInfo := common.GetPodInfo(daemonSet.Status.CurrentNumberScheduled, &daemonSet.Status.DesiredNumberScheduled, matchingPods)
podInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods)
return DaemonSet{
ObjectMeta: api.NewObjectMeta(daemonSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDaemonSet),
Pods: podInfo,
ContainerImages: common.GetContainerImages(&daemonSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&daemonSet.Spec.Template.Spec),
}
}
......@@ -23,7 +23,7 @@ import (
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......@@ -393,8 +393,7 @@ func TestToDaemonSetList(t *testing.T) {
for _, c := range cases {
actual := toDaemonSetList(c.daemonSets, c.pods, events, nil, dataselect.NoDataSelect, nil)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("toDaemonSetList(%#v, %#v, %#v) == \n%#v\nexpected \n%#v\n",
c.daemonSets, c.services, events, actual, c.expected)
t.Errorf("toDaemonSetList(%#v, %#v, %#v) == \n%#v\nexpected \n%#v\n", c.daemonSets, c.services, events, actual, c.expected)
}
}
}
......@@ -23,7 +23,6 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
apps "k8s.io/api/apps/v1beta2"
api "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
......@@ -51,7 +50,7 @@ func GetDaemonSetPods(client k8sClient.Interface, metricClient metricapi.MetricC
// Returns array of api pods targeting daemon set with given name.
func getRawDaemonSetPods(client k8sClient.Interface, daemonSetName, namespace string) ([]api.Pod, error) {
daemonSet, err := client.AppsV1beta2().DaemonSets(namespace).Get(daemonSetName, metaV1.GetOptions{})
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(daemonSetName, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......@@ -68,17 +67,3 @@ func getRawDaemonSetPods(client k8sClient.Interface, daemonSetName, namespace st
matchingPods := common.FilterPodsByControllerRef(daemonSet, podList.Items)
return matchingPods, nil
}
// Returns simple info about pods(running, desired, failing, etc.) related to given daemon set.
func getDaemonSetPodInfo(client k8sClient.Interface, daemonSet *apps.DaemonSet) (
*common.PodInfo, error) {
pods, err := getRawDaemonSetPods(client, daemonSet.Name, daemonSet.Namespace)
if err != nil {
return nil, err
}
podInfo := common.GetPodInfo(daemonSet.Status.CurrentNumberScheduled,
&daemonSet.Status.DesiredNumberScheduled, pods)
return &podInfo, nil
}
......@@ -28,7 +28,7 @@ import (
func GetDaemonSetServices(client client.Interface, dsQuery *dataselect.DataSelectQuery,
namespace, name string) (*service.ServiceList, error) {
daemonSet, err := client.AppsV1beta2().DaemonSets(namespace).Get(name, metaV1.GetOptions{})
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......
......@@ -20,7 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
......
......@@ -21,7 +21,7 @@ import (
"strings"
"github.com/kubernetes/dashboard/src/app/backend/errors"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......@@ -222,7 +222,7 @@ func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
},
},
}
_, err := client.AppsV1beta2().Deployments(spec.Namespace).Create(deployment)
_, err := client.AppsV1().Deployments(spec.Namespace).Create(deployment)
if err != nil {
// TODO(bryk): Roll back created resources in case of error.
......@@ -345,7 +345,7 @@ func DeployAppFromFile(cfg *rest.Config, spec *AppDeploymentFromFileSpec) (bool,
}
}
if resource == nil {
return false, fmt.Errorf("Unknown resource kind: %s", kind)
return false, fmt.Errorf("unknown resource kind: %s", kind)
}
dynamicClient, err := dynamic.NewForConfig(cfg)
......
......@@ -19,7 +19,7 @@ import (
"regexp"
"testing"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
api "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......
......@@ -17,16 +17,9 @@ package deployment
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
hpa "github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/resource/replicaset"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
client "k8s.io/client-go/kubernetes"
......@@ -55,11 +48,8 @@ type StatusInfo struct {
// DeploymentDetail is a presentation layer view of Kubernetes Deployment resource.
type DeploymentDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Detailed information about Pods belonging to this Deployment.
PodList pod.PodList `json:"podList"`
// Extends list item structure.
Deployment `json:",inline"`
// Label selector of the service.
Selector map[string]string `json:"selector"`
......@@ -80,32 +70,19 @@ type DeploymentDetail struct {
// Rolling update strategy containing maxSurge and maxUnavailable
RollingUpdateStrategy *RollingUpdateStrategy `json:"rollingUpdateStrategy,omitempty"`
// RepliaSetList containing old replica sets from the deployment
OldReplicaSetList replicaset.ReplicaSetList `json:"oldReplicaSetList"`
// New replica set used by this deployment
NewReplicaSet replicaset.ReplicaSet `json:"newReplicaSet"`
// Optional field that specifies the number of old Replica Sets to retain to allow rollback.
RevisionHistoryLimit *int32 `json:"revisionHistoryLimit"`
// List of events related to this Deployment
EventList common.EventList `json:"eventList"`
// List of Horizontal Pod AutoScalers targeting this Deployment
HorizontalPodAutoscalerList hpa.HorizontalPodAutoscalerList `json:"horizontalPodAutoscalerList"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
// GetDeploymentDetail returns model object of deployment and error, if any.
func GetDeploymentDetail(client client.Interface, metricClient metricapi.MetricClient, namespace string,
deploymentName string) (*DeploymentDetail, error) {
func GetDeploymentDetail(client client.Interface, namespace string, deploymentName string) (*DeploymentDetail, error) {
log.Printf("Getting details of %s deployment in %s namespace", deploymentName, namespace)
deployment, err := client.AppsV1beta2().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
deployment, err := client.AppsV1().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......@@ -121,6 +98,8 @@ func GetDeploymentDetail(client client.Interface, metricClient metricapi.MetricC
common.NewSameNamespaceQuery(namespace), options, 1),
PodList: common.GetPodListChannelWithOptions(client,
common.NewSameNamespaceQuery(namespace), options, 1),
EventList: common.GetEventListChannelWithOptions(client,
common.NewSameNamespaceQuery(namespace), options, 1),
}
rawRs := <-channels.ReplicaSetList.List
......@@ -137,54 +116,13 @@ func GetDeploymentDetail(client client.Interface, metricClient metricapi.MetricC
return nil, criticalError
}
podList, err := GetDeploymentPods(client, metricClient, dataselect.DefaultDataSelectWithMetrics, namespace, deploymentName)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
eventList, err := event.GetResourceEvents(client, dataselect.DefaultDataSelect, namespace, deploymentName)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
hpas, err := hpa.GetHorizontalPodAutoscalerListForResource(client, namespace, "Deployment", deploymentName)
rawEvents := <-channels.EventList.List
err = <-channels.EventList.Error
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
oldReplicaSetList, err := GetDeploymentOldReplicaSets(client, dataselect.DefaultDataSelect, namespace, deploymentName)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
rawRepSets := make([]*apps.ReplicaSet, 0)
for i := range rawRs.Items {
rawRepSets = append(rawRepSets, &rawRs.Items[i])
}
newRs, err := FindNewReplicaSet(deployment, rawRepSets)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
var newReplicaSet replicaset.ReplicaSet
if newRs != nil {
matchingPods := common.FilterPodsByControllerRef(newRs, rawPods.Items)
newRsPodInfo := common.GetPodInfo(newRs.Status.Replicas, newRs.Spec.Replicas, matchingPods)
events, err := event.GetPodsEvents(client, namespace, matchingPods)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
newRsPodInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods)
newReplicaSet = replicaset.ToReplicaSet(newRs, &newRsPodInfo)
}
// Extra Info
var rollingUpdateStrategy *RollingUpdateStrategy
if deployment.Spec.Strategy.RollingUpdate != nil {
......@@ -195,23 +133,16 @@ func GetDeploymentDetail(client client.Interface, metricClient metricapi.MetricC
}
return &DeploymentDetail{
ObjectMeta: api.NewObjectMeta(deployment.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDeployment),
PodList: *podList,
Selector: deployment.Spec.Selector.MatchLabels,
StatusInfo: GetStatusInfo(&deployment.Status),
Conditions: getConditions(deployment.Status.Conditions),
Strategy: deployment.Spec.Strategy.Type,
MinReadySeconds: deployment.Spec.MinReadySeconds,
RollingUpdateStrategy: rollingUpdateStrategy,
OldReplicaSetList: *oldReplicaSetList,
NewReplicaSet: newReplicaSet,
RevisionHistoryLimit: deployment.Spec.RevisionHistoryLimit,
EventList: *eventList,
HorizontalPodAutoscalerList: *hpas,
Errors: nonCriticalErrors,
Deployment: toDeployment(deployment, rawRs.Items, rawPods.Items, rawEvents.Items),
Selector: deployment.Spec.Selector.MatchLabels,
StatusInfo: GetStatusInfo(&deployment.Status),
Conditions: getConditions(deployment.Status.Conditions),
Strategy: deployment.Spec.Strategy.Type,
MinReadySeconds: deployment.Spec.MinReadySeconds,
RollingUpdateStrategy: rollingUpdateStrategy,
RevisionHistoryLimit: deployment.Spec.RevisionHistoryLimit,
Errors: nonCriticalErrors,
}, nil
}
func GetStatusInfo(deploymentStatus *apps.DeploymentStatus) StatusInfo {
......
......@@ -19,14 +19,10 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/resource/replicaset"
apps "k8s.io/api/apps/v1beta2"
v1 "k8s.io/api/core/v1"
apps "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/kubernetes/fake"
......@@ -78,15 +74,14 @@ func createReplicaSet(name, namespace string, replicas int32, labelSelector map[
func TestGetDeploymentDetail(t *testing.T) {
podList := &v1.PodList{}
eventList := &v1.EventList{}
var desired int32 = 4
var replicas int32 = 4
deployment := createDeployment("dp-1", "ns-1", "pod-1", replicas,
map[string]string{"track": "beta"}, map[string]string{"foo": "bar"})
podTemplateSpec := GetNewReplicaSetTemplate(deployment)
newReplicaSet := createReplicaSet("rs-1", "ns-1", replicas, map[string]string{"foo": "bar"},
podTemplateSpec)
newReplicaSet := createReplicaSet("rs-1", "ns-1", replicas, map[string]string{"foo": "bar"}, podTemplateSpec)
replicaSetList := &apps.ReplicaSetList{
Items: []apps.ReplicaSet{
......@@ -107,19 +102,24 @@ func TestGetDeploymentDetail(t *testing.T) {
}{
{
"ns-1", "dp-1",
[]string{"get", "list", "list", "get", "list", "list", "list", "list", "list", "get", "list", "list", "list", "list"},
[]string{"get", "list", "list", "list"},
deployment,
&DeploymentDetail{
ObjectMeta: api.ObjectMeta{
Name: "dp-1",
Namespace: "ns-1",
Labels: map[string]string{"foo": "bar"},
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindDeployment},
PodList: pod.PodList{
Pods: []pod.Pod{},
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: []error{},
Deployment: Deployment{
ObjectMeta: api.ObjectMeta{
Name: "dp-1",
Namespace: "ns-1",
Labels: map[string]string{"foo": "bar"},
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindDeployment},
Pods: common.PodInfo{
Desired: &desired,
Current: 4,
Running: 0,
Failed: 0,
Pending: 0,
Warnings: []common.Event{},
},
},
Selector: map[string]string{"foo": "bar"},
StatusInfo: StatusInfo{
......@@ -135,27 +135,6 @@ func TestGetDeploymentDetail(t *testing.T) {
MaxSurge: &maxSurge,
MaxUnavailable: &maxUnavailable,
},
OldReplicaSetList: replicaset.ReplicaSetList{
ReplicaSets: []replicaset.ReplicaSet{},
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: []error{},
},
NewReplicaSet: replicaset.ReplicaSet{
ObjectMeta: api.NewObjectMeta(newReplicaSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindReplicaSet),
Pods: common.PodInfo{
Warnings: []common.Event{},
Desired: &replicas,
},
},
EventList: common.EventList{
Events: []common.Event{},
Errors: []error{},
},
HorizontalPodAutoscalerList: horizontalpodautoscaler.HorizontalPodAutoscalerList{
HorizontalPodAutoscalers: []horizontalpodautoscaler.HorizontalPodAutoscaler{},
Errors: []error{},
},
Errors: []error{},
},
},
......@@ -164,7 +143,7 @@ func TestGetDeploymentDetail(t *testing.T) {
for _, c := range cases {
fakeClient := fake.NewSimpleClientset(c.deployment, replicaSetList, podList, eventList)
dataselect.DefaultDataSelectWithMetrics.MetricQuery = dataselect.NoMetrics
actual, _ := GetDeploymentDetail(fakeClient, nil, c.namespace, c.name)
actual, _ := GetDeploymentDetail(fakeClient, c.namespace, c.name)
actions := fakeClient.Actions()
if len(actions) != len(c.expectedActions) {
......
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
client "k8s.io/client-go/kubernetes"
)
......@@ -132,18 +132,7 @@ func toDeploymentList(deployments []apps.Deployment, pods []v1.Pod, events []v1.
deploymentList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, deployment := range deployments {
matchingPods := common.FilterDeploymentPodsByOwnerReference(deployment, rs, pods)
podInfo := common.GetPodInfo(deployment.Status.Replicas, deployment.Spec.Replicas, matchingPods)
podInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods)
deploymentList.Deployments = append(deploymentList.Deployments,
Deployment{
ObjectMeta: api.NewObjectMeta(deployment.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDeployment),
ContainerImages: common.GetContainerImages(&deployment.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&deployment.Spec.Template.Spec),
Pods: podInfo,
})
deploymentList.Deployments = append(deploymentList.Deployments, toDeployment(&deployment, rs, pods, events))
}
cumulativeMetrics, err := metricPromises.GetMetrics()
......@@ -154,3 +143,17 @@ func toDeploymentList(deployments []apps.Deployment, pods []v1.Pod, events []v1.
return deploymentList
}
func toDeployment(deployment *apps.Deployment, rs []apps.ReplicaSet, pods []v1.Pod, events []v1.Event) Deployment {
matchingPods := common.FilterDeploymentPodsByOwnerReference(*deployment, rs, pods)
podInfo := common.GetPodInfo(deployment.Status.Replicas, deployment.Spec.Replicas, matchingPods)
podInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods)
return Deployment{
ObjectMeta: api.NewObjectMeta(deployment.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindDeployment),
Pods: podInfo,
ContainerImages: common.GetContainerImages(&deployment.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&deployment.Spec.Template.Spec),
}
}
......@@ -23,7 +23,7 @@ import (
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......
......@@ -20,7 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/replicaset"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
client "k8s.io/client-go/kubernetes"
)
......@@ -34,7 +34,7 @@ func GetDeploymentOldReplicaSets(client client.Interface, dsQuery *dataselect.Da
ListMeta: api.ListMeta{TotalItems: 0},
}
deployment, err := client.AppsV1beta2().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
deployment, err := client.AppsV1().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
if err != nil {
return oldReplicaSetList, err
}
......
......@@ -29,7 +29,7 @@ import (
func GetDeploymentPods(client client.Interface, metricClient metricapi.MetricClient,
dsQuery *dataselect.DataSelectQuery, namespace, deploymentName string) (*pod.PodList, error) {
deployment, err := client.AppsV1beta2().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
deployment, err := client.AppsV1().Deployments(namespace).Get(deploymentName, metaV1.GetOptions{})
if err != nil {
return pod.EmptyPodList, err
}
......
......@@ -16,7 +16,7 @@ package deployment
import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
......
......@@ -21,7 +21,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
......
......@@ -32,7 +32,6 @@ var FailedReasonPartials = []string{"failed", "err", "exceeded", "invalid", "unh
"mismatch", "insufficient", "conflict", "outof", "nil", "backoff"}
// GetPodsEventWarnings returns warning pod events by filtering out events targeting only given pods
// TODO(floreks) : Import and use Set instead of custom function to get rid of duplicates
func GetPodsEventWarnings(events []api.Event, pods []api.Pod) []common.Event {
result := make([]common.Event, 0)
......
......@@ -17,30 +17,19 @@ package horizontalpodautoscaler
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
autoscaling "k8s.io/api/autoscaling/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
client "k8s.io/client-go/kubernetes"
)
// HorizontalPodAutoscalerDetail provides the presentation layer view of Kubernetes Horizontal Pod Autoscaler resource.
// close mapping of the autoscaling.HorizontalPodAutoscaler type with part of the *Spec and *Detail childs
type HorizontalPodAutoscalerDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
HorizontalPodAutoscaler `json:",inline"`
ScaleTargetRef ScaleTargetRef `json:"scaleTargetRef"`
MinReplicas *int32 `json:"minReplicas"`
MaxReplicas int32 `json:"maxReplicas"`
CurrentCPUUtilizationPercentage *int32 `json:"currentCPUUtilizationPercentage"`
TargetCPUUtilizationPercentage *int32 `json:"targetCPUUtilizationPercentage"`
CurrentReplicas int32 `json:"currentReplicas"`
DesiredReplicas int32 `json:"desiredReplicas"`
LastScaleTime *v1.Time `json:"lastScaleTime"`
CurrentReplicas int32 `json:"currentReplicas"`
DesiredReplicas int32 `json:"desiredReplicas"`
LastScaleTime *v1.Time `json:"lastScaleTime"`
}
// GetHorizontalPodAutoscalerDetail returns detailed information about a horizontal pod autoscaler
......@@ -48,7 +37,6 @@ func GetHorizontalPodAutoscalerDetail(client client.Interface, namespace string,
log.Printf("Getting details of %s horizontal pod autoscaler", name)
rawHorizontalPodAutoscaler, err := client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, v1.GetOptions{})
if err != nil {
return nil, err
}
......@@ -56,25 +44,11 @@ func GetHorizontalPodAutoscalerDetail(client client.Interface, namespace string,
return getHorizontalPodAutoscalerDetail(rawHorizontalPodAutoscaler), nil
}
func getHorizontalPodAutoscalerDetail(horizontalPodAutoscaler *autoscaling.HorizontalPodAutoscaler) *HorizontalPodAutoscalerDetail {
func getHorizontalPodAutoscalerDetail(hpa *autoscaling.HorizontalPodAutoscaler) *HorizontalPodAutoscalerDetail {
return &HorizontalPodAutoscalerDetail{
ObjectMeta: api.NewObjectMeta(horizontalPodAutoscaler.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindHorizontalPodAutoscaler),
ScaleTargetRef: ScaleTargetRef{
Kind: horizontalPodAutoscaler.Spec.ScaleTargetRef.Kind,
Name: horizontalPodAutoscaler.Spec.ScaleTargetRef.Name,
},
MinReplicas: horizontalPodAutoscaler.Spec.MinReplicas,
MaxReplicas: horizontalPodAutoscaler.Spec.MaxReplicas,
CurrentCPUUtilizationPercentage: horizontalPodAutoscaler.Status.CurrentCPUUtilizationPercentage,
TargetCPUUtilizationPercentage: horizontalPodAutoscaler.Spec.TargetCPUUtilizationPercentage,
CurrentReplicas: horizontalPodAutoscaler.Status.CurrentReplicas,
DesiredReplicas: horizontalPodAutoscaler.Status.DesiredReplicas,
LastScaleTime: horizontalPodAutoscaler.Status.LastScaleTime,
HorizontalPodAutoscaler: toHorizontalPodAutoScaler(hpa),
CurrentReplicas: hpa.Status.CurrentReplicas,
DesiredReplicas: hpa.Status.DesiredReplicas,
LastScaleTime: hpa.Status.LastScaleTime,
}
}
......@@ -51,13 +51,15 @@ func TestGetHorizontalPodAutoscalerDetail(t *testing.T) {
},
},
&HorizontalPodAutoscalerDetail{
ObjectMeta: api.ObjectMeta{Name: "test-name", Namespace: "test-ns"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindHorizontalPodAutoscaler},
ScaleTargetRef: ScaleTargetRef{
Kind: "test-kind",
Name: "test-name2",
HorizontalPodAutoscaler: HorizontalPodAutoscaler{
ObjectMeta: api.ObjectMeta{Name: "test-name", Namespace: "test-ns"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindHorizontalPodAutoscaler},
ScaleTargetRef: ScaleTargetRef{
Kind: "test-kind",
Name: "test-name2",
},
MaxReplicas: 3,
},
MaxReplicas: 3,
CurrentReplicas: 1,
DesiredReplicas: 2,
},
......
......@@ -17,7 +17,6 @@ package ingress
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
extensions "k8s.io/api/extensions/v1beta1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
client "k8s.io/client-go/kubernetes"
......@@ -26,10 +25,9 @@ import (
// IngressDetail API resource provides mechanisms to inject containers with configuration data while keeping
// containers agnostic of Kubernetes
type IngressDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
Ingress `json:",inline"`
// TODO(bryk): replace this with UI specific fields.
// Spec is the desired state of the Ingress.
Spec extensions.IngressSpec `json:"spec"`
......@@ -53,11 +51,10 @@ func GetIngressDetail(client client.Interface, namespace, name string) (*Ingress
return getIngressDetail(rawIngress), nil
}
func getIngressDetail(rawIngress *extensions.Ingress) *IngressDetail {
func getIngressDetail(i *extensions.Ingress) *IngressDetail {
return &IngressDetail{
ObjectMeta: api.NewObjectMeta(rawIngress.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindIngress),
Spec: rawIngress.Spec,
Status: rawIngress.Status,
Ingress: toIngress(i),
Spec: i.Spec,
Status: i.Status,
}
}
......@@ -56,19 +56,6 @@ func GetIngressList(client client.Interface, namespace *common.NamespaceQuery,
return toIngressList(ingressList.Items, nonCriticalErrors, dsQuery), nil
}
// GetIngressListFromChannels - return all ingresses in the given namespace.
func GetIngressListFromChannels(channels *common.ResourceChannels, dsQuery *dataselect.DataSelectQuery) (*IngressList, error) {
ingress := <-channels.IngressList.List
err := <-channels.IngressList.Error
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
return toIngressList(ingress.Items, nonCriticalErrors, dsQuery), nil
}
func getEndpoints(ingress *extensions.Ingress) []common.Endpoint {
endpoints := make([]common.Endpoint, 0)
if len(ingress.Status.LoadBalancer.Ingress) > 0 {
......@@ -80,13 +67,12 @@ func getEndpoints(ingress *extensions.Ingress) []common.Endpoint {
return endpoints
}
func toIngress(ingress *extensions.Ingress) *Ingress {
modelIngress := &Ingress{
func toIngress(ingress *extensions.Ingress) Ingress {
return Ingress{
ObjectMeta: api.NewObjectMeta(ingress.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindIngress),
Endpoints: getEndpoints(ingress),
}
return modelIngress
}
func toIngressList(ingresses []extensions.Ingress, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *IngressList {
......@@ -101,7 +87,7 @@ func toIngressList(ingresses []extensions.Ingress, nonCriticalErrors []error, ds
newIngressList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, ingress := range ingresses {
newIngressList.Items = append(newIngressList.Items, *toIngress(&ingress))
newIngressList.Items = append(newIngressList.Items, toIngress(&ingress))
}
return newIngressList
......
......@@ -15,41 +15,17 @@
package job
import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
batch "k8s.io/api/batch/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
)
// JobDetail is a presentation layer view of Kubernetes Job resource. This means
// it is Job plus additional augmented data we can get from other sources
// (like services that target the same pods).
// JobDetail is a presentation layer view of Kubernetes Job resource.
type JobDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Job.
PodInfo common.PodInfo `json:"podInfo"`
// Detailed information about Pods belonging to this Job.
PodList pod.PodList `json:"podList"`
// Container images of the Job.
ContainerImages []string `json:"containerImages"`
// Init container images of the Job.
InitContainerImages []string `json:"initContainerImages"`
// List of events related to this Job.
EventList common.EventList `json:"eventList"`
// Parallelism specifies the maximum desired number of pods the job should run at any given time.
Parallelism *int32 `json:"parallelism"`
// Extends list item structure.
Job `json:",inline"`
// Completions specifies the desired number of successfully finished pods the job should be run with.
Completions *int32 `json:"completions"`
......@@ -59,48 +35,26 @@ type JobDetail struct {
}
// GetJobDetail gets job details.
func GetJobDetail(client k8sClient.Interface, metricClient metricapi.MetricClient, namespace, name string) (
*JobDetail, error) {
func GetJobDetail(client k8sClient.Interface, namespace, name string) (*JobDetail, error) {
jobData, err := client.BatchV1().Jobs(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
podList, err := GetJobPods(client, metricClient, dataselect.DefaultDataSelectWithMetrics, namespace, name)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
podInfo, err := getJobPodInfo(client, jobData)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
eventList, err := GetJobEvents(client, dataselect.DefaultDataSelect, jobData.Namespace, jobData.Name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
job := toJobDetail(jobData, *eventList, *podList, *podInfo, nonCriticalErrors)
job := toJobDetail(jobData, *podInfo, nonCriticalErrors)
return &job, nil
}
func toJobDetail(job *batch.Job, eventList common.EventList, podList pod.PodList, podInfo common.PodInfo,
nonCriticalErrors []error) JobDetail {
func toJobDetail(job *batch.Job, podInfo common.PodInfo, nonCriticalErrors []error) JobDetail {
return JobDetail{
ObjectMeta: api.NewObjectMeta(job.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindJob),
ContainerImages: common.GetContainerImages(&job.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&job.Spec.Template.Spec),
PodInfo: podInfo,
PodList: podList,
EventList: eventList,
Parallelism: job.Spec.Parallelism,
Completions: job.Spec.Completions,
Errors: nonCriticalErrors,
Job: toJob(job, &podInfo),
Completions: job.Spec.Completions,
Errors: nonCriticalErrors,
}
}
......@@ -19,18 +19,16 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
batch "k8s.io/api/batch/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func createJob(name, namespace string, jobCompletions int32, labelSelector map[string]string) *batch.Job {
var parallelism int32
var parallelism int32 = 0
return &batch.Job{
ObjectMeta: metaV1.ObjectMeta{
Name: name, Namespace: namespace, Labels: labelSelector,
......@@ -55,23 +53,23 @@ func TestGetJobDetail(t *testing.T) {
}{
{
"ns-1", "job-1",
[]string{"get", "get", "list", "list", "list", "list"},
[]string{"get", "list"},
createJob("job-1", "ns-1", jobCompletions, map[string]string{"app": "test"}),
&JobDetail{
ObjectMeta: api.ObjectMeta{Name: "job-1", Namespace: "ns-1",
Labels: map[string]string{"app": "test"}},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindJob},
PodInfo: common.PodInfo{
Warnings: []common.Event{},
Desired: &jobCompletions,
Job: Job{
ObjectMeta: api.ObjectMeta{Name: "job-1", Namespace: "ns-1",
Labels: map[string]string{"app": "test"}},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindJob},
Pods: common.PodInfo{
Warnings: []common.Event{},
Desired: &jobCompletions,
},
Parallelism: &jobCompletions,
JobStatus: JobStatus{
Status: "Running",
Message: "",
},
},
PodList: pod.PodList{
Pods: []pod.Pod{},
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: []error{},
},
EventList: common.EventList{Events: []common.Event{}},
Parallelism: &jobCompletions,
Completions: &parallelism,
Errors: []error{},
},
......@@ -80,14 +78,12 @@ func TestGetJobDetail(t *testing.T) {
for _, c := range cases {
fakeClient := fake.NewSimpleClientset(c.job)
dataselect.DefaultDataSelectWithMetrics.MetricQuery = dataselect.NoMetrics
actual, _ := GetJobDetail(fakeClient, nil, c.namespace, c.name)
actual, _ := GetJobDetail(fakeClient, c.namespace, c.name)
actions := fakeClient.Actions()
if len(actions) != len(c.expectedActions) {
t.Errorf("Unexpected actions: %v, expected %d actions got %d", actions,
len(c.expectedActions), len(actions))
t.Errorf("Unexpected actions: %v, expected %d actions got %d", actions, len(c.expectedActions), len(actions))
continue
}
......@@ -99,8 +95,7 @@ func TestGetJobDetail(t *testing.T) {
}
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("GetEvents(client,heapsterClient,%#v, %#v) == \ngot: %#v, \nexpected %#v",
c.namespace, c.name, actual, c.expected)
t.Errorf("TestGetJobDetail() == \ngot: %#v, \nexpected %#v", actual, c.expected)
}
}
}
......@@ -68,7 +68,7 @@ type Job struct {
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Job.
Pods common.PodInfo `json:"pods"`
Pods common.PodInfo `json:"podInfo"`
// Container images of the Job.
ContainerImages []string `json:"containerImages"`
......
......@@ -19,9 +19,6 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/limitrange"
rq "github.com/kubernetes/dashboard/src/app/backend/resource/resourcequota"
v1 "k8s.io/api/core/v1"
......@@ -32,14 +29,8 @@ import (
// NamespaceDetail is a presentation layer view of Kubernetes Namespace resource. This means it is Namespace plus
// additional augmented data we can get from other sources.
type NamespaceDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Phase is the current lifecycle phase of the namespace.
Phase v1.NamespacePhase `json:"phase"`
// Events is list of events associated to the namespace.
EventList common.EventList `json:"eventList"`
// Extends list item structure.
Namespace `json:",inline"`
// ResourceQuotaList is list of resource quotas associated to the namespace
ResourceQuotaList *rq.ResourceQuotaDetailList `json:"resourceQuotaList"`
......@@ -60,14 +51,8 @@ func GetNamespaceDetail(client k8sClient.Interface, name string) (*NamespaceDeta
return nil, err
}
events, err := event.GetNamespaceEvents(client, dataselect.DefaultDataSelect, namespace.Name)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
resourceQuotaList, err := getResourceQuotas(client, *namespace)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
......@@ -78,18 +63,15 @@ func GetNamespaceDetail(client k8sClient.Interface, name string) (*NamespaceDeta
return nil, criticalError
}
namespaceDetails := toNamespaceDetail(*namespace, events, resourceQuotaList, resourceLimits, nonCriticalErrors)
namespaceDetails := toNamespaceDetail(*namespace, resourceQuotaList, resourceLimits, nonCriticalErrors)
return &namespaceDetails, nil
}
func toNamespaceDetail(namespace v1.Namespace, events common.EventList, resourceQuotaList *rq.ResourceQuotaDetailList,
func toNamespaceDetail(namespace v1.Namespace, resourceQuotaList *rq.ResourceQuotaDetailList,
resourceLimits []limitrange.LimitRangeItem, nonCriticalErrors []error) NamespaceDetail {
return NamespaceDetail{
ObjectMeta: api.NewObjectMeta(namespace.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindNamespace),
Phase: namespace.Status.Phase,
EventList: events,
Namespace: toNamespace(namespace),
ResourceQuotaList: resourceQuotaList,
ResourceLimits: resourceLimits,
Errors: nonCriticalErrors,
......
......@@ -19,7 +19,6 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
......@@ -37,14 +36,16 @@ func TestGetNamespaceDetail(t *testing.T) {
},
},
&NamespaceDetail{
TypeMeta: api.TypeMeta{Kind: "namespace"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
Phase: v1.NamespaceActive,
Namespace: Namespace{
TypeMeta: api.TypeMeta{Kind: "namespace"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
Phase: v1.NamespaceActive,
},
},
},
}
for _, c := range cases {
actual := toNamespaceDetail(c.namespace, common.EventList{}, nil, nil, nil)
actual := toNamespaceDetail(c.namespace, nil, nil, nil)
if !reflect.DeepEqual(&actual, c.expected) {
t.Errorf("toNamespaceDetail(%#v) == \n%#v\nexpected \n%#v\n",
c.namespace, actual, c.expected)
......
......@@ -78,15 +78,12 @@ type NodeAllocatedResources struct {
// NodeDetail is a presentation layer view of Kubernetes Node resource. This means it is Node plus
// additional augmented data we can get from other sources.
type NodeDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
Node `json:",inline"`
// NodePhase is the current lifecycle phase of the node.
Phase v1.NodePhase `json:"phase"`
// Resources allocated by node.
AllocatedResources NodeAllocatedResources `json:"allocatedResources"`
// PodCIDR represents the pod IP range assigned to the node.
PodCIDR string `json:"podCIDR"`
......@@ -325,23 +322,24 @@ func getNodePods(client k8sClient.Interface, node v1.Node) (*v1.PodList, error)
func toNodeDetail(node v1.Node, pods *pod.PodList, eventList *common.EventList,
allocatedResources NodeAllocatedResources, metrics []metricapi.Metric, nonCriticalErrors []error) NodeDetail {
return NodeDetail{
ObjectMeta: api.NewObjectMeta(node.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindNode),
Phase: node.Status.Phase,
ProviderID: node.Spec.ProviderID,
PodCIDR: node.Spec.PodCIDR,
Unschedulable: node.Spec.Unschedulable,
NodeInfo: node.Status.NodeInfo,
Conditions: getNodeConditions(node),
ContainerImages: getContainerImages(node),
PodList: *pods,
EventList: *eventList,
AllocatedResources: allocatedResources,
Metrics: metrics,
Taints: node.Spec.Taints,
Addresses: node.Status.Addresses,
Errors: nonCriticalErrors,
Node: Node{
ObjectMeta: api.NewObjectMeta(node.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindNode),
AllocatedResources: allocatedResources,
},
Phase: node.Status.Phase,
ProviderID: node.Spec.ProviderID,
PodCIDR: node.Spec.PodCIDR,
Unschedulable: node.Spec.Unschedulable,
NodeInfo: node.Status.NodeInfo,
Conditions: getNodeConditions(node),
ContainerImages: getContainerImages(node),
PodList: *pods,
EventList: *eventList,
Metrics: metrics,
Taints: node.Spec.Taints,
Addresses: node.Status.Addresses,
Errors: nonCriticalErrors,
}
}
......@@ -45,8 +45,25 @@ func TestGetNodeDetail(t *testing.T) {
},
},
&NodeDetail{
ObjectMeta: api.ObjectMeta{Name: "test-node"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindNode},
Node: Node{
ObjectMeta: api.ObjectMeta{Name: "test-node"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindNode},
AllocatedResources: NodeAllocatedResources{
CPURequests: 0,
CPURequestsFraction: 0,
CPULimits: 0,
CPULimitsFraction: 0,
CPUCapacity: 0,
MemoryRequests: 0,
MemoryRequestsFraction: 0,
MemoryLimits: 0,
MemoryLimitsFraction: 0,
MemoryCapacity: 0,
AllocatedPods: 0,
PodCapacity: 0,
PodFraction: 0,
},
},
PodCIDR: "127.0.0.1",
ProviderID: "ID-1",
Unschedulable: true,
......@@ -58,21 +75,6 @@ func TestGetNodeDetail(t *testing.T) {
EventList: common.EventList{
Events: make([]common.Event, 0),
},
AllocatedResources: NodeAllocatedResources{
CPURequests: 0,
CPURequestsFraction: 0,
CPULimits: 0,
CPULimitsFraction: 0,
CPUCapacity: 0,
MemoryRequests: 0,
MemoryRequestsFraction: 0,
MemoryLimits: 0,
MemoryLimitsFraction: 0,
MemoryCapacity: 0,
AllocatedPods: 0,
PodCapacity: 0,
PodFraction: 0,
},
Metrics: make([]metricapi.Metric, 0),
Errors: []error{},
},
......
......@@ -20,7 +20,6 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
v1 "k8s.io/api/core/v1"
client "k8s.io/client-go/kubernetes"
......@@ -45,21 +44,6 @@ type Node struct {
AllocatedResources NodeAllocatedResources `json:"allocatedResources"`
}
// GetNodeListFromChannels returns a list of all Nodes in the cluster.
func GetNodeListFromChannels(client client.Interface, channels *common.ResourceChannels,
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*NodeList, error) {
nodes := <-channels.NodeList.List
err := <-channels.NodeList.Error
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
return toNodeList(client, nodes.Items, nonCriticalErrors, dsQuery, metricClient), nil
}
// GetNodeList returns a list of all Nodes in the cluster.
func GetNodeList(client client.Interface, dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*NodeList, error) {
nodes, err := client.CoreV1().Nodes().List(api.ListEverything)
......
......@@ -17,7 +17,6 @@ package persistentvolume
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
client "k8s.io/client-go/kubernetes"
......@@ -25,17 +24,11 @@ import (
// PersistentVolumeDetail provides the presentation layer view of Kubernetes Persistent Volume resource.
type PersistentVolumeDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Status v1.PersistentVolumePhase `json:"status"`
Claim string `json:"claim"`
ReclaimPolicy v1.PersistentVolumeReclaimPolicy `json:"reclaimPolicy"`
AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes"`
StorageClass string `json:"storageClass"`
Capacity v1.ResourceList `json:"capacity"`
Message string `json:"message"`
PersistentVolumeSource v1.PersistentVolumeSource `json:"persistentVolumeSource"`
Reason string `json:"reason"`
// Extends list item structure.
PersistentVolume `json:",inline"`
Message string `json:"message"`
PersistentVolumeSource v1.PersistentVolumeSource `json:"persistentVolumeSource"`
}
// GetPersistentVolumeDetail returns detailed information about a persistent volume
......@@ -47,21 +40,13 @@ func GetPersistentVolumeDetail(client client.Interface, name string) (*Persisten
return nil, err
}
return getPersistentVolumeDetail(rawPersistentVolume), nil
return getPersistentVolumeDetail(*rawPersistentVolume), nil
}
func getPersistentVolumeDetail(persistentVolume *v1.PersistentVolume) *PersistentVolumeDetail {
func getPersistentVolumeDetail(pv v1.PersistentVolume) *PersistentVolumeDetail {
return &PersistentVolumeDetail{
ObjectMeta: api.NewObjectMeta(persistentVolume.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindPersistentVolume),
Status: persistentVolume.Status.Phase,
Claim: getPersistentVolumeClaim(persistentVolume),
ReclaimPolicy: persistentVolume.Spec.PersistentVolumeReclaimPolicy,
AccessModes: persistentVolume.Spec.AccessModes,
StorageClass: persistentVolume.Spec.StorageClassName,
Capacity: persistentVolume.Spec.Capacity,
Message: persistentVolume.Status.Message,
PersistentVolumeSource: persistentVolume.Spec.PersistentVolumeSource,
Reason: persistentVolume.Status.Reason,
PersistentVolume: toPersistentVolume(pv),
Message: pv.Status.Message,
PersistentVolumeSource: pv.Spec.PersistentVolumeSource,
}
}
......@@ -19,6 +19,7 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
......@@ -54,14 +55,16 @@ func TestGetPersistentVolumeDetail(t *testing.T) {
},
},
&PersistentVolumeDetail{
TypeMeta: api.TypeMeta{Kind: "persistentvolume"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
Status: v1.VolumePending,
ReclaimPolicy: v1.PersistentVolumeReclaimRecycle,
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Capacity: nil,
Claim: "default/myclaim-name",
Message: "my-message",
PersistentVolume: PersistentVolume{
TypeMeta: api.TypeMeta{Kind: "persistentvolume"},
ObjectMeta: api.ObjectMeta{Name: "foo"},
Status: v1.VolumePending,
ReclaimPolicy: v1.PersistentVolumeReclaimRecycle,
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
Capacity: nil,
Claim: "default/myclaim-name",
},
Message: "my-message",
PersistentVolumeSource: v1.PersistentVolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: "my-path",
......
......@@ -85,19 +85,22 @@ func toPersistentVolumeList(persistentVolumes []v1.PersistentVolume, nonCritical
result.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, item := range persistentVolumes {
result.Items = append(result.Items,
PersistentVolume{
ObjectMeta: api.NewObjectMeta(item.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindPersistentVolume),
Capacity: item.Spec.Capacity,
AccessModes: item.Spec.AccessModes,
ReclaimPolicy: item.Spec.PersistentVolumeReclaimPolicy,
StorageClass: item.Spec.StorageClassName,
Status: item.Status.Phase,
Claim: getPersistentVolumeClaim(&item),
Reason: item.Status.Reason,
})
result.Items = append(result.Items, toPersistentVolume(item))
}
return result
}
func toPersistentVolume(pv v1.PersistentVolume) PersistentVolume {
return PersistentVolume{
ObjectMeta: api.NewObjectMeta(pv.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindPersistentVolume),
Capacity: pv.Spec.Capacity,
AccessModes: pv.Spec.AccessModes,
ReclaimPolicy: pv.Spec.PersistentVolumeReclaimPolicy,
StorageClass: pv.Spec.StorageClassName,
Status: pv.Status.Phase,
Claim: getPersistentVolumeClaim(&pv),
Reason: pv.Status.Reason,
}
}
......@@ -17,7 +17,6 @@ package persistentvolumeclaim
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
......@@ -25,37 +24,24 @@ import (
// PersistentVolumeClaimDetail provides the presentation layer view of Kubernetes Persistent Volume Claim resource.
type PersistentVolumeClaimDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Status v1.PersistentVolumeClaimPhase `json:"status"`
Volume string `json:"volume"`
Capacity v1.ResourceList `json:"capacity"`
AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes"`
StorageClass *string `json:"storageClass"`
// Extends list item structure.
PersistentVolumeClaim `json:",inline"`
}
// GetPersistentVolumeClaimDetail returns detailed information about a persistent volume claim
func GetPersistentVolumeClaimDetail(client kubernetes.Interface, namespace string, name string) (*PersistentVolumeClaimDetail, error) {
log.Printf("Getting details of %s persistent volume claim", name)
rawPersistentVolumeClaim, err := client.CoreV1().PersistentVolumeClaims(namespace).Get(name, metaV1.GetOptions{})
pvc, err := client.CoreV1().PersistentVolumeClaims(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
return getPersistentVolumeClaimDetail(rawPersistentVolumeClaim), nil
return getPersistentVolumeClaimDetail(*pvc), nil
}
func getPersistentVolumeClaimDetail(persistentVolumeClaim *v1.PersistentVolumeClaim) *PersistentVolumeClaimDetail {
func getPersistentVolumeClaimDetail(pvc v1.PersistentVolumeClaim) *PersistentVolumeClaimDetail {
return &PersistentVolumeClaimDetail{
ObjectMeta: api.NewObjectMeta(persistentVolumeClaim.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindPersistentVolumeClaim),
Status: persistentVolumeClaim.Status.Phase,
Volume: persistentVolumeClaim.Spec.VolumeName,
Capacity: persistentVolumeClaim.Status.Capacity,
AccessModes: persistentVolumeClaim.Spec.AccessModes,
StorageClass: persistentVolumeClaim.Spec.StorageClassName,
PersistentVolumeClaim: toPersistentVolumeClaim(pvc),
}
}
......@@ -45,17 +45,19 @@ func TestGetPersistentVolumeClaimDetail(t *testing.T) {
},
},
&PersistentVolumeClaimDetail{
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
TypeMeta: api.TypeMeta{Kind: "persistentvolumeclaim"},
Status: v1.ClaimPending,
Volume: "volume",
Capacity: nil,
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
PersistentVolumeClaim: PersistentVolumeClaim{
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
TypeMeta: api.TypeMeta{Kind: "persistentvolumeclaim"},
Status: string(v1.ClaimPending),
Volume: "volume",
Capacity: nil,
AccessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce},
},
},
},
}
for _, c := range cases {
actual := getPersistentVolumeClaimDetail(c.persistentVolumeClaims)
actual := getPersistentVolumeClaimDetail(*c.persistentVolumeClaims)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("getPersistentVolumeClaimDetail(%#v) == \n%#v\nexpected \n%#v\n",
c.persistentVolumeClaims, actual, c.expected)
......
......@@ -20,38 +20,10 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
// ReplicaSet is a presentation layer view of Kubernetes Replica Set resource. This means
// it is Replica Set plus additional augmented data we can get from other sources
// (like services that target the same pods).
type ReplicaSet struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Replica Set.
Pods common.PodInfo `json:"pods"`
// Container images of the Replica Set.
ContainerImages []string `json:"containerImages"`
// Init Container images of the Replica Set.
InitContainerImages []string `json:"initContainerImages"`
}
// ToReplicaSet converts replica set api object to replica set model object.
func ToReplicaSet(replicaSet *apps.ReplicaSet, podInfo *common.PodInfo) ReplicaSet {
return ReplicaSet{
ObjectMeta: api.NewObjectMeta(replicaSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindReplicaSet),
ContainerImages: common.GetContainerImages(&replicaSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&replicaSet.Spec.Template.Spec),
Pods: *podInfo,
}
}
// The code below allows to perform complex data section on Replica Set
type ReplicaSetCell apps.ReplicaSet
......
......@@ -20,7 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
......
......@@ -17,16 +17,11 @@ package replicaset
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
ds "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
hpa "github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
resourceService "github.com/kubernetes/dashboard/src/app/backend/resource/service"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
)
......@@ -35,26 +30,8 @@ import (
// it is Replica Set plus additional augmented data we can get from other sources
// (like services that target the same pods).
type ReplicaSetDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Replica Set.
PodInfo common.PodInfo `json:"podInfo"`
// Detailed information about Pods belonging to this Replica Set.
PodList pod.PodList `json:"podList"`
// Detailed information about service related to Replica Set.
ServiceList resourceService.ServiceList `json:"serviceList"`
// Container images of the Replica Set.
ContainerImages []string `json:"containerImages"`
// Init Container images of the Replica Set.
InitContainerImages []string `json:"initContainerImages"`
// List of events related to this Replica Set.
EventList common.EventList `json:"eventList"`
// Extends list item structure.
ReplicaSet `json:",inline"`
// Selector of this replica set.
Selector *metaV1.LabelSelector `json:"selector"`
......@@ -71,31 +48,13 @@ func GetReplicaSetDetail(client k8sClient.Interface, metricClient metricapi.Metr
namespace, name string) (*ReplicaSetDetail, error) {
log.Printf("Getting details of %s service in %s namespace", name, namespace)
rs, err := client.AppsV1beta2().ReplicaSets(namespace).Get(name, metaV1.GetOptions{})
rs, err := client.AppsV1().ReplicaSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
eventList, err := event.GetResourceEvents(client, ds.DefaultDataSelect, rs.Namespace, rs.Name)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
podList, err := GetReplicaSetPods(client, metricClient, ds.DefaultDataSelectWithMetrics, name, namespace)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
podInfo, err := getReplicaSetPodInfo(client, rs)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
serviceList, err := GetReplicaSetServices(client, ds.DefaultDataSelect, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
......@@ -106,24 +65,14 @@ func GetReplicaSetDetail(client k8sClient.Interface, metricClient metricapi.Metr
return nil, criticalError
}
rsDetail := toReplicaSetDetail(rs, *eventList, *podList, *podInfo, *serviceList, *hpas, nonCriticalErrors)
rsDetail := toReplicaSetDetail(rs, *podInfo, *hpas, nonCriticalErrors)
return &rsDetail, nil
}
func toReplicaSetDetail(replicaSet *apps.ReplicaSet, eventList common.EventList, podList pod.PodList,
podInfo common.PodInfo, serviceList resourceService.ServiceList,
hpas hpa.HorizontalPodAutoscalerList, nonCriticalErrors []error) ReplicaSetDetail {
func toReplicaSetDetail(rs *apps.ReplicaSet, podInfo common.PodInfo, hpas hpa.HorizontalPodAutoscalerList, nonCriticalErrors []error) ReplicaSetDetail {
return ReplicaSetDetail{
ObjectMeta: api.NewObjectMeta(replicaSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindReplicaSet),
ContainerImages: common.GetContainerImages(&replicaSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&replicaSet.Spec.Template.Spec),
Selector: replicaSet.Spec.Selector,
PodInfo: podInfo,
PodList: podList,
ServiceList: serviceList,
EventList: eventList,
ReplicaSet: ToReplicaSet(rs, &podInfo),
Selector: rs.Spec.Selector,
HorizontalPodAutoscalerList: hpas,
Errors: nonCriticalErrors,
}
......
......@@ -19,13 +19,12 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
"github.com/kubernetes/dashboard/src/app/backend/resource/service"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
......@@ -40,7 +39,7 @@ func TestGetReplicaSetDetail(t *testing.T) {
}{
{
"ns-1", "rs-1",
[]string{"get", "list", "get", "list", "list", "list", "get", "list", "list"},
[]string{"get", "list", "list"},
&apps.ReplicaSet{
ObjectMeta: metaV1.ObjectMeta{Name: "rs-1", Namespace: "ns-1",
Labels: map[string]string{"app": "test"}},
......@@ -52,29 +51,18 @@ func TestGetReplicaSetDetail(t *testing.T) {
},
},
&ReplicaSetDetail{
ObjectMeta: api.ObjectMeta{Name: "rs-1", Namespace: "ns-1",
Labels: map[string]string{"app": "test"}},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
PodInfo: common.PodInfo{
Warnings: []common.Event{},
Desired: &replicas,
},
PodList: pod.PodList{
Pods: []pod.Pod{},
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: []error{},
ReplicaSet: ReplicaSet{
ObjectMeta: api.ObjectMeta{Name: "rs-1", Namespace: "ns-1",
Labels: map[string]string{"app": "test"}},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
Pods: common.PodInfo{
Warnings: []common.Event{},
Desired: &replicas,
},
},
Selector: &metaV1.LabelSelector{
MatchLabels: map[string]string{"app": "test"},
},
ServiceList: service.ServiceList{
Services: []service.Service{},
Errors: []error{},
},
EventList: common.EventList{
Events: []common.Event{},
Errors: []error{},
},
HorizontalPodAutoscalerList: horizontalpodautoscaler.HorizontalPodAutoscalerList{
HorizontalPodAutoscalers: []horizontalpodautoscaler.HorizontalPodAutoscaler{},
Errors: []error{},
......@@ -129,8 +117,10 @@ func TestToReplicaSetDetail(t *testing.T) {
service.ServiceList{},
horizontalpodautoscaler.HorizontalPodAutoscalerList{},
ReplicaSetDetail{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
Errors: []error{},
ReplicaSet: ReplicaSet{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
},
Errors: []error{},
},
}, {
&apps.ReplicaSet{ObjectMeta: metaV1.ObjectMeta{Name: "replica-set"}},
......@@ -144,18 +134,9 @@ func TestToReplicaSetDetail(t *testing.T) {
}},
},
ReplicaSetDetail{
ObjectMeta: api.ObjectMeta{Name: "replica-set"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
EventList: common.EventList{Events: []common.Event{{Message: "event-msg"}}},
PodList: pod.PodList{
Pods: []pod.Pod{{
ObjectMeta: api.ObjectMeta{Name: "pod-1"},
}},
},
ServiceList: service.ServiceList{
Services: []service.Service{{
ObjectMeta: api.ObjectMeta{Name: "service-1"},
}},
ReplicaSet: ReplicaSet{
ObjectMeta: api.ObjectMeta{Name: "replica-set"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindReplicaSet},
},
HorizontalPodAutoscalerList: horizontalpodautoscaler.HorizontalPodAutoscalerList{
HorizontalPodAutoscalers: []horizontalpodautoscaler.HorizontalPodAutoscaler{{
......@@ -168,7 +149,7 @@ func TestToReplicaSetDetail(t *testing.T) {
}
for _, c := range cases {
actual := toReplicaSetDetail(c.replicaSet, c.eventList, c.podList, c.podInfo, c.serviceList, c.hpaList, []error{})
actual := toReplicaSetDetail(c.replicaSet, c.podInfo, c.hpaList, []error{})
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("toReplicaSetDetail(%#v, %#v, %#v, %#v, %#v) == \ngot %#v, \nexpected %#v",
......
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
client "k8s.io/client-go/kubernetes"
)
......@@ -43,6 +43,32 @@ type ReplicaSetList struct {
Errors []error `json:"errors"`
}
// ReplicaSet is a presentation layer view of Kubernetes Replica Set resource.
type ReplicaSet struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Replica Set.
Pods common.PodInfo `json:"podInfo"`
// Container images of the Replica Set.
ContainerImages []string `json:"containerImages"`
// Init Container images of the Replica Set.
InitContainerImages []string `json:"initContainerImages"`
}
// ToReplicaSet converts replica set api object to replica set model object.
func ToReplicaSet(replicaSet *apps.ReplicaSet, podInfo *common.PodInfo) ReplicaSet {
return ReplicaSet{
ObjectMeta: api.NewObjectMeta(replicaSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindReplicaSet),
ContainerImages: common.GetContainerImages(&replicaSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&replicaSet.Spec.Template.Spec),
Pods: *podInfo,
}
}
// GetReplicaSetList returns a list of all Replica Sets in the cluster.
func GetReplicaSetList(client client.Interface, nsQuery *common.NamespaceQuery,
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*ReplicaSetList, error) {
......
......@@ -23,7 +23,7 @@ import (
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
......@@ -52,7 +52,7 @@ func GetReplicaSetPods(client k8sClient.Interface, metricClient metricapi.Metric
}
func getRawReplicaSetPods(client k8sClient.Interface, petSetName, namespace string) ([]v1.Pod, error) {
rs, err := client.AppsV1beta2().ReplicaSets(namespace).Get(petSetName, metaV1.GetOptions{})
rs, err := client.AppsV1().ReplicaSets(namespace).Get(petSetName, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......
......@@ -27,7 +27,7 @@ import (
func GetReplicaSetServices(client client.Interface, dsQuery *dataselect.DataSelectQuery,
namespace, name string) (*service.ServiceList, error) {
replicaSet, err := client.AppsV1beta2().ReplicaSets(namespace).Get(name, metaV1.GetOptions{})
replicaSet, err := client.AppsV1().ReplicaSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......
......@@ -27,22 +27,6 @@ import (
client "k8s.io/client-go/kubernetes"
)
// ReplicationController (aka. Replication Controller) plus zero or more Kubernetes services that
// target the Replication Controller.
type ReplicationController struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Replication Controller.
Pods common.PodInfo `json:"pods"`
// Container images of the Replication Controller.
ContainerImages []string `json:"containerImages"`
// Init Container images of the Replication Controller.
InitContainerImages []string `json:"initContainerImages"`
}
// Transforms simple selector map to labels.Selector object that can be used when querying for
// object.
func toLabelSelector(selector map[string]string) (labels.Selector, error) {
......
......@@ -17,15 +17,8 @@ package replicationcontroller
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
ds "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
hpa "github.com/kubernetes/dashboard/src/app/backend/resource/horizontalpodautoscaler"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
resourceService "github.com/kubernetes/dashboard/src/app/backend/resource/service"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
......@@ -33,36 +26,11 @@ import (
// ReplicationControllerDetail represents detailed information about a Replication Controller.
type ReplicationControllerDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
ReplicationController `json:",inline"`
// Label selector of the Replication Controller.
LabelSelector map[string]string `json:"labelSelector"`
// Container image list of the pod template specified by this Replication Controller.
ContainerImages []string `json:"containerImages"`
// Init Container image list of the pod template specified by this Replication Controller.
InitContainerImages []string `json:"initContainerImages"`
// Aggregate information about pods of this replication controller.
PodInfo common.PodInfo `json:"podInfo"`
// Detailed information about Pods belonging to this Replication Controller.
PodList pod.PodList `json:"podList"`
// Detailed information about service related to Replication Controller.
ServiceList resourceService.ServiceList `json:"serviceList"`
// List of events related to this Replication Controller.
EventList common.EventList `json:"eventList"`
// True when the data contains at least one pod with metrics information, false otherwise.
HasMetrics bool `json:"hasMetrics"`
// List of Horizontal Pod AutoScalers targeting this Replication Controller.
HorizontalPodAutoscalerList hpa.HorizontalPodAutoscalerList `json:"horizontalPodAutoscalerList"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
......@@ -75,8 +43,7 @@ type ReplicationControllerSpec struct {
// GetReplicationControllerDetail returns detailed information about the given replication controller
// in the given namespace.
func GetReplicationControllerDetail(client k8sClient.Interface, metricClient metricapi.MetricClient,
namespace, name string) (*ReplicationControllerDetail, error) {
func GetReplicationControllerDetail(client k8sClient.Interface, namespace, name string) (*ReplicationControllerDetail, error) {
log.Printf("Getting details of %s replication controller in %s namespace", name, namespace)
replicationController, err := client.CoreV1().ReplicationControllers(namespace).Get(name, metaV1.GetOptions{})
......@@ -90,33 +57,7 @@ func GetReplicationControllerDetail(client k8sClient.Interface, metricClient met
return nil, criticalError
}
podList, err := GetReplicationControllerPods(client, metricClient, ds.DefaultDataSelectWithMetrics,
name, namespace)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
eventList, err := event.GetResourceEvents(client, ds.DefaultDataSelect, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
serviceList, err := GetReplicationControllerServices(client, ds.DefaultDataSelect, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
hpas, err := hpa.GetHorizontalPodAutoscalerListForResource(client, namespace, "ReplicationController", name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
replicationControllerDetail := toReplicationControllerDetail(replicationController, *podInfo,
*podList, *eventList, *serviceList, *hpas, nonCriticalErrors)
replicationControllerDetail := toReplicationControllerDetail(replicationController, podInfo, nonCriticalErrors)
return &replicationControllerDetail, nil
}
......@@ -143,21 +84,10 @@ func UpdateReplicasCount(client k8sClient.Interface, namespace, name string, spe
return nil
}
func toReplicationControllerDetail(replicationController *v1.ReplicationController, podInfo common.PodInfo,
podList pod.PodList, eventList common.EventList, serviceList resourceService.ServiceList,
hpas hpa.HorizontalPodAutoscalerList, nonCriticalErrors []error) ReplicationControllerDetail {
func toReplicationControllerDetail(replicationController *v1.ReplicationController, podInfo *common.PodInfo, nonCriticalErrors []error) ReplicationControllerDetail {
return ReplicationControllerDetail{
ObjectMeta: api.NewObjectMeta(replicationController.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindReplicationController),
LabelSelector: replicationController.Spec.Selector,
PodInfo: podInfo,
PodList: podList,
EventList: eventList,
ServiceList: serviceList,
HorizontalPodAutoscalerList: hpas,
ContainerImages: common.GetContainerImages(&replicationController.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&replicationController.Spec.Template.Spec),
Errors: nonCriticalErrors,
ReplicationController: ToReplicationController(replicationController, podInfo),
LabelSelector: replicationController.Spec.Selector,
Errors: nonCriticalErrors,
}
}
......@@ -42,6 +42,22 @@ type ReplicationControllerList struct {
Errors []error `json:"errors"`
}
// ReplicationController (aka. Replication Controller) plus zero or more Kubernetes services that
// target the Replication Controller.
type ReplicationController struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Replication Controller.
Pods common.PodInfo `json:"podInfo"`
// Container images of the Replication Controller.
ContainerImages []string `json:"containerImages"`
// Init Container images of the Replication Controller.
InitContainerImages []string `json:"initContainerImages"`
}
// GetReplicationControllerList returns a list of all Replication Controllers in the cluster.
func GetReplicationControllerList(client client.Interface, nsQuery *common.NamespaceQuery,
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*ReplicationControllerList, error) {
......
......@@ -17,7 +17,6 @@ package secret
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
......@@ -26,17 +25,14 @@ import (
// SecretDetail API resource provides mechanisms to inject containers with configuration data while keeping
// containers agnostic of Kubernetes
type SecretDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Extends list item structure.
Secret `json:",inline"`
// Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN
// or leading dot followed by valid DNS_SUBDOMAIN.
// The serialized form of the secret data is a base64 encoded string,
// representing the arbitrary (possibly non-string) data value here.
Data map[string][]byte `json:"data"`
// Used to facilitate programmatic handling of secret data.
Type v1.SecretType `json:"type"`
}
// GetSecretDetail returns detailed information about a secret
......@@ -53,9 +49,7 @@ func GetSecretDetail(client kubernetes.Interface, namespace, name string) (*Secr
func getSecretDetail(rawSecret *v1.Secret) *SecretDetail {
return &SecretDetail{
ObjectMeta: api.NewObjectMeta(rawSecret.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindSecret),
Data: rawSecret.Data,
Type: rawSecret.Type,
Secret: toSecret(rawSecret),
Data: rawSecret.Data,
}
}
......@@ -19,6 +19,7 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
......@@ -36,11 +37,13 @@ func TestGetSecretDetail(t *testing.T) {
},
},
&SecretDetail{
TypeMeta: api.TypeMeta{
Kind: "secret",
},
ObjectMeta: api.ObjectMeta{
Name: "foo",
Secret: Secret{
TypeMeta: api.TypeMeta{
Kind: "secret",
},
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
},
Data: map[string][]byte{"app": {0, 1, 2, 3}},
},
......
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubernetes "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes"
)
// SecretSpec is a common interface for the specification of different secrets.
......@@ -95,20 +95,6 @@ func GetSecretList(client kubernetes.Interface, namespace *common.NamespaceQuery
return toSecretList(secretList.Items, nonCriticalErrors, dsQuery), nil
}
// GetSecretListFromChannels returns a list of all Secrets in the cluster reading required resource list once from the channels.
func GetSecretListFromChannels(channels *common.ResourceChannels, dsQuery *dataselect.DataSelectQuery) (*SecretList, error) {
secretList := <-channels.SecretList.List
err := <-channels.SecretList.Error
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
return toSecretList(secretList.Items, nonCriticalErrors, dsQuery), nil
}
// CreateSecret creates a single secret using the cluster API client
func CreateSecret(client kubernetes.Interface, spec SecretSpec) (*Secret, error) {
namespace := spec.GetNamespace()
......@@ -121,11 +107,12 @@ func CreateSecret(client kubernetes.Interface, spec SecretSpec) (*Secret, error)
Data: spec.GetData(),
}
_, err := client.CoreV1().Secrets(namespace).Create(secret)
return toSecret(secret), err
result := toSecret(secret)
return &result, err
}
func toSecret(secret *v1.Secret) *Secret {
return &Secret{
func toSecret(secret *v1.Secret) Secret {
return Secret{
ObjectMeta: api.NewObjectMeta(secret.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindSecret),
Type: secret.Type,
......@@ -144,7 +131,7 @@ func toSecretList(secrets []v1.Secret, nonCriticalErrors []error, dsQuery *datas
newSecretList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, secret := range secrets {
newSecretList.Secrets = append(newSecretList.Secrets, *toSecret(&secret))
newSecretList.Secrets = append(newSecretList.Secrets, toSecret(&secret))
}
return newSecretList
......
......@@ -15,65 +15,10 @@
package service
import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"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"
v1 "k8s.io/api/core/v1"
)
// ToService returns api service object based on kubernetes service object
func ToService(service *v1.Service) Service {
return Service{
ObjectMeta: api.NewObjectMeta(service.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindService),
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
ExternalEndpoints: common.GetExternalEndpoints(service),
Selector: service.Spec.Selector,
ClusterIP: service.Spec.ClusterIP,
Type: service.Spec.Type,
}
}
// ToServiceDetail returns api service object based on kubernetes service object
func ToServiceDetail(service *v1.Service, events common.EventList, pods pod.PodList, endpointList endpoint.EndpointList,
nonCriticalErrors []error) ServiceDetail {
return ServiceDetail{
ObjectMeta: api.NewObjectMeta(service.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindService),
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
ExternalEndpoints: common.GetExternalEndpoints(service),
EndpointList: endpointList,
Selector: service.Spec.Selector,
ClusterIP: service.Spec.ClusterIP,
Type: service.Spec.Type,
EventList: events,
PodList: pods,
SessionAffinity: service.Spec.SessionAffinity,
Errors: nonCriticalErrors,
}
}
// CreateServiceList returns paginated service list based on given service array and pagination query.
func CreateServiceList(services []v1.Service, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *ServiceList {
serviceList := &ServiceList{
Services: make([]Service, 0),
ListMeta: api.ListMeta{TotalItems: len(services)},
Errors: nonCriticalErrors,
}
serviceCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(services), dsQuery)
services = fromCells(serviceCells)
serviceList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, service := range services {
serviceList.Services = append(serviceList.Services, ToService(&service))
}
return serviceList
}
// The code below allows to perform complex data section on []api.Service
type ServiceCell v1.Service
......
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package service
import (
"reflect"
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/endpoint"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestToServiceDetail(t *testing.T) {
cases := []struct {
service *v1.Service
eventList common.EventList
podList pod.PodList
endpointList endpoint.EndpointList
expected ServiceDetail
}{
{
service: &v1.Service{},
eventList: common.EventList{},
podList: pod.PodList{},
endpointList: endpoint.EndpointList{},
expected: ServiceDetail{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
ExternalEndpoints: []common.Endpoint{},
},
}, {
service: &v1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service", Namespace: "test-namespace",
}},
expected: ServiceDetail{
ObjectMeta: api.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "test-service.test-namespace"},
ExternalEndpoints: []common.Endpoint{},
},
},
}
for _, c := range cases {
actual := ToServiceDetail(c.service, c.eventList, c.podList, c.endpointList, nil)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("ToServiceDetail(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
c.expected)
}
}
}
func TestToService(t *testing.T) {
cases := []struct {
service *v1.Service
expected Service
}{
{
service: &v1.Service{}, expected: Service{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
ExternalEndpoints: []common.Endpoint{},
},
}, {
service: &v1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service", Namespace: "test-namespace",
}},
expected: Service{
ObjectMeta: api.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "test-service.test-namespace"},
ExternalEndpoints: []common.Endpoint{},
},
},
}
for _, c := range cases {
actual := ToService(c.service)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("ToService(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
c.expected)
}
}
}
......@@ -17,13 +17,8 @@ package service
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"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"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
k8sClient "k8s.io/client-go/kubernetes"
......@@ -31,36 +26,12 @@ import (
// Service is a representation of a service.
type ServiceDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// InternalEndpoint of all Kubernetes services that have the same label selector as connected Replication
// Controller. Endpoints is DNS name merged with ports.
InternalEndpoint common.Endpoint `json:"internalEndpoint"`
// ExternalEndpoints of all Kubernetes services that have the same label selector as connected Replication
// Controller. Endpoints is external IP address name merged with ports.
ExternalEndpoints []common.Endpoint `json:"externalEndpoints"`
// Extends list item structure.
Service `json:",inline"`
// List of Endpoint obj. that are endpoints of this Service.
EndpointList endpoint.EndpointList `json:"endpointList"`
// Label selector of the service.
Selector map[string]string `json:"selector"`
// Type determines how the service will be exposed. Valid options: ClusterIP, NodePort, LoadBalancer
Type v1.ServiceType `json:"type"`
// ClusterIP is usually assigned by the master. Valid values are None, empty string (""), or
// a valid IP address. None can be specified for headless services when proxying is not required
ClusterIP string `json:"clusterIP"`
// List of events related to this Service
EventList common.EventList `json:"eventList"`
// PodList represents list of pods targeted by same label selector as this service.
PodList pod.PodList `json:"podList"`
// Show the value of the SessionAffinity of the Service.
SessionAffinity v1.ServiceAffinity `json:"sessionAffinity"`
......@@ -69,9 +40,7 @@ type ServiceDetail struct {
}
// GetServiceDetail gets service details.
func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricClient, namespace, name string,
dsQuery *dataselect.DataSelectQuery) (*ServiceDetail, error) {
func GetServiceDetail(client k8sClient.Interface, namespace, name string) (*ServiceDetail, error) {
log.Printf("Getting details of %s service in %s namespace", name, namespace)
serviceData, err := client.CoreV1().Services(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
......@@ -84,18 +53,15 @@ func GetServiceDetail(client k8sClient.Interface, metricClient metricapi.MetricC
return nil, criticalError
}
podList, err := GetServicePods(client, metricClient, namespace, name, dsQuery)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
service := toServiceDetail(serviceData, *endpointList, nonCriticalErrors)
return &service, nil
}
eventList, err := GetServiceEvents(client, dataselect.DefaultDataSelect, namespace, name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
func toServiceDetail(service *v1.Service, endpointList endpoint.EndpointList, nonCriticalErrors []error) ServiceDetail {
return ServiceDetail{
Service: toService(service),
EndpointList: endpointList,
SessionAffinity: service.Spec.SessionAffinity,
Errors: nonCriticalErrors,
}
service := ToServiceDetail(serviceData, *eventList, *podList, *endpointList, nonCriticalErrors)
return &service, nil
}
......@@ -19,11 +19,8 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"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"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
......@@ -41,22 +38,17 @@ func TestGetServiceDetail(t *testing.T) {
Name: "svc-1", Namespace: "ns-1", Labels: map[string]string{},
}},
namespace: "ns-1", name: "svc-1",
expectedActions: []string{"get", "list", "get", "list"},
expectedActions: []string{"get", "list"},
expected: &ServiceDetail{
ObjectMeta: api.ObjectMeta{
Name: "svc-1",
Namespace: "ns-1",
Labels: map[string]string{},
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "svc-1.ns-1"},
ExternalEndpoints: []common.Endpoint{},
PodList: pod.PodList{
Pods: []pod.Pod{},
CumulativeMetrics: make([]metricapi.Metric, 0),
},
EventList: common.EventList{
Events: []common.Event{},
Service: Service{
ObjectMeta: api.ObjectMeta{
Name: "svc-1",
Namespace: "ns-1",
Labels: map[string]string{},
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "svc-1.ns-1"},
ExternalEndpoints: []common.Endpoint{},
},
EndpointList: endpoint.EndpointList{
Endpoints: []endpoint.Endpoint{},
......@@ -75,24 +67,19 @@ func TestGetServiceDetail(t *testing.T) {
},
},
namespace: "ns-2", name: "svc-2",
expectedActions: []string{"get", "list", "get", "list", "list", "list"},
expectedActions: []string{"get", "list"},
expected: &ServiceDetail{
ObjectMeta: api.ObjectMeta{
Name: "svc-2",
Namespace: "ns-2",
},
Selector: map[string]string{"app": "app2"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "svc-2.ns-2"},
ExternalEndpoints: []common.Endpoint{},
PodList: pod.PodList{
Pods: []pod.Pod{},
CumulativeMetrics: make([]metricapi.Metric, 0),
Errors: []error{},
},
EventList: common.EventList{
Events: []common.Event{},
Service: Service{
ObjectMeta: api.ObjectMeta{
Name: "svc-2",
Namespace: "ns-2",
},
Selector: map[string]string{"app": "app2"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "svc-2.ns-2"},
ExternalEndpoints: []common.Endpoint{},
},
EndpointList: endpoint.EndpointList{
Endpoints: []endpoint.Endpoint{},
},
......@@ -103,7 +90,7 @@ func TestGetServiceDetail(t *testing.T) {
for _, c := range cases {
fakeClient := fake.NewSimpleClientset(c.service)
actual, _ := GetServiceDetail(fakeClient, nil, c.namespace, c.name, dataselect.NoDataSelect)
actual, _ := GetServiceDetail(fakeClient, c.namespace, c.name)
actions := fakeClient.Actions()
if len(actions) != len(c.expectedActions) {
......
......@@ -84,3 +84,34 @@ func GetServiceListFromChannels(channels *common.ResourceChannels,
return CreateServiceList(services.Items, nonCriticalErrors, dsQuery), nil
}
func toService(service *v1.Service) Service {
return Service{
ObjectMeta: api.NewObjectMeta(service.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindService),
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
ExternalEndpoints: common.GetExternalEndpoints(service),
Selector: service.Spec.Selector,
ClusterIP: service.Spec.ClusterIP,
Type: service.Spec.Type,
}
}
// CreateServiceList returns paginated service list based on given service array and pagination query.
func CreateServiceList(services []v1.Service, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *ServiceList {
serviceList := &ServiceList{
Services: make([]Service, 0),
ListMeta: api.ListMeta{TotalItems: len(services)},
Errors: nonCriticalErrors,
}
serviceCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(services), dsQuery)
services = fromCells(serviceCells)
serviceList.ListMeta = api.ListMeta{TotalItems: filteredTotal}
for _, service := range services {
serviceList.Services = append(serviceList.Services, toService(&service))
}
return serviceList
}
......@@ -18,6 +18,9 @@ import (
"reflect"
"testing"
"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/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
......@@ -83,3 +86,88 @@ func TestGetServiceList(t *testing.T) {
}
}
}
func TestToServiceDetail(t *testing.T) {
cases := []struct {
service *v1.Service
eventList common.EventList
podList pod.PodList
endpointList endpoint.EndpointList
expected ServiceDetail
}{
{
service: &v1.Service{},
eventList: common.EventList{},
podList: pod.PodList{},
endpointList: endpoint.EndpointList{},
expected: ServiceDetail{
Service: Service{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
ExternalEndpoints: []common.Endpoint{},
},
},
}, {
service: &v1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service", Namespace: "test-namespace",
}},
expected: ServiceDetail{
Service: Service{
ObjectMeta: api.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "test-service.test-namespace"},
ExternalEndpoints: []common.Endpoint{},
},
},
},
}
for _, c := range cases {
actual := toServiceDetail(c.service, c.endpointList, nil)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("ToServiceDetail(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
c.expected)
}
}
}
func TestToService(t *testing.T) {
cases := []struct {
service *v1.Service
expected Service
}{
{
service: &v1.Service{}, expected: Service{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
ExternalEndpoints: []common.Endpoint{},
},
}, {
service: &v1.Service{
ObjectMeta: metaV1.ObjectMeta{
Name: "test-service", Namespace: "test-namespace",
}},
expected: Service{
ObjectMeta: api.ObjectMeta{
Name: "test-service",
Namespace: "test-namespace",
},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindService},
InternalEndpoint: common.Endpoint{Host: "test-service.test-namespace"},
ExternalEndpoints: []common.Endpoint{},
},
},
}
for _, c := range cases {
actual := toService(c.service)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("ToService(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
c.expected)
}
}
}
......@@ -20,7 +20,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
)
......
......@@ -17,28 +17,18 @@ package statefulset
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
ds "github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// StatefulSetDetail is a presentation layer view of Kubernetes Stateful Set resource. This means it is Stateful
// Set plus additional augmented data we can get from other sources (like services that target the same pods).
type StatefulSetDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
PodInfo common.PodInfo `json:"podInfo"`
PodList pod.PodList `json:"podList"`
ContainerImages []string `json:"containerImages"`
InitContainerImages []string `json:"initContainerImages"`
EventList common.EventList `json:"eventList"`
// Extends list item structure.
StatefulSet `json:",inline"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
......@@ -49,43 +39,24 @@ func GetStatefulSetDetail(client kubernetes.Interface, metricClient metricapi.Me
name string) (*StatefulSetDetail, error) {
log.Printf("Getting details of %s statefulset in %s namespace", name, namespace)
ss, err := client.AppsV1beta2().StatefulSets(namespace).Get(name, metaV1.GetOptions{})
ss, err := client.AppsV1().StatefulSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
podList, err := GetStatefulSetPods(client, metricClient, ds.DefaultDataSelectWithMetrics, name, namespace)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
podInfo, err := getStatefulSetPodInfo(client, ss)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
if criticalError != nil {
return nil, criticalError
}
events, err := event.GetResourceEvents(client, ds.DefaultDataSelect, ss.Namespace, ss.Name)
nonCriticalErrors, criticalError = errors.AppendError(err, nonCriticalErrors)
nonCriticalErrors, criticalError := errors.HandleError(err)
if criticalError != nil {
return nil, criticalError
}
ssDetail := getStatefulSetDetail(ss, *events, *podList, *podInfo, nonCriticalErrors)
ssDetail := getStatefulSetDetail(ss, podInfo, nonCriticalErrors)
return &ssDetail, nil
}
func getStatefulSetDetail(statefulSet *apps.StatefulSet, eventList common.EventList, podList pod.PodList,
podInfo common.PodInfo, nonCriticalErrors []error) StatefulSetDetail {
func getStatefulSetDetail(statefulSet *apps.StatefulSet, podInfo *common.PodInfo, nonCriticalErrors []error) StatefulSetDetail {
return StatefulSetDetail{
ObjectMeta: api.NewObjectMeta(statefulSet.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindStatefulSet),
ContainerImages: common.GetContainerImages(&statefulSet.Spec.Template.Spec),
InitContainerImages: common.GetInitContainerImages(&statefulSet.Spec.Template.Spec),
PodInfo: podInfo,
PodList: podList,
EventList: eventList,
Errors: nonCriticalErrors,
StatefulSet: toStatefulSet(statefulSet, podInfo),
Errors: nonCriticalErrors,
}
}
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
)
......@@ -32,32 +32,21 @@ import (
type StatefulSetList struct {
ListMeta api.ListMeta `json:"listMeta"`
// Basic information about resources status on the list.
Status common.ResourceStatus `json:"status"`
// Unordered list of Pet Sets.
StatefulSets []StatefulSet `json:"statefulSets"`
CumulativeMetrics []metricapi.Metric `json:"cumulativeMetrics"`
Status common.ResourceStatus `json:"status"`
StatefulSets []StatefulSet `json:"statefulSets"`
CumulativeMetrics []metricapi.Metric `json:"cumulativeMetrics"`
// List of non-critical errors, that occurred during resource retrieval.
Errors []error `json:"errors"`
}
// StatefulSet is a presentation layer view of Kubernetes Stateful Set resource. This means it is
// Stateful Set plus additional augmented data we can get from other sources (like services that
// target the same pods).
// StatefulSet is a presentation layer view of Kubernetes Stateful Set resource.
type StatefulSet struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// Aggregate information about pods belonging to this Pet Set.
Pods common.PodInfo `json:"pods"`
// Container images of the Stateful Set.
ContainerImages []string `json:"containerImages"`
// Init container images of the Stateful Set.
InitContainerImages []string `json:"initContainerImages"`
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Pods common.PodInfo `json:"podInfo"`
ContainerImages []string `json:"containerImages"`
InitContainerImages []string `json:"initContainerImages"`
}
// GetStatefulSetList returns a list of all Stateful Sets in the cluster.
......
......@@ -23,7 +23,7 @@ import (
metricapi "github.com/kubernetes/dashboard/src/app/backend/integration/metric/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
......
......@@ -23,7 +23,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/pod"
apps "k8s.io/api/apps/v1beta2"
apps "k8s.io/api/apps/v1"
v1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
......@@ -52,7 +52,7 @@ func GetStatefulSetPods(client kubernetes.Interface, metricClient metricapi.Metr
// getRawStatefulSetPods return array of api pods targeting pet set with given name.
func getRawStatefulSetPods(client kubernetes.Interface, name, namespace string) ([]v1.Pod, error) {
statefulSet, err := client.AppsV1beta1().StatefulSets(namespace).Get(name, metaV1.GetOptions{})
statefulSet, err := client.AppsV1().StatefulSets(namespace).Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
......
......@@ -15,32 +15,10 @@
package storageclass
import (
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/persistentvolume"
storage "k8s.io/api/storage/v1"
)
func toStorageClass(storageClass *storage.StorageClass) StorageClass {
return StorageClass{
ObjectMeta: api.NewObjectMeta(storageClass.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindStorageClass),
Provisioner: storageClass.Provisioner,
Parameters: storageClass.Parameters,
}
}
func toStorageClassDetail(storageClass *storage.StorageClass,
persistentVolumeList *persistentvolume.PersistentVolumeList) StorageClassDetail {
return StorageClassDetail{
ObjectMeta: api.NewObjectMeta(storageClass.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindStorageClass),
Provisioner: storageClass.Provisioner,
Parameters: storageClass.Parameters,
PersistentVolumeList: *persistentVolumeList,
}
}
// The code below allows to perform complex data section on []storage.StorageClass
type StorageClassCell storage.StorageClass
......
......@@ -17,55 +17,32 @@ package storageclass
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/persistentvolume"
storage "k8s.io/api/storage/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// StorageClass is a representation of a kubernetes StorageClass object.
type StorageClass struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
// provisioner is the driver expected to handle this StorageClass.
// This is an optionally-prefixed name, like a label key.
// For example: "kubernetes.io/gce-pd" or "kubernetes.io/aws-ebs".
// This value may not be empty.
Provisioner string `json:"provisioner"`
// parameters holds parameters for the provisioner.
// These values are opaque to the system and are passed directly
// to the provisioner. The only validation done on keys is that they are
// not empty. The maximum number of parameters is
// 512, with a cumulative max size of 256K
// +optional
Parameters map[string]string `json:"parameters"`
}
// StorageClassDetail provides the presentation layer view of Kubernetes StorageClass resource,
// It is StorageClassDetail plus PersistentVolumes associated with StorageClass.
// StorageClassDetail provides the presentation layer view of Storage Class resource.
type StorageClassDetail struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Provisioner string `json:"provisioner"`
Parameters map[string]string `json:"parameters"`
PersistentVolumeList persistentvolume.PersistentVolumeList `json:"persistentVolumeList"`
// Extends list item structure.
StorageClass `json:",inline"`
}
// GetStorageClass returns storage class object.
// GetStorageClass returns Storage Class resource.
func GetStorageClass(client kubernetes.Interface, name string) (*StorageClassDetail, error) {
log.Printf("Getting details of %s storage class", name)
storage, err := client.StorageV1().StorageClasses().Get(name, metaV1.GetOptions{})
sc, err := client.StorageV1().StorageClasses().Get(name, metaV1.GetOptions{})
if err != nil {
return nil, err
}
persistentVolumeList, err := persistentvolume.GetStorageClassPersistentVolumes(client,
storage.Name, dataselect.DefaultDataSelect)
storageClass := toStorageClassDetail(storage, persistentVolumeList)
storageClass := toStorageClassDetail(sc)
return &storageClass, err
}
func toStorageClassDetail(storageClass *storage.StorageClass) StorageClassDetail {
return StorageClassDetail{
StorageClass: toStorageClass(storageClass),
}
}
......@@ -19,7 +19,6 @@ import (
"testing"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/resource/persistentvolume"
storage "k8s.io/api/storage/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
......@@ -52,41 +51,3 @@ func TestToStorageClass(t *testing.T) {
}
}
}
func TestToStorageClassDetail(t *testing.T) {
cases := []struct {
storage *storage.StorageClass
persistentVolumeList persistentvolume.PersistentVolumeList
expected StorageClassDetail
}{
{
&storage.StorageClass{},
persistentvolume.PersistentVolumeList{},
StorageClassDetail{
TypeMeta: api.TypeMeta{Kind: api.ResourceKindStorageClass},
},
},
{
&storage.StorageClass{ObjectMeta: metaV1.ObjectMeta{Name: "storage-class"}},
persistentvolume.PersistentVolumeList{Items: []persistentvolume.PersistentVolume{{ObjectMeta: api.ObjectMeta{Name: "pv-1"}}}},
StorageClassDetail{
ObjectMeta: api.ObjectMeta{Name: "storage-class"},
TypeMeta: api.TypeMeta{Kind: api.ResourceKindStorageClass},
PersistentVolumeList: persistentvolume.PersistentVolumeList{
Items: []persistentvolume.PersistentVolume{{
ObjectMeta: api.ObjectMeta{Name: "pv-1"},
}},
},
},
},
}
for _, c := range cases {
actual := toStorageClassDetail(c.storage, &c.persistentVolumeList)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("toStorageClassDetail(%#v, %#v) == \ngot %#v, \nexpected %#v",
c.storage, c.persistentVolumeList, actual, c.expected)
}
}
}
......@@ -25,7 +25,7 @@ import (
"k8s.io/client-go/kubernetes"
)
// StorageClassList holds a list of storage class objects in the cluster.
// StorageClassList holds a list of Storage Class objects in the cluster.
type StorageClassList struct {
ListMeta api.ListMeta `json:"listMeta"`
StorageClasses []StorageClass `json:"storageClasses"`
......@@ -34,6 +34,14 @@ type StorageClassList struct {
Errors []error `json:"errors"`
}
// StorageClass is a representation of a Kubernetes Storage Class object.
type StorageClass struct {
ObjectMeta api.ObjectMeta `json:"objectMeta"`
TypeMeta api.TypeMeta `json:"typeMeta"`
Provisioner string `json:"provisioner"`
Parameters map[string]string `json:"parameters"`
}
// GetStorageClassList returns a list of all storage class objects in the cluster.
func GetStorageClassList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (
*StorageClassList, error) {
......@@ -78,3 +86,12 @@ func toStorageClassList(storageClasses []storage.StorageClass, nonCriticalErrors
return storageClassList
}
func toStorageClass(storageClass *storage.StorageClass) StorageClass {
return StorageClass{
ObjectMeta: api.NewObjectMeta(storageClass.ObjectMeta),
TypeMeta: api.NewTypeMeta(api.ResourceKindStorageClass),
Provisioner: storageClass.Provisioner,
Parameters: storageClass.Parameters,
}
}
......@@ -42,7 +42,7 @@ func ValidateAppName(spec *AppNameValiditySpec, client client.Interface) (*AppNa
isValidDeployment := false
isValidService := false
_, err := client.AppsV1beta2().Deployments(spec.Namespace).Get(spec.Name, metaV1.GetOptions{})
_, err := client.AppsV1().Deployments(spec.Namespace).Get(spec.Name, metaV1.GetOptions{})
if err != nil {
if kdErrors.IsNotFoundError(err) || kdErrors.IsForbiddenError(err) {
isValidDeployment = true
......
......@@ -63,23 +63,23 @@ export class DaemonSetListComponent extends ResourceListWithStatuses<DaemonSetLi
}
isInErrorState(resource: DaemonSet): boolean {
return resource.pods.warnings.length > 0;
return resource.podInfo.warnings.length > 0;
}
isInPendingState(resource: DaemonSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending > 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending > 0;
}
isInSuccessState(resource: DaemonSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending === 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending === 0;
}
hasErrors(daemonSet: DaemonSet): boolean {
return daemonSet.pods.warnings.length > 0;
return daemonSet.podInfo.warnings.length > 0;
}
getEvents(daemonSet: DaemonSet): Event[] {
return daemonSet.pods.warnings;
return daemonSet.podInfo.warnings;
}
getDisplayColumns(): string[] {
......
......@@ -76,7 +76,7 @@ limitations under the License.
<ng-container matColumnDef="pods">
<mat-header-cell *matHeaderCellDef>Pods</mat-header-cell>
<mat-cell *matCellDef="let daemonSet">
{{daemonSet.pods.running}} / {{daemonSet.pods.desired}}
{{daemonSet.podInfo.running}} / {{daemonSet.podInfo.desired}}
</mat-cell>
</ng-container>
......
......@@ -64,15 +64,15 @@ export class JobListComponent extends ResourceListWithStatuses<JobList, Job> {
}
isInErrorState(resource: Job): boolean {
return resource.pods.warnings.length > 0;
return resource.podInfo.warnings.length > 0;
}
isInPendingState(resource: Job): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending > 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending > 0;
}
isInSuccessState(resource: Job): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending === 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending === 0;
}
getDisplayColumns(): string[] {
......@@ -80,11 +80,11 @@ export class JobListComponent extends ResourceListWithStatuses<JobList, Job> {
}
hasErrors(job: Job): boolean {
return job.pods.warnings.length > 0;
return job.podInfo.warnings.length > 0;
}
getEvents(job: Job): Event[] {
return job.pods.warnings;
return job.podInfo.warnings;
}
private shouldShowNamespaceColumn_(): boolean {
......
......@@ -79,7 +79,7 @@ limitations under the License.
<ng-container matColumnDef="pods">
<mat-header-cell *matHeaderCellDef>Pods</mat-header-cell>
<mat-cell *matCellDef="let job">
{{job.pods.running}} / {{job.pods.desired}}
{{job.podInfo.running}} / {{job.podInfo.desired}}
</mat-cell>
</ng-container>
......
......@@ -64,15 +64,15 @@ export class ReplicaSetListComponent extends ResourceListWithStatuses<ReplicaSet
}
isInErrorState(resource: ReplicaSet): boolean {
return resource.pods.warnings.length > 0;
return resource.podInfo.warnings.length > 0;
}
isInPendingState(resource: ReplicaSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending > 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending > 0;
}
isInSuccessState(resource: ReplicaSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending === 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending === 0;
}
protected getDisplayColumns(): string[] {
......@@ -84,10 +84,10 @@ export class ReplicaSetListComponent extends ResourceListWithStatuses<ReplicaSet
}
hasErrors(replicaSet: ReplicaSet): boolean {
return replicaSet.pods.warnings.length > 0;
return replicaSet.podInfo.warnings.length > 0;
}
getEvents(replicaSet: ReplicaSet): Event[] {
return replicaSet.pods.warnings;
return replicaSet.podInfo.warnings;
}
}
......@@ -79,7 +79,7 @@ limitations under the License.
<ng-container matColumnDef="pods">
<mat-header-cell *matHeaderCellDef>Pods</mat-header-cell>
<mat-cell *matCellDef="let replicaSet">
{{replicaSet.pods.running}} / {{replicaSet.pods.desired}}
{{replicaSet.podInfo.running}} / {{replicaSet.podInfo.desired}}
</mat-cell>
</ng-container>
......
......@@ -65,15 +65,15 @@ export class ReplicationControllerListComponent extends
}
isInErrorState(resource: ReplicationController): boolean {
return resource.pods.warnings.length > 0;
return resource.podInfo.warnings.length > 0;
}
isInPendingState(resource: ReplicationController): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending > 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending > 0;
}
isInSuccessState(resource: ReplicationController): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending === 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending === 0;
}
protected getDisplayColumns(): string[] {
......@@ -85,10 +85,10 @@ export class ReplicationControllerListComponent extends
}
hasErrors(rc: ReplicationController): boolean {
return rc.pods.warnings.length > 0;
return rc.podInfo.warnings.length > 0;
}
getEvents(rc: ReplicationController): Event[] {
return rc.pods.warnings;
return rc.podInfo.warnings;
}
}
......@@ -64,15 +64,15 @@ export class StatefulSetListComponent extends
}
isInErrorState(resource: StatefulSet): boolean {
return resource.pods.warnings.length > 0;
return resource.podInfo.warnings.length > 0;
}
isInPendingState(resource: StatefulSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending > 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending > 0;
}
isInSuccessState(resource: StatefulSet): boolean {
return resource.pods.warnings.length === 0 && resource.pods.pending === 0;
return resource.podInfo.warnings.length === 0 && resource.podInfo.pending === 0;
}
getDisplayColumns(): string[] {
......@@ -80,11 +80,11 @@ export class StatefulSetListComponent extends
}
hasErrors(statefulSet: StatefulSet): boolean {
return statefulSet.pods.warnings.length > 0;
return statefulSet.podInfo.warnings.length > 0;
}
getEvents(statefulSet: StatefulSet): Event[] {
return statefulSet.pods.warnings;
return statefulSet.podInfo.warnings;
}
private shouldShowNamespaceColumn_(): boolean {
......
......@@ -76,7 +76,7 @@ limitations under the License.
<ng-container matColumnDef="pods">
<mat-header-cell *matHeaderCellDef>Pods</mat-header-cell>
<mat-cell *matCellDef="let ss">
{{ss.pods.running}} / {{ss.pods.desired}}
{{ss.podInfo.running}} / {{ss.podInfo.desired}}
</mat-cell>
</ng-container>
......
......@@ -184,7 +184,7 @@ export interface CronJob extends Resource {
}
export interface DaemonSet extends Resource {
pods: PodInfo;
podInfo: PodInfo;
containerImages: string[];
initContainerImages: string[];
}
......@@ -253,7 +253,7 @@ export interface Ingress extends Resource {
}
export interface Job extends Resource {
pods: PodInfo;
podInfo: PodInfo;
containerImages: string[];
initContainerImages: string[];
parallelism: number;
......@@ -298,13 +298,13 @@ export interface PodContainer {
}
export interface ReplicaSet extends Resource {
pods: PodInfo;
podInfo: PodInfo;
containerImages: string[];
initContainerImages: string[];
}
export interface ReplicationController extends Resource {
pods: PodInfo;
podInfo: PodInfo;
containerImages: string[];
initContainerImages: string[];
}
......@@ -322,7 +322,7 @@ export interface Service extends Resource {
}
export interface StatefulSet extends Resource {
pods: PodInfo;
podInfo: PodInfo;
containerImages: string[];
initContainerImages: string[];
}
......@@ -388,10 +388,6 @@ export interface DaemonSetDetail extends ResourceDetail {
containerImages: string[];
initContainerImages: string[];
podInfo: PodInfo;
podList: PodList;
serviceList: ServiceList;
hasMetrics: boolean;
eventList: EventList;
}
export interface NamespaceDetail extends ResourceDetail {
......@@ -453,8 +449,6 @@ export interface CronJobDetail extends ResourceDetail {
lastSchedule: string;
concurrencyPolicy: string;
startingDeadlineSeconds: number;
activeJobs: JobList;
events: EventList;
}
export interface StatefulSetDetail extends ResourceDetail {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册