Skip to content

Commit

Permalink
Merge pull request #2152 from headlamp-k8s/plugins-ok
Browse files Browse the repository at this point in the history
plugin catalog: small improvements
  • Loading branch information
illume authored Jul 11, 2024
2 parents efc166f + 5eb25d6 commit ab5f2c8
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 21 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ frontend-test:
plugins-test:
cd plugins/headlamp-plugin && npm install && ./test-headlamp-plugin.js
cd plugins/headlamp-plugin && ./test-plugins-examples.sh
cd plugins/headlamp-plugin && node ./headlamp-plugin-management.test.js
cd plugins/headlamp-plugin && npx jest ./plugin-management-utils.test.js
cd plugins/headlamp-plugin/plugin-management && node ./plugin-management.e2e.js
cd plugins/headlamp-plugin/plugin-management && npx jest ./plugin-management.test.js

# IMAGE_BASE can be used to specify a base final image.
# IMAGE_BASE=debian:latest make image
Expand Down
2 changes: 1 addition & 1 deletion app/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import open from 'open';
import path from 'path';
import url from 'url';
import yargs from 'yargs';
import PluginManager from '../../plugins/headlamp-plugin/plugin-management-utils';
import PluginManager from '../../plugins/headlamp-plugin/plugin-management/plugin-management';
import i18n from './i18next.config';
import windowSize from './windowSize';

Expand Down
2 changes: 1 addition & 1 deletion plugins/headlamp-plugin/bin/headlamp-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const child_process = require('child_process');
const validate = require('validate-npm-package-name');
const yargs = require('yargs/yargs');
const headlampPluginPkg = require('../package.json');
const pluginManager = require('../plugin-management-utils');
const pluginManager = require('../plugin-management/plugin-management');
const { table } = require('table');

/**
Expand Down
2 changes: 1 addition & 1 deletion plugins/headlamp-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@
"lib",
"types",
".storybook",
"plugin-management-utils.js"
"plugin-management/plugin-management.js"
],
"keywords": [
"headlamp",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/bin/env node
const { execSync } = require('child_process');
const assert = require('assert');
const fs = require('fs');
Expand Down Expand Up @@ -28,7 +29,7 @@ if (!fs.existsSync(pluginsDir)) {
}

// List plugins initially
let output = runCommand('node ./bin/headlamp-plugin.js list --json');
let output = runCommand('node ../bin/headlamp-plugin.js list --json');
console.log('Initial list output:', output);
let plugins = JSON.parse(output);
console.log('Initial plugins:', plugins);
Expand All @@ -40,33 +41,33 @@ assert.strictEqual(pluginExists, false, 'Plugin should not be initially installe

// Install the plugin
const pluginURL = 'https://artifacthub.io/packages/headlamp/test-123/prometheus_headlamp_plugin';
output = runCommand(`node ./bin/headlamp-plugin.js install ${pluginURL}`);
output = runCommand(`node ../bin/headlamp-plugin.js install ${pluginURL}`);
console.log('Install output:', output);

// List plugins to verify installation
output = runCommand('node ./bin/headlamp-plugin.js list --json');
output = runCommand('node ../bin/headlamp-plugin.js list --json');
plugins = JSON.parse(output);
console.log('Plugins after install:', plugins);
pluginExists = plugins.some(plugin => plugin.pluginName === pluginName);
assert.strictEqual(pluginExists, true, 'Plugin should be installed');

// Update the plugin
output = runCommand(`node ./bin/headlamp-plugin.js update ${pluginName}`);
output = runCommand(`node ../bin/headlamp-plugin.js update ${pluginName}`);
console.log('Update output:', output);

// List plugins to verify update
output = runCommand('node ./bin/headlamp-plugin.js list --json');
output = runCommand('node ../bin/headlamp-plugin.js list --json');
plugins = JSON.parse(output);
console.log('Plugins after update:', plugins);
pluginExists = plugins.some(plugin => plugin.pluginName === pluginName);
assert.strictEqual(pluginExists, true, 'Plugin should still be installed after update');

// Uninstall the plugin
output = runCommand(`node ./bin/headlamp-plugin.js uninstall ${pluginName}`);
output = runCommand(`node ../bin/headlamp-plugin.js uninstall ${pluginName}`);
console.log('Uninstall output:', output);

// List plugins to verify uninstallation
output = runCommand('node ./bin/headlamp-plugin.js list --json');
output = runCommand('node ../bin/headlamp-plugin.js list --json');
console.log('Initial list output:', output);
plugins = JSON.parse(output);
console.log('Plugins after uninstall:', plugins);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/*plugin-management-utils.js has the core logic for managing plugins in Headlamp.
* It provides methods for installing, updating, and uninstalling plugins, as well as listing installed plugins.
* It is used by headlamp-plugin cli and the Headlamp electron app to manage plugins.
/**
* plugin-management-utils.js has the core logic for managing plugins in Headlamp.
*
* Provides methods for installing, updating, listing and uninstalling plugins.
*
* Used by:
* - plugins/headlamp-plugin/bin/headlamp-plugin.js cli
* - app/ to manage plugins.
*/
const fetch = require('node-fetch').default;
const fs = require('fs');
Expand Down Expand Up @@ -237,6 +242,31 @@ class PluginManager {
}
}

