Some general cleanup/fixes for Arc dashboards (#11066)

* Some general cleanup/fixes for Arc dashboards

* more disposables

* refresh controller model for miaa dashboard too

* fixes
This commit is contained in:
Charles Gagnon
2020-06-24 09:06:28 -07:00
committed by GitHub
parent ca4ab55380
commit 2ba0de10df
20 changed files with 378 additions and 257 deletions

View File

@@ -12,18 +12,11 @@ import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresConnectionStringsPage extends DashboardPage {
private disposables: vscode.Disposable[] = [];
private keyValueContainer?: KeyValueContainer;
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
modelView.onClosed(() =>
this.disposables.forEach(d => {
try { d.dispose(); }
catch { }
}));
this.disposables.push(this._postgresModel.onServiceUpdated(
() => this.eventuallyRunOnInitialized(() => this.refresh())));
}
@@ -77,16 +70,17 @@ export class PostgresConnectionStringsPage extends DashboardPage {
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;
}
});
this.disposables.push(
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 }

View File

@@ -21,6 +21,12 @@ export class PostgresDashboard extends Dashboard {
super(loc.postgresDashboard);
}
public async showDashboard(): Promise<void> {
await super.showDashboard();
// Kick off the model refresh but don't wait on it since that's all handled with callbacks anyways
this._postgresModel.refresh().catch(err => console.log(`Error refreshing Postgres dashboard ${err}`));
}
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new PostgresOverviewPage(modelView, this._controllerModel, this._postgresModel);
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this._postgresModel);

View File

@@ -48,11 +48,12 @@ export class PostgresDiagnoseAndSolveProblemsPage extends DashboardPage {
width: '160px'
}).component();
troubleshootButton.onDidClick(() => {
process.env['POSTGRES_SERVER_NAMESPACE'] = this._postgresModel.namespace;
process.env['POSTGRES_SERVER_NAME'] = this._postgresModel.name;
vscode.commands.executeCommand('bookTreeView.openBook', this._context.asAbsolutePath('notebooks/arcDataServices'), true, 'postgres/tsg100-troubleshoot-postgres');
});
this.disposables.push(
troubleshootButton.onDidClick(() => {
process.env['POSTGRES_SERVER_NAMESPACE'] = this._postgresModel.namespace;
process.env['POSTGRES_SERVER_NAME'] = this._postgresModel.name;
vscode.commands.executeCommand('bookTreeView.openBook', this._context.asAbsolutePath('notebooks/arcDataServices'), true, 'postgres/tsg100-troubleshoot-postgres');
}));
content.addItem(troubleshootButton);
return root;

View File

