Skip to content

Commit

Permalink
feat: add restart button after enabling / disabling mac os compatibility
Browse files Browse the repository at this point in the history
### What does this PR do?

* Adds a button that will ask if the user if they'd like to restart the
  podman machine to enable compatibility mode

### Screenshot/screencast of this PR

<!-- Please include a screenshot or a screencast explaining what is doing this PR -->

### What issues does this PR fix or reference?

<!-- Please include any related issue from Podman Desktop repository (or from another issue tracker).
-->

Fixes #2406

### How to test this PR?

1. Press the compatibility button while on Mac OS
2. Enable / Disable
3. At the end it should ask if you'd like to restart your podman machine
4. Click and it will restart.

<!-- Please explain steps to reproduce -->

Signed-off-by: Charlie Drage <charlie@charliedrage.com>
  • Loading branch information
cdrage committed Jun 22, 2023
1 parent ddece86 commit e680f0e
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 6 deletions.
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 @@ -816,6 +816,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

0 comments on commit e680f0e

Please sign in to comment.