From 81db83c3a3703d776bbbbe20296c576e275dd5d4 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Fri, 15 May 2020 15:17:32 +0100 Subject: [PATCH] Final TODO's --- .../create-release.component.ts | 9 +--- .../app/custom/helm/helm-entity-generator.ts | 21 ++++++-- .../monocular-charts-data-source.ts | 2 +- .../custom/helm/store/helm.action-builders.ts | 11 ++-- .../app/custom/helm/store/helm.actions.ts | 14 +++++ .../app/custom/helm/store/helm.effects.ts | 45 ++++++++++++++-- .../services/kubernetes-endpoint.service.ts | 1 - .../kubernetes-summary.component.ts | 54 +++++++++---------- .../store/workload-action-builders.ts | 13 +---- .../workloads/store/workloads.actions.ts | 15 ------ .../workloads/store/workloads.effects.ts | 42 +-------------- 11 files changed, 112 insertions(+), 115 deletions(-) diff --git a/custom-src/frontend/app/custom/helm/create-release/create-release.component.ts b/custom-src/frontend/app/custom/helm/create-release/create-release.component.ts index 283ba6b23c..1c359a71cb 100644 --- a/custom-src/frontend/app/custom/helm/create-release/create-release.component.ts +++ b/custom-src/frontend/app/custom/helm/create-release/create-release.component.ts @@ -18,14 +18,9 @@ import { StepOnNextFunction, StepOnNextResult } from '../../../shared/components import { kubeEntityCatalog } from '../../kubernetes/kubernetes-entity-catalog'; import { KUBERNETES_ENDPOINT_TYPE } from '../../kubernetes/kubernetes-entity-factory'; import { KubernetesNamespace } from '../../kubernetes/store/kube.types'; -import { workloadsEntityCatalog } from '../../kubernetes/workloads/workloads-entity-catalog'; +import { helmEntityCatalog } from '../helm-entity-catalog'; import { HelmInstallValues } from '../store/helm.types'; - -// private pmf: PaginationMonitorFactory, // TODO: RC search and destroy -// private emf: EntityMonitorFactory // TODO: RC search and destroy -// store.dispatch - @Component({ selector: 'app-create-release', templateUrl: './create-release.component.html', @@ -263,7 +258,7 @@ export class CreateReleaseComponent implements OnInit, OnDestroy { }; // Make the request - return workloadsEntityCatalog.release.api.install(values).pipe( + return helmEntityCatalog.chart.api.install(values).pipe( // Wait for result of request filter(state => !!state), pairwise(), diff --git a/custom-src/frontend/app/custom/helm/helm-entity-generator.ts b/custom-src/frontend/app/custom/helm/helm-entity-generator.ts index 928e03e767..380b225a40 100644 --- a/custom-src/frontend/app/custom/helm/helm-entity-generator.ts +++ b/custom-src/frontend/app/custom/helm/helm-entity-generator.ts @@ -12,7 +12,12 @@ import { helmVersionsEntityType, monocularChartsEntityType, } from './helm-entity-factory'; -import { HelmChartActionBuilders, HelmVersionActionBuilders } from './store/helm.action-builders'; +import { + HelmChartActionBuilders, + helmChartActionBuilders, + HelmVersionActionBuilders, + helmVersionActionBuilders, +} from './store/helm.action-builders'; import { HelmVersion, MonocularChart } from './store/helm.types'; @@ -51,7 +56,12 @@ function generateChartEntity(endpointDefinition: StratosEndpointExtensionDefinit schema: helmEntityFactory(monocularChartsEntityType), endpoint: endpointDefinition }; - helmEntityCatalog.chart = new StratosCatalogEntity(definition); + helmEntityCatalog.chart = new StratosCatalogEntity( + definition, + { + actionBuilders: helmChartActionBuilders + } + ); return helmEntityCatalog.chart; } @@ -61,7 +71,12 @@ function generateVersionEntity(endpointDefinition: StratosEndpointExtensionDefin schema: helmEntityFactory(helmVersionsEntityType), endpoint: endpointDefinition }; - helmEntityCatalog.version = new StratosCatalogEntity(definition); + helmEntityCatalog.version = new StratosCatalogEntity( + definition, + { + actionBuilders: helmVersionActionBuilders + } + ); return helmEntityCatalog.version; } diff --git a/custom-src/frontend/app/custom/helm/list-types/monocular-charts-data-source.ts b/custom-src/frontend/app/custom/helm/list-types/monocular-charts-data-source.ts index eebb7ad29b..afefeae64e 100644 --- a/custom-src/frontend/app/custom/helm/list-types/monocular-charts-data-source.ts +++ b/custom-src/frontend/app/custom/helm/list-types/monocular-charts-data-source.ts @@ -18,7 +18,7 @@ export class MonocularChartsDataSource extends ListDataSource { store, action, schema: action.entity[0], - getRowUniqueId: action.entity[0].getId, + getRowUniqueId: (row) => action.entity[0].getId(row), paginationKey: action.paginationKey, isLocal: true, listConfig, diff --git a/custom-src/frontend/app/custom/helm/store/helm.action-builders.ts b/custom-src/frontend/app/custom/helm/store/helm.action-builders.ts index 9af72dca3d..53c20f4de9 100644 --- a/custom-src/frontend/app/custom/helm/store/helm.action-builders.ts +++ b/custom-src/frontend/app/custom/helm/store/helm.action-builders.ts @@ -1,12 +1,17 @@ import { OrchestratedActionBuilders } from '../../../../../store/src/entity-catalog/action-orchestrator/action-orchestrator'; -import { GetHelmVersions, GetMonocularCharts } from './helm.actions'; +import { GetHelmVersions, GetMonocularCharts, HelmInstall } from './helm.actions'; +import { HelmInstallValues } from './helm.types'; export interface HelmChartActionBuilders extends OrchestratedActionBuilders { - getMultiple: () => GetMonocularCharts + getMultiple: () => GetMonocularCharts, + // Helm install added to chart action builder and not helm release/workload to ensure action & effect are available in this module + // (others may not have loaded) + install: (values: HelmInstallValues) => HelmInstall } export const helmChartActionBuilders: HelmChartActionBuilders = { - getMultiple: () => new GetMonocularCharts() + getMultiple: () => new GetMonocularCharts(), + install: (values: HelmInstallValues) => new HelmInstall(values) } export interface HelmVersionActionBuilders extends OrchestratedActionBuilders { diff --git a/custom-src/frontend/app/custom/helm/store/helm.actions.ts b/custom-src/frontend/app/custom/helm/store/helm.actions.ts index 03bc05a385..d0c0db844e 100644 --- a/custom-src/frontend/app/custom/helm/store/helm.actions.ts +++ b/custom-src/frontend/app/custom/helm/store/helm.actions.ts @@ -6,6 +6,7 @@ import { monocularChartsEntityType, } from '../helm-entity-factory'; import { PaginatedAction } from './../../../../../store/src/types/pagination.types'; +import { HelmInstallValues } from './helm.types'; export const GET_MONOCULAR_CHARTS = '[Monocular] Get Charts'; export const GET_MONOCULAR_CHARTS_SUCCESS = '[Monocular] Get Charts Success'; @@ -15,6 +16,10 @@ export const GET_HELM_VERSIONS = '[Helm] Get Versions'; export const GET_HELM_VERSIONS_SUCCESS = '[Helm] Get Versions Success'; export const GET_HELM_VERSIONS_FAILURE = '[Helm] Get Versions Failure'; +export const HELM_INSTALL = '[Helm] Install'; +export const HELM_INSTALL_SUCCESS = '[Helm] Install Success'; +export const HELM_INSTALL_FAILURE = '[Helm] Install Failure'; + export interface MonocularPaginationAction extends PaginatedAction, EntityRequestAction { } export class GetMonocularCharts implements MonocularPaginationAction { @@ -38,6 +43,15 @@ export class GetMonocularCharts implements MonocularPaginationAction { flattenPagination = true; } +export class HelmInstall implements EntityRequestAction { + type = HELM_INSTALL; + endpointType = HELM_ENDPOINT_TYPE; + entityType = monocularChartsEntityType; + guid: string; + constructor(public values: HelmInstallValues) { + this.guid = '' + this.values.releaseName; + } +} export class GetHelmVersions implements MonocularPaginationAction { constructor() { diff --git a/custom-src/frontend/app/custom/helm/store/helm.effects.ts b/custom-src/frontend/app/custom/helm/store/helm.effects.ts index 46dcbca74e..dfd8a6db60 100644 --- a/custom-src/frontend/app/custom/helm/store/helm.effects.ts +++ b/custom-src/frontend/app/custom/helm/store/helm.effects.ts @@ -15,10 +15,20 @@ import { import { Observable } from 'rxjs'; import { catchError, flatMap, mergeMap } from 'rxjs/operators'; +import { ClearPaginationOfType } from '../../../../../store/src/actions/pagination.actions'; +import { ApiRequestTypes } from '../../../../../store/src/reducers/api-request-reducer/request-helpers'; import { environment } from '../../../environments/environment'; import { isJetstreamError } from '../../../jetstream.helpers'; +import { helmEntityCatalog } from '../helm-entity-catalog'; import { getHelmVersionId, getMonocularChartId, HELM_ENDPOINT_TYPE } from '../helm-entity-factory'; -import { GET_HELM_VERSIONS, GET_MONOCULAR_CHARTS, GetHelmVersions, GetMonocularCharts } from './helm.actions'; +import { + GET_HELM_VERSIONS, + GET_MONOCULAR_CHARTS, + GetHelmVersions, + GetMonocularCharts, + HELM_INSTALL, + HelmInstall, +} from './helm.actions'; import { HelmVersion } from './helm.types'; @Injectable() @@ -118,7 +128,36 @@ export class HelmEffects { }) ); - + @Effect() + helmInstall$ = this.actions$.pipe( + ofType(HELM_INSTALL), + flatMap(action => { + const requestType: ApiRequestTypes = 'create'; + const url = '/pp/v1/helm/install'; + this.store.dispatch(new StartRequestAction(action, requestType)); + return this.httpClient.post(url, action.values).pipe( + mergeMap(() => { + return [ + new ClearPaginationOfType(action), + new WrapperRequestActionSuccess(null, action) + ]; + }), + catchError(error => { + const { status, message } = HelmEffects.createHelmError(error); + const errorMessage = `Failed to install helm chart: ${message}`; + return [ + new WrapperRequestActionFailed(errorMessage, action, requestType, { + endpointIds: [action.values.endpoint], + url: error.url || url, + eventCode: status, + message: errorMessage, + error + }) + ]; + }) + ); + }) + ); private makeRequest( action: EntityRequestAction, @@ -204,7 +243,7 @@ export class HelmEffects { this.syncing = syncing; if (remaining !== existing) { // Dispatch action to refresh charts - this.store.dispatch(new GetMonocularCharts()); + helmEntityCatalog.chart.api.getMultiple(); } if (remaining > 0) { this.scheduleSyncStatusCheck(); diff --git a/custom-src/frontend/app/custom/kubernetes/services/kubernetes-endpoint.service.ts b/custom-src/frontend/app/custom/kubernetes/services/kubernetes-endpoint.service.ts index cd6c67b9f3..7bafc4d2ca 100644 --- a/custom-src/frontend/app/custom/kubernetes/services/kubernetes-endpoint.service.ts +++ b/custom-src/frontend/app/custom/kubernetes/services/kubernetes-endpoint.service.ts @@ -188,7 +188,6 @@ export class KubernetesEndpointService { } public refreshKubernetesDashboardStatus() { - // this.store.dispatch(new GetKubernetesDashboard(this.kubeGuid)); // TODO: RC store.dispatch kubeEntityCatalog.dashboard.api.get(this.kubeGuid); } diff --git a/custom-src/frontend/app/custom/kubernetes/tabs/kubernetes-summary-tab/kubernetes-summary.component.ts b/custom-src/frontend/app/custom/kubernetes/tabs/kubernetes-summary-tab/kubernetes-summary.component.ts index aa4186c638..fc4b0a9ce5 100644 --- a/custom-src/frontend/app/custom/kubernetes/tabs/kubernetes-summary-tab/kubernetes-summary.component.ts +++ b/custom-src/frontend/app/custom/kubernetes/tabs/kubernetes-summary-tab/kubernetes-summary.component.ts @@ -4,13 +4,13 @@ import { SafeResourceUrl } from '@angular/platform-browser'; import { Router } from '@angular/router'; import { Store } from '@ngrx/store'; import { combineLatest, interval, Observable, Subscription } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; +import { first, map, startWith } from 'rxjs/operators'; import { AppState } from '../../../../../../store/src/app-state'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; import { PaginationMonitorFactory } from '../../../../../../store/src/monitors/pagination-monitor.factory'; -import { getPaginationObservables } from '../../../../../../store/src/reducers/pagination-reducer/pagination-reducer.helper'; -import { PaginatedAction } from '../../../../../../store/src/types/pagination.types'; +import { getCurrentPageRequestInfo } from '../../../../../../store/src/reducers/pagination-reducer/pagination-reducer.types'; +import { PaginatedAction, PaginationEntityState } from '../../../../../../store/src/types/pagination.types'; import { safeUnsubscribe } from '../../../../core/utils.service'; import { IChartThresholds, @@ -113,14 +113,15 @@ export class KubernetesSummaryTabComponent implements OnInit, OnDestroy { ngOnInit() { const guid = this.kubeEndpointService.baseKube.guid; - - - const podCountAction = kubeEntityCatalog.pod.actions.getMultiple(guid); - const nodeCountAction = kubeEntityCatalog.node.actions.getMultiple(guid); - const namespacesCountAction = kubeEntityCatalog.namespace.actions.getMultiple(guid); - const pods$ = this.getPaginationObservable(podCountAction); - const nodes$ = this.getPaginationObservable(nodeCountAction); - const namespaces$ = this.getPaginationObservable(namespacesCountAction); + const podsObs = kubeEntityCatalog.pod.store.getPaginationService(guid); + const pods$ = podsObs.entities$; + this.poll(kubeEntityCatalog.pod.actions.getMultiple(guid), podsObs.pagination$) + const nodesObs = kubeEntityCatalog.node.store.getPaginationService(guid); + const nodes$ = nodesObs.entities$; + this.poll(kubeEntityCatalog.node.actions.getMultiple(guid), nodesObs.pagination$) + const namespacesObs = kubeEntityCatalog.namespace.store.getPaginationService(guid); + const namespaces$ = namespacesObs.entities$; + this.poll(kubeEntityCatalog.namespace.actions.getMultiple(guid), namespacesObs.pagination$) this.podCount$ = this.kubeEndpointService.getCountObservable(pods$); this.nodeCount$ = this.kubeEndpointService.getCountObservable(nodes$); @@ -177,29 +178,22 @@ export class KubernetesSummaryTabComponent implements OnInit, OnDestroy { ); } - private getPaginationObservable(action: PaginatedAction) { - const paginationMonitor = this.paginationMonitorFactory.create( - action.paginationKey, - action, - true - ); - - // TODO: RC this could easily get backed up, would entityService .poll be better?? - this.ngZone.runOutsideAngular(() => { + private poll(action: PaginatedAction, pagination$: Observable) { + this.ngZone.runOutsideAngular(() => this.polls.push( interval(10000).subscribe(() => { - this.ngZone.run(() => { - this.store.dispatch(action); - }); + this.ngZone.run(() => this.updateList(action, pagination$)); }) - ); - }); + ) + ); + } - return getPaginationObservables({ - store: this.store, - action, - paginationMonitor - }).entities$; + private updateList(action: PaginatedAction, pagination$: Observable) { + pagination$.pipe(first()).subscribe(pag => { + if (!getCurrentPageRequestInfo(pag, { busy: true, error: false, message: '' }).busy) { + this.store.dispatch(action); + } + }) } ngOnDestroy() { diff --git a/custom-src/frontend/app/custom/kubernetes/workloads/store/workload-action-builders.ts b/custom-src/frontend/app/custom/kubernetes/workloads/store/workload-action-builders.ts index c325f2b932..eb7591f9c5 100644 --- a/custom-src/frontend/app/custom/kubernetes/workloads/store/workload-action-builders.ts +++ b/custom-src/frontend/app/custom/kubernetes/workloads/store/workload-action-builders.ts @@ -1,14 +1,7 @@ import { OrchestratedActionBuilders, } from '../../../../../../store/src/entity-catalog/action-orchestrator/action-orchestrator'; -import { HelmInstallValues } from '../../../helm/store/helm.types'; -import { - GetHelmRelease, - GetHelmReleaseGraph, - GetHelmReleaseResource, - GetHelmReleases, - HelmInstall, -} from './workloads.actions'; +import { GetHelmRelease, GetHelmReleaseGraph, GetHelmReleaseResource, GetHelmReleases } from './workloads.actions'; export interface WorkloadReleaseBuilders extends OrchestratedActionBuilders { get: ( @@ -17,15 +10,13 @@ export interface WorkloadReleaseBuilders extends OrchestratedActionBuilders { extraArgs: { namespace: string } ) => GetHelmRelease; getMultiple: () => GetHelmReleases; - install: (values: HelmInstallValues) => HelmInstall } export const workloadReleaseBuilders: WorkloadReleaseBuilders = { get: (title: string, endpointGuid: string, { namespace }: { namespace: string }) => { return new GetHelmRelease(endpointGuid, namespace, title); }, - getMultiple: () => new GetHelmReleases(), - install: (values: HelmInstallValues) => new HelmInstall(values) + getMultiple: () => new GetHelmReleases() } export interface WorkloadGraphBuilders extends OrchestratedActionBuilders { diff --git a/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.actions.ts b/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.actions.ts index 9fad760fb7..319ef74b8b 100644 --- a/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.actions.ts +++ b/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.actions.ts @@ -2,7 +2,6 @@ import { EntityRequestAction } from 'frontend/packages/store/src/types/request.t import { PaginatedAction } from '../../../../../../store/src/types/pagination.types'; import { MonocularPaginationAction } from '../../../helm/store/helm.actions'; -import { HelmInstallValues } from '../../../helm/store/helm.types'; import { KUBERNETES_ENDPOINT_TYPE, kubernetesEntityFactory, @@ -39,10 +38,6 @@ export const UPDATE_HELM_RELEASE = '[Helm] Update Release'; export const UPDATE_HELM_RELEASE_SUCCESS = '[Helm] Update Release Success'; export const UPDATE_HELM_RELEASE_FAILURE = '[Helm] Update Release Failure'; -export const HELM_INSTALL = '[Helm] Install'; -export const HELM_INSTALL_SUCCESS = '[Helm] Install Success'; -export const HELM_INSTALL_FAILURE = '[Helm] Install Failure'; - interface HelmReleaseSingleEntity extends EntityRequestAction { guid: string; } @@ -51,16 +46,6 @@ interface HelmReleasePaginated extends PaginatedAction, EntityRequestAction { } -export class HelmInstall implements HelmReleaseSingleEntity { - type = HELM_INSTALL; - endpointType = KUBERNETES_ENDPOINT_TYPE; - entityType = helmReleaseEntityKey; - guid: string; - constructor(public values: HelmInstallValues) { - this.guid = '' + this.values.releaseName; - } -} - export class GetHelmReleases implements MonocularPaginationAction { constructor() { this.paginationKey = 'helm-releases'; diff --git a/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.effects.ts b/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.effects.ts index dd9bc41611..ea7add12fe 100644 --- a/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.effects.ts +++ b/custom-src/frontend/app/custom/kubernetes/workloads/store/workloads.effects.ts @@ -6,10 +6,8 @@ import { environment } from 'frontend/packages/core/src/environments/environment import { Observable } from 'rxjs'; import { catchError, flatMap, mergeMap } from 'rxjs/operators'; -import { ClearPaginationOfType } from '../../../../../../store/src/actions/pagination.actions'; import { AppState } from '../../../../../../store/src/app-state'; import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog'; -import { ApiRequestTypes } from '../../../../../../store/src/reducers/api-request-reducer/request-helpers'; import { NormalizedResponse } from '../../../../../../store/src/types/api.types'; import { EntityRequestAction, @@ -20,14 +18,7 @@ import { import { HelmEffects } from '../../../helm/store/helm.effects'; import { HelmRelease } from '../workload.types'; import { getHelmReleaseId } from './workloads-entity-factory'; -import { - GET_HELM_RELEASE, - GET_HELM_RELEASES, - GetHelmRelease, - GetHelmReleases, - HELM_INSTALL, - HelmInstall, -} from './workloads.actions'; +import { GET_HELM_RELEASE, GET_HELM_RELEASES, GetHelmRelease, GetHelmReleases } from './workloads.actions'; @Injectable() export class WorkloadsEffects { @@ -91,37 +82,6 @@ export class WorkloadsEffects { }) ); - @Effect() - helmInstall$ = this.actions$.pipe( - ofType(HELM_INSTALL), - flatMap(action => { - const requestType: ApiRequestTypes = 'create'; - const url = '/pp/v1/helm/install'; - this.store.dispatch(new StartRequestAction(action, requestType)); - return this.httpClient.post(url, action.values).pipe( - mergeMap(() => { - return [ - new ClearPaginationOfType(action), - new WrapperRequestActionSuccess(null, action) - ]; - }), - catchError(error => { - const { status, message } = HelmEffects.createHelmError(error); - const errorMessage = `Failed to install helm chart: ${message}`; - return [ - new WrapperRequestActionFailed(errorMessage, action, requestType, { - endpointIds: [action.values.endpoint], - url: error.url || url, - eventCode: status, - message: errorMessage, - error - }) - ]; - }) - ); - }) - ); - private mapHelmRelease(data, endpointId, guid: string) { const helmRelease: HelmRelease = { ...data,