@@ -14,7 +14,6 @@ import { PostgresModel, PodRole } from '../../../models/postgresModel';
import { promptForResourceDeletion, promptAndConfirmPassword } from '../../../common/utils';
export class PostgresOverviewPage extends DashboardPage {
private disposables: vscode.Disposable[] = [];
private propertiesLoading?: azdata.LoadingComponent;
private kibanaLoading?: azdata.LoadingComponent;
@@ -29,29 +28,27 @@ export class PostgresOverviewPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
modelView.onClosed(() =>
this.disposables.forEach(d => {
try { d.dispose(); }
catch { }
}));
this.disposables.push(
this._controllerModel.onEndpointsUpdated(
() => this.eventuallyRunOnInitialized(() => this.refreshEndpoints())));
this.disposables.push(this._controllerModel.onEndpointsUpdated(
() => this.eventuallyRunOnInitialized(() => this.refreshEndpoints())));
this.disposables.push(
this._controllerModel.onRegistrationsUpdated(
() => this.eventuallyRunOnInitialized(() => this.refreshProperties())));
this.disposables.push(this._controllerModel.onRegistrationsUpdated(
() => this.eventuallyRunOnInitialized(() => this.refreshProperties())));
this.disposables.push(
this._postgresModel.onServiceUpdated(
() => this.eventuallyRunOnInitialized(() => {
this.refreshProperties();
this.refreshNodes();
})));
this.disposables.push(this._postgresModel.onServiceUpdated(
() => this.eventuallyRunOnInitialized(() => {
this.refreshProperties();
this.refreshNodes();
})));
this.disposables.push(this._postgresModel.onPodsUpdated(
() => this.eventuallyRunOnInitialized(() => {
this.refreshProperties();
this.refreshNodes();
})));
this.disposables.push(
this._postgresModel.onPodsUpdated(
() => this.eventuallyRunOnInitialized(() => {
this.refreshProperties();
this.refreshNodes();
})));
}
protected get title(): string {
@@ -186,22 +183,23 @@ export class PostgresOverviewPage extends DashboardPage {
iconPath: IconPathHelper.add
}).component();
newDatabaseButton.onDidClick(async () => {
newDatabaseButton.enabled = false;
let name;
try {
name = await vscode.window.showInputBox({ prompt: loc.databaseName });
if (name) {
const db: DuskyObjectModelsDatabase = { name: name }; // TODO support other options (sharded, owner)
await this._postgresModel.createDatabase(db);
vscode.window.showInformationMessage(loc.databaseCreated(db.name ?? ''));
this.disposables.push(
newDatabaseButton.onDidClick(async () => {
newDatabaseButton.enabled = false;
let name;
try {
name = await vscode.window.showInputBox({ prompt: loc.databaseName });
if (name) {
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(name ?? '', error));
} finally {
newDatabaseButton.enabled = true;
}
} catch (error) {
vscode.window.showErrorMessage(loc.databaseCreationFailed(name ?? '', error));
} finally {
newDatabaseButton.enabled = true;
}
});
}));
// Reset password
const resetPasswordButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
@@ -209,23 +207,24 @@ export class PostgresOverviewPage extends DashboardPage {
iconPath: IconPathHelper.edit
}).component();
resetPasswordButton.onDidClick(async () => {
resetPasswordButton.enabled = false;
try {
const password = await promptAndConfirmPassword(input => !input ? loc.enterANonEmptyPassword : '');
if (password) {
await this._postgresModel.update(s => {
s.arc = s.arc ?? new DuskyObjectModelsDatabaseServiceArcPayload();
s.arc.servicePassword = password;
});
vscode.window.showInformationMessage(loc.passwordReset);
this.disposables.push(
resetPasswordButton.onDidClick(async () => {
resetPasswordButton.enabled = false;
try {
const password = await promptAndConfirmPassword(input => !input ? loc.enterANonEmptyPassword : '');
if (password) {
await this._postgresModel.update(s => {
s.arc = s.arc ?? new DuskyObjectModelsDatabaseServiceArcPayload();
s.arc.servicePassword = password;
});
vscode.window.showInformationMessage(loc.passwordReset);
}
} catch (error) {
vscode.window.showErrorMessage(loc.passwordResetFailed(error));
} finally {
resetPasswordButton.enabled = true;
}
} catch (error) {
vscode.window.showErrorMessage(loc.passwordResetFailed(error));
} finally {
resetPasswordButton.enabled = true;
}
});
}));
// Delete service
const deleteButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
@@ -233,19 +232,20 @@ export class PostgresOverviewPage extends DashboardPage {
iconPath: IconPathHelper.delete
}).component();
deleteButton.onDidClick(async () => {
deleteButton.enabled = false;
try {
if (await promptForResourceDeletion(this._postgresModel.namespace, this._postgresModel.name)) {
await this._postgresModel.delete();
vscode.window.showInformationMessage(loc.resourceDeleted(this._postgresModel.fullName));
this.disposables.push(
deleteButton.onDidClick(async () => {
deleteButton.enabled = false;
try {
if (await promptForResourceDeletion(this._postgresModel.namespace, this._postgresModel.name)) {
await this._postgresModel.delete();
vscode.window.showInformationMessage(loc.resourceDeleted(this._postgresModel.fullName));
}
} catch (error) {
vscode.window.showErrorMessage(loc.resourceDeletionFailed(this._postgresModel.fullName, error));
} finally {
deleteButton.enabled = true;
}
} catch (error) {
vscode.window.showErrorMessage(loc.resourceDeletionFailed(this._postgresModel.fullName, error));
} finally {
deleteButton.enabled = true;
}
});
}));
// Refresh
const refreshButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
@@ -253,25 +253,26 @@ export class PostgresOverviewPage extends DashboardPage {
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;
this.disposables.push(
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;
}
});
await Promise.all([
this._postgresModel.refresh(),
this._controllerModel.refresh()
]);
} catch (error) {
vscode.window.showErrorMessage(loc.refreshFailed(error));
}
finally {
refreshButton.enabled = true;
}
}));
// Open in Azure portal
const openInAzurePortalButton = this.modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({
@@ -279,15 +280,16 @@ export class PostgresOverviewPage extends DashboardPage {
iconPath: IconPathHelper.openInTab
}).component();
openInAzurePortalButton.onDidClick(async () => {
const r = this._controllerModel.getRegistration(ResourceType.postgresInstances, this._postgresModel.namespace, this._postgresModel.name);
if (!r) {
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/${ResourceType.postgresInstances}/${r.instanceName}`));
}
});
this.disposables.push(
openInAzurePortalButton.onDidClick(async () => {
const r = this._controllerModel.getRegistration(ResourceType.postgresInstances, this._postgresModel.namespace, this._postgresModel.name);
if (!r) {
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/${ResourceType.postgresInstances}/${r.instanceName}`));
}
}));
return this.modelView.modelBuilder.toolbarContainer().withToolbarItems([
{ component: newDatabaseButton },

View File

@@ -13,18 +13,11 @@ import { ControllerModel } from '../../../models/controllerModel';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresPropertiesPage extends DashboardPage {
private disposables: vscode.Disposable[] = [];
private keyValueContainer?: KeyValueContainer;
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
modelView.onClosed(() =>
this.disposables.forEach(d => {
try { d.dispose(); }
catch { }
}));
this.disposables.push(this._postgresModel.onServiceUpdated(
() => this.eventuallyRunOnInitialized(() => this.refresh())));
@@ -66,20 +59,21 @@ export class PostgresPropertiesPage extends DashboardPage {
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;
}
});
this.disposables.push(
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 }

View File

@@ -12,7 +12,6 @@ import { PostgresModel } from '../../../models/postgresModel';
import { fromNow } from '../../../common/date';
export class PostgresResourceHealthPage extends DashboardPage {
private disposables: vscode.Disposable[] = [];
private interval: NodeJS.Timeout;
private podsUpdated?: azdata.TextComponent;
private podsTable?: azdata.DeclarativeTableComponent;
@@ -21,15 +20,11 @@ export class PostgresResourceHealthPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
modelView.onClosed(() => {
try { clearInterval(this.interval); }
catch { }
this.disposables.forEach(d => {
try { d.dispose(); }
this.disposables.push(
modelView.onClosed(() => {
try { clearInterval(this.interval); }
catch { }
});
});
}));
this.disposables.push(this._postgresModel.onServiceUpdated(
() => this.eventuallyRunOnInitialized(() => this.refresh())));
@@ -144,16 +139,17 @@ export class PostgresResourceHealthPage extends DashboardPage {
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;
}
});
this.disposables.push(
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 }

View File

@@ -49,15 +49,16 @@ export class PostgresSupportRequestPage extends DashboardPage {
width: '205px'
}).component();
supportRequestButton.onDidClick(() => {
const r = this._controllerModel.getRegistration(ResourceType.postgresInstances, this._postgresModel.namespace, this._postgresModel.name);
if (!r) {
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/${ResourceType.postgresInstances}/${r.instanceName}/supportrequest`));
}
});
this.disposables.push(
supportRequestButton.onDidClick(() => {
const r = this._controllerModel.getRegistration(ResourceType.postgresInstances, this._postgresModel.namespace, this._postgresModel.name);
if (!r) {
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/${ResourceType.postgresInstances}/${r.instanceName}/supportrequest`));
}
}));
content.addItem(supportRequestButton);
return root;