提交 64b321a3 编写于 作者: S Sebastian Florek

Add initial version of service list and service details pages (#726)

上级 4104146d
......@@ -203,14 +203,11 @@ func UpdateReplicasCount(client k8sClient.Interface, namespace, name string,
// Returns detailed information about service from given service
func getService(service api.Service, replicationController api.ReplicationController,
pods []api.Pod, nodes []api.Node) resourceService.Service {
return resourceService.Service{
ObjectMeta: common.CreateObjectMeta(service.ObjectMeta),
TypeMeta: common.CreateTypeMeta(service.TypeMeta),
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace,
service.Spec.Ports),
ExternalEndpoints: getExternalEndpoints(replicationController, pods, service, nodes),
Selector: service.Spec.Selector,
}
result := resourceService.GetServiceDetails(&service);
result.ExternalEndpoints = getExternalEndpoints(replicationController, pods, service, nodes)
return result;
}
// Returns array of external endpoints for a replication controller.
......
......@@ -37,6 +37,13 @@ type Service struct {
// 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 api.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"`
}
// ServiceList contains a list of services in the cluster.
......@@ -55,7 +62,7 @@ func GetService(client client.Interface, namespace, name string) (*Service, erro
return nil, err
}
service := getServices(serviceData)
service := GetServiceDetails(serviceData)
return &service, nil
}
......@@ -74,18 +81,21 @@ func GetServiceList(client client.Interface) (*ServiceList, error) {
serviceList := &ServiceList{Services: make([]Service, 0)}
for _, service := range services.Items {
serviceList.Services = append(serviceList.Services, getServices(&service))
serviceList.Services = append(serviceList.Services, GetServiceDetails(&service))
}
return serviceList, nil
}
func getServices(service *api.Service) Service {
// GetServiceDetails returns api service object based on kubernetes service object
func GetServiceDetails(service *api.Service) Service {
return Service{
ObjectMeta: common.CreateObjectMeta(service.ObjectMeta),
TypeMeta: common.CreateTypeMeta(service.TypeMeta),
InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports),
// TODO(maciaszczykm): Fill ExternalEndpoints with data.
Selector: service.Spec.Selector,
Selector: service.Spec.Selector,
ClusterIP: service.Spec.ClusterIP,
Type: service.Spec.Type,
}
}
......@@ -214,7 +214,7 @@ backendApi.TypeMeta;
* containerImages: !Array<string>,
* podInfo: !backendApi.PodInfo,
* pods: !backendApi.PodList,
* services: !Array<!backendApi.Service>,
* services: !Array<!backendApi.ServiceDetail>,
* hasMetrics: boolean
* }}
*/
......@@ -253,10 +253,20 @@ backendApi.Pod;
* typeMeta: !backendApi.TypeMeta,
* internalEndpoint: !backendApi.Endpoint,
* externalEndpoints: !Array<!backendApi.Endpoint>,
* selector: !Object<string, string>
* selector: !Object<string, string>,
* labels: !Object<string, string>,
* clusterIP: string,
* type: string
* }}
*/
backendApi.Service;
backendApi.ServiceDetail;
/**
* @typedef {{
* services: !Array<backendApi.ServiceDetail>
* }}
*/
backendApi.ServiceList;
/**
* @typedef {{
......
......@@ -18,14 +18,16 @@
*/
import chromeModule from './chrome/chrome_module';
import deployModule from './deploy/deploy_module';
import deprecatedReplicationControllerListModule from './replicationcontrollerlistdeprecated/replicationcontrollerlist_module';
import errorModule from './error/error_module';
import indexConfig from './index_config';
import routeConfig from './index_route';
import logsModule from './logs/logs_module';
import replicaSetListModule from './replicasetlist/replicasetlist_module';
import replicationControllerDetailModule from './replicationcontrollerdetail/replicationcontrollerdetail_module';
import replicationControllerListModule from './replicationcontrollerlist/replicationcontrollerlist_module';
import deprecatedReplicationControllerListModule from './replicationcontrollerlistdeprecated/replicationcontrollerlist_module';
import replicaSetListModule from './replicasetlist/replicasetlist_module';
import routeConfig from './index_route';
import serviceDetailModule from './servicedetail/servicedetail_module';
import serviceListModule from './servicelist/servicelist_module';
import workloadsModule from './workloads/workloads_module';
export default angular
......@@ -48,6 +50,8 @@ export default angular
deprecatedReplicationControllerListModule.name,
replicaSetListModule.name,
workloadsModule.name,
serviceDetailModule.name,
serviceListModule.name,
])
.config(indexConfig)
.config(routeConfig);
......@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<kd-resource-card-list selectable="false" with-statuses="false" ng-if="::$ctrl.podList.pods">
<kd-resource-card-list selectable="::$ctrl.selectable" with-statuses="::$ctrl.withStatuses"
ng-if="::$ctrl.podList.pods">
<kd-resource-card-header-columns>
<kd-resource-card-header-column size="medium" grow="4">Name</kd-resource-card-header-column>
<kd-resource-card-header-column>Status</kd-resource-card-header-column>
......
......@@ -54,5 +54,9 @@ export const podCardListComponent = {
'podList': '<',
/** {!function({pod: !backendApi.Pod}): string} */
'logsHrefFn': '&',
/** {boolean} */
'selectable': '<',
/** {boolean} */
'withStatuses': '<',
},
};
......@@ -16,7 +16,9 @@ import stateConfig from './podlist_stateconfig';
import {podCardListComponent} from './podcardlist_component';
/**
* Module containing endpoint components.
* Angular module for the Pods list view.
*
* The view shows Pods running in the cluster and allows to manage them.
*/
export default angular
.module(
......
......@@ -20,9 +20,9 @@ import {replicaSetCardListComponent} from './replicasetcardlist_component';
import replicaSetDetailModule from 'replicasetdetail/replicasetdetail_module';
/**
* Angular module for the Replication Controller list view.
* Angular module for the Replica Set list view.
*
* The view shows Replication Controllers running in the cluster and allows to manage them.
* The view shows Replica Set running in the cluster and allows to manage them.
*/
export default angular
.module(
......
......@@ -18,19 +18,22 @@ limitations under the License.
<md-content>
<md-tabs md-border-bottom md-dynamic-height>
<md-tab label="Overview">
<kd-replication-controller-info details="::ctrl.replicationControllerDetail">
<kd-replication-controller-info replication-controller="::ctrl.replicationControllerDetail">
</kd-replication-controller-info>
<kd-replication-controller-services services="::ctrl.replicationControllerDetail.services">
</kd-replication-controller-services>
<kd-content-card ng-if="::ctrl.replicationControllerDetail.services">
<kd-title>Services</kd-title>
<kd-content>
<kd-service-card-list services="::ctrl.replicationControllerDetail.services">
</kd-service-card-list>
</kd-content>
</kd-content-card>
<kd-content-card>
<kd-title>
Pods
</kd-title>
<kd-title>Pods</kd-title>
<kd-content>
<kd-pod-card-list pod-list="::ctrl.replicationControllerDetail.pods"
logs-href-fn="::ctrl.getPodLogsHref(pod)">
logs-href-fn="::ctrl.getPodLogsHref(pod)">
</kd-pod-card-list>
</kd-content>
</kd-content-card>
......
......@@ -16,11 +16,11 @@ import componentsModule from './../common/components/components_module';
import filtersModule from 'common/filters/filters_module';
import logsModule from 'logs/logs_module';
import podListModule from 'podlist/podlist_module';
import serviceListModule from 'servicelist/servicelist_module';
import stateConfig from './replicationcontrollerdetail_stateconfig';
import {replicationControllerEventsComponent} from './replicationcontrollerevents_component';
import {replicationControllerInfoComponent} from './replicationcontrollerinfo_component';
import {ReplicationControllerService} from './replicationcontroller_service';
import {replicationControllerServicesComponent} from './replicationcontrollerservices_component';
/**
* Angular module for the Replication Controller details view.
......@@ -38,9 +38,9 @@ export default angular
filtersModule.name,
logsModule.name,
podListModule.name,
serviceListModule.name,
])
.config(stateConfig)
.component('kdReplicationControllerInfo', replicationControllerInfoComponent)
.component('kdReplicationControllerServices', replicationControllerServicesComponent)
.component('kdReplicationControllerEvents', replicationControllerEventsComponent)
.service('kdReplicationControllerService', ReplicationControllerService);
......@@ -15,22 +15,24 @@ limitations under the License.
-->
<kd-info-card>
<kd-info-card-header>Resource details</kd-info-card-header>
<kd-info-card-header>Resource Details</kd-info-card-header>
<kd-info-card-section name="Details">
<kd-info-card-entry title="Name">
<kd-middle-ellipsis display-string="{{::infoCtrl.details.objectMeta.name}}"></kd-middle-ellipsis>
<kd-middle-ellipsis
display-string="{{::$ctrl.replicationController.objectMeta.name}}">
</kd-middle-ellipsis>
</kd-info-card-entry>
<kd-info-card-entry title="Namespace">
{{::infoCtrl.details.objectMeta.namespace}}
{{::$ctrl.replicationController.objectMeta.namespace}}
</kd-info-card-entry>
<kd-info-card-entry title="Label selector">
<kd-labels labels="::infoCtrl.details.labelSelector"></kd-labels>
<kd-labels labels="::$ctrl.replicationController.labelSelector"></kd-labels>
</kd-info-card-entry>
<kd-info-card-entry title="Labels">
<kd-labels labels="::infoCtrl.details.objectMeta.labels"></kd-labels>
<kd-labels labels="::$ctrl.replicationController.objectMeta.labels"></kd-labels>
</kd-info-card-entry>
<kd-info-card-entry title="Images">
<div ng-repeat="image in infoCtrl.details.containerImages">
<div ng-repeat="image in $ctrl.replicationController.containerImages">
<kd-middle-ellipsis display-string="{{::image}}"></kd-middle-ellipsis>
</div>
</kd-info-card-entry>
......@@ -38,24 +40,24 @@ limitations under the License.
<kd-info-card-section name="Status">
<kd-info-card-entry title="Pods">
<div ng-if="!infoCtrl.areDesiredPodsRunning()">
{{::infoCtrl.details.podInfo.current}} created,
{{::infoCtrl.details.podInfo.desired}} desired
<div ng-if="!$ctrl.areDesiredPodsRunning()">
{{::$ctrl.replicationController.podInfo.current}} created,
{{::$ctrl.replicationController.podInfo.desired}} desired
</div>
<div ng-if="infoCtrl.areDesiredPodsRunning()">
{{::infoCtrl.details.podInfo.running}} running
<div ng-if="$ctrl.areDesiredPodsRunning()">
{{::$ctrl.replicationController.podInfo.running}} running
</div>
</kd-info-card-entry>
<kd-info-card-entry title="Pods status" ng-if="!infoCtrl.areDesiredPodsRunning()">
<div ng-if="!infoCtrl.areDesiredPodsRunning()">
<div ng-if="::infoCtrl.details.podInfo.pending" class="kd-comma-separated-item">
{{::infoCtrl.details.podInfo.pending}} pending<!-- Collapse whitespace
<kd-info-card-entry title="Pods status" ng-if="!$ctrl.areDesiredPodsRunning()">
<div ng-if="!$ctrl.areDesiredPodsRunning()">
<div ng-if="::$ctrl.replicationController.podInfo.pending" class="kd-comma-separated-item">
{{::$ctrl.replicationController.podInfo.pending}} pending<!-- Collapse whitespace
--></div>
<div ng-if="::infoCtrl.details.podInfo.failed" class="kd-comma-separated-item">
{{::infoCtrl.details.podInfo.failed}} failed<!-- Collapse whitespace
<div ng-if="::$ctrl.replicationController.podInfo.failed" class="kd-comma-separated-item">
{{::$ctrl.replicationController.podInfo.failed}} failed<!-- Collapse whitespace
--></div>
<div ng-if="::infoCtrl.details.podInfo.running" class="kd-comma-separated-item">
{{::infoCtrl.details.podInfo.running}} running
<div ng-if="::$ctrl.replicationController.podInfo.running" class="kd-comma-separated-item">
{{::$ctrl.replicationController.podInfo.running}} running
</div>
</div>
</kd-info-card-entry>
......
......@@ -24,14 +24,17 @@ export default class ReplicationControllerInfoController {
* Replication controller details. Initialized from the scope.
* @export {!backendApi.ReplicationControllerDetail}
*/
this.details;
this.replicationController;
}
/**
* @return {boolean}
* @export
*/
areDesiredPodsRunning() { return this.details.podInfo.running === this.details.podInfo.desired; }
areDesiredPodsRunning() {
return this.replicationController.podInfo.running ===
this.replicationController.podInfo.desired;
}
}
/**
......@@ -41,10 +44,9 @@ export default class ReplicationControllerInfoController {
*/
export const replicationControllerInfoComponent = {
controller: ReplicationControllerInfoController,
controllerAs: 'infoCtrl',
templateUrl: 'replicationcontrollerdetail/replicationcontrollerinfo.html',
bindings: {
/** {!backendApi.ReplicationControllerDetail} */
'details': '=',
'replicationController': '<',
},
};
<!--
Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<kd-content-card ng-if="::$ctrl.services">
<kd-title>Services</kd-title>
<kd-content>
<kd-resource-card-list selectable="false" with-statuses="false">
<kd-resource-card-header-columns>
<kd-resource-card-header-column>Name</kd-resource-card-header-column>
<kd-resource-card-header-column>Label selector</kd-resource-card-header-column>
<kd-resource-card-header-column>Internal IP</kd-resource-card-header-column>
<kd-resource-card-header-column>External IP</kd-resource-card-header-column>
</kd-resource-card-header-columns>
<kd-resource-card ng-repeat="service in $ctrl.services">
<kd-resource-card-columns>
<kd-resource-card-column>{{::service.name}}</kd-resource-card-column>
<kd-resource-card-column>
<kd-labels labels="::service.selector"></kd-labels>
</kd-resource-card-column>
<kd-resource-card-column>
<div ng-if="::service.internalEndpoint">
<kd-internal-endpoint endpoint="::service.internalEndpoint"></kd-internal-endpoint>
</div>
<div ng-hide="service.internalEndpoint">none</div>
</kd-resource-card-column>
<kd-resource-card-column>
<div ng-repeat="endpoint in service.externalEndpoints">
<kd-external-endpoint endpoint="::endpoint"></kd-external-endpoint>
</div>
<div ng-hide="::service.externalEndpoints">none</div>
</kd-resource-card-column>
</kd-resource-card-columns>
</kd-resource-card>
</kd-resource-card-list>
</kd-content>
</kd-content-card>
<!--
Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<kd-service-info service="ctrl.serviceDetail"></kd-service-info>
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
/**
* @final
*/
export class ServiceDetailController {
/**
* @param {!backendApi.ServiceDetail} serviceDetail
*/
constructor(serviceDetail) {
/** @export {!backendApi.ServiceDetail} */
this.serviceDetail = serviceDetail;
}
}
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import componentsModule from './../common/components/components_module';
import stateConfig from './servicedetail_stateconfig';
import {serviceInfoComponent} from './servicedetailinfo_component';
/**
* Angular module for the Service details view.
*
* The view shows detailed view of a Service.
*/
export default angular
.module(
'kubernetesDashboard.serviceDetail',
[
'ngMaterial',
componentsModule.name,
])
.config(stateConfig)
.component('kdServiceInfo', serviceInfoComponent);
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
/** Name of the state. Can be used in, e.g., $state.go method. */
export const stateName = 'serviceDetail';
/**
* Parameters for this state.
*
* All properties are @exported and in sync with URL param names.
* @final
*/
export class StateParams {
/**
* @param {string} namespace
* @param {string} service
*/
constructor(namespace, service) {
/** @export {string} Namespace of this Service. */
this.namespace = namespace;
/** @export {string} Name of this Service. */
this.service = service;
}
}
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import {actionbarViewName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_component';
import {stateName} from './servicedetail_state';
import {stateName as serviceList, stateUrl} from './../servicelist/servicelist_state';
import {ServiceDetailController} from './servicedetail_controller';
/**
* Configures states for the service details view.
*
* @param {!ui.router.$stateProvider} $stateProvider
* @ngInject
*/
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
url: `${stateUrl}/:namespace/:service`,
resolve: {
'serviceDetailResource': getServiceDetailResource,
'serviceDetail': resolveServiceDetail,
},
data: {
[breadcrumbsConfig]: {
'label': '{{$stateParams.service}}',
'parent': serviceList,
},
},
views: {
'': {
controller: ServiceDetailController,
controllerAs: 'ctrl',
templateUrl: 'servicedetail/servicedetail.html',
},
[actionbarViewName]: {},
},
});
}
/**
* @param {!./servicedetail_state.StateParams} $stateParams
* @param {!angular.$resource} $resource
* @return {!angular.Resource<!backendApi.ServiceDetail>}
*/
export function getServiceDetailResource($stateParams, $resource) {
return $resource(`api/v1/services/${$stateParams.namespace}/${$stateParams.service}`);
}
/**
* @param {!angular.Resource<!backendApi.ServiceDetail>} serviceDetailResource
* @return {!angular.$q.Promise}
*/
export function resolveServiceDetail(serviceDetailResource) {
return serviceDetailResource.get().$promise;
}
<!--
Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<kd-info-card>
<kd-info-card-header>Resource Details</kd-info-card-header>
<kd-info-card-section name="Details">
<kd-info-card-entry title="Name">
<kd-middle-ellipsis display-string="{{::$ctrl.service.objectMeta.name}}"></kd-middle-ellipsis>
</kd-info-card-entry>
<kd-info-card-entry title="Namespace">
{{::$ctrl.service.objectMeta.namespace}}
</kd-info-card-entry>
<kd-info-card-entry title="Label selector">
<div ng-if="::$ctrl.service.selector">
<kd-labels labels="::$ctrl.service.selector"></kd-labels>
</div>
<div ng-hide="::$ctrl.service.selector">
none
</div>
</kd-info-card-entry>
<kd-info-card-entry title="Labels">
<div ng-if="::$ctrl.service.objectMeta.labels">
<kd-labels labels="::$ctrl.service.objectMeta.labels"></kd-labels>
</div>
<div ng-hide="::$ctrl.service.objectMeta.labels">
none
</div>
</kd-info-card-entry>
<kd-info-card-entry title="Type">
{{::$ctrl.service.type}}
</kd-info-card-entry>
</kd-info-card-section>
<kd-info-card-section name="Connection">
<kd-info-card-entry title="Cluster IP">
{{::$ctrl.service.clusterIP}}
</kd-info-card-entry>
<kd-info-card-entry title="Internal endpoints" ng-if="::$ctrl.service.internalEndpoint">
<kd-internal-endpoint endpoint="::$ctrl.service.internalEndpoint"></kd-internal-endpoint>
</kd-info-card-entry>
<kd-info-card-entry title="External endpoints" ng-if="::$ctrl.detail.externalEndpoints">
<kd-external-endpoint endpoint="::$ctrl.service.internalEndpoint"></kd-external-endpoint>
</kd-info-card-entry>
</kd-info-card-section>
</kd-info-card>
......@@ -13,14 +13,14 @@
// limitations under the License.
/**
* Definition object for the component that displays replication controller services card.
* Definition object for the component that displays service info.
*
* @type {!angular.Component}
* @return {!angular.Directive}
*/
export const replicationControllerServicesComponent = {
templateUrl: 'replicationcontrollerdetail/replicationcontrollerservices.html',
export const serviceInfoComponent = {
templateUrl: 'servicedetail/servicedetailinfo.html',
bindings: {
/** {!Array<!backendApi.Service>} */
'services': '=',
/** {!backendApi.ServiceDetail} */
'service': '<',
},
};
<!--
Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<kd-resource-card-list selectable="::$ctrl.selectable" with-statuses="::$ctrl.withStatuses">
<kd-resource-card-header-columns>
<kd-resource-card-header-column>Name</kd-resource-card-header-column>
<kd-resource-card-header-column>Labels</kd-resource-card-header-column>
<kd-resource-card-header-column>Cluster IP</kd-resource-card-header-column>
<kd-resource-card-header-column>Internal endpoints</kd-resource-card-header-column>
<kd-resource-card-header-column>External endpoints</kd-resource-card-header-column>
</kd-resource-card-header-columns>
<kd-resource-card ng-repeat="service in ::$ctrl.services">
<kd-resource-card-columns>
<kd-resource-card-column>
<a ng-href="{{::$ctrl.getServiceDetailHref(service)}}">
<kd-middle-ellipsis display-string="{{::service.objectMeta.name}}"></kd-middle-ellipsis>
</a>
</kd-resource-card-column>
<kd-resource-card-column>
<kd-labels labels="::service.objectMeta.labels"></kd-labels>
</kd-resource-card-column>
<kd-resource-card-column>{{::service.clusterIP}}</kd-resource-card-column>
<kd-resource-card-column>
<div ng-if="::service.internalEndpoint">
<kd-internal-endpoint endpoint="::service.internalEndpoint"></kd-internal-endpoint>
</div>
<div ng-hide="service.internalEndpoint">-</div>
</kd-resource-card-column>
<kd-resource-card-column>
<div ng-if="::service.externalEndpoints"
ng-repeat="endpoint in ::service.externalEndpoints">
<kd-external-endpoint endpoint="endpoint"></kd-external-endpoint>
</div>
<div ng-hide="service.externalEndpoints">-</div>
</kd-resource-card-column>
</kd-resource-card-columns>
</kd-resource-card>
</kd-resource-card-list>
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import {StateParams, stateName} from 'servicedetail/servicedetail_state';
/**
* @final
*/
export class ServiceCardListController {
/**
* @param {!ui.router.$state} $state
* @ngInject
*/
constructor($state) { this.state_ = $state; }
/**
* @param {!backendApi.ServiceDetail} service
* @return {string}
* @export
*/
getServiceDetailHref(service) {
return this.state_.href(
stateName, new StateParams(service.objectMeta.namespace, service.objectMeta.name));
}
}
/**
* Definition object for the component that displays service card list.
*
* @type {!angular.Component}
*/
export const serviceCardListComponent = {
templateUrl: 'servicelist/servicecardlist.html',
controller: ServiceCardListController,
bindings: {
/** {!Array<!backendApi.ServiceDetail>} */
'services': '<',
/** {boolean} */
'selectable': '<',
/** {boolean} */
'withStatuses': '<',
},
};
<!--
Copyright 2015 Google Inc. All Rights Reserved.
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.
-->
<kd-content-card>
<kd-content>
<kd-service-card-list services="::ctrl.serviceList.services"></kd-service-card-list>
</kd-content>
</kd-content-card>
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
/**
* @final
*/
export class ServiceListController {
/**
* @param {!backendApi.ServiceList} serviceList
*/
constructor(serviceList) {
/** @export {!backendApi.ServiceList} */
this.serviceList = serviceList;
}
}
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import componentsModule from './../common/components/components_module';
import filtersModule from 'common/filters/filters_module';
import stateConfig from './servicelist_stateconfig';
import {serviceCardListComponent} from './servicecardlist_component';
/**
* Angular module for the Service list view.
*
* The view shows Service running in the cluster and allows to manage them.
*/
export default angular
.module(
'kubernetesDashboard.serviceList',
[
'ngMaterial',
'ngResource',
'ui.router',
filtersModule.name,
componentsModule.name,
])
.config(stateConfig)
.component('kdServiceCardList', serviceCardListComponent);
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
/** Name of the state. Can be used in, e.g., $state.go method. */
export const stateName = 'services';
/** Absolute URL of the state. */
export const stateUrl = '/services';
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import {ServiceListController} from './servicelist_controller';
import {actionbarViewName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_component';
import {stateName, stateUrl} from './servicelist_state';
/**
* Configures states for the service list view.
*
* @param {!ui.router.$stateProvider} $stateProvider
* @ngInject
*/
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
url: stateUrl,
resolve: {
'serviceListResource': getServiceListResource,
'serviceList': resolveServiceList,
},
data: {
[breadcrumbsConfig]: {
'label': 'Services',
},
},
views: {
'': {
controller: ServiceListController,
controllerAs: 'ctrl',
templateUrl: 'servicelist/servicelist.html',
},
[actionbarViewName]: {},
},
});
}
/**
* @param {!angular.$resource} $resource
* @return {!angular.Resource<!backendApi.ServiceList>}
*/
export function getServiceListResource($resource) {
return $resource('api/v1/services');
}
/**
* @param {!angular.Resource<!backendApi.ServiceList>} serviceListResource
* @return {!angular.$q.Promise}
*/
export function resolveServiceList(serviceListResource) {
return serviceListResource.get().$promise;
}
......@@ -134,7 +134,7 @@ func TestGetServiceList(t *testing.T) {
}
}
func TestGetServices(t *testing.T) {
func TestGetServiceDetails(t *testing.T) {
cases := []struct {
service *api.Service
expected Service
......@@ -157,7 +157,7 @@ func TestGetServices(t *testing.T) {
}
for _, c := range cases {
actual := getServices(c.service)
actual := GetServiceDetails(c.service)
if !reflect.DeepEqual(actual, c.expected) {
t.Errorf("getServices(%#v) == \ngot %#v, \nexpected %#v", c.service, actual,
......
......@@ -14,7 +14,7 @@
import replicationControllerDetailModule from 'replicationcontrollerdetail/replicationcontrollerdetail_module';
describe('Replication Controller Detail controller', () => {
describe('Replication Controller Info controller', () => {
/**
* Replication Controller Detail controller.
* @type {!ReplicationControllerDetailController}
......@@ -31,7 +31,7 @@ describe('Replication Controller Detail controller', () => {
it('should return true when all desired pods are running', () => {
// given
ctrl.details = {
ctrl.replicationController = {
podInfo: {
running: 0,
desired: 0,
......@@ -44,7 +44,7 @@ describe('Replication Controller Detail controller', () => {
it('should return false when not all desired pods are running', () => {
// given
ctrl.details = {
ctrl.replicationController = {
podInfo: {
running: 0,
desired: 1,
......
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import {ServiceDetailController} from 'servicedetail/servicedetail_controller';
import serviceDetailModule from 'servicedetail/servicedetail_module';
describe('Service detail controller', () => {
beforeEach(() => { angular.mock.module(serviceDetailModule.name); });
it('should initialize controller', angular.mock.inject(($controller) => {
let data = {serviceDetail: {}};
/** @type {!ServiceDetailController} */
let ctrl = $controller(ServiceDetailController, {serviceDetail: data});
expect(ctrl.serviceDetail).toBe(data);
}));
});
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import serviceListModule from 'servicelist/servicelist_module';
import serviceDetailModule from 'servicedetail/servicedetail_module';
describe('Service list controller', () => {
/**
* @type {!servicelist/servicecardlist_component.ServiceCardListController}
*/
let ctrl;
beforeEach(() => {
angular.mock.module(serviceListModule.name);
angular.mock.module(serviceDetailModule.name);
angular.mock.inject(
($componentController) => { ctrl = $componentController('kdServiceCardList', {}, {}); });
});
it('should return service details link', () => {
expect(ctrl.getServiceDetailHref({
objectMeta: {
name: 'foo-service',
namespace: 'foo-namespace',
},
})).toBe('#/services/foo-namespace/foo-service');
});
});
// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.
import {ServiceListController} from 'servicelist/servicelist_controller';
import serviceListModule from 'servicelist/servicelist_module';
describe('Service list controller', () => {
beforeEach(() => { angular.mock.module(serviceListModule.name); });
it('should initialize controller', angular.mock.inject(($controller) => {
let data = {serviceList: {}};
/** @type {!ServiceListController} */
let ctrl = $controller(ServiceListController, {serviceList: data});
expect(ctrl.serviceList).toBe(data);
}));
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册