Skip to content

Commit

Permalink
feat(dd): add support for backend extensions of Docker Desktop (#3435)
Browse files Browse the repository at this point in the history
fix #2397

Signed-off-by: Florent Benoit <fbenoit@redhat.com>
  • Loading branch information
benoitf committed Aug 9, 2023
1 parent eaa8a87 commit 97239a7
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 19 deletions.
Expand Up @@ -36,9 +36,15 @@ let dockerDesktopInstallation: TestDockerDesktopInstallation;

const contributionManagerLoadMetadataMock = vi.fn();
const contributionManagerInitMock = vi.fn();
const contributionManagerFindComposeBinaryMock = vi.fn();
const contributionManagerEnhanceComposeFileMock = vi.fn();
const containerProviderStartVMMock = vi.fn();
const contributionManager = {
init: contributionManagerInitMock,
loadMetadata: contributionManagerLoadMetadataMock,
findComposeBinary: contributionManagerFindComposeBinaryMock,
enhanceComposeFile: contributionManagerEnhanceComposeFileMock,
startVM: containerProviderStartVMMock,
} as unknown as ContributionManager;

const containerProviderGetFirstRunningConnectionMock = vi.fn();
Expand Down Expand Up @@ -318,8 +324,17 @@ test('Check handlePluginInstall', async () => {
// mock extractDockerDesktopFiles
vi.spyOn(dockerDesktopInstallation, 'extractDockerDesktopFiles').mockResolvedValue();

// mock findComposeBinary
contributionManagerFindComposeBinaryMock.mockResolvedValue('/my-compose-binary');

// mock enhanceComposeFile
contributionManagerEnhanceComposeFileMock.mockResolvedValue('/my-enhanced-compose-file.yaml');

contributionManagerLoadMetadataMock.mockResolvedValue({
name: 'My Extension',
vm: {
composefile: 'docker-compose.yaml',
},
});

const logCallbackId = 2503;
Expand All @@ -336,4 +351,6 @@ test('Check handlePluginInstall', async () => {

// contribution manager is called
expect(contributionManagerInitMock).toBeCalled();

expect(containerProviderStartVMMock).toBeCalledWith('My Extension', '/my-enhanced-compose-file.yaml', true);
});
Expand Up @@ -67,6 +67,10 @@ export class DockerDesktopInstallation {
});
}

if (metadata.vm?.composefile) {
files.push(metadata.vm.composefile);
}

// host binaries
const hostFiles: string[] = [];
if (metadata?.host?.binaries) {
Expand Down Expand Up @@ -377,6 +381,7 @@ export class DockerDesktopInstallation {

await this.extractDockerDesktopFiles(tmpFolderPath, finalFolderPath, reportLog);

event.reply('docker-desktop-plugin:install-log', logCallbackId, 'Loading metadata...');
// check metadata. If name is missing, add the one from the image
const metadata = await this.contributionManager.loadMetadata(finalFolderPath);
if (!metadata.name) {
Expand All @@ -385,8 +390,41 @@ export class DockerDesktopInstallation {
await this.contributionManager.saveMetadata(finalFolderPath, metadata);
}

// if there is a VM, need to generate the updated compose file
let enhancedComposeFile;
if (metadata.vm) {
// check compose presence
event.reply('docker-desktop-plugin:install-log', logCallbackId, 'Check compose being setup...');
const foundPath = await this.contributionManager.findComposeBinary();
if (!foundPath) {
event.reply('docker-desktop-plugin:install-error', logCallbackId, 'Compose binary not found.');
return;
} else {
event.reply('docker-desktop-plugin:install-log', logCallbackId, `Compose binary found at ${foundPath}.`);
}

event.reply('docker-desktop-plugin:install-log', logCallbackId, 'Enhance compose file...');
// need to update the compose file
try {
enhancedComposeFile = await this.contributionManager.enhanceComposeFile(finalFolderPath, imageName, metadata);
} catch (error) {
event.reply('docker-desktop-plugin:install-error', logCallbackId, error);
return;
}

// try to start the VM
event.reply('docker-desktop-plugin:install-log', logCallbackId, 'Starting compose project...');
await this.contributionManager.startVM(metadata.name, enhancedComposeFile, true);
}

event.reply('docker-desktop-plugin:install-end', logCallbackId, 'Extension Successfully installed.');

// refresh contributions
await this.contributionManager.init();
try {
await this.contributionManager.init();
} catch (error) {
event.reply('docker-desktop-plugin:install-error', logCallbackId, error);
return;
}
}
}
36 changes: 20 additions & 16 deletions packages/preload-docker-extension/src/index.ts
Expand Up @@ -295,40 +295,44 @@ export class DockerExtensionPreload {
hostname,
};

const vmServicePort = urlParams.get('vmServicePort') || undefined;

// do we have a service being exposed ?
const doRequest = async (config: RequestConfig): Promise<unknown> => {
if (vmServicePort) {
return ipcRenderer.invoke('docker-desktop-adapter:extensionVMServiceRequest', vmServicePort, config);
} else {
throw new Error(`no service port defined for request ${config}`);
}
};

const extensionVMService: dockerDesktopAPI.HttpService = {
get: async (url: string): Promise<unknown> => {
console.error('extensionVMService.get not implemented', url);
return {} as any;
return doRequest({ url, method: 'GET', headers: {}, data: undefined });
},
post: async (url: string, data: any): Promise<unknown> => {
console.error('extensionVMService.post not implemented', url, data);
return {} as any;
return doRequest({ url, method: 'POST', headers: {}, data });
},
put: async (url: string, data: any): Promise<unknown> => {
console.error('extensionVMService.put not implemented', url, data);
return {} as any;
return doRequest({ url, method: 'PUT', headers: {}, data });
},
patch: async (url: string, data: any): Promise<unknown> => {
console.error('extensionVMService.patch not implemented', url, data);
return {} as any;
return doRequest({ url, method: 'PATCH', headers: {}, data });
},
delete: async (url: string): Promise<unknown> => {
console.error('extensionVMService.delete not implemented', url);
return {} as any;
return doRequest({ url, method: 'DELETE', headers: {}, data: undefined });
},
head: async (url: string): Promise<unknown> => {
console.error('extensionVMService.head not implemented', url);
return {} as any;
return doRequest({ url, method: 'HEAD', headers: {}, data: undefined });
},
request: async (config: RequestConfig): Promise<unknown> => {
console.error('extensionVMService.request not implemented', config);
return {} as any;
return doRequest(config);
},
};

const extensionCliVM: dockerDesktopAPI.ExtensionCli = {
//FIXME:
exec: {} as any,
// need to call exec inside a container for the VM service
exec: this.getExec('VM_SERVICE'),
};

const extensionVM: dockerDesktopAPI.ExtensionVM = {
Expand Down
2 changes: 1 addition & 1 deletion packages/preload/src/index.ts
Expand Up @@ -1229,7 +1229,7 @@ function initExposure(): void {
});

contextBridge.exposeInMainWorld('ddExtensionDelete', async (extensionName: string): Promise<void> => {
return ipcRenderer.invoke('docker-desktop-plugin:delete', extensionName);
return ipcInvoke('docker-desktop-plugin:delete', extensionName);
});

contextBridge.exposeInMainWorld('getDDPreloadPath', async (): Promise<string> => {
Expand Down
Expand Up @@ -41,7 +41,7 @@ window.events?.receive('dev-tools:open-extension', extensionId => {
<Route path="/*" breadcrumb="{name}">
<webview
id="dd-webview-{webviewId}"
src="{source}?extensionName={currentContrib.extensionId}&arch={arch}&hostname={hostname}&platform={platform}"
src="{source}?extensionName={currentContrib.extensionId}&arch={arch}&hostname={hostname}&platform={platform}&vmServicePort={currentContrib.vmServicePort}"
preload="{preloadPath}"
style="height: 100%; width: 100%"></webview>
</Route>
Expand Down

0 comments on commit 97239a7

Please sign in to comment.