Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add restart button after enabling / disabling mac os compatibility #2841

Merged
merged 1 commit into from Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 38 additions & 0 deletions extensions/podman/src/compatibility-mode.spec.ts
Expand Up @@ -44,6 +44,16 @@ afterEach(() => {
vi.restoreAllMocks();
});

// mock isDefaultMachineRunning from extension to always return true
// this is to prevent execPromise to be ran within it and cause errors
vi.mock('./extension', () => {
return {
findRunningMachine: () => {
return 'default';
},
};
});

test('darwin: compatibility mode binary not found failure', async () => {
// Mock platform to be darwin
Object.defineProperty(process, 'platform', {
Expand Down Expand Up @@ -85,6 +95,34 @@ test('darwin: DarwinSocketCompatibility class, test runSudoMacHelperCommand ran
expect(spyMacHelperCommand).toHaveBeenCalled();
});

test('darwin: DarwinSocketCompatibility class, test promptRestart ran within runCommand', async () => {
// Mock platform to be darwin
Object.defineProperty(process, 'platform', {
value: 'darwin',
});

const socketCompatClass = new DarwinSocketCompatibility();

// Mock execPromise was ran successfully
vi.mock('execPromise', () => {
return Promise.resolve();
});

// Mock that enable ran successfully
const spyEnable = vi.spyOn(socketCompatClass, 'runCommand');
spyEnable.mockImplementation(() => {
return Promise.resolve();
});

const spyPromptRestart = vi.spyOn(socketCompatClass, 'promptRestart');

// Run the command
await socketCompatClass.enable();

// Expect that promptRestart was ran
expect(spyPromptRestart).toHaveBeenCalled();
});

test('darwin: mock fs.existsSync returns /usr/local/bin/podman-mac-helper', async () => {
// Mock platform to be darwin
Object.defineProperty(process, 'platform', {
Expand Down
43 changes: 37 additions & 6 deletions extensions/podman/src/compatibility-mode.ts
Expand Up @@ -20,7 +20,8 @@ import * as extensionApi from '@podman-desktop/api';
import * as sudo from 'sudo-prompt';
import * as fs from 'node:fs';
import * as os from 'node:os';
import { execPromise } from './podman-cli';
import { execPromise, getPodmanCli } from './podman-cli';
import { findRunningMachine } from './extension';

const podmanSystemdSocket = 'podman.socket';

Expand Down Expand Up @@ -107,23 +108,53 @@ export class DarwinSocketCompatibility extends SocketCompatibility {
const fullCommand = `${podmanHelperBinary} ${command}`;
try {
await this.runSudoMacHelperCommand(fullCommand);
await extensionApi.window
.showInformationMessage(`Docker socket compatibility mode for Podman has been ${description}.
Restart your Podman machine to apply the changes.`);
await extensionApi.window.showInformationMessage(
`Docker socket compatibility mode for Podman has been ${description}.`,
);
} catch (error) {
console.error(`Error running podman-mac-helper: ${error}`);
await extensionApi.window.showErrorMessage(`Error running podman-mac-helper: ${error}`, 'OK');
}
}

// Prompt the user that you need to restart the current podman machine for the changes to take effect
async promptRestart(machine: string): Promise<void> {
const result = await extensionApi.window.showInformationMessage(
`Restarting your Podman machine is required to apply the changes. Would you like to restart the Podman machine '${machine}' now?`,
'Yes',
'Cancel',
);
if (result === 'Yes') {
// Await since we must wait for the machine to stop before starting it again
await execPromise(getPodmanCli(), ['machine', 'stop', machine]);
await execPromise(getPodmanCli(), ['machine', 'start', machine]);
}
}

// Enable the compatibility mode by running podman-mac-helper install
// Run the command with sudo privileges and output the result to the user
async enable(): Promise<void> {
return this.runCommand('install', 'enabled');
await this.runCommand('install', 'enabled');

// Prompt the user to restart the podman machine if it's running
const isRunning = await findRunningMachine();
if (isRunning !== '') {
await this.promptRestart(isRunning);
}

return Promise.resolve();
}

async disable(): Promise<void> {
return this.runCommand('uninstall', 'disabled');
await this.runCommand('uninstall', 'disabled');

// Prompt the user to restart the podman machine if it's running
const isRunning = await findRunningMachine();
if (isRunning !== '') {
await this.promptRestart(isRunning);
}

return Promise.resolve();
}
}

Expand Down
39 changes: 39 additions & 0 deletions extensions/podman/src/extension.ts
Expand Up @@ -823,6 +823,45 @@ export async function activate(extensionContext: extensionApi.ExtensionContext):
await podmanConfiguration.init();
}

// Restart current machine
export async function restartCurrentMachine(): Promise<void> {
// Find the machines
const machineListOutput = await execPromise(getPodmanCli(), ['machine', 'list', '--format', 'json']);
const machines = JSON.parse(machineListOutput) as MachineJSON[];

// Find the autostarted machine and check its status
const currentMachine: MachineJSON = machines.find(machine => machine?.Name === autoMachineName);

// If it's not running or starting, we can't restart it
if (!currentMachine?.Running && !currentMachine?.Starting) {
console.log('No machine to restart');
autoMachineStarted = false;
return;
}

// Restart the current machine
console.log('restarting autostarted machine', autoMachineName);
await execPromise(getPodmanCli(), ['machine', 'restart', autoMachineName]);
}

// Function that checks to see if the default machine is running and return a boolean
export async function findRunningMachine(): Promise<string> {
let runningMachine: string;

// Find the machines
const machineListOutput = await execPromise(getPodmanCli(), ['machine', 'list', '--format', 'json']);
const machines = JSON.parse(machineListOutput) as MachineJSON[];

// Find the machine that is running
const found: MachineJSON = machines.find(machine => machine?.Running);

if (found) {
runningMachine = found.Name;
}

return runningMachine;
}

async function stopAutoStartedMachine() {
if (!autoMachineStarted) {
console.log('No machine to stop');
Expand Down