From 35c8a20eb322443d493b9f2b7b006de00f832084 Mon Sep 17 00:00:00 2001 From: nasc17 <69922333+nasc17@users.noreply.github.com> Date: Fri, 12 Feb 2021 16:24:27 -0800 Subject: [PATCH] Added Server Group Nodes status table to Overview page (#14194) * Add podstatus to spec * Added image to table and fixed spacing. * Added pod status to spec * PR fixes * Edited so that when page is closed and reopened, does not have empty server group node table --- extensions/arc/src/localizedConstants.ts | 2 + .../postgres/postgresOverviewPage.ts | 127 +++++++++++++++++- extensions/azdata/src/typings/azdata-ext.d.ts | 13 +- 3 files changed, 139 insertions(+), 3 deletions(-) diff --git a/extensions/arc/src/localizedConstants.ts b/extensions/arc/src/localizedConstants.ts index fa61919cdc..56cca58f7d 100644 --- a/extensions/arc/src/localizedConstants.ts +++ b/extensions/arc/src/localizedConstants.ts @@ -76,6 +76,8 @@ export const resetToDefault = localize('arc.resetToDefault', "Reset to default") export const troubleshoot = localize('arc.troubleshoot', "Troubleshoot"); export const clickTheNewSupportRequestButton = localize('arc.clickTheNewSupportRequestButton', "Click the new support request button to file a support request in the Azure Portal."); export const running = localize('arc.running', "Running"); +export const ready = localize('arc.ready', "Ready"); +export const notReady = localize('arc.notReady', "Not Ready"); export const pending = localize('arc.pending', "Pending"); export const failed = localize('arc.failed', "Failed"); export const unknown = localize('arc.unknown', "Unknown"); diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts b/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts index fb7609ff1b..da3a3ce8cb 100644 --- a/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts +++ b/extensions/arc/src/ui/dashboards/postgres/postgresOverviewPage.ts @@ -7,16 +7,23 @@ import * as vscode from 'vscode'; import * as azdata from 'azdata'; import * as azdataExt from 'azdata-ext'; import * as loc from '../../../localizedConstants'; -import { IconPathHelper, cssStyles } from '../../../constants'; +import { IconPathHelper, cssStyles, iconSize } from '../../../constants'; import { DashboardPage } from '../../components/dashboardPage'; import { ControllerModel } from '../../../models/controllerModel'; import { PostgresModel } from '../../../models/postgresModel'; import { promptAndConfirmPassword, promptForInstanceDeletion } from '../../../common/utils'; import { ResourceType } from 'arc'; +export type PodStatusModel = { + podName: azdata.Component, + type: string, + status: string +}; + export class PostgresOverviewPage extends DashboardPage { private propertiesLoading!: azdata.LoadingComponent; + private serverGroupNodesLoading!: azdata.LoadingComponent; private kibanaLoading!: azdata.LoadingComponent; private grafanaLoading!: azdata.LoadingComponent; @@ -24,6 +31,9 @@ export class PostgresOverviewPage extends DashboardPage { private kibanaLink!: azdata.HyperlinkComponent; private grafanaLink!: azdata.HyperlinkComponent; + private podStatusTable!: azdata.DeclarativeTableComponent; + private podStatusData: PodStatusModel[] = []; + private readonly _azdataApi: azdataExt.IExtension; constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) { @@ -132,8 +142,63 @@ export class PostgresOverviewPage extends DashboardPage { [loc.kibanaDashboard, this.kibanaLoading, loc.kibanaDashboardDescription], [loc.grafanaDashboard, this.grafanaLoading, loc.grafanaDashboardDescription]] }).component(); - content.addItem(endpointsTable); + + // Server Group Nodes + content.addItem(this.modelView.modelBuilder.text().withProperties({ + value: loc.serverGroupNodes, + CSSStyles: titleCSS + }).component()); + + this.podStatusTable = this.modelView.modelBuilder.declarativeTable().withProps({ + width: '100%', + columns: [ + { + displayName: loc.name, + valueType: azdata.DeclarativeDataType.component, + isReadOnly: true, + width: '35%', + headerCssStyles: cssStyles.tableHeader, + rowCssStyles: { + ...cssStyles.tableRow, + 'overflow': 'hidden', + 'text-overflow': 'ellipsis', + 'white-space': 'nowrap', + 'max-width': '0' + } + }, + { + displayName: loc.type, + valueType: azdata.DeclarativeDataType.string, + isReadOnly: true, + width: '35%', + headerCssStyles: cssStyles.tableHeader, + rowCssStyles: cssStyles.tableRow + }, + { + displayName: loc.status, + valueType: azdata.DeclarativeDataType.string, + isReadOnly: true, + width: '30%', + headerCssStyles: cssStyles.tableHeader, + rowCssStyles: cssStyles.tableRow + } + ], + data: [this.podStatusData.map(p => [p.podName, p.type, p.status])] + }).component(); + + + + this.serverGroupNodesLoading = this.modelView.modelBuilder.loadingComponent() + .withItem(this.podStatusTable) + .withProperties({ + loading: !this._postgresModel.configLastUpdated + }).component(); + + this.refreshServerNodes(); + + content.addItem(this.serverGroupNodesLoading, { CSSStyles: cssStyles.text }); + this.initialized = true; return root; } @@ -223,6 +288,7 @@ export class PostgresOverviewPage extends DashboardPage { refreshButton.enabled = false; try { this.propertiesLoading!.loading = true; + this.serverGroupNodesLoading!.loading = true; this.kibanaLoading!.loading = true; this.grafanaLoading!.loading = true; @@ -281,6 +347,54 @@ export class PostgresOverviewPage extends DashboardPage { ]; } + private getPodStatus(): PodStatusModel[] { + let podModels: PodStatusModel[] = []; + const podStatus = this._postgresModel.config?.status.podsStatus; + + podStatus?.forEach(p => { + // If a condition of the pod has a status of False, pod is not Ready + const status = p.conditions.find(c => c.status === 'False') ? loc.notReady : loc.ready; + + const podLabelContainer = this.modelView.modelBuilder.flexContainer().withProps({ + CSSStyles: { 'alignItems': 'center', 'height': '15px' } + }).component(); + + const imageComponent = this.modelView.modelBuilder.image().withProps({ + iconPath: IconPathHelper.postgres, + width: iconSize, + height: iconSize, + iconHeight: '15px', + iconWidth: '15px' + }).component(); + + let podLabel = this.modelView.modelBuilder.text().withProps({ + value: p.name, + }).component(); + + if (p.role.toUpperCase() === loc.worker.toUpperCase()) { + podLabelContainer.addItem(imageComponent, { CSSStyles: { 'margin-left': '15px', 'margin-right': '0px' } }); + podLabelContainer.addItem(podLabel); + let pod: PodStatusModel = { + podName: podLabelContainer, + type: loc.worker, + status: status + }; + podModels.push(pod); + } else { + podLabelContainer.addItem(imageComponent, { CSSStyles: { 'margin-right': '0px' } }); + podLabelContainer.addItem(podLabel); + let pod: PodStatusModel = { + podName: podLabelContainer, + type: loc.coordinator, + status: status + }; + podModels.unshift(pod); + } + }); + + return podModels; + } + private refreshDashboardLinks(): void { if (this._postgresModel.config) { const kibanaUrl = this._postgresModel.config.status.logSearchDashboard ?? ''; @@ -295,6 +409,14 @@ export class PostgresOverviewPage extends DashboardPage { } } + private refreshServerNodes(): void { + if (this._postgresModel.config) { + this.podStatusData = this.getPodStatus(); + this.podStatusTable.data = this.podStatusData.map(p => [p.podName, p.type, p.status]); + this.serverGroupNodesLoading.loading = false; + } + } + private handleRegistrationsUpdated() { this.properties!.propertyItems = this.getProperties(); this.propertiesLoading!.loading = false; @@ -304,5 +426,6 @@ export class PostgresOverviewPage extends DashboardPage { this.properties!.propertyItems = this.getProperties(); this.propertiesLoading!.loading = false; this.refreshDashboardLinks(); + this.refreshServerNodes(); } } diff --git a/extensions/azdata/src/typings/azdata-ext.d.ts b/extensions/azdata/src/typings/azdata-ext.d.ts index f0b90b24a0..ff7b7b6ee7 100644 --- a/extensions/azdata/src/typings/azdata-ext.d.ts +++ b/extensions/azdata/src/typings/azdata-ext.d.ts @@ -17,7 +17,7 @@ declare module 'azdata-ext' { name = 'Microsoft.azdata' } - export type AdditionalEnvVars = { [key: string]: string}; + export type AdditionalEnvVars = { [key: string]: string }; export interface ErrorWithLink extends Error { messageWithLink: string; @@ -222,6 +222,17 @@ declare module 'azdata-ext' { state: string, // "Ready" logSearchDashboard: string, // https://127.0.0.1:30777/kibana/app/kibana#/discover?_a=(query:(language:kuery,query:'custom_resource_name:pg1')) metricsDashboard: string, // https://127.0.0.1:30777/grafana/d/40q72HnGk/sql-managed-instance-metrics?var-hostname=pg1 + podsStatus: { + conditions: { + lastTransitionTime: string, // "2020-08-19T17:05:39Z" + message?: string, // "containers with unready status: [fluentbit postgres telegraf]" + reason?: string, // "ContainersNotReady" + status: string, // "True" + type: string // "Ready" + }[], + name: string, // "pg-instancew-0", + role: string // "worker" + }[] } }