diff --git a/package.json b/package.json index 633ad9a..dcda8d8 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,11 @@ "configuration": { "title": "Minikube", "properties": { + "minikube.home": { + "type": "string", + "default": "", + "markdownDescription": "Path for the `.minikube` directory that minikube uses for state/configuration. See [documentation](https://minikube.sigs.k8s.io/docs/handbook/config/#environment-variables)" + }, "minikube.cluster.creation.name": { "type": "string", "default": "minikube", @@ -51,7 +56,6 @@ "scope": "KubernetesProviderConnectionFactory", "markdownDescription": "Optional mount definition `host-path:container-path` to include during the start of minikube container. See [documentation](https://minikube.sigs.k8s.io/docs/commands/start/#options)" } - } }, "menus": { diff --git a/src/create-cluster.spec.ts b/src/create-cluster.spec.ts index fa28162..3f18617 100644 --- a/src/create-cluster.spec.ts +++ b/src/create-cluster.spec.ts @@ -37,6 +37,7 @@ vi.mock('@podman-desktop/api', async () => { vi.mock('./util', async () => { return { getMinikubePath: vi.fn(), + getMinikubeHome: vi.fn(), }; }); diff --git a/src/create-cluster.ts b/src/create-cluster.ts index 91716c0..c812747 100644 --- a/src/create-cluster.ts +++ b/src/create-cluster.ts @@ -15,7 +15,7 @@ * * SPDX-License-Identifier: Apache-2.0 ***********************************************************************/ -import { getMinikubePath } from './util'; +import { getMinikubePath, getMinikubeHome } from './util'; import type { Logger, TelemetryLogger, CancellationToken } from '@podman-desktop/api'; import { process as processApi } from '@podman-desktop/api'; @@ -51,6 +51,8 @@ export async function createCluster( // update PATH to include minikube env.PATH = getMinikubePath(); + env.MINIKUBE_HOME = getMinikubeHome(); + // now execute the command to create the cluster try { await processApi.exec(minikubeCli, startArgs, { env, logger, token }); diff --git a/src/extension.spec.ts b/src/extension.spec.ts index a846407..5903a9d 100644 --- a/src/extension.spec.ts +++ b/src/extension.spec.ts @@ -31,6 +31,9 @@ vi.mock('@podman-desktop/api', async () => { containerEngine: { listContainers: vi.fn(), }, + configuration: { + getConfiguration: vi.fn(), + }, process: { exec: vi.fn(), diff --git a/src/extension.ts b/src/extension.ts index 3374dd1..a9bd4e8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -17,7 +17,7 @@ ***********************************************************************/ import * as extensionApi from '@podman-desktop/api'; -import { detectMinikube, getMinikubePath } from './util'; +import { detectMinikube, getMinikubePath, getMinikubeHome } from './util'; import { MinikubeInstaller } from './minikube-installer'; import type { CancellationToken, Logger } from '@podman-desktop/api'; import { window } from '@podman-desktop/api'; @@ -128,6 +128,7 @@ async function updateClusters(provider: extensionApi.Provider, containers: exten delete: async (logger): Promise => { const env = Object.assign({}, process.env); env.PATH = getMinikubePath(); + env.MINIKUBE_HOME = getMinikubeHome(); await extensionApi.process.exec(minikubeCli, ['delete', '--profile', cluster.name], { env, logger }); }, }; diff --git a/src/image-handler.spec.ts b/src/image-handler.spec.ts index 60efa03..922d948 100644 --- a/src/image-handler.spec.ts +++ b/src/image-handler.spec.ts @@ -42,6 +42,7 @@ vi.mock('@podman-desktop/api', async () => { vi.mock('./util', async () => { return { getMinikubePath: vi.fn(), + getMinikubeHome: vi.fn(), }; }); diff --git a/src/image-handler.ts b/src/image-handler.ts index 01bedd4..b16a97b 100644 --- a/src/image-handler.ts +++ b/src/image-handler.ts @@ -18,7 +18,7 @@ import type { MinikubeCluster } from './extension'; import * as extensionApi from '@podman-desktop/api'; import { tmpName } from 'tmp-promise'; -import { getMinikubePath } from './util'; +import { getMinikubePath, getMinikubeHome } from './util'; import * as fs from 'node:fs'; type ImageInfo = { engineId: string; name?: string; tag?: string }; @@ -63,6 +63,7 @@ export class ImageHandler { } env.PATH = getMinikubePath(); + env.MINIKUBE_HOME = getMinikubeHome(); try { // Create a temporary file to store the image filename = await tmpName(); diff --git a/src/minikube-installer.spec.ts b/src/minikube-installer.spec.ts index f27453f..aec33bc 100644 --- a/src/minikube-installer.spec.ts +++ b/src/minikube-installer.spec.ts @@ -38,6 +38,9 @@ vi.mock('@podman-desktop/api', async () => { env: { isWindows: vi.fn(), }, + configuration: { + getConfiguration: vi.fn(), + }, ProgressLocation: { APP_ICON: 1, }, diff --git a/src/util.spec.ts b/src/util.spec.ts index 1945203..f86d08a 100644 --- a/src/util.spec.ts +++ b/src/util.spec.ts @@ -20,11 +20,21 @@ import * as extensionApi from '@podman-desktop/api'; import { afterEach, beforeEach, expect, test, vi } from 'vitest'; -import { detectMinikube, getMinikubePath, installBinaryToSystem } from './util'; +import { detectMinikube, getMinikubePath, getMinikubeHome, installBinaryToSystem } from './util'; import type { MinikubeInstaller } from './minikube-installer'; import * as fs from 'node:fs'; import * as path from 'node:path'; +const { config } = vi.hoisted(() => { + return { + config: { + get: vi.fn(), + has: vi.fn(), + update: vi.fn(), + }, + }; +}); + vi.mock('@podman-desktop/api', async () => { return { window: { @@ -41,6 +51,9 @@ vi.mock('@podman-desktop/api', async () => { isWindows: vi.fn(), isLinux: vi.fn(), }, + configuration: { + getConfiguration: (): extensionApi.Configuration => config, + }, ProgressLocation: { APP_ICON: 1, }, @@ -85,6 +98,34 @@ test('getMinikubePath on macOS with existing PATH', async () => { expect(computedPath).toEqual(`${existingPATH}:/usr/local/bin:/opt/homebrew/bin:/opt/local/bin:/opt/podman/bin`); }); +test('getMinikubeHome with empty configuration property', async () => { + const existingEnvHome = '/my-existing-minikube-home'; + const existingConfigHome = ''; + process.env.MINIKUBE_HOME = existingEnvHome; + + const spyGetConfiguration = vi.spyOn(config, 'get'); + spyGetConfiguration.mockReturnValue(existingConfigHome); + + const computedHome = getMinikubeHome(); + + expect(computedHome).toEqual(existingEnvHome); + expect(computedHome).not.toEqual(existingConfigHome); +}); + +test('getMinikubeHome with empty configuration property', async () => { + const existingEnvHome = '/my-existing-minikube-home'; + const existingConfigHome = '/my-another-existing-minikube-home'; + process.env.MINIKUBE_HOME = existingEnvHome; + + const spyGetConfiguration = vi.spyOn(config, 'get'); + spyGetConfiguration.mockReturnValue(existingConfigHome); + + const computedHome = getMinikubeHome(); + + expect(computedHome).not.toEqual(existingEnvHome); + expect(computedHome).toEqual(existingConfigHome); +}); + test('detectMinikube', async () => { const fakeMinikubeInstaller = { getAssetInfo: vi.fn(), diff --git a/src/util.ts b/src/util.ts index 3df9e3a..17b7d45 100644 --- a/src/util.ts +++ b/src/util.ts @@ -33,6 +33,7 @@ export interface RunOptions { logger?: extensionApi.Logger; } +const minikubeConfiguration = extensionApi.configuration.getConfiguration('minikube'); const macosExtraPath = '/usr/local/bin:/opt/homebrew/bin:/opt/local/bin:/opt/podman/bin'; export function getMinikubePath(): string { @@ -48,10 +49,26 @@ export function getMinikubePath(): string { } } +export function getMinikubeHome(): string | undefined { + const minikubeHome = minikubeConfiguration.get('home'); + // Check env if configuration is not applied in UI + if (!minikubeHome) { + const env = process.env; + return env.MINIKUBE_HOME; + } else { + return minikubeHome; + } +} + // search if minikube is available in the path export async function detectMinikube(pathAddition: string, installer: MinikubeInstaller): Promise { try { - await extensionApi.process.exec('minikube', ['version'], { env: { PATH: getMinikubePath() } }); + await extensionApi.process.exec('minikube', ['version'], { + env: { + PATH: getMinikubePath(), + MINIKUBE_HOME: getMinikubeHome(), + }, + }); return 'minikube'; } catch (e) { // ignore and try another way @@ -61,7 +78,10 @@ export async function detectMinikube(pathAddition: string, installer: MinikubeIn if (assetInfo) { try { await extensionApi.process.exec(assetInfo.name, ['version'], { - env: { PATH: getMinikubePath().concat(path.delimiter).concat(pathAddition) }, + env: { + PATH: getMinikubePath().concat(path.delimiter).concat(pathAddition), + MINIKUBE_HOME: getMinikubeHome(), + }, }); return pathAddition .concat(path.sep)