mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-05-24 10:18:53 +00:00
feat: detect podman v4 machines not compliant with the new format of v5 (#6570)
* feat: detect podman v4 machines not compliant with the new format of podman v5 fixes https://github.com/containers/podman-desktop/issues/6566 Signed-off-by: Florent Benoit <fbenoit@redhat.com>
This commit is contained in:
parent
d366e775e0
commit
67ee7ef9fd
3 changed files with 313 additions and 27 deletions
|
|
@ -296,7 +296,7 @@
|
|||
"content": [
|
||||
[
|
||||
{
|
||||
"value": "Podman Machines created with podman v4 are no longer supported by podman v5"
|
||||
"value": "Podman Machines created by Podman v4 are no longer supported by v5"
|
||||
}
|
||||
],
|
||||
[
|
||||
|
|
|
|||
|
|
@ -142,7 +142,8 @@ beforeEach(() => {
|
|||
VMType: 'wsl',
|
||||
},
|
||||
};
|
||||
|
||||
vi.resetAllMocks();
|
||||
extension.resetShouldNotifySetup();
|
||||
(extensionApi.env.createTelemetryLogger as Mock).mockReturnValue(telemetryLogger);
|
||||
|
||||
extension.initTelemetryLogger();
|
||||
|
|
@ -259,7 +260,7 @@ vi.mock('./util', async () => {
|
|||
});
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.resetAllMocks();
|
||||
console.error = consoleErrorMock;
|
||||
});
|
||||
|
||||
|
|
@ -1136,11 +1137,19 @@ test('if there are no machines, make sure checkDefaultMachine is not being ran i
|
|||
expect(spyCheckDefaultMachine).not.toBeCalled();
|
||||
});
|
||||
|
||||
describe('initCheckAndRegisterUpdate', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
test('Should notify clean machine if getJSONMachineList is erroring due to an invalid format on mac', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
vi.spyOn(extensionApi.process, 'exec').mockRejectedValue({
|
||||
name: 'name',
|
||||
message: 'description',
|
||||
stderr: 'cannot unmarshal string',
|
||||
});
|
||||
await expect(extension.updateMachines(provider)).rejects.toThrow('description');
|
||||
expect(extensionApi.window.showNotification).toBeCalled();
|
||||
expect(extensionApi.context.setValue).toBeCalledWith(extension.CLEANUP_REQUIRED_MACHINE_KEY, true);
|
||||
});
|
||||
|
||||
describe('initCheckAndRegisterUpdate', () => {
|
||||
test('check there is an update', async () => {
|
||||
const podmanInstall = {
|
||||
checkForUpdate: vi.fn(),
|
||||
|
|
@ -1299,6 +1308,7 @@ describe('initCheckAndRegisterUpdate', () => {
|
|||
|
||||
describe('registerOnboardingMachineExistsCommand', () => {
|
||||
test('check with error when calling podman machine ls command', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockRejectedValue(new Error('error'));
|
||||
|
|
@ -1324,6 +1334,8 @@ describe('registerOnboardingMachineExistsCommand', () => {
|
|||
});
|
||||
|
||||
test('check with 2 machines', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
// return 2 empty machines
|
||||
|
|
@ -1350,6 +1362,8 @@ describe('registerOnboardingMachineExistsCommand', () => {
|
|||
});
|
||||
|
||||
test('check with 0 machine', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
// return empty machine array
|
||||
|
|
@ -1378,14 +1392,21 @@ describe('registerOnboardingMachineExistsCommand', () => {
|
|||
|
||||
describe('registerOnboardingUnsupportedPodmanMachineCommand', () => {
|
||||
test('check with v5 and previous qemu folders', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValue({
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 5.0.0',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// second call to get the machine list
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: '[]',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// perform the call
|
||||
const disposable = registerOnboardingUnsupportedPodmanMachineCommand();
|
||||
|
||||
|
|
@ -1407,15 +1428,23 @@ describe('registerOnboardingUnsupportedPodmanMachineCommand', () => {
|
|||
});
|
||||
|
||||
test('check with v5 and no previous qemu folders', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
// no qemu folders
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValue({
|
||||
// first call to get the podman version
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 5.0.0',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// second call to get the machine list
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: '[]',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// perform the call
|
||||
const disposable = registerOnboardingUnsupportedPodmanMachineCommand();
|
||||
|
||||
|
|
@ -1437,14 +1466,21 @@ describe('registerOnboardingUnsupportedPodmanMachineCommand', () => {
|
|||
});
|
||||
|
||||
test('check with v4 and qemu folders', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValue({
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 4.9.3',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// second call to get the machine list
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: '[]',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// perform the call
|
||||
const disposable = registerOnboardingUnsupportedPodmanMachineCommand();
|
||||
|
||||
|
|
@ -1464,10 +1500,50 @@ describe('registerOnboardingUnsupportedPodmanMachineCommand', () => {
|
|||
// check called with false as there are qemu folders but we're with podman v4
|
||||
expect(extensionApi.context.setValue).toBeCalledWith('unsupportedPodmanMachine', false, 'onboarding');
|
||||
});
|
||||
|
||||
test('check with v5 and error in JSON of machines', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
// no qemu folders
|
||||
vi.mocked(fs.existsSync).mockReturnValue(false);
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
// first call to get the podman version
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 5.0.0',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// second call to get the machine list
|
||||
vi.mocked(extensionApi.process.exec).mockRejectedValue({
|
||||
stderr: 'incompatible machine config',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// perform the call
|
||||
const disposable = registerOnboardingUnsupportedPodmanMachineCommand();
|
||||
|
||||
// checks
|
||||
expect(disposable).toBeDefined();
|
||||
|
||||
// check command is called
|
||||
expect(extensionApi.commands.registerCommand).toBeCalledWith(
|
||||
'podman.onboarding.checkUnsupportedPodmanMachine',
|
||||
expect.any(Function),
|
||||
);
|
||||
|
||||
const func = vi.mocked(extensionApi.commands.registerCommand).mock.calls[0][1];
|
||||
// call the function
|
||||
await func();
|
||||
|
||||
// check it is false as there are no qemu folders
|
||||
expect(extensionApi.context.setValue).toBeCalledWith('unsupportedPodmanMachine', true, 'onboarding');
|
||||
});
|
||||
});
|
||||
|
||||
describe('registerOnboardingRemoveUnsupportedMachinesCommand', () => {
|
||||
test('check with previous qemu folders', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
vi.mocked(fs.existsSync).mockReturnValue(true);
|
||||
|
||||
// mock confirmation window message to true
|
||||
|
|
@ -1475,10 +1551,14 @@ describe('registerOnboardingRemoveUnsupportedMachinesCommand', () => {
|
|||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValue({
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 5.0.0',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: '[]',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
// perform the call
|
||||
const disposable = extension.registerOnboardingRemoveUnsupportedMachinesCommand();
|
||||
|
||||
|
|
@ -1505,4 +1585,72 @@ describe('registerOnboardingRemoveUnsupportedMachinesCommand', () => {
|
|||
// check called with true as there are qemu folders
|
||||
expect(extensionApi.context.setValue).toBeCalledWith('unsupportedMachineRemoved', 'ok', 'onboarding');
|
||||
});
|
||||
|
||||
test('check with previous podman v4 config files', async () => {
|
||||
vi.mocked(isMac).mockReturnValue(true);
|
||||
|
||||
// mock confirmation window message to true
|
||||
vi.mocked(extensionApi.window.showWarningMessage).mockResolvedValue('Yes');
|
||||
|
||||
vi.mocked(extensionApi.commands.registerCommand).mockReturnValue({ dispose: vi.fn() });
|
||||
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: 'podman version 5.0.0',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
// two times false (no qemu folders)
|
||||
vi.mocked(fs.existsSync).mockReturnValueOnce(false);
|
||||
vi.mocked(fs.existsSync).mockReturnValueOnce(false);
|
||||
|
||||
// return an error when trying to list output
|
||||
vi.mocked(fs.existsSync).mockReturnValueOnce(true);
|
||||
vi.mocked(extensionApi.process.exec).mockResolvedValueOnce({
|
||||
stdout: '[]',
|
||||
stderr: 'incompatible machine config',
|
||||
} as unknown as extensionApi.RunResult);
|
||||
|
||||
vi.mocked(fs.promises.readdir).mockResolvedValue(['foo.json'] as unknown as fs.Dirent[]);
|
||||
|
||||
// mock readfile
|
||||
vi.mocked(fs.promises.readFile).mockResolvedValueOnce('{"Driver": "podman"}');
|
||||
|
||||
// perform the call
|
||||
const disposable = extension.registerOnboardingRemoveUnsupportedMachinesCommand();
|
||||
|
||||
// checks
|
||||
expect(disposable).toBeDefined();
|
||||
|
||||
// check command is called
|
||||
expect(extensionApi.commands.registerCommand).toBeCalledWith(
|
||||
'podman.onboarding.removeUnsupportedMachines',
|
||||
expect.any(Function),
|
||||
);
|
||||
|
||||
const func = vi.mocked(extensionApi.commands.registerCommand).mock.calls[0][1];
|
||||
// call the function
|
||||
await func();
|
||||
|
||||
// expect rm to be called
|
||||
expect(fs.promises.rm).toBeCalledWith(expect.stringContaining('foo.json'), {
|
||||
recursive: true,
|
||||
maxRetries: 3,
|
||||
retryDelay: 1000,
|
||||
});
|
||||
|
||||
// check called with true as there are qemu folders
|
||||
expect(extensionApi.context.setValue).toBeCalledWith('unsupportedMachineRemoved', 'ok', 'onboarding');
|
||||
});
|
||||
});
|
||||
|
||||
test('isIncompatibleMachineOutput', () => {
|
||||
const emptyResponse = extension.isIncompatibleMachineOutput(undefined);
|
||||
expect(emptyResponse).toBeFalsy();
|
||||
|
||||
const unknownErrorResponse = extension.isIncompatibleMachineOutput('unknown error');
|
||||
expect(unknownErrorResponse).toBeFalsy();
|
||||
|
||||
const wslErrorResponse = extension.isIncompatibleMachineOutput('cannot unmarshal string');
|
||||
expect(wslErrorResponse).toBeTruthy();
|
||||
|
||||
const applehvErrorResponse = extension.isIncompatibleMachineOutput('incompatible machine config');
|
||||
expect(applehvErrorResponse).toBeTruthy();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -125,12 +125,33 @@ export type MachineListOutput = {
|
|||
stderr: string;
|
||||
};
|
||||
|
||||
export function isIncompatibleMachineOutput(output: string | undefined): boolean {
|
||||
// apple HV v4 to v5 machine config error
|
||||
const APPLE_HV_V4_V5_ERROR = 'incompatible machine config';
|
||||
|
||||
// wsl v4 to v5 machine config error
|
||||
const WSL_V4_V5_ERROR = 'cannot unmarshal string';
|
||||
|
||||
if (output) {
|
||||
return output.includes(APPLE_HV_V4_V5_ERROR) || output.includes(WSL_V4_V5_ERROR);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateMachines(provider: extensionApi.Provider): Promise<void> {
|
||||
// init machines available
|
||||
let machineListOutput: MachineListOutput;
|
||||
try {
|
||||
machineListOutput = await getJSONMachineList();
|
||||
} catch (error) {
|
||||
let shouldCleanMachine = false;
|
||||
// check if field stderr is present in the error object
|
||||
if (error.stderr) {
|
||||
shouldCleanMachine = isIncompatibleMachineOutput(error.stderr);
|
||||
}
|
||||
extensionApi.context.setValue(CLEANUP_REQUIRED_MACHINE_KEY, shouldCleanMachine);
|
||||
|
||||
// Only on macOS and Windows should we show the setup notification
|
||||
// if for some reason doing getJSONMachineList fails..
|
||||
if (shouldNotifySetup && !isLinux()) {
|
||||
|
|
@ -150,6 +171,18 @@ export async function updateMachines(provider: extensionApi.Provider): Promise<v
|
|||
if (installedPodman) {
|
||||
shouldCleanMachine = shouldNotifyQemuMachinesWithV5(installedPodman);
|
||||
}
|
||||
// check if the machine needs to be cleaned for v4 --> v5 format
|
||||
if (!shouldCleanMachine) {
|
||||
shouldCleanMachine = isIncompatibleMachineOutput(machineListOutput.stderr);
|
||||
}
|
||||
|
||||
// invalid machines is not making the provider working properly so always notify
|
||||
if (shouldCleanMachine && shouldNotifySetup && !isLinux()) {
|
||||
// push setup notification
|
||||
notificationDisposable = extensionApi.window.showNotification(setupPodmanNotification);
|
||||
shouldCleanMachine = false;
|
||||
}
|
||||
|
||||
extensionApi.context.setValue(CLEANUP_REQUIRED_MACHINE_KEY, shouldCleanMachine);
|
||||
|
||||
// Only show the notification on macOS and Windows
|
||||
|
|
@ -920,40 +953,128 @@ export function registerOnboardingUnsupportedPodmanMachineCommand(): extensionAp
|
|||
isUnsupported = shouldNotifyQemuMachinesWithV5(installedPodman);
|
||||
}
|
||||
|
||||
// check if the machine needs to be cleaned for v4 --> v5 format
|
||||
if (!isUnsupported) {
|
||||
try {
|
||||
const machineListOutput = await getJSONMachineList();
|
||||
isUnsupported = isIncompatibleMachineOutput(machineListOutput.stderr);
|
||||
} catch (error) {
|
||||
// check if stderr in the error object
|
||||
if (error.stderr) {
|
||||
isUnsupported = isIncompatibleMachineOutput(error.stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extensionApi.context.setValue('unsupportedPodmanMachine', isUnsupported, 'onboarding');
|
||||
});
|
||||
}
|
||||
|
||||
export function registerOnboardingRemoveUnsupportedMachinesCommand(): extensionApi.Disposable {
|
||||
return extensionApi.commands.registerCommand('podman.onboarding.removeUnsupportedMachines', async () => {
|
||||
// only on macOS
|
||||
// do not check if version is v5 as it is being checked by the command that triggers this one
|
||||
if (extensionApi.env.isMac) {
|
||||
const fileAndFoldersToRemove = [];
|
||||
const wslMachinesToUnregister = [];
|
||||
|
||||
const installedPodman = await getPodmanInstallation();
|
||||
|
||||
if (extensionApi.env.isMac && installedPodman?.version.startsWith('5.')) {
|
||||
// remove the qemu machines folder
|
||||
const qemuSharePath = path.resolve(os.homedir(), appHomeDir(), 'machine', 'qemu');
|
||||
const qemuConfigPath = path.resolve(os.homedir(), appConfigDir(), 'machine', 'qemu');
|
||||
|
||||
// remove folders if exists
|
||||
const foldersToRemove = [];
|
||||
if (fs.existsSync(qemuSharePath)) {
|
||||
foldersToRemove.push(qemuSharePath);
|
||||
fileAndFoldersToRemove.push(qemuSharePath);
|
||||
}
|
||||
if (fs.existsSync(qemuConfigPath)) {
|
||||
foldersToRemove.push(qemuConfigPath);
|
||||
fileAndFoldersToRemove.push(qemuConfigPath);
|
||||
}
|
||||
|
||||
// prompt the user to confirm
|
||||
const result = await extensionApi.window.showWarningMessage(
|
||||
'Removing old unsupported Podman machines will delete all of their data. Confirm approval?',
|
||||
'Yes',
|
||||
'No',
|
||||
);
|
||||
if (result === 'No') {
|
||||
return;
|
||||
if (fileAndFoldersToRemove.length > 0) {
|
||||
const result = await extensionApi.window.showWarningMessage(
|
||||
'Removing old unsupported provider Podman machines will delete all of their data. Confirm approval?',
|
||||
'Yes',
|
||||
'No',
|
||||
);
|
||||
if (result === 'No') {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errors: string[] = [];
|
||||
for (const folder of foldersToRemove) {
|
||||
// check if unmarshalling errors
|
||||
let machineListError = '';
|
||||
try {
|
||||
const machineListOutput = await getJSONMachineList();
|
||||
machineListError = machineListOutput.stderr;
|
||||
} catch (error) {
|
||||
machineListError = error.stderr;
|
||||
}
|
||||
|
||||
let machineFolderToCheck: string | undefined;
|
||||
// check invalid config files only with v5
|
||||
if (installedPodman?.version.startsWith('5.')) {
|
||||
if (isMac()) {
|
||||
machineFolderToCheck = path.resolve(os.homedir(), appConfigDir(), 'machine', 'applehv');
|
||||
} else if (isWindows()) {
|
||||
machineFolderToCheck = path.resolve(os.homedir(), appConfigDir(), 'machine', 'wsl');
|
||||
}
|
||||
}
|
||||
|
||||
if (machineFolderToCheck && isIncompatibleMachineOutput(machineListError) && fs.existsSync(machineFolderToCheck)) {
|
||||
// check for JSON files in the folder
|
||||
const files = await fs.promises.readdir(machineFolderToCheck);
|
||||
const machineFilesToAnalyze = files.filter(file => file.endsWith('.json'));
|
||||
let machineConfigJson: { GvProxy?: string } = {};
|
||||
const allMachines = await Promise.all(
|
||||
machineFilesToAnalyze.map(async file => {
|
||||
// read content of the file
|
||||
const absoluteFile = path.join(machineFolderToCheck, file);
|
||||
try {
|
||||
const machineConfigJsonRaw = await fs.promises.readFile(absoluteFile, 'utf-8');
|
||||
machineConfigJson = JSON.parse(machineConfigJsonRaw);
|
||||
} catch (error: unknown) {
|
||||
console.error('Error reading machine file', file, error);
|
||||
}
|
||||
const machineName = file.replace('.json', '');
|
||||
return {
|
||||
file,
|
||||
machineName,
|
||||
machineFile: absoluteFile,
|
||||
json: machineConfigJson,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
const invalidMachines = allMachines.filter(machine => {
|
||||
// check if the machine has GvProxy field, if it doesn't, it's an invalid machine
|
||||
return !machine.json.GvProxy;
|
||||
});
|
||||
|
||||
// prompt to remove these invalid machines
|
||||
if (invalidMachines.length > 0) {
|
||||
const result = await extensionApi.window.showWarningMessage(
|
||||
`Removing old unsupported Podman machines "${invalidMachines.map(m => m.machineName).join(', ')}" will delete all of their data. Confirm approval?`,
|
||||
'Yes',
|
||||
'No',
|
||||
);
|
||||
if (result === 'No') {
|
||||
return;
|
||||
}
|
||||
for (const machine of invalidMachines) {
|
||||
fileAndFoldersToRemove.push(machine.machineFile);
|
||||
if (machine.machineFile.includes('wsl') && isWindows()) {
|
||||
wslMachinesToUnregister.push(machine.machineName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errors: string[] = [];
|
||||
|
||||
if (fileAndFoldersToRemove.length > 0) {
|
||||
for (const folder of fileAndFoldersToRemove) {
|
||||
try {
|
||||
await fs.promises.rm(folder, { recursive: true, retryDelay: 1000, maxRetries: 3 });
|
||||
} catch (error) {
|
||||
|
|
@ -961,10 +1082,23 @@ export function registerOnboardingRemoveUnsupportedMachinesCommand(): extensionA
|
|||
errors.push(`Unable to remove the folder ${folder}: ${String(error)}`);
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
await extensionApi.window.showErrorMessage(`Error removing unsupported Podman machines. ${errors.join('\n')}`);
|
||||
|
||||
shouldNotifySetup = true;
|
||||
// notification is no more required
|
||||
notificationDisposable?.dispose();
|
||||
}
|
||||
|
||||
for (const wslMachineName of wslMachinesToUnregister) {
|
||||
try {
|
||||
await extensionApi.process.exec('wsl', ['--unregister', wslMachineName]);
|
||||
} catch (error) {
|
||||
console.error('Error removing WSL machine', wslMachineName, error);
|
||||
errors.push(`Unable to remove the WSL machine ${wslMachineName}: ${String(error)}`);
|
||||
}
|
||||
}
|
||||
if (errors.length > 0) {
|
||||
await extensionApi.window.showErrorMessage(`Error removing unsupported Podman machines. ${errors.join('\n')}`);
|
||||
}
|
||||
|
||||
extensionApi.context.setValue('unsupportedMachineRemoved', 'ok', 'onboarding');
|
||||
});
|
||||
|
|
@ -1656,6 +1790,10 @@ export async function createMachine(
|
|||
notificationDisposable?.dispose();
|
||||
}
|
||||
|
||||
export function resetShouldNotifySetup(): void {
|
||||
shouldNotifySetup = true;
|
||||
}
|
||||
|
||||
function setupDisguisedPodmanSocketWatcher(
|
||||
provider: extensionApi.Provider,
|
||||
socketFile: string,
|
||||
|
|
|
|||
Loading…
Reference in a new issue