Skip to content

Commit 26319f2

Browse files
committed
refactor: send signals with rpcExtension
1 parent d4e2aea commit 26319f2

File tree

15 files changed

+425
-117
lines changed

15 files changed

+425
-117
lines changed

packages/common/src/channels.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,14 @@ import { createRpcChannel } from './rpc';
33

44
// RPC channels (used by the webview to send requests to the extension)
55
export const API_DASHBOARD = createRpcChannel<DashboardApi>('DashboardApi');
6+
7+
export interface KubernetesUpdateResourceInfo {
8+
resourceName: string;
9+
}
10+
11+
// Broadcast events (sent by extension and received by the webview)
12+
export const ACTIVE_RESOURCES_COUNT = createRpcChannel<undefined>('ActiveResourcesCount');
13+
export const KUBERNETES_CONTEXTS_HEALTHS = createRpcChannel<undefined>('KubernetesContextsHealths');
14+
export const KUBERNETES_CONTEXTS_PERMISSIONS = createRpcChannel<undefined>('KubernetesContextsPermissions');
15+
export const KUBERNETES_RESOURCES_COUNT = createRpcChannel<undefined>('KubernetesResourcesCount');
16+
export const KUBERNETES_UPDATE_RESOURCE = createRpcChannel<KubernetesUpdateResourceInfo>('KubernetesUpdateResource');

packages/common/src/interface/dashboard-api.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
* SPDX-License-Identifier: Apache-2.0
1717
***********************************************************************/
1818

