diff --git a/src/app/externs/backendapi.js b/src/app/externs/backendapi.js index 1afd9dca189746e83fa7000b43d56fa7c0c69b7d..46f3e9b28320dcd16c35d422785e781bfe0ba219 100644 --- a/src/app/externs/backendapi.js +++ b/src/app/externs/backendapi.js @@ -213,6 +213,40 @@ backendApi.Deployment; */ backendApi.DeploymentList; +/** + * @typedef {{ + * maxSurge: !number, + * maxUnavailabe: !number, + * }} + */ +backendApi.RollingUpdateStrategy; + +/** + * @typedef {{ + * replicas: !number, + * updated: !number, + * available: !number, + * unavailable: !number, + * }} + */ +backendApi.DeploymentInfo; + +/** + * @typedef {{ + * objectMeta: !backendApi.ObjectMeta, + * typeMeta: !backendApi.TypeMeta, + * selector: !Array, + * status: !backendApi.DeploymentInfo, + * strategy: !string, + * minReadySeconds: !number, + * rollingUpdateStrategy: !backendApi.RollingUpdateStrategy, + * oldReplicaSetList: !backendApi.ReplicaSetList, + * newReplicaSet: !backendApi.ReplicaSet, + * events: !backendApi.EventList, + * }} + */ +backendApi.DeploymentDetail; + /** * @typedef {{ * pods: !Array diff --git a/src/app/frontend/deploymentdetail/deploymentdetail.html b/src/app/frontend/deploymentdetail/deploymentdetail.html new file mode 100644 index 0000000000000000000000000000000000000000..a5354e52989c6eed663ab8aa61e7a083c20463cb --- /dev/null +++ b/src/app/frontend/deploymentdetail/deploymentdetail.html @@ -0,0 +1,12 @@ +
+ + + + + + + + + + +
diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_controller.js b/src/app/frontend/deploymentdetail/deploymentdetail_controller.js new file mode 100644 index 0000000000000000000000000000000000000000..d6c87a31a7bf461ab2ea547fea9648d38185f1e2 --- /dev/null +++ b/src/app/frontend/deploymentdetail/deploymentdetail_controller.js @@ -0,0 +1,14 @@ + +/** + * @final + */ +export class DeploymentDetailController { + /** + * @param {!backendApi.DeploymentDetail} deploymentDetail + * @ngInject + */ + constructor(deploymentDetail) { + /** @export {!backendApi.DeploymentDetail} */ + this.deploymentDetail = deploymentDetail; + } +} diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_module.js b/src/app/frontend/deploymentdetail/deploymentdetail_module.js index 3fbd137d570bd1fc3939c5368217498afa65b060..92914b18ba493da73da696a341a3a8754f155ee3 100644 --- a/src/app/frontend/deploymentdetail/deploymentdetail_module.js +++ b/src/app/frontend/deploymentdetail/deploymentdetail_module.js @@ -12,9 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +import stateConfig from './deploymentdetail_stateconfig'; import filtersModule from 'common/filters/filters_module'; import componentsModule from 'common/components/components_module'; -import stateConfig from './deploymentdetail_stateconfig'; +import {deploymentInfoComponent} from './deploymentinfo_component'; /** * Angular module for the Deployment details view. @@ -31,4 +32,5 @@ export default angular componentsModule.name, filtersModule.name, ]) - .config(stateConfig); + .config(stateConfig) + .component('kdDeploymentInfo', deploymentInfoComponent); diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_state.js b/src/app/frontend/deploymentdetail/deploymentdetail_state.js index fee6d8be5d346fcb523fe8f98bed4820fa3bbc6e..c6a3585001addf5f816206edf5241f417ad715b6 100644 --- a/src/app/frontend/deploymentdetail/deploymentdetail_state.js +++ b/src/app/frontend/deploymentdetail/deploymentdetail_state.js @@ -15,6 +15,9 @@ /** Name of the state. Can be used in, e.g., $state.go method. */ export const stateName = 'deploymentdetail'; +/** Absolute URL of the state. */ +export const stateUrl = '/deployment/:namespace/:deployment'; + /** * Parameters for this state. * diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js b/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js index 30f9912d871f5414ec44d4c532584d48341e22e9..eda33ca5be1e8abe2c7cc81d030aa5b4b2f0e207 100644 --- a/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js +++ b/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js @@ -12,16 +12,57 @@ // See the License for the specific language governing permissions and // limitations under the License. -import {stateName} from './deploymentdetail_state'; +import {actionbarViewName} from 'chrome/chrome_state'; +import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service'; +import {DeploymentDetailController} from './deploymentdetail_controller'; +import {stateName as deploymentList} from 'deploymentlist/deploymentlist_state'; +import {stateName, stateUrl} from './deploymentdetail_state'; /** - * Configures states for the replica set details view. + * Configures states for the deployment detail view. * * @param {!ui.router.$stateProvider} $stateProvider * @ngInject */ export default function stateConfig($stateProvider) { $stateProvider.state(stateName, { - url: '/deployment/:namespace/:deployment', + url: stateUrl, + resolve: { + 'deploymentDetailResource': getDeploymentDetailResource, + 'deploymentDetail': getDeploymentDetail, + }, + data: { + [breadcrumbsConfig]: { + 'label': '{{$stateParams.deployment}}', + 'parent': deploymentList, + }, + }, + views: { + '': { + controller: DeploymentDetailController, + controllerAs: 'ctrl', + templateUrl: 'deploymentdetail/deploymentdetail.html', + }, + [actionbarViewName]: {}, + }, }); } + +/** + * @param {!./deploymentdetail_state.StateParams} $stateParams + * @param {!angular.$resource} $resource + * @return {!angular.Resource} + * @ngInject + */ +export function getDeploymentDetailResource($resource, $stateParams) { + return $resource(`api/v1/deployment/${$stateParams.namespace}/${$stateParams.deployment}`); +} + +/** + * @param {!angular.Resource} deploymentDetailResource + * @return {!angular.$q.Promise} + * @ngInject + */ +export function getDeploymentDetail(deploymentDetailResource) { + return deploymentDetailResource.get().$promise; +} diff --git a/src/app/frontend/deploymentdetail/deploymentinfo.html b/src/app/frontend/deploymentdetail/deploymentinfo.html new file mode 100644 index 0000000000000000000000000000000000000000..9febecab937ec5f84ddde6f4f8806b12be2872dd --- /dev/null +++ b/src/app/frontend/deploymentdetail/deploymentinfo.html @@ -0,0 +1,52 @@ + + Resource details + + + + + + + {{::$ctrl.deployment.objectMeta.namespace}} + + + + + + + + + {{::$ctrl.deployment.strategy}} + + + {{::$ctrl.deployment.minReadySeconds}} + + + + Max Surge: {{::$ctrl.deployment.rollingUpdateStrategy.maxSurge}} + Max Unavailable: {{::$ctrl.deployment.rollingUpdateStrategy.maxUnavailable}} + + + + + + + {{::$ctrl.deployment.statusInfo.updated}} updated, + {{::$ctrl.deployment.statusInfo.replicas}} total, + {{::$ctrl.deployment.statusInfo.available}} available, + {{::$ctrl.deployment.statusInfo.unavailable}} unavailable + + + + + + +
+ {{rs.objectMeta.name}} +
+
+ None +
+
+
+
diff --git a/src/app/frontend/deploymentdetail/deploymentinfo_component.js b/src/app/frontend/deploymentdetail/deploymentinfo_component.js new file mode 100644 index 0000000000000000000000000000000000000000..cd3d5ed2b0a47098151ebe0d5233d3e91295693f --- /dev/null +++ b/src/app/frontend/deploymentdetail/deploymentinfo_component.js @@ -0,0 +1,36 @@ +/** + * @final + */ +export default class DeploymentInfoController { + /** + * Constructs replication controller info object. + */ + constructor() { + /** + * Deployment details. Initialized from the scope. + * @export {!backendApi.DeploymentDetail} + */ + this.deployment; + } + + /** + * Returns true if the deployment strategy is RollingUpdate + * @return {boolean} + * @export + */ + rollingUpdateStrategy() { return this.deployment.strategy === 'RollingUpdate'; } +} + +/** + * Definition object for the component that displays replica set info. + * + * @return {!angular.Directive} + */ +export const deploymentInfoComponent = { + controller: DeploymentInfoController, + templateUrl: 'deploymentdetail/deploymentinfo.html', + bindings: { + /** {!backendApi.DeploymentDetail} */ + 'deployment': '=', + }, +}; diff --git a/src/test/frontend/deploymentdetail/deploymentdetail_controller_test.js b/src/test/frontend/deploymentdetail/deploymentdetail_controller_test.js new file mode 100644 index 0000000000000000000000000000000000000000..51a3a2c2a4089855bd26e36880dda1b93e541184 --- /dev/null +++ b/src/test/frontend/deploymentdetail/deploymentdetail_controller_test.js @@ -0,0 +1,16 @@ + +import {DeploymentDetailController} from 'deploymentdetail/deploymentdetail_controller'; +import deploymentDetailModule from 'deploymentdetail/deploymentdetail_module'; + +describe('Deployment Detail controller', () => { + + beforeEach(() => { angular.mock.module(deploymentDetailModule.name); }); + + it('should initialize deployment detail', angular.mock.inject(($controller) => { + let data = {}; + /** @type {!DeploymentDetailController} */ + let ctrl = $controller(DeploymentDetailController, {deploymentDetail: data}); + + expect(ctrl.deploymentDetail).toBe(data); + })); +}); diff --git a/src/test/frontend/deploymentdetail/deploymentinfo_component_test.js b/src/test/frontend/deploymentdetail/deploymentinfo_component_test.js new file mode 100644 index 0000000000000000000000000000000000000000..bf1124cdc06f59875d54162ae62b43cfa384f54f --- /dev/null +++ b/src/test/frontend/deploymentdetail/deploymentinfo_component_test.js @@ -0,0 +1,38 @@ +import deploymentDetailModule from 'deploymentdetail/deploymentdetail_module'; + +describe('Deployment Info controller', () => { + /** +* Deployment Info controller. +* @type {!DeploymentInfoController} +*/ + let ctrl; + + beforeEach(() => { + angular.mock.module(deploymentDetailModule.name); + + angular.mock.inject( + ($componentController) => { ctrl = $componentController('kdDeploymentInfo', {}); }); + }); + + describe('#rollingUpdateStrategy', () => { + it('returns true when strategy is rolling update', () => { + // given + ctrl.deployment = { + strategy: 'RollingUpdate', + }; + + // then + expect(ctrl.rollingUpdateStrategy()).toBeTruthy(); + }); + + it('returns true when strategy is rolling update', () => { + // given + ctrl.deployment = { + strategy: 'Recreate', + }; + + // then + expect(ctrl.rollingUpdateStrategy()).toBeFalsy(); + }); + }); +});