Add refresh support to Arc Postgres pages (#10607)

This commit is contained in:
Brian Bergeron
2020-05-29 10:24:24 -07:00
committed by GitHub
parent 1305743479
commit e9e2a0b8b4
14 changed files with 348 additions and 181 deletions

View File

@@ -6,9 +6,9 @@
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper } from '../../../constants';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { DashboardPage } from '../../components/dashboardPage';
export class PostgresBackupPage extends PostgresDashboardPage {
export class PostgresBackupPage extends DashboardPage {
protected get title(): string {
return loc.backup;
}

View File

@@ -6,9 +6,9 @@
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper } from '../../../constants';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { DashboardPage } from '../../components/dashboardPage';
export class PostgresComputeStoragePage extends PostgresDashboardPage {
export class PostgresComputeStoragePage extends DashboardPage {
protected get title(): string {
return loc.computeAndStorage;
}

View File

@@ -3,13 +3,23 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { KeyValueContainer, KeyValue, InputKeyValue } from '../../components/keyValueContainer';
import { KeyValueContainer, InputKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresConnectionStringsPage extends DashboardPage {
private keyValueContainer?: KeyValueContainer;
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
this._postgresModel.onServiceUpdated(() => this.eventuallyRunOnInitialized(() => this.refresh()));
this._postgresModel.onPasswordUpdated(() => this.eventuallyRunOnInitialized(() => this.refresh()));
}
export class PostgresConnectionStringsPage extends PostgresDashboardPage {
protected get title(): string {
return loc.connectionStrings;
}
@@ -46,10 +56,39 @@ export class PostgresConnectionStringsPage extends PostgresDashboardPage {
this.modelView.modelBuilder.flexContainer().withItems([info, link]).withLayout({ flexWrap: 'wrap' }).component(),
{ CSSStyles: { display: 'inline-flex', 'margin-bottom': '25px' } });
const endpoint: { ip?: string, port?: number } = this.databaseModel.endpoint();
const password = this.databaseModel.password();
this.keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, []);
content.addItem(this.keyValueContainer.container);
this.initialized = true;
return root;
}
const pairs: KeyValue[] = [
protected get toolbarContainer(): azdata.ToolbarContainer {
const refreshButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await this._postgresModel.refresh();
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
} finally {
refreshButton.enabled = true;
}
});
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private refresh() {
const endpoint: { ip?: string, port?: number } = this._postgresModel.endpoint();
const password = this._postgresModel.password();
this.keyValueContainer?.refresh([
new InputKeyValue('ADO.NET', `Server=${endpoint.ip};Database=postgres;Port=${endpoint.port};User Id=postgres;Password=${password};Ssl Mode=Require;`),
new InputKeyValue('C++ (libpq)', `host=${endpoint.ip} port=${endpoint.port} dbname=postgres user=postgres password=${password} sslmode=require`),
new InputKeyValue('JDBC', `jdbc:postgresql://${endpoint.ip}:${endpoint.port}/postgres?user=postgres&password=${password}&sslmode=require`),
@@ -59,14 +98,6 @@ export class PostgresConnectionStringsPage extends PostgresDashboardPage {
new InputKeyValue('Python', `dbname='postgres' user='postgres' host='${endpoint.ip}' password='${password}' port='${endpoint.port}' sslmode='true'`),
new InputKeyValue('Ruby', `host=${endpoint.ip}; dbname=postgres user=postgres password=${password} port=${endpoint.port} sslmode=require`),
new InputKeyValue('Web App', `Database=postgres; Data Source=${endpoint.ip}; User Id=postgres; Password=${password}`)
];
const keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, pairs);
content.addItem(keyValueContainer.container);
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
return this.modelView.modelBuilder.toolbarContainer().component();
]);
}
}

View File

