blob: 176e77f5887f1312e9dfe342e6ec1767d80b9d8b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as retry from 'async-retry';
import { WskAction } from '../wskEntity';
import { resolve } from 'path';
import * as path from 'path';
import openwhisk = require('openwhisk');
import { getAuthFromUri } from '../wskContent';
import { WEBVIEW_TEMPLATE_PATH } from '../constant/path';
interface ActionInvocationMeata {
client: openwhisk.Client;
fullname: string;
}
// use global output channel
const output = vscode.window.createOutputChannel('Invoke Result');
let lastActivationId = '';
/**
* It fetches activation logs asynchronously and appends it to the invoke result panel.
* @param client openwhisk client
* @param activation activation result
*/
async function printLogs(client: openwhisk.Client, activation: openwhisk.Dict): Promise<void> {
const res = await retry(
async () => {
return await client.activations.logs(activation.activationId);
},
{ retries: 5 }
);
if (lastActivationId === activation.activationId) {
output.append(res.logs.join('\n'));
}
}
/**
* It prints activation results without logs.
* @param client openwhisk client
* @param activation activation result
*/
function printActivationResult(client: openwhisk.Client, activation: openwhisk.Dict): void {
lastActivationId = activation.activationId;
printLogs(client, activation);
output.clear();
output.append(`Response:\n${JSON.stringify(activation.response.result)}\n\n`);
output.append(`ActivationID:\n${activation.activationId}\n\n`);
output.append(`Logs:\n`);
output.show();
}
function setParameters(panel: vscode.WebviewPanel, params: string): Thenable<boolean> {
return panel.webview.postMessage({ command: 'getParameters', params: params });
}
export async function invokeAction(
item: WskAction | vscode.Uri,
context: vscode.ExtensionContext
): Promise<void> {
let invocationMeta: ActionInvocationMeata;
if (item instanceof vscode.Uri) {
invocationMeta = {
client: openwhisk(getAuthFromUri(item)),
fullname: WskAction.removeExtension(item.path),
};
} else {
invocationMeta = {
client: item.client,
fullname: item.getFullName(),
};
}
const panel = vscode.window.createWebviewPanel(
'invokeAction',
`Invoke Action: ${invocationMeta.fullname}`,
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [vscode.Uri.file(path.join(context.extensionPath, 'node_modules'))],
}
);
const nodeModulesDiskPath = vscode.Uri.file(path.join(context.extensionPath, 'node_modules'));
const nodeModulePath = panel.webview.asWebviewUri(nodeModulesDiskPath);
const metadata = await invocationMeta.client.actions.get(invocationMeta.fullname);
const html = await fs.promises.readFile(
resolve(WEBVIEW_TEMPLATE_PATH, 'invokeAction.html'),
'utf-8'
);
panel.webview.html = html
.replace(/{{nodeModulePath}}/gi, nodeModulePath.toString())
.replace(/{{actionName}}/gi, invocationMeta.fullname);
let defaultParameters = '';
if (metadata.parameters) {
defaultParameters = JSON.stringify(
metadata.parameters.reduce((acc: { [key: string]: string }, cur) => {
acc[cur.key] = cur.value;
return acc;
}, {}),
null,
4
);
}
setParameters(panel, defaultParameters);
panel.webview.onDidReceiveMessage(async (message) => {
if (message.command === 'invoke') {
try {
const activation = await invocationMeta.client.actions.invoke({
name: invocationMeta.fullname,
params: JSON.parse(message.parameters),
blocking: true,
result: false,
});
printActivationResult(invocationMeta.client, activation);
} catch (e) {
if (e.error.activationId) {
printActivationResult(invocationMeta.client, e.error);
} else {
vscode.window.showErrorMessage(e);
}
}
}
});
}