From ef6013384847c1727fe916bf91a6cf341221fb6a Mon Sep 17 00:00:00 2001 From: Philippe Martin Date: Mon, 4 Mar 2024 16:13:06 +0100 Subject: [PATCH] fix: clear local state for services when informer is stopped (#6250) * fix: clear local state for services when informer is stopped Signed-off-by: Philippe Martin * test: add unit test Signed-off-by: Philippe Martin --- .../src/plugin/kubernetes-context-state.spec.ts | 7 +++++-- .../main/src/plugin/kubernetes-context-state.ts | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/main/src/plugin/kubernetes-context-state.spec.ts b/packages/main/src/plugin/kubernetes-context-state.spec.ts index 3ec1603d9eb47..8b990f62126ca 100644 --- a/packages/main/src/plugin/kubernetes-context-state.spec.ts +++ b/packages/main/src/plugin/kubernetes-context-state.spec.ts @@ -1131,7 +1131,7 @@ test('calling getCurrentContextResources should start service informer, the firs expect(makeInformerMock).not.toHaveBeenCalled(); }); -test('changing context should stop service informer on previous current context', async () => { +test('changing context should stop service informer on previous current context and clear state', async () => { vi.useFakeTimers(); const makeInformerMock = vi.mocked(makeInformer); makeInformerMock.mockImplementation( @@ -1140,7 +1140,7 @@ test('changing context should stop service informer on previous current context' path: string, _listPromiseFn: kubeclient.ListPromise, ) => { - return new FakeInformer(kubeconfig.currentContext, path, 0, undefined, [], []); + return new FakeInformer(kubeconfig.currentContext, path, 1, undefined, [], []); }, ); const client = new ContextsManager(apiSender); @@ -1188,6 +1188,8 @@ test('changing context should stop service informer on previous current context' expect.anything(), ); + expect(client.getContextResources('context1', 'services').length).toBe(1); + makeInformerMock.mockClear(); config.currentContext = 'context2'; @@ -1199,6 +1201,7 @@ test('changing context should stop service informer on previous current context' expect(informerStopMock).toHaveBeenCalledTimes(1); expect(informerStopMock).toHaveBeenCalledWith('context1', '/api/v1/namespaces/ns1/services'); + expect(client.getContextResources('context1', 'services').length).toBe(0); }); describe('ContextsStates tests', () => { diff --git a/packages/main/src/plugin/kubernetes-context-state.ts b/packages/main/src/plugin/kubernetes-context-state.ts index c44eec33cd109..991e28caf3aba 100644 --- a/packages/main/src/plugin/kubernetes-context-state.ts +++ b/packages/main/src/plugin/kubernetes-context-state.ts @@ -220,7 +220,7 @@ export class ContextsStates { }; } - getCurrentContextResources(current: string, resourceName: ResourceName): KubernetesObject[] { + getContextResources(current: string, resourceName: ResourceName): KubernetesObject[] { if (current) { const state = this.state.get(current); if (!state?.reachable) { @@ -273,9 +273,13 @@ export class ContextsStates { if (informers) { for (const [resourceName, informer] of informers) { if (isSecondaryResourceName(resourceName)) { - console.debug(`stop watching ${resourceName} in context ${contextName}`); await informer?.stop(); + // We clear the informer and the local state informers.delete(resourceName); + const state = this.state.get(contextName); + if (state) { + state.resources[resourceName] = []; + } } } } @@ -663,7 +667,7 @@ export class ContextsManager { private dispatchCurrentContextResource(resourceName: ResourceName): void { this.apiSender.send( `kubernetes-current-context-${resourceName}-update`, - this.states.getCurrentContextResources(this.kubeConfig.currentContext, resourceName), + this.states.getContextResources(this.kubeConfig.currentContext, resourceName), ); } @@ -673,7 +677,7 @@ export class ContextsManager { } if (this.states.hasInformer(this.currentContext, resourceName)) { console.debug(`already watching ${resourceName} in context ${this.currentContext}`); - return this.states.getCurrentContextResources(this.kubeConfig.currentContext, resourceName); + return this.states.getContextResources(this.kubeConfig.currentContext, resourceName); } if (!this.states.isReachable(this.currentContext)) { console.debug(`skip watching ${resourceName} in context ${this.currentContext}, as the context is not reachable`); @@ -683,4 +687,9 @@ export class ContextsManager { this.startResourceInformer(this.currentContext, resourceName); return []; } + + // for tests + public getContextResources(contextName: string, resourceName: ResourceName): KubernetesObject[] { + return this.states.getContextResources(contextName, resourceName); + } }