@@ -16,19 +16,17 @@ import { PostgresNetworkingPage } from './postgresNetworkingPage';
import { Dashboard } from '../../components/dashboard';
export class PostgresDashboard extends Dashboard {
constructor(title: string, private _controllerModel: ControllerModel, private _databaseModel: PostgresModel) {
constructor(title: string, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(title);
}
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
await Promise.all([this._controllerModel.refresh(), this._databaseModel.refresh()]);
const overviewPage = new PostgresOverviewPage(modelView, this._controllerModel, this._databaseModel);
const computeStoragePage = new PostgresComputeStoragePage(modelView, this._controllerModel, this._databaseModel);
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this._controllerModel, this._databaseModel);
const backupPage = new PostgresBackupPage(modelView, this._controllerModel, this._databaseModel);
const propertiesPage = new PostgresPropertiesPage(modelView, this._controllerModel, this._databaseModel);
const networkingPage = new PostgresNetworkingPage(modelView, this._controllerModel, this._databaseModel);
const overviewPage = new PostgresOverviewPage(modelView, this._controllerModel, this._postgresModel);
const computeStoragePage = new PostgresComputeStoragePage(modelView);
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this._postgresModel);
const backupPage = new PostgresBackupPage(modelView);
const propertiesPage = new PostgresPropertiesPage(modelView, this._controllerModel, this._postgresModel);
const networkingPage = new PostgresNetworkingPage(modelView);
return [
overviewPage.tab,

View File

@@ -1,15 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
import { DashboardPage } from '../../components/dashboardPage';
export abstract class PostgresDashboardPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, protected controllerModel: ControllerModel, protected databaseModel: PostgresModel) {
super(modelView);
}
}

View File