19+
import type { ResourceCount } from '../model/kubernetes-resource-count';
20+
1921
export const DashboardApi = Symbol.for('DashboardApi');
2022
export interface DashboardApi {
21-
ping(): Promise<string>;
23+
getActiveResourcesCount(): Promise<ResourceCount[]>;
2224
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**********************************************************************
2+
* Copyright (C) 2025 Red Hat, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
***********************************************************************/
18+
19+
import type { ContextsStatesDispatcher } from '../manager/contexts-states-dispatcher';
20+
import { API_DASHBOARD } from '/@common/channels';
21+
import type { DashboardApi } from '/@common/interface/dashboard-api';
22+
import type { ResourceCount } from '/@common/model/kubernetes-resource-count';
23+
import type { RpcChannel } from '/@common/rpc';
24+
25+
export class DashboardImpl implements DashboardApi {
26+
constructor(private contextsStatesDispatcher: ContextsStatesDispatcher) {}
27+
28+
getChannel(): RpcChannel<DashboardApi> {
29+
return API_DASHBOARD;
30+
}
31+
32+
async getActiveResourcesCount(): Promise<ResourceCount[]> {
33+
return this.contextsStatesDispatcher.getActiveResourcesCount();
34+
}
35+
}

packages/extension/src/dashboard-extension.spec.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,19 @@ import { assert, beforeEach, describe, expect, test, vi } from 'vitest';
2222
import { DashboardExtension } from './dashboard-extension';
2323
import { vol } from 'memfs';
2424

25-
import type { ContextsManager } from './manager/contexts-manager';
26-
import type { ContextsStatesDispatcher } from './manager/contexts-states-dispatcher';
25+
import { ContextsManager } from './manager/contexts-manager';
26+
import { ContextsStatesDispatcher } from './manager/contexts-states-dispatcher';
2727

2828
let extensionContextMock: ExtensionContext;
2929
let dashboardExtension: DashboardExtension;
3030
let contextsManagerMock: ContextsManager;
31-
let contextsStatesDispatcher: ContextsStatesDispatcher;
31+
let contextsStatesDispatcherMock: ContextsStatesDispatcher;
3232

3333
vi.mock(import('node:fs'));
3434
vi.mock(import('node:fs/promises'));
3535
vi.mock(import('@kubernetes/client-node'));
36+
vi.mock(import('./manager/contexts-manager'));
37+
vi.mock(import('./manager/contexts-states-dispatcher'));
3638

3739
beforeEach(() => {
3840
vi.restoreAllMocks();
@@ -50,14 +52,18 @@ beforeEach(() => {
5052
extensionContextMock = {
5153
subscriptions: [],
5254
} as unknown as ExtensionContext;
53-
// Create a mock for the contextsManager
55+
5456
contextsManagerMock = {
5557
update: vi.fn(),
5658
} as unknown as ContextsManager;
57-
contextsStatesDispatcher = {
59+
vi.mocked(ContextsManager).mockReturnValue(contextsManagerMock);
60+
61+
contextsStatesDispatcherMock = {
5862
init: vi.fn(),
5963
} as unknown as ContextsStatesDispatcher;
60-
dashboardExtension = new DashboardExtension(extensionContextMock, contextsManagerMock, contextsStatesDispatcher);
64+
vi.mocked(ContextsStatesDispatcher).mockReturnValue(contextsStatesDispatcherMock);
65+
66+
dashboardExtension = new DashboardExtension(extensionContextMock);
6167
vi.mocked(kubernetes.getKubeconfig).mockReturnValue({
6268
path: '/path/to/kube/config',
6369
} as Uri);
@@ -80,7 +86,7 @@ describe('a kubeconfig file is not present', () => {
8086
callback({ type: 'UPDATE', location: { path: '/path/to/kube/config' } as Uri });
8187
expect(contextsManagerMock.update).toHaveBeenCalledOnce();
8288

83-
expect(contextsStatesDispatcher.init).toHaveBeenCalledOnce();
89+
expect(contextsStatesDispatcherMock.init).toHaveBeenCalledOnce();
8490
});
8591

8692
test('should deactivate correctly', async () => {
@@ -107,7 +113,7 @@ describe('a kubeconfig file is present', () => {
107113
callback({ type: 'UPDATE', location: { path: '/path/to/kube/config' } as Uri });
108114
expect(contextsManagerMock.update).toHaveBeenCalledOnce();
109115

110-
expect(contextsStatesDispatcher.init).toHaveBeenCalledOnce();
116+
expect(contextsStatesDispatcherMock.init).toHaveBeenCalledOnce();
111117
});
112118

113119
test('should deactivate correctly', async () => {

packages/extension/src/dashboard-extension.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,19 @@ import { kubernetes, Uri, window } from '@podman-desktop/api';
2222
import { RpcExtension } from '/@common/rpc/rpc';
2323

2424
import { readFile } from 'node:fs/promises';
25-
import type { ContextsManager } from './manager/contexts-manager';
25+
import { ContextsManager } from './manager/contexts-manager';
2626
import { existsSync } from 'node:fs';
2727
import { KubeConfig } from '@kubernetes/client-node';
28-
import type { ContextsStatesDispatcher } from './manager/contexts-states-dispatcher';
28+
import { ContextsStatesDispatcher } from './manager/contexts-states-dispatcher';
29+
import { DashboardImpl } from './controller/dashboard-impl';
2930

3031
export class DashboardExtension {
3132
#extensionContext: ExtensionContext;
3233
#contextsManager: ContextsManager;
3334
#contextsStatesDispatcher: ContextsStatesDispatcher;
3435

35-
constructor(
36-
readonly extensionContext: ExtensionContext,
37-
readonly contextManager: ContextsManager,
38-
readonly contextsStatesDispatcher: ContextsStatesDispatcher,
39-
) {
36+
constructor(readonly extensionContext: ExtensionContext) {
4037
this.#extensionContext = extensionContext;
41-
this.#contextsManager = contextManager;
42-
this.#contextsStatesDispatcher = contextsStatesDispatcher;
4338
}
4439

4540
async activate(): Promise<void> {
@@ -50,12 +45,19 @@ export class DashboardExtension {
5045
rpcExtension.init();
5146
this.#extensionContext.subscriptions.push(rpcExtension);
5247

48+
this.#contextsManager = new ContextsManager();
49+
this.#contextsStatesDispatcher = new ContextsStatesDispatcher(this.#contextsManager, rpcExtension);
50+
5351
const now = performance.now();
5452

5553
const afterFirst = performance.now();
5654

5755
console.log('activation time:', afterFirst - now);
5856

57+
// Register all controllers
58+
const dashboardImpl = new DashboardImpl(this.#contextsStatesDispatcher);
59+
rpcExtension.registerInstance(dashboardImpl.getChannel(), dashboardImpl);
60+
5961
await this.listenMonitoring();
6062
await this.startMonitoring();
6163
}

packages/extension/src/main.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,12 @@
1919
import type { ExtensionContext } from '@podman-desktop/api';
2020

2121
import { DashboardExtension } from './dashboard-extension';
22-
import { ContextsManager } from './manager/contexts-manager';
23-
import { ContextsStatesDispatcher } from './manager/contexts-states-dispatcher';
2422

2523
let dashboardExtension: DashboardExtension | undefined;
2624

2725
// Initialize the activation of the extension.
2826
export async function activate(extensionContext: ExtensionContext): Promise<void> {
29-
const contextsManager = new ContextsManager();
30-
const apiSender = {
31-
send: (channel: string, data?: unknown): void => {
32-
console.log(`==> recv data "${data}" on channel ${channel}`);
33-
},
34-
};
35-
const contextsStatesDispatcher = new ContextsStatesDispatcher(contextsManager, apiSender);
36-
dashboardExtension ??= new DashboardExtension(extensionContext, contextsManager, contextsStatesDispatcher);
27+
dashboardExtension ??= new DashboardExtension(extensionContext);
3728

3829
await dashboardExtension.activate();
3930
}

0 commit comments

Comments
 (0)