Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/server_manager/model/digitalocean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export enum Status {
}

export interface Account {
// Returns the Account's unique id.
getId(): string;
// Returns a user-friendly name (email address) associated with the account.
getName(): Promise<string>;
// Returns the status of the account.
Expand Down
25 changes: 15 additions & 10 deletions src/server_manager/web_app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export class App {
}
const servers = await this.digitalOceanAccount.listServers();
for (const server of servers) {
this.addServer(server);
this.addServer(this.digitalOceanAccount.getId(), server);
}
return servers;
} catch (error) {
Expand All @@ -360,15 +360,15 @@ export class App {

private async loadManualServers() {
for (const server of await this.manualServerRepository.listServers()) {
this.addServer(server);
this.addServer(null, server);
}
}

private makeServerListEntry(server: server.Server): ServerListEntry {
private makeServerListEntry(accountId: string, server: server.Server): ServerListEntry {
return {
id: server.getId(),
accountId,
name: this.makeDisplayName(server),
isManaged: isManagedServer(server),
isSynced: !!server.getName(),
};
}
Expand All @@ -384,10 +384,10 @@ export class App {
return name;
}

private addServer(server: server.Server): void {
private addServer(accountId: string, server: server.Server): void {
console.log('Loading server', server);
this.idServerMap.set(server.getId(), server);
const serverEntry = this.makeServerListEntry(server);
const serverEntry = this.makeServerListEntry(accountId, server);
this.appRoot.serverList = this.appRoot.serverList.concat([serverEntry]);

if (isManagedServer(server) && !server.isInstallCompleted()) {
Expand Down Expand Up @@ -428,7 +428,7 @@ export class App {

private updateServerEntry(server: server.Server): void {
this.appRoot.serverList = this.appRoot.serverList.map(
(ds) => ds.id === server.getId() ? this.makeServerListEntry(server) : ds);
(ds) => ds.id === server.getId() ? this.makeServerListEntry(ds.accountId, server) : ds);
}

private getServerById(serverId: string): server.Server {
Expand Down Expand Up @@ -607,10 +607,15 @@ export class App {

// Clears the DigitalOcean credentials and returns to the intro screen.
private disconnectDigitalOceanAccount(): void {
if (!this.digitalOceanAccount) {
// Not connected.
return;
}
const accountId = this.digitalOceanAccount.getId();
this.cloudAccounts.disconnectDigitalOceanAccount();
this.digitalOceanAccount = null;
for (const serverEntry of this.appRoot.serverList) {
if (serverEntry.isManaged) {
if (serverEntry.accountId === accountId) {
this.removeServer(serverEntry.id);
}
}
Expand Down Expand Up @@ -665,7 +670,7 @@ export class App {
const server = await this.digitalOceanRetry(() => {
return this.digitalOceanAccount.createServer(regionId, serverName);
});
this.addServer(server);
this.addServer(this.digitalOceanAccount.getId(), server);
this.showServer(server);
} catch (error) {
console.error('Error from createDigitalOceanServer', error);
Expand Down Expand Up @@ -1050,7 +1055,7 @@ export class App {
}
const manualServer = await this.manualServerRepository.addServer(serverConfig);
if (await manualServer.isHealthy()) {
this.addServer(manualServer);
this.addServer(null, manualServer);
this.showServer(manualServer);
} else {
// Remove inaccessible manual server from local storage if it was just created.
Expand Down
2 changes: 1 addition & 1 deletion src/server_manager/web_app/cloud_accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class CloudAccounts implements accounts.CloudAccounts {
}

private createDigitalOceanAccount(accessToken: string): DigitalOceanAccount {
return new DigitalOceanAccount(accessToken, this.shadowboxSettings, this.isDebugMode);
return new DigitalOceanAccount('do', accessToken, this.shadowboxSettings, this.isDebugMode);
}

private createGcpAccount(refreshToken: string): GcpAccount {
Expand Down
9 changes: 7 additions & 2 deletions src/server_manager/web_app/digitalocean_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ export class DigitalOceanAccount implements digitalocean.Account {
private servers: DigitalOceanServer[] = [];

constructor(
private accessToken: string, private shadowboxSettings: ShadowboxSettings,
private id: string, private accessToken: string, private shadowboxSettings: ShadowboxSettings,
private debugMode: boolean) {
this.digitalOcean = new RestApiSession(accessToken);
}

getId(): string {
return this.id;
}

async getName(): Promise<string> {
return (await this.digitalOcean.getAccount())?.email;
}
Expand Down Expand Up @@ -121,7 +125,8 @@ export class DigitalOceanAccount implements digitalocean.Account {

// Creates a DigitalOceanServer object and adds it to the in-memory server list.
private createDigitalOceanServer(digitalOcean: DigitalOceanSession, dropletInfo: DropletInfo) {
const server = new DigitalOceanServer(digitalOcean, dropletInfo);
const server =
new DigitalOceanServer(`${this.id}:${dropletInfo.id}`, digitalOcean, dropletInfo);
this.servers.push(server);
return server;
}
Expand Down
5 changes: 3 additions & 2 deletions src/server_manager/web_app/digitalocean_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ export class DigitalOceanServer extends ShadowboxServer implements server.Manage
private eventQueue = new EventEmitter();
private installState: InstallState = InstallState.UNKNOWN;

constructor(private digitalOcean: DigitalOceanSession, private dropletInfo: DropletInfo) {
constructor(
id: string, private digitalOcean: DigitalOceanSession, private dropletInfo: DropletInfo) {
// Consider passing a RestEndpoint object to the parent constructor,
// to better encapsulate the management api address logic.
super(String(dropletInfo.id));
super(id);
console.info('DigitalOceanServer created');
this.eventQueue.once('server-active', () => console.timeEnd('activeServer'));
this.pollInstallState();
Expand Down
7 changes: 4 additions & 3 deletions src/server_manager/web_app/manual_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import {ShadowboxServer} from './shadowbox_server';

class ManualServer extends ShadowboxServer implements server.ManualServer {
constructor(
private manualServerConfig: server.ManualServerConfig, private forgetCallback: Function) {
super(manualServerConfig.apiUrl);
id: string, private manualServerConfig: server.ManualServerConfig,
private forgetCallback: Function) {
super(id);
this.setManagementApiUrl(manualServerConfig.apiUrl);
// manualServerConfig.certSha256 is expected to be in hex format (install script).
// Electron requires that this be decoded from hex (to unprintable binary),
Expand Down Expand Up @@ -92,7 +93,7 @@ export class ManualServerRepository implements server.ManualServerRepository {
}

private createServer(config: server.ManualServerConfig) {
const server = new ManualServer(config, () => {
const server = new ManualServer(`manual:${config.apiUrl}`, config, () => {
this.forgetServer(server);
});
return server;
Expand Down
4 changes: 4 additions & 0 deletions src/server_manager/web_app/testing/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export class FakeDigitalOceanAccount implements digitalocean.Account {

constructor(private accessToken = 'fake-access-token') {}

getId(): string {
return 'account-id';
}

async getName(): Promise<string> {
return 'fake-digitalocean-account-name';
}
Expand Down
8 changes: 4 additions & 4 deletions src/server_manager/web_app/ui_components/app-root.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ const TOS_ACK_LOCAL_STORAGE_KEY = 'tos-ack';
* An access key to be displayed
* @typedef {Object} ServerListEntry
* @prop {string} id
* @prop {string|null} accountId
* @prop {string} name
* @prop {boolean} isManaged
* @prop {boolean} isSynced
*/

Expand Down Expand Up @@ -769,7 +769,7 @@ export class AppRoot extends mixinBehaviors
}

_computeHasManualServers(serverList) {
return this.serverList.filter(server => !server.isManaged).length > 0;
return this.serverList.filter(server => !server.accountId).length > 0;
}

_userAcceptedTosChanged(userAcceptedTos) {
Expand Down Expand Up @@ -905,11 +905,11 @@ export class AppRoot extends mixinBehaviors
}

_isServerManaged(server) {
return server.isManaged;
return !!server.accountId;
}

_isServerManual(server) {
return !server.isManaged;
return !server.accountId;
}

_sortServersByName(a, b) {
Expand Down