@@ -6,9 +6,9 @@
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper } from '../../../constants';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { DashboardPage } from '../../components/dashboardPage';
export class PostgresNetworkingPage extends PostgresDashboardPage {
export class PostgresNetworkingPage extends DashboardPage {
protected get title(): string {
return loc.networking;
}

View File

@@ -8,9 +8,32 @@ import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { DuskyObjectModelsDatabase, DuskyObjectModelsDatabaseServiceArcPayload } from '../../../controller/generated/dusky/api';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresOverviewPage extends DashboardPage {
private propertiesLoading?: azdata.LoadingComponent;
private kibanaLoading?: azdata.LoadingComponent;
private grafanaLoading?: azdata.LoadingComponent;
private nodesTableLoading?: azdata.LoadingComponent;
private properties?: azdata.PropertiesContainerComponent;
private kibanaLink?: azdata.HyperlinkComponent;
private grafanaLink?: azdata.HyperlinkComponent;
private nodesTable?: azdata.DeclarativeTableComponent;
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
this._controllerModel.onEndpointsUpdated(() => this.eventuallyRunOnInitialized(() => this.refreshEndpoints()));
this._controllerModel.onRegistrationsUpdated(() => this.eventuallyRunOnInitialized(() => this.refreshProperties()));
this._postgresModel.onPasswordUpdated(() => this.eventuallyRunOnInitialized(() => this.refreshProperties()));
this._postgresModel.onServiceUpdated(() => this.eventuallyRunOnInitialized(() => {
this.refreshProperties();
this.refreshNodes();
}));
}
export class PostgresOverviewPage extends PostgresDashboardPage {
protected get title(): string {
return loc.overview;
}
@@ -28,34 +51,18 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
const content = this.modelView.modelBuilder.divContainer().component();
root.addItem(content, { CSSStyles: { 'margin': '10px 20px 0px 20px' } });
const registration = this.controllerModel.registration('postgresInstances', this.databaseModel.namespace(), this.databaseModel.name());
const endpoint: { ip?: string, port?: number } = this.databaseModel.endpoint();
const essentials = this.modelView.modelBuilder.propertiesContainer().withProperties<azdata.PropertiesContainerComponentProperties>({
propertyItems: [
{ displayName: loc.name, value: this.databaseModel.name() },
{ displayName: loc.serverGroupType, value: loc.postgresArcProductName },
{ displayName: loc.resourceGroup, value: registration?.resourceGroupName ?? 'None' },
{ displayName: loc.coordinatorEndpoint, value: `postgresql://postgres:${this.databaseModel.password()}@${endpoint.ip}:${endpoint.port}` },
{ displayName: loc.status, value: this.databaseModel.service().status?.state ?? '' },
{ displayName: loc.postgresAdminUsername, value: 'postgres' },
{ displayName: loc.dataController, value: this.controllerModel.namespace() },
{ displayName: loc.nodeConfiguration, value: this.databaseModel.configuration() },
{ displayName: loc.subscriptionId, value: registration?.subscriptionId ?? 'None' },
{ displayName: loc.postgresVersion, value: this.databaseModel.service().spec.engine.version?.toString() ?? '' }
]
}).component();
content.addItem(essentials, { CSSStyles: cssStyles.text });
// Properties
this.properties = this.modelView.modelBuilder.propertiesContainer().component();
this.propertiesLoading = this.modelView.modelBuilder.loadingComponent().withItem(this.properties).component();
content.addItem(this.propertiesLoading, { CSSStyles: cssStyles.text });
// Service endpoints
const titleCSS = { ...cssStyles.title, 'margin-block-start': '2em', 'margin-block-end': '0' };
content.addItem(this.modelView.modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.serviceEndpoints, CSSStyles: titleCSS }).component());
const kibanaQuery = `kubernetes_namespace:"${this.databaseModel.namespace()}" and cluster_name:"${this.databaseModel.name()}"`;
const kibanaUrl = `${this.controllerModel.endpoint('logsui')?.endpoint}/app/kibana#/discover?_a=(query:(language:kuery,query:'${kibanaQuery}'))`;
const grafanaUrl = `${this.controllerModel.endpoint('metricsui')?.endpoint}/d/postgres-metrics?var-Namespace=${this.databaseModel.namespace()}&var-Name=${this.databaseModel.name()}`;
const kibanaLink = this.modelView.modelBuilder.hyperlink().withProperties<azdata.HyperlinkComponentProperties>({ label: kibanaUrl, url: kibanaUrl, }).component();
const grafanaLink = this.modelView.modelBuilder.hyperlink().withProperties<azdata.HyperlinkComponentProperties>({ label: grafanaUrl, url: grafanaUrl }).component();
this.kibanaLink = this.modelView.modelBuilder.hyperlink().component();
this.grafanaLink = this.modelView.modelBuilder.hyperlink().component();
this.kibanaLoading = this.modelView.modelBuilder.loadingComponent().withItem(this.kibanaLink).component();
this.grafanaLoading = this.modelView.modelBuilder.loadingComponent().withItem(this.grafanaLink).component();
const endpointsTable = this.modelView.modelBuilder.declarativeTable().withProperties<azdata.DeclarativeTableProperties>({
width: '100%',
@@ -92,14 +99,14 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
}
],
data: [
[loc.kibanaDashboard, kibanaLink, loc.kibanaDashboardDescription],
[loc.grafanaDashboard, grafanaLink, loc.grafanaDashboardDescription]]
[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<azdata.TextComponentProperties>({ value: loc.serverGroupNodes, CSSStyles: titleCSS }).component());
const nodesTable = this.modelView.modelBuilder.declarativeTable().withProperties<azdata.DeclarativeTableProperties>({
this.nodesTable = this.modelView.modelBuilder.declarativeTable().withProperties<azdata.DeclarativeTableProperties>({
width: '100%',
columns: [
{
@@ -130,15 +137,9 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
data: []
}).component();
const nodes = this.databaseModel.numNodes();
for (let i = 0; i < nodes; i++) {
nodesTable.data.push([
`${this.databaseModel.name()}-${i}`,
i === 0 ? loc.coordinatorEndpoint : loc.worker,
i === 0 ? `${endpoint.ip}:${endpoint.port}` : `${this.databaseModel.name()}-${i}.${this.databaseModel.name()}-svc.${this.databaseModel.namespace()}.svc.cluster.local`]);
}
content.addItem(nodesTable, { CSSStyles: { 'margin-bottom': '20px' } });
this.nodesTableLoading = this.modelView.modelBuilder.loadingComponent().withItem(this.nodesTable).component();
content.addItem(this.nodesTableLoading, { CSSStyles: { 'margin-bottom': '20px' } });
this.initialized = true;
return root;
}
@@ -150,14 +151,18 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
}).component();
newDatabaseButton.onDidClick(async () => {
const name = await vscode.window.showInputBox({ prompt: loc.databaseName });
if (name === undefined) { return; }
const db: DuskyObjectModelsDatabase = { name: name }; // TODO support other options (sharded, owner)
newDatabaseButton.enabled = false;
let name;
try {
await this.databaseModel.createDatabase(db);
name = await vscode.window.showInputBox({ prompt: loc.databaseName });
if (name === undefined) { return; }
const db: DuskyObjectModelsDatabase = { name: name }; // TODO support other options (sharded, owner)
await this._postgresModel.createDatabase(db);
vscode.window.showInformationMessage(loc.databaseCreated(db.name));
} catch (error) {
vscode.window.showErrorMessage(loc.databaseCreationFailed(db.name, error));
vscode.window.showErrorMessage(loc.databaseCreationFailed(name ?? '', error));
} finally {
newDatabaseButton.enabled = true;
}
});
@@ -168,16 +173,19 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
}).component();
resetPasswordButton.onDidClick(async () => {
const password = await vscode.window.showInputBox({ prompt: loc.newPassword, password: true });
if (password === undefined) { return; }
resetPasswordButton.enabled = false;
try {
await this.databaseModel.update(s => {
const password = await vscode.window.showInputBox({ prompt: loc.newPassword, password: true });
if (password === undefined) { return; }
await this._postgresModel.update(s => {
s.arc = s.arc ?? new DuskyObjectModelsDatabaseServiceArcPayload();
s.arc.servicePassword = password;
});
vscode.window.showInformationMessage(loc.passwordReset(this.databaseModel.fullName()));
vscode.window.showInformationMessage(loc.passwordReset(this._postgresModel.fullName()));
} catch (error) {
vscode.window.showErrorMessage(loc.passwordResetFailed(this.databaseModel.fullName(), error));
vscode.window.showErrorMessage(loc.passwordResetFailed(this._postgresModel.fullName(), error));
} finally {
resetPasswordButton.enabled = true;
}
});
@@ -188,15 +196,44 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
}).component();
deleteButton.onDidClick(async () => {
const response = await vscode.window.showQuickPick([loc.yes, loc.no], {
placeHolder: loc.deleteServicePrompt(this.databaseModel.fullName())
});
if (response !== loc.yes) { return; }
deleteButton.enabled = false;
try {
await this.databaseModel.delete();
vscode.window.showInformationMessage(loc.serviceDeleted(this.databaseModel.fullName()));
const response = await vscode.window.showQuickPick([loc.yes, loc.no], {
placeHolder: loc.deleteServicePrompt(this._postgresModel.fullName())
});
if (response !== loc.yes) { return; }
await this._postgresModel.delete();
vscode.window.showInformationMessage(loc.serviceDeleted(this._postgresModel.fullName()));
} catch (error) {
vscode.window.showErrorMessage(loc.serviceDeletionFailed(this.databaseModel.fullName(), error));
vscode.window.showErrorMessage(loc.serviceDeletionFailed(this._postgresModel.fullName(), error));
} finally {
deleteButton.enabled = true;
}
});
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
this.propertiesLoading!.loading = true;
this.kibanaLoading!.loading = true;
this.grafanaLoading!.loading = true;
this.nodesTableLoading!.loading = true;
await Promise.all([
this._postgresModel.refresh(),
this._controllerModel.refresh()
]);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
});
@@ -207,27 +244,70 @@ export class PostgresOverviewPage extends PostgresDashboardPage {
}).component();
openInAzurePortalButton.onDidClick(async () => {
const r = this.controllerModel.registration('postgresInstances', this.databaseModel.namespace(), this.databaseModel.name());
const r = this._controllerModel.registration('postgresInstances', this._postgresModel.namespace(), this._postgresModel.name());
if (r === undefined) {
vscode.window.showErrorMessage(loc.couldNotFindAzureResource(this.databaseModel.fullName()));
vscode.window.showErrorMessage(loc.couldNotFindAzureResource(this._postgresModel.fullName()));
} else {
vscode.env.openExternal(vscode.Uri.parse(
`https://portal.azure.com/#resource/subscriptions/${r.subscriptionId}/resourceGroups/${r.resourceGroupName}/providers/Microsoft.AzureData/postgresInstances/${r.instanceName}`));
}
});
// TODO implement click
const feedbackButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
label: loc.feedback,
iconPath: IconPathHelper.heart
}).component();
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: newDatabaseButton },
{ component: resetPasswordButton },
{ component: deleteButton, toolbarSeparatorAfter: true },
{ component: openInAzurePortalButton },
{ component: feedbackButton }
{ component: deleteButton },
{ component: refreshButton, toolbarSeparatorAfter: true },
{ component: openInAzurePortalButton }
]).component();
}
private refreshProperties() {
const registration = this._controllerModel.registration('postgresInstances', this._postgresModel.namespace(), this._postgresModel.name());
const endpoint: { ip?: string, port?: number } = this._postgresModel.endpoint();
this.properties!.propertyItems = [
{ displayName: loc.name, value: this._postgresModel.name() },
{ displayName: loc.coordinatorEndpoint, value: `postgresql://postgres:${this._postgresModel.password()}@${endpoint.ip}:${endpoint.port}` },
{ displayName: loc.status, value: this._postgresModel.service()?.status?.state ?? '' },
{ displayName: loc.postgresAdminUsername, value: 'postgres' },
{ displayName: loc.dataController, value: this._controllerModel?.namespace() ?? '' },
{ displayName: loc.nodeConfiguration, value: this._postgresModel.configuration() },
{ displayName: loc.subscriptionId, value: registration?.subscriptionId ?? '' },
{ displayName: loc.postgresVersion, value: this._postgresModel.service()?.spec.engine.version?.toString() ?? '' }
];
this.propertiesLoading!.loading = false;
}
private refreshEndpoints() {
const kibanaQuery = `kubernetes_namespace:"${this._postgresModel.namespace()}" and cluster_name:"${this._postgresModel.name()}"`;
const kibanaUrl = `${this._controllerModel.endpoint('logsui')?.endpoint}/app/kibana#/discover?_a=(query:(language:kuery,query:'${kibanaQuery}'))`;
this.kibanaLink!.label = kibanaUrl;
this.kibanaLink!.url = kibanaUrl;
const grafanaUrl = `${this._controllerModel.endpoint('metricsui')?.endpoint}/d/postgres-metrics?var-Namespace=${this._postgresModel.namespace()}&var-Name=${this._postgresModel.name()}`;
this.grafanaLink!.label = grafanaUrl;
this.grafanaLink!.url = grafanaUrl;
this.kibanaLoading!.loading = false;
this.grafanaLoading!.loading = false;
}
private refreshNodes() {
const nodes = this._postgresModel.numNodes();
const endpoint: { ip?: string, port?: number } = this._postgresModel.endpoint();
const data: any[][] = [];
for (let i = 0; i < nodes; i++) {
data.push([
`${this._postgresModel.name()}-${i}`,
i === 0 ? loc.coordinatorEndpoint : loc.worker,
i === 0 ? `${endpoint.ip}:${endpoint.port}` :
`${this._postgresModel.name()}-${i}.${this._postgresModel.name()}-svc.${this._postgresModel.namespace()}.svc.cluster.local`]);
}
this.nodesTable!.data = data;
this.nodesTableLoading!.loading = false;
}
}

