mirror of
https://github.com/podman-desktop/podman-desktop
synced 2026-04-21 17:47:22 +00:00
feat: create Docker context for Podman machine (#12126)
This commit is contained in:
parent
b838bbc0a5
commit
b2b56cb648
15 changed files with 591 additions and 6 deletions
|
|
@ -37,5 +37,7 @@ export interface DockerContextInfo {
|
|||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface DockerContextParsingInfo extends Omit<DockerContextInfo, 'isCurrentContext'> {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface DockerExtensionApi {}
|
||||
export interface DockerExtensionApi {
|
||||
createContext: (context: DockerContextParsingInfo) => Promise<void>;
|
||||
removeContext: (context: string) => Promise<void>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,3 +293,46 @@ describe('getContexts', () => {
|
|||
expect(contexts.find(c => c.name === 'bar')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createContext', () => {
|
||||
test('creating default context should throw exception', async () => {
|
||||
let error: unknown;
|
||||
try {
|
||||
await dockerContextHandler.createContext({ name: 'default' } as unknown as DockerContextParsingInfo);
|
||||
} catch (err: unknown) {
|
||||
error = err;
|
||||
}
|
||||
expect(error).toBeDefined();
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
});
|
||||
|
||||
test('creating non default context should write file', async () => {
|
||||
const mkdirSpy = vi.spyOn(fs.promises, 'mkdir');
|
||||
const writeFileSpy = vi.spyOn(fs.promises, 'writeFile');
|
||||
await dockerContextHandler.createContext({
|
||||
name: 'non-default',
|
||||
metadata: { description: '' },
|
||||
endpoints: { docker: { host: '' } },
|
||||
} as unknown as DockerContextParsingInfo);
|
||||
expect(mkdirSpy).toBeCalled();
|
||||
expect(writeFileSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeContext', () => {
|
||||
test('removing default context should be noop', async () => {
|
||||
const rmSpy = vi.spyOn(fs.promises, 'rm');
|
||||
await dockerContextHandler.removeContext('default');
|
||||
|
||||
// no rm folder
|
||||
expect(rmSpy).not.toBeCalled();
|
||||
});
|
||||
|
||||
test('removing non default context should delete folder', async () => {
|
||||
const rmSpy = vi.spyOn(fs.promises, 'rm');
|
||||
await dockerContextHandler.removeContext('non-default');
|
||||
|
||||
// no rm folder
|
||||
expect(rmSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -183,4 +183,40 @@ export class DockerContextHandler {
|
|||
// write back the file with the current context and using tabs for indentation
|
||||
await promises.writeFile(this.getDockerConfigPath(), JSON.stringify(config, null, '\t'));
|
||||
}
|
||||
|
||||
async createContext(context: DockerContextParsingInfo): Promise<void> {
|
||||
if (context.name === 'default') {
|
||||
throw new Error('Cannot create a context with the name default');
|
||||
}
|
||||
// create the context directory
|
||||
const dockerContextsMetaPath = join(this.#dockerConfig.getPath(), 'contexts', 'meta');
|
||||
const sha256ContextName = createHash('sha256').update(context.name).digest('hex');
|
||||
const dockerContextDirectory = join(dockerContextsMetaPath, sha256ContextName);
|
||||
await promises.mkdir(dockerContextDirectory, { recursive: true });
|
||||
|
||||
// write the meta.json file
|
||||
const metaFilePath = join(dockerContextDirectory, 'meta.json');
|
||||
const meta = {
|
||||
Name: context.name,
|
||||
Metadata: {
|
||||
Description: context.metadata.description,
|
||||
},
|
||||
Endpoints: {
|
||||
docker: {
|
||||
Host: context.endpoints.docker.host,
|
||||
},
|
||||
},
|
||||
};
|
||||
await promises.writeFile(metaFilePath, JSON.stringify(meta));
|
||||
}
|
||||
|
||||
async removeContext(name: string): Promise<void> {
|
||||
if (name !== 'default') {
|
||||
// remove the context directory
|
||||
const dockerContextsMetaPath = join(this.#dockerConfig.getPath(), 'contexts', 'meta');
|
||||
const sha256ContextName = createHash('sha256').update(name).digest('hex');
|
||||
const dockerContextDirectory = join(dockerContextsMetaPath, sha256ContextName);
|
||||
await promises.rm(dockerContextDirectory, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,8 @@ export async function activate(extensionContext: extensionApi.ExtensionContext):
|
|||
}
|
||||
});
|
||||
return {
|
||||
dummy: '',
|
||||
createContext: dockerContextHandler.createContext.bind(dockerContextHandler),
|
||||
removeContext: dockerContextHandler.removeContext.bind(dockerContextHandler),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
3
extensions/podman-docker-context/README.md
Normal file
3
extensions/podman-docker-context/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# podman-docker-context extension
|
||||
|
||||
This extension creates Docker contexts for Podman connections (machines, remote,...).
|
||||
BIN
extensions/podman-docker-context/icon.png
Normal file
BIN
extensions/podman-docker-context/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
30
extensions/podman-docker-context/package.json
Normal file
30
extensions/podman-docker-context/package.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "podman-docker-context",
|
||||
"displayName": "Podman Docker Context",
|
||||
"description": "Synchronize Docker Contexts with Podman",
|
||||
"version": "1.23.0-next",
|
||||
"icon": "icon.png",
|
||||
"publisher": "podman-desktop",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"podman-desktop": "^0.0.1"
|
||||
},
|
||||
"main": "./dist/extension.js",
|
||||
"source": "./src/extension.ts",
|
||||
"scripts": {
|
||||
"build": "vite build && node ./scripts/build.js",
|
||||
"test": "vitest run --coverage",
|
||||
"test:watch": "vitest watch --coverage",
|
||||
"watch": "vite build --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@podman-desktop/api": "workspace:*",
|
||||
"@podman-desktop/docker-extension-api": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"adm-zip": "^0.5.16",
|
||||
"mkdirp": "^3.0.1",
|
||||
"vite": "^7.1.9",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
}
|
||||
46
extensions/podman-docker-context/scripts/build.js
Normal file
46
extensions/podman-docker-context/scripts/build.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env node
|
||||
/**********************************************************************
|
||||
* Copyright (C) 2022-2023 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
***********************************************************************/
|
||||
|
||||
const AdmZip = require('adm-zip');
|
||||
const path = require('path');
|
||||
const packageJson = require('../package.json');
|
||||
const fs = require('fs');
|
||||
const { mkdirp } = require('mkdirp');
|
||||
|
||||
const destFile = path.resolve(__dirname, `../${packageJson.name}.cdix`);
|
||||
const builtinDirectory = path.resolve(__dirname, '../builtin');
|
||||
const unzippedDirectory = path.resolve(builtinDirectory, `${packageJson.name}.cdix`);
|
||||
// remove the .cdix file before zipping
|
||||
if (fs.existsSync(destFile)) {
|
||||
fs.rmSync(destFile);
|
||||
}
|
||||
// remove the builtin folder before zipping
|
||||
if (fs.existsSync(builtinDirectory)) {
|
||||
fs.rmSync(builtinDirectory, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
const zip = new AdmZip();
|
||||
zip.addLocalFolder(path.resolve(__dirname, '../'));
|
||||
zip.writeZip(destFile);
|
||||
|
||||
// create unzipped built-in
|
||||
mkdirp(unzippedDirectory).then(() => {
|
||||
const unzip = new AdmZip(destFile);
|
||||
unzip.extractAllTo(unzippedDirectory);
|
||||
});
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/**********************************************************************
|
||||
* Copyright (C) 2025 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
***********************************************************************/
|
||||
|
||||
import type { ContainerProviderConnection, ProviderContainerConnection } from '@podman-desktop/api';
|
||||
import { env, provider } from '@podman-desktop/api';
|
||||
import type { DockerExtensionApi } from '@podman-desktop/docker-extension-api';
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
DockerContextSynchronizer,
|
||||
toDescription,
|
||||
toDockerContextName,
|
||||
toEndpoint,
|
||||
} from './docker-context-synchronizer.js';
|
||||
|
||||
vi.mock('@podman-desktop/api', async () => {
|
||||
return {
|
||||
env: {
|
||||
isLinux: false,
|
||||
isWindows: false,
|
||||
isMac: false,
|
||||
},
|
||||
provider: {
|
||||
onDidUpdateContainerConnection: vi.fn(),
|
||||
onDidRegisterContainerConnection: vi.fn(),
|
||||
getContainerConnections: vi.fn(() => []),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const DOCKER_CONNECTION = {
|
||||
providerId: 'docker',
|
||||
connection: {
|
||||
type: 'docker',
|
||||
name: 'docker',
|
||||
endpoint: {
|
||||
socketPath: '/var/run/docker.sock',
|
||||
},
|
||||
status: vi.fn(),
|
||||
},
|
||||
} as unknown as ProviderContainerConnection;
|
||||
|
||||
const PODMAN_CONNECTION1 = {
|
||||
providerId: 'podman',
|
||||
connection: {
|
||||
type: 'podman',
|
||||
name: 'podman-test-1',
|
||||
endpoint: {
|
||||
socketPath: '/var/run/podman1.sock',
|
||||
},
|
||||
status: vi.fn(),
|
||||
},
|
||||
} as unknown as ProviderContainerConnection;
|
||||
|
||||
const PODMAN_CONNECTION2 = {
|
||||
providerId: 'podman',
|
||||
connection: {
|
||||
type: 'podman',
|
||||
name: 'test-2',
|
||||
endpoint: {
|
||||
socketPath: '/var/run/podman2.sock',
|
||||
},
|
||||
status: vi.fn(),
|
||||
},
|
||||
} as unknown as ProviderContainerConnection;
|
||||
|
||||
const dockerExtensionAPI: DockerExtensionApi = {
|
||||
createContext: vi.fn(),
|
||||
removeContext: vi.fn(),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
DOCKER_CONNECTION.connection.status = vi.fn().mockReturnValue('started');
|
||||
PODMAN_CONNECTION1.connection.status = vi.fn().mockReturnValue('started');
|
||||
PODMAN_CONNECTION2.connection.status = vi.fn().mockReturnValue('started');
|
||||
});
|
||||
|
||||
class TestDockerContextSynchronizer extends DockerContextSynchronizer {
|
||||
override async processUpdatedConnection(connection: ContainerProviderConnection): Promise<void> {
|
||||
return super.processUpdatedConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
describe('toDockerContextName', () => {
|
||||
test.each(['Windows', 'Linux', 'MacOS'])('should return the name prefixed with podman- (%s)', platform => {
|
||||
vi.mocked(env).isWindows = platform === 'Windows';
|
||||
vi.mocked(env).isLinux = platform === 'Linux';
|
||||
vi.mocked(env).isMac = platform === 'MacOS';
|
||||
const name = toDockerContextName('foo');
|
||||
expect(name).toBe(env.isWindows ? 'podman-foo' : 'podman');
|
||||
});
|
||||
|
||||
test.each(['Windows', 'Linux', 'MacOS'])('should return the name (%s)', platform => {
|
||||
vi.mocked(env).isWindows = platform === 'Windows';
|
||||
vi.mocked(env).isLinux = platform === 'Linux';
|
||||
vi.mocked(env).isMac = platform === 'MacOS';
|
||||
const name = toDockerContextName('podman-foo');
|
||||
expect(name).toBe(env.isWindows ? 'podman-foo' : 'podman');
|
||||
});
|
||||
});
|
||||
|
||||
describe('toDescription', () => {
|
||||
test.each(['Windows', 'Linux', 'MacOS'])('should return the description (%s)', platform => {
|
||||
vi.mocked(env).isWindows = platform === 'Windows';
|
||||
vi.mocked(env).isLinux = platform === 'Linux';
|
||||
vi.mocked(env).isMac = platform === 'MacOS';
|
||||
const name = toDescription('foo');
|
||||
expect(name).toBe(env.isWindows ? 'Podman machine foo' : 'Podman');
|
||||
});
|
||||
|
||||
test.each(['Windows', 'Linux', 'MacOS'])('should also return the description (%s)', platform => {
|
||||
vi.mocked(env).isWindows = platform === 'Windows';
|
||||
vi.mocked(env).isLinux = platform === 'Linux';
|
||||
vi.mocked(env).isMac = platform === 'MacOS';
|
||||
const name = toDescription('podman-foo');
|
||||
expect(name).toBe(env.isWindows ? 'Podman machine podman-foo' : 'Podman');
|
||||
});
|
||||
});
|
||||
|
||||
describe('toEndpoint', () => {
|
||||
test('should return npipe on Windows', () => {
|
||||
vi.mocked(env).isWindows = true;
|
||||
const name = toEndpoint('foo');
|
||||
expect(name).toBe('npipe://foo');
|
||||
});
|
||||
|
||||
test('should return unix on Linux/MacOS', () => {
|
||||
vi.mocked(env).isWindows = false;
|
||||
const name = toEndpoint('podman-foo');
|
||||
expect(name).toBe('unix://podman-foo');
|
||||
});
|
||||
});
|
||||
|
||||
describe('create contexts', () => {
|
||||
test('should not create contexts if no connection', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([]);
|
||||
const dockerContextSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should not create contexts if only docker connections', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([DOCKER_CONNECTION]);
|
||||
const dockerContextSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should create context if single podman connection', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([PODMAN_CONNECTION1]);
|
||||
const dockerContextSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
test('should create context if podman and docker connections', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([DOCKER_CONNECTION, PODMAN_CONNECTION1]);
|
||||
const dockerContextSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
test('should create contexts if several podman connections', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([PODMAN_CONNECTION1, PODMAN_CONNECTION2]);
|
||||
const dockerContextSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete context', () => {
|
||||
test('should delete context if podman connection is removed', async () => {
|
||||
vi.mocked(provider.getContainerConnections).mockReturnValue([PODMAN_CONNECTION1, PODMAN_CONNECTION2]);
|
||||
const dockerContextSynchronizer = new TestDockerContextSynchronizer(dockerExtensionAPI);
|
||||
await dockerContextSynchronizer.init();
|
||||
expect(dockerExtensionAPI.createContext).toHaveBeenCalledTimes(2);
|
||||
vi.mocked(PODMAN_CONNECTION2.connection.status).mockReturnValue('stopped');
|
||||
await dockerContextSynchronizer.processUpdatedConnection(PODMAN_CONNECTION2.connection);
|
||||
expect(dockerExtensionAPI.removeContext).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/**********************************************************************
|
||||
* Copyright (C) 2025 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
***********************************************************************/
|
||||
import type { ContainerProviderConnection, Disposable } from '@podman-desktop/api';
|
||||
import { env, provider } from '@podman-desktop/api';
|
||||
import type { DockerExtensionApi } from '@podman-desktop/docker-extension-api';
|
||||
|
||||
export function toDockerContextName(name: string): string {
|
||||
return env.isWindows ? (name.startsWith('podman-') ? name : `podman-${name}`) : 'podman';
|
||||
}
|
||||
|
||||
export function toDescription(name: string): string {
|
||||
return env.isWindows ? `Podman machine ${name}` : 'Podman';
|
||||
}
|
||||
|
||||
export function toEndpoint(socketPath: string): string {
|
||||
return env.isWindows ? `npipe://${socketPath.replace(/\\/g, '/')}` : `unix://${socketPath}`;
|
||||
}
|
||||
|
||||
export class DockerContextSynchronizer implements Disposable {
|
||||
#disposable: Disposable[] = [];
|
||||
|
||||
constructor(private dockerExtensionAPI: DockerExtensionApi) {
|
||||
this.#disposable.push(
|
||||
provider.onDidUpdateContainerConnection(event => this.processUpdatedConnection(event.connection)),
|
||||
);
|
||||
this.#disposable.push(
|
||||
provider.onDidRegisterContainerConnection(event => this.processUpdatedConnection(event.connection)),
|
||||
);
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
const connections = provider
|
||||
.getContainerConnections()
|
||||
.filter(connection => connection.connection.status() === 'started');
|
||||
for (const connection of connections) {
|
||||
await this.processUpdatedConnection(connection.connection);
|
||||
}
|
||||
}
|
||||
|
||||
protected async processUpdatedConnection(connection: ContainerProviderConnection): Promise<void> {
|
||||
if (connection.type === 'podman') {
|
||||
if (connection.status() === 'started') {
|
||||
try {
|
||||
await this.dockerExtensionAPI.createContext({
|
||||
name: toDockerContextName(connection.name),
|
||||
metadata: { description: toDescription(connection.name) },
|
||||
endpoints: { docker: { host: toEndpoint(connection.endpoint.socketPath) } },
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
console.warn(`Error creating Docker context for Podman machine ${connection.name}`, error);
|
||||
}
|
||||
} else if (connection.status() === 'stopped') {
|
||||
const dockerContextName = toDockerContextName(connection.name);
|
||||
try {
|
||||
await this.dockerExtensionAPI.removeContext(dockerContextName);
|
||||
} catch (error: unknown) {
|
||||
console.warn(`Error removing Docker context ${dockerContextName}`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.#disposable.forEach(disposable => disposable.dispose());
|
||||
}
|
||||
}
|
||||
38
extensions/podman-docker-context/src/extension.ts
Normal file
38
extensions/podman-docker-context/src/extension.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/**********************************************************************
|
||||
* Copyright (C) 2025 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
***********************************************************************/
|
||||
|
||||
import * as extensionApi from '@podman-desktop/api';
|
||||
import type { DockerExtensionApi } from '@podman-desktop/docker-extension-api';
|
||||
|
||||
import { DockerContextSynchronizer } from './docker-context-synchronizer';
|
||||
|
||||
export async function activate(extensionContext: extensionApi.ExtensionContext): Promise<void> {
|
||||
const dockerExtensionAPI = extensionApi.extensions.getExtension<DockerExtensionApi>('podman-desktop.docker');
|
||||
if (!dockerExtensionAPI) {
|
||||
throw new Error('Docker extension not found');
|
||||
}
|
||||
const dockerSynchronizer = new DockerContextSynchronizer(dockerExtensionAPI.exports);
|
||||
extensionContext.subscriptions.push(dockerSynchronizer);
|
||||
dockerSynchronizer.init().catch((err: unknown) => {
|
||||
console.error('Error while initializing docker synchronizer', err);
|
||||
});
|
||||
}
|
||||
|
||||
export function deactivate(): void {
|
||||
console.log('stopping docker context extension');
|
||||
}
|
||||
17
extensions/podman-docker-context/tsconfig.json
Normal file
17
extensions/podman-docker-context/tsconfig.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"module": "esnext",
|
||||
"lib": ["ES2017"],
|
||||
"sourceMap": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "dist",
|
||||
"target": "esnext",
|
||||
"moduleResolution": "Node",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src", "types/*.d.ts"]
|
||||
}
|
||||
66
extensions/podman-docker-context/vite.config.js
Normal file
66
extensions/podman-docker-context/vite.config.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/**********************************************************************
|
||||
* Copyright (C) 2023-2025 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
***********************************************************************/
|
||||
|
||||
import { join } from 'path';
|
||||
import { builtinModules } from 'module';
|
||||
|
||||
const PACKAGE_ROOT = __dirname;
|
||||
|
||||
/**
|
||||
* @type {import('vite').UserConfig}
|
||||
* @see https://vitejs.dev/config/
|
||||
*/
|
||||
const config = {
|
||||
mode: process.env.MODE,
|
||||
root: PACKAGE_ROOT,
|
||||
envDir: process.cwd(),
|
||||
resolve: {
|
||||
alias: {
|
||||
'/@/': join(PACKAGE_ROOT, 'src') + '/',
|
||||
},
|
||||
},
|
||||
build: {
|
||||
sourcemap: 'inline',
|
||||
target: 'esnext',
|
||||
outDir: 'dist',
|
||||
assetsDir: '.',
|
||||
minify: process.env.MODE === 'production' ? 'esbuild' : false,
|
||||
lib: {
|
||||
entry: 'src/extension.ts',
|
||||
formats: ['cjs'],
|
||||
},
|
||||
rollupOptions: {
|
||||
external: ['@podman-desktop/api', ...builtinModules.flatMap(p => [p, `node:${p}`])],
|
||||
output: {
|
||||
entryFileNames: '[name].js',
|
||||
},
|
||||
},
|
||||
emptyOutDir: true,
|
||||
reportCompressedSize: false,
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['src/**/*.{test,spec}.?(c|m)[jt]s?(x)'],
|
||||
alias: {
|
||||
'@podman-desktop/api': join(PACKAGE_ROOT, '..', '..', '__mocks__/@podman-desktop/api.js'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
@ -15,9 +15,10 @@
|
|||
"scripts": {
|
||||
"build": "pnpm run build:main && pnpm run build:preload && pnpm run build:preload-docker-extension && pnpm run build:preload-webview && npm run build:preload:types && pnpm run build:ui && pnpm run build:renderer && pnpm run build:extensions",
|
||||
"build:main": "cd ./packages/main && vite build",
|
||||
"build:extensions": "pnpm run build:extensions:compose && pnpm run build:extensions:docker && pnpm run build:extensions:lima && pnpm run build:extensions:podman && pnpm run build:extensions:kubecontext && pnpm run build:extensions:kind && pnpm run build:extensions:registries && pnpm run build:extensions:kubectl-cli",
|
||||
"build:extensions": "pnpm run build:extensions:compose && pnpm run build:extensions:docker && pnpm run build:extensions:podman-docker-context && pnpm run build:extensions:lima && pnpm run build:extensions:podman && pnpm run build:extensions:kubecontext && pnpm run build:extensions:kind && pnpm run build:extensions:registries && pnpm run build:extensions:kubectl-cli",
|
||||
"build:extensions:compose": "cd ./extensions/compose && pnpm run build",
|
||||
"build:extensions:docker": "cd ./extensions/docker/packages/extension && pnpm run build",
|
||||
"build:extensions:podman-docker-context": "cd extensions/podman-docker-context && pnpm run build",
|
||||
"build:extensions:kubecontext": "cd ./extensions/kube-context && pnpm run build",
|
||||
"build:extensions:kind": "cd ./extensions/kind && pnpm run build",
|
||||
"build:extensions:lima": "cd ./extensions/lima && pnpm run build",
|
||||
|
|
@ -63,10 +64,11 @@
|
|||
"test:preload": "vitest --run --project=preload --passWithNoTests",
|
||||
"test:preload-docker-extension": "vitest --run --project=preload-docker-extension --passWithNoTests",
|
||||
"test:preload-webview": "vitest --run --project=preload-webview",
|
||||
"test:extensions": "vitest --run --project=extensions --passWithNoTests && pnpm run test:extensions:compose && pnpm run test:extensions:kind && pnpm run test:extensions:docker && pnpm run test:extensions:lima && pnpm run test:extensions:kube && pnpm run test:extensions:podman && pnpm run test:extensions:registries && pnpm run test:extensions:kubectl-cli",
|
||||
"test:extensions": "vitest --run --project=extensions --passWithNoTests && pnpm run test:extensions:compose && pnpm run test:extensions:kind && pnpm run test:extensions:docker && pnpm run test:extensions:podman-docker-context && pnpm run test:extensions:lima && pnpm run test:extensions:kube && pnpm run test:extensions:podman && pnpm run test:extensions:registries && pnpm run test:extensions:kubectl-cli",
|
||||
"test:extensions:kind": "vitest --run --project=kind --passWithNoTests",
|
||||
"test:extensions:compose": "vitest --run --project=compose --passWithNoTests",
|
||||
"test:extensions:docker": "vitest --run --project=docker --passWithNoTests",
|
||||
"test:extensions:podman-docker-context": "vitest --run --project=podman-docker-context --passWithNoTests",
|
||||
"test:extensions:kube": "vitest --run --project=kube-context --passWithNoTests ",
|
||||
"test:extensions:lima": "vitest --run --project=lima --passWithNoTests ",
|
||||
"test:extensions:podman": "vitest --run --project=podman --passWithNoTests ",
|
||||
|
|
@ -93,10 +95,11 @@
|
|||
"typecheck:preload-webview": "tsc --noEmit -p packages/preload-webview/tsconfig.json",
|
||||
"typecheck:renderer": "pnpm run build:preload:types && svelte-check --tsconfig packages/renderer/tsconfig.json",
|
||||
"typecheck:ui": "pnpm run build:ui && pnpm run build:preload:types && svelte-check --tsconfig packages/ui/tsconfig.json",
|
||||
"typecheck:extensions": "pnpm run typecheck:extensions:compose && pnpm run typecheck:extensions:kind && pnpm run typecheck:extensions:docker && pnpm run typecheck:extensions:lima && pnpm run typecheck:extensions:kube-context && pnpm run typecheck:extensions:podman && pnpm run typecheck:extensions:registries && pnpm run typecheck:extensions:kubectl-cli",
|
||||
"typecheck:extensions": "pnpm run typecheck:extensions:compose && pnpm run typecheck:extensions:kind && pnpm run typecheck:extensions:docker && pnpm run typecheck:extensions:podman-docker-context && pnpm run typecheck:extensions:lima && pnpm run typecheck:extensions:kube-context && pnpm run typecheck:extensions:podman && pnpm run typecheck:extensions:registries && pnpm run typecheck:extensions:kubectl-cli",
|
||||
"typecheck:extensions:kind": "tsc --noEmit --project extensions/kind",
|
||||
"typecheck:extensions:compose": "tsc --noEmit --project extensions/compose",
|
||||
"typecheck:extensions:docker": "tsc --noEmit --project extensions/docker/packages/extension",
|
||||
"typecheck:extensions:podman-docker-context": "tsc --noEmit --project extensions/podman-docker-context",
|
||||
"typecheck:extensions:kube-context": "tsc --noEmit --project extensions/kube-context",
|
||||
"typecheck:extensions:lima": "tsc --noEmit --project extensions/lima",
|
||||
"typecheck:extensions:podman": "tsc --noEmit --project extensions/podman/packages/extension",
|
||||
|
|
|
|||
|
|
@ -480,6 +480,28 @@ importers:
|
|||
specifier: ^3.2.4
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.0)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(msw@2.11.6(@types/node@24.10.0)(typescript@5.9.3))(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)
|
||||
|
||||
extensions/podman-docker-context:
|
||||
dependencies:
|
||||
'@podman-desktop/api':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/extension-api
|
||||
'@podman-desktop/docker-extension-api':
|
||||
specifier: workspace:*
|
||||
version: link:../docker/packages/api
|
||||
devDependencies:
|
||||
adm-zip:
|
||||
specifier: ^0.5.16
|
||||
version: 0.5.16
|
||||
mkdirp:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.1
|
||||
vite:
|
||||
specifier: ^7.1.9
|
||||
version: 7.1.10(@types/node@24.7.2)(jiti@2.6.1)(lightningcss@1.30.1)(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)
|
||||
vitest:
|
||||
specifier: ^3.2.4
|
||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@24.7.2)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.1)(msw@2.11.5(@types/node@24.7.2)(typescript@5.9.3))(terser@5.36.0)(tsx@4.20.6)(yaml@2.8.1)
|
||||
|
||||
extensions/podman/packages/api:
|
||||
dependencies:
|
||||
'@podman-desktop/api':
|
||||
|
|
|
|||
Loading…
Reference in a new issue