/**
* Checks the plugin name is a valid one.
*
* Look for "..", "/", or "\" in the plugin name.
*
* @param {string} pluginName
*
* @returns true if the name is valid.
*/
function validatePluginName(pluginName) {
const invalidPattern = /[\/\\]|(\.\.)/;
return !invalidPattern.test(pluginName);
}

/**
* @param {string} archiveURL - the one to validate
* @returns true if the archiveURL looks good.
*/
function validateArchiveURL(archiveURL) {
return (
archiveURL.startsWith('https://artifacthub.io/packages/') ||
archiveURL.startsWith('https://github.com/yolossn/headlamp-plugins/')
);
}

/**
* Downloads and extracts a plugin from the specified URL.
* @param {string} URL - The URL of the plugin to download and extract.
Expand All @@ -260,7 +290,15 @@ async function downloadExtractPlugin(URL, headlampVersion, progressCallback, sig
progressCallback({ type: 'info', message: 'Plugin Metadata Fetched' });
}
const pluginName = pluginInfo.name;
if (!validatePluginName(pluginName)) {
throw new Error('Invalid plugin name');
}

const archiveURL = pluginInfo.data['headlamp/plugin/archive-url'];
if (!validateArchiveURL(archiveURL)) {
throw new Error('Invalid plugin/archive-url');
}

let checksum = pluginInfo.data['headlamp/plugin/archive-checksum'];
if (!archiveURL || !checksum) {
throw new Error('Invalid plugin metadata. Please check the plugin details.');
Expand Down Expand Up @@ -288,11 +326,8 @@ async function downloadExtractPlugin(URL, headlampVersion, progressCallback, sig
throw new Error('Download cancelled');
}

// create a temp folder
const tempFolder = fs.mkdirSync(
path.join(os.tmpdir() + `/${pluginName}-${Date.now().toString()}/${pluginName}`),
{ recursive: true }
);
const tempDir = await fs.mkdtempSync(path.join(os.tmpdir(), 'headlamp-plugin-temp-'));
const tempFolder = fs.mkdirSync(path.join(tempDir, pluginName), { recursive: true });

if (progressCallback) {
progressCallback({ type: 'info', message: 'Downloading Plugin' });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const PluginManager = require('./plugin-management-utils.js');
const PluginManager = require('./plugin-management.js');
const tmp = require('tmp');
const fs = require('fs');
const semver = require('semver');
Expand Down

0 comments on commit ab5f2c8

Please sign in to comment.