View File

@@ -7,11 +7,21 @@ import * as vscode from 'vscode';
import * as azdata from 'azdata';
import * as loc from '../../../localizedConstants';
import { IconPathHelper, cssStyles } from '../../../constants';
import { PostgresDashboardPage } from './postgresDashboardPage';
import { KeyValueContainer, KeyValue, InputKeyValue, LinkKeyValue, TextKeyValue } from '../../components/keyValueContainer';
import { KeyValueContainer, InputKeyValue, LinkKeyValue, TextKeyValue } from '../../components/keyValueContainer';
import { DashboardPage } from '../../components/dashboardPage';
import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresPropertiesPage extends DashboardPage {
private keyValueContainer?: KeyValueContainer;
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
this._postgresModel.onServiceUpdated(() => this.eventuallyRunOnInitialized(() => this.refresh()));
this._postgresModel.onPasswordUpdated(() => this.eventuallyRunOnInitialized(() => this.refresh()));
this._controllerModel.onRegistrationsUpdated(() => this.eventuallyRunOnInitialized(() => this.refresh()));
}
export class PostgresPropertiesPage extends PostgresDashboardPage {
protected get title(): string {
return loc.properties;
}
@@ -34,27 +44,52 @@ export class PostgresPropertiesPage extends PostgresDashboardPage {
CSSStyles: { ...cssStyles.title, 'margin-bottom': '25px' }
}).component());
const endpoint: { ip?: string, port?: number } = this.databaseModel.endpoint();
const connectionString = `postgresql://postgres:${this.databaseModel.password()}@${endpoint.ip}:${endpoint.port}`;
const registration = this.controllerModel.registration('postgresInstances', this.databaseModel.namespace(), this.databaseModel.name());
const pairs: KeyValue[] = [
new InputKeyValue(loc.coordinatorEndpoint, connectionString),
new InputKeyValue(loc.postgresAdminUsername, 'postgres'),
new TextKeyValue(loc.status, this.databaseModel.service().status?.state ?? 'Unknown'),
new LinkKeyValue(loc.dataController, this.controllerModel.namespace(), _ => vscode.window.showInformationMessage('goto data controller')),
new LinkKeyValue(loc.nodeConfiguration, this.databaseModel.configuration(), _ => vscode.window.showInformationMessage('goto configuration')),
new TextKeyValue(loc.postgresVersion, this.databaseModel.service().spec.engine.version?.toString() ?? ''),
new TextKeyValue(loc.resourceGroup, registration?.resourceGroupName ?? ''),
new TextKeyValue(loc.subscriptionId, registration?.subscriptionId ?? '')
];
const keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, pairs);
content.addItem(keyValueContainer.container);
this.keyValueContainer = new KeyValueContainer(this.modelView.modelBuilder, []);
content.addItem(this.keyValueContainer.container);
this.initialized = true;
return root;
}
protected get toolbarContainer(): azdata.ToolbarContainer {
return this.modelView.modelBuilder.toolbarContainer().component();
const refreshButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
label: loc.refresh,
iconPath: IconPathHelper.refresh
}).component();
refreshButton.onDidClick(async () => {
refreshButton.enabled = false;
try {
await Promise.all([
this._postgresModel.refresh(),
this._controllerModel.refresh()
]);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
});
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: refreshButton }
]).component();
}
private refresh() {
const endpoint: { ip?: string, port?: number } = this._postgresModel.endpoint();
const connectionString = `postgresql://postgres:${this._postgresModel.password()}@${endpoint.ip}:${endpoint.port}`;
const registration = this._controllerModel.registration('postgresInstances', this._postgresModel.namespace(), this._postgresModel.name());
this.keyValueContainer?.refresh([
new InputKeyValue(loc.coordinatorEndpoint, connectionString),
new InputKeyValue(loc.postgresAdminUsername, 'postgres'),
new TextKeyValue(loc.status, this._postgresModel.service()?.status?.state ?? 'Unknown'),
new LinkKeyValue(loc.dataController, this._controllerModel.namespace() ?? '', _ => vscode.window.showInformationMessage('TODO: Go to data controller')),
new LinkKeyValue(loc.nodeConfiguration, this._postgresModel.configuration(), _ => vscode.window.showInformationMessage('TODO: Go to configuration')),
new TextKeyValue(loc.postgresVersion, this._postgresModel.service()?.spec.engine.version?.toString() ?? ''),
new TextKeyValue(loc.resourceGroup, registration?.resourceGroupName ?? ''),
new TextKeyValue(loc.subscriptionId, registration?.subscriptionId ?? '')
]);
}
}