Skip to content

Commit

Permalink
feat(extension-api): Allows to provide logger for kube/container fact…
Browse files Browse the repository at this point in the history
…ory creation (podman-desktop#1060)

It allows to display the creation details in a terminal

Change-Id: Iceb11b6ee91365bd5a0921e09627429bbce51fa9
Signed-off-by: Florent Benoit <[email protected]>

Signed-off-by: Florent Benoit <[email protected]>
  • Loading branch information
benoitf authored Dec 19, 2022
1 parent d18e14c commit 578ea94
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 24 deletions.
6 changes: 3 additions & 3 deletions extensions/podman/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ export async function activate(extensionContext: extensionApi.ExtensionContext):
// allows to create machines
if (isMac || isWindows) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createFunction = async (params: { [key: string]: any }): Promise<void> => {
const createFunction = async (params: { [key: string]: any }, logger: extensionApi.Logger): Promise<void> => {
const parameters = [];
parameters.push('machine');
parameters.push('init');
Expand Down Expand Up @@ -442,11 +442,11 @@ export async function activate(extensionContext: extensionApi.ExtensionContext):
}
}
}
await execPromise(getPodmanCli(), parameters, { env });
await execPromise(getPodmanCli(), parameters, { logger, env });
};

provider.setContainerProviderConnectionFactory({
initialize: () => createFunction({}),
initialize: () => createFunction({}, undefined),
create: createFunction,
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/extension-api/src/extension-api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,13 @@ declare module '@tmpwip/extension-api' {
export interface ContainerProviderConnectionFactory {
initialize(): Promise<void>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
create(params: { [key: string]: any }): Promise<void>;
create(params: { [key: string]: any }, logger?: Logger): Promise<void>;
}

// create a kubernetes provider
export interface KubernetesProviderConnectionFactory {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
create(params: { [key: string]: any }): Promise<void>;
create(params: { [key: string]: any }, logger?: Logger): Promise<void>;
}

export interface Link {
Expand Down
28 changes: 26 additions & 2 deletions packages/main/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,8 +896,13 @@ export class PluginSystem {
_listener: Electron.IpcMainInvokeEvent,
internalProviderId: string,
params: { [key: string]: unknown },
loggerId: string,
): Promise<void> => {
return providerRegistry.createContainerProviderConnection(internalProviderId, params);
return providerRegistry.createContainerProviderConnection(
internalProviderId,
params,
this.getLogHandlerCreateConnection(loggerId),
);
},
);

Expand All @@ -907,8 +912,13 @@ export class PluginSystem {
_listener: Electron.IpcMainInvokeEvent,
internalProviderId: string,
params: { [key: string]: unknown },
loggerId: string,
): Promise<void> => {
return providerRegistry.createKubernetesProviderConnection(internalProviderId, params);
return providerRegistry.createKubernetesProviderConnection(
internalProviderId,
params,
this.getLogHandlerCreateConnection(loggerId),
);
},
);

Expand Down Expand Up @@ -982,4 +992,18 @@ export class PluginSystem {
autoStartConfiguration.start();
return this.extensionLoader;
}

getLogHandlerCreateConnection(loggerId: string): containerDesktopAPI.Logger {
return {
log: (...data: unknown[]) => {
this.getWebContentsSender().send('provider-registry:createConnection-onData', loggerId, 'log', data);
},
warn: (...data: unknown[]) => {
this.getWebContentsSender().send('provider-registry:createConnection-onData', loggerId, 'warn', data);
},
error: (...data: unknown[]) => {
this.getWebContentsSender().send('provider-registry:createConnection-onData', loggerId, 'error', data);
},
};
}
}
24 changes: 18 additions & 6 deletions packages/main/src/plugin/provider-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
KubernetesProviderConnection,
UnregisterKubernetesConnectionEvent,
RegisterKubernetesConnectionEvent,
Logger,
} from '@tmpwip/extension-api';
import type {
ProviderContainerConnectionInfo,
Expand Down Expand Up @@ -558,26 +559,37 @@ export class ProviderRegistry {
return context;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async createContainerProviderConnection(internalProviderId: string, params: { [key: string]: any }): Promise<void> {
async createContainerProviderConnection(
internalProviderId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: { [key: string]: any },
logHandler: Logger,
): Promise<void> {
// grab the correct provider
const provider = this.getMatchingProvider(internalProviderId);

if (!provider.containerProviderConnectionFactory) {
throw new Error('The provider does not support container connection creation');
}
return provider.containerProviderConnectionFactory.create(params);

// create a logger

return provider.containerProviderConnectionFactory.create(params, logHandler);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async createKubernetesProviderConnection(internalProviderId: string, params: { [key: string]: any }): Promise<void> {
async createKubernetesProviderConnection(
internalProviderId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: { [key: string]: any },
logHandler: Logger,
): Promise<void> {
// grab the correct provider
const provider = this.getMatchingProvider(internalProviderId);

if (!provider.kubernetesProviderConnectionFactory) {
throw new Error('The provider does not support kubernetes connection creation');
}
return provider.kubernetesProviderConnectionFactory.create(params);
return provider.kubernetesProviderConnectionFactory.create(params, logHandler);
}

// helper method
Expand Down
59 changes: 51 additions & 8 deletions packages/preload/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -495,19 +495,62 @@ function initExposure(): void {
},
);

let onDataCallbacksCreateConnectionId = 0;

const onDataCallbacksCreateConnectionLogs = new Map<number, containerDesktopAPI.Logger>();

contextBridge.exposeInMainWorld(
'createContainerProviderConnection',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async (internalProviderId: string, params: { [key: string]: any }): Promise<void> => {
return ipcInvoke('provider-registry:createContainerProviderConnection', internalProviderId, params);
async (
internalProviderId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: { [key: string]: any },
logger: containerDesktopAPI.Logger,
): Promise<void> => {
onDataCallbacksCreateConnectionId++;
onDataCallbacksCreateConnectionLogs.set(onDataCallbacksCreateConnectionId, logger);
return ipcInvoke(
'provider-registry:createContainerProviderConnection',
internalProviderId,
params,
onDataCallbacksCreateConnectionId,
);
},
);

contextBridge.exposeInMainWorld(
'createKubernetesProviderConnection',
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async (internalProviderId: string, params: { [key: string]: any }): Promise<void> => {
return ipcInvoke('provider-registry:createKubernetesProviderConnection', internalProviderId, params);
async (
internalProviderId: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: { [key: string]: any },
logger: containerDesktopAPI.Logger,
): Promise<void> => {
onDataCallbacksCreateConnectionId++;
onDataCallbacksCreateConnectionLogs.set(onDataCallbacksCreateConnectionId, logger);
return ipcInvoke(
'provider-registry:createKubernetesProviderConnection',
internalProviderId,
params,
onDataCallbacksCreateConnectionId,
);
},
);

ipcRenderer.on(
'provider-registry:createConnection-onData',
(_, onDataCallbacksCreateConnectionId: number, channel: string, data: unknown[]) => {
// grab callback from the map
const callback = onDataCallbacksCreateConnectionLogs.get(onDataCallbacksCreateConnectionId);
if (callback) {
if (channel === 'log') {
callback.log(data);
} else if (channel === 'warn') {
callback.warn(data);
} else if (channel === 'error') {
callback.error(data);
}
}
},
);

Expand Down Expand Up @@ -808,9 +851,9 @@ function initExposure(): void {
if (channel === 'log') {
callback.log(data);
} else if (channel === 'warn') {
callback.log(data);
callback.warn(data);
} else if (channel === 'error') {
callback.log(data);
callback.error(data);
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion packages/renderer/src/lib/preferences/Logger.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async function refreshTerminal() {
// disable cursor
logsTerminal.write('\x1b[?25l');
logsTerminal.write(`Log output will appear here...\n\r`);
logsTerminal.write('\n\r');
resizeHandler = () => {
fitAddon.fit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
import type { IConfigurationPropertyRecordedSchema } from '../../../../main/src/plugin/configuration-registry';
import type { ProviderInfo } from '../../../../main/src/plugin/api/provider-info';
import PreferencesRenderingItemFormat from './PreferencesRenderingItemFormat.svelte';
import type { Logger as LoggerType } from '@tmpwip/extension-api';
import Logger from './Logger.svelte';
import { writeToTerminal } from './Util';
export let properties: IConfigurationPropertyRecordedSchema[] = [];
export let providerInfo: ProviderInfo;
export let propertyScope: string;
export let callback: (string, data) => Promise<void>;
export let callback: (param: string, data, logger: LoggerType) => Promise<void>;
let creationInProgress = false;
let creationStarted = false;
let creationSuccessful = false;
// get only ContainerProviderConnectionFactory scope fields that are starting by the provider id
Expand All @@ -27,6 +31,8 @@ function handleValidComponent() {
isValid = true;
}
let logsTerminal;
async function handleOnSubmit(e) {
errorMessage = undefined;
const formData = new FormData(e.target);
Expand All @@ -40,8 +46,24 @@ async function handleOnSubmit(e) {
// send the data to the right provider
creationInProgress = true;
errorMessage = undefined;
creationStarted = true;
const loggerHandler: LoggerType = {
log: args => {
writeToTerminal(logsTerminal, args, '\x1b[37m');
},
warn: args => {
writeToTerminal(logsTerminal, args, '\x1b[33m');
},
error: args => {
writeToTerminal(logsTerminal, args, '\x1b[1;31m');
},
};
try {
await callback(providerInfo.internalId, data);
// clear terminal
logsTerminal?.clear();
await callback(providerInfo.internalId, data, loggerHandler);
window.dispatchEvent(new CustomEvent('provider-lifecycle-change'));
creationSuccessful = true;
} catch (error) {
Expand Down Expand Up @@ -90,6 +112,13 @@ async function handleOnSubmit(e) {
Create
</button>
</form>
{#if creationStarted}
<div id="log" class="w-full h-96 mt-4">
<div class="w-full h-full">
<Logger bind:logsTerminal="{logsTerminal}" onInit="{() => {}}" />
</div>
</div>
{/if}
{#if errorMessage}
<div class="text-red-600">
{errorMessage}
Expand Down

0 comments on commit 578ea94

Please sign in to comment.