Skip to content

Commit

Permalink
Check only current kubecontext when there are more than 10 contexts i…
Browse files Browse the repository at this point in the history
…n config (podman-desktop#7657)

* feat: do not check non current contexts if contexts.length > 10
Signed-off-by: Philippe Martin <[email protected]>

* test: unit tests
Signed-off-by: Philippe Martin <[email protected]>

* fix: create constant MAX_NON_CURRENT_CONTEXTS_TO_CHECK
Signed-off-by: Philippe Martin <[email protected]>

* fix: rebase after rebase
Signed-off-by: Philippe Martin <[email protected]>
  • Loading branch information
feloy authored Jun 19, 2024
1 parent 25953ef commit fe235e7
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
51 changes: 51 additions & 0 deletions packages/main/src/plugin/kubernetes-context-state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,57 @@ describe('update', async () => {
expect(dispatchCurrentContextResourceSpy).toHaveBeenCalledWith('deployments', Array(DEPLOYMENTS_NS1).fill({}));
});

test('should check current context if contexts are > 10', async () => {
vi.mocked(makeInformer).mockImplementation(fakeMakeInformer);
client = new ContextsManager(apiSender);
const kubeConfig = new kubeclient.KubeConfig();
const config = {
clusters: [
{
name: 'cluster1',
server: 'server1',
},
],
users: [
{
name: 'user1',
},
],
contexts: [
{
name: `context1`,
cluster: 'cluster1',
user: 'user1',
},
],
currentContext: 'context1',
};

for (let i = 2; i <= 11; i++) {
config.contexts.push({
name: `context${i}`,
cluster: 'cluster1',
user: 'user1',
});
}

kubeConfig.loadFromOptions(config);
await client.update(kubeConfig);
const expectedMap = new Map<string, ContextGeneralState>();
expectedMap.set('context1', {
checking: { state: 'waiting' },
reachable: false,
error: 'Error: connection error',
resources: {
pods: 0,
deployments: 0,
},
} as ContextGeneralState);
vi.advanceTimersToNextTimer();
vi.advanceTimersToNextTimer();
expect(apiSenderSendMock).toHaveBeenCalledWith('kubernetes-contexts-general-state-update', expectedMap);
});

test('should write logs when connection fails', async () => {
vi.mocked(makeInformer).mockImplementation(fakeMakeInformer);
client = new ContextsManager(apiSender);
Expand Down
17 changes: 13 additions & 4 deletions packages/main/src/plugin/kubernetes-context-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ import {
dispatchTimeout,
} from './kubernetes-context-state-constants.js';

// If the number of contexts in the kubeconfig file is greater than this number,
// only the connectivity to the current context will be checked
const MAX_NON_CURRENT_CONTEXTS_TO_CHECK = 10;

// ContextInternalState stores informers for a kube context
type ContextInternalState = Map<ResourceName, Informer<KubernetesObject> & ObjectCache<KubernetesObject>>;

Expand Down Expand Up @@ -431,9 +435,9 @@ export class ContextsManager {
);
}

// update is the reconcile function, it gets as input the last known kube config
// and starts/stops informers for different kube contexts, depending on these inputs
async update(kubeconfig: KubeConfig): Promise<void> {
const checkOnlyCurrentContext = kubeconfig.contexts.length > MAX_NON_CURRENT_CONTEXTS_TO_CHECK;

this.kubeConfig = kubeconfig;
let contextChanged = false;
if (this.isContextChanged(kubeconfig)) {
Expand All @@ -453,20 +457,25 @@ export class ContextsManager {

// Delete informers for removed contexts
// We also remove the state of the current context if it has changed. It may happen that the name of the context is the same but it is pointing to a different cluster
// We also delete informers for non-current contexts wif we are checking only current context
let removed = false;
for (const name of this.states.getContextsNames()) {
if (
!this.kubeConfig.contexts.find(c => c.name === name) ||
(contextChanged && name === this.currentContext?.name)
(contextChanged && name === this.currentContext?.name) ||
(checkOnlyCurrentContext && name !== this.currentContext?.name)
) {
await this.states.dispose(name);
removed = true;
}
}

// Add informers for new contexts
// Add informers for new contexts (only current context if we are checking only it)
let added = false;
for (const context of this.kubeConfig.contexts) {
if (checkOnlyCurrentContext && context.name !== this.currentContext?.name) {
continue;
}
if (!this.states.hasContext(context.name)) {
const kubeContext: KubeContext = this.getKubeContext(context);
const informers = this.createKubeContextInformers(kubeContext);
Expand Down

0 comments on commit fe235e7

Please sign in to comment.