Skip to content

Commit

Permalink
Add option to list plugins
Browse files Browse the repository at this point in the history
This change creates a CLI option in the backend + desktop to list all
plugins, with a distinction between static/shipped plugins and
user-added ones.

Fixes: #2161

Signed-off-by: Evangelos Skopelitis <[email protected]>
  • Loading branch information
skoeva committed Sep 11, 2024
1 parent 2266251 commit 2c966db
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
26 changes: 26 additions & 0 deletions app/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ const args = yargs(hideBin(process.argv))
describe: 'Disable use of GPU. For people who may have buggy graphics drivers',
type: 'boolean',
},
'list-plugins': {
describe: 'List all static and user-added plugins.',
type: 'boolean',
},
})
.positional('kubeconfig', {
describe:
Expand All @@ -78,6 +82,28 @@ const args = yargs(hideBin(process.argv))
.help()
.parseSync();

const listPlugins = args['list-plugins'] === true;

// If the user wants to list plugins, we don't need to start the app.
if (listPlugins) {
const staticDir = path.join(process.resourcesPath, '.plugins');
const pluginsDir = path.join(app.getPath('userData'), 'plugins');

const staticPlugins = fs.existsSync(staticDir) ? fs.readdirSync(staticDir) : [];
const userPlugins = fs.existsSync(pluginsDir) ? fs.readdirSync(pluginsDir) : [];

console.log(' Static Plugins:');
staticPlugins.forEach(plugin => {
console.log(` - ${plugin}`);
});
console.log(' User Plugins:');
userPlugins.forEach(plugin => {
console.log(` - ${plugin}`);
});

process.exit(0);
}

const isHeadlessMode = args.headless === true;
let disableGPU = args['disable-gpu'] === true;
const defaultPort = 4466;
Expand Down
10 changes: 10 additions & 0 deletions backend/cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/headlamp-k8s/headlamp/backend/pkg/config"
"github.com/headlamp-k8s/headlamp/backend/pkg/kubeconfig"
"github.com/headlamp-k8s/headlamp/backend/pkg/logger"
"github.com/headlamp-k8s/headlamp/backend/pkg/plugins"
)

func main() {
Expand All @@ -17,6 +18,15 @@ func main() {
os.Exit(1)
}

if conf.ListPlugins {
if err := plugins.ListPlugins(conf.StaticDir, conf.PluginsDir); err != nil {
logger.Log(logger.LevelError, nil, err, "error listing plugins")
os.Exit(1)
}

os.Exit(0)
}

cache := cache.New[interface{}]()
kubeConfigStore := kubeconfig.NewContextStore()

Expand Down
2 changes: 2 additions & 0 deletions backend/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Config struct {
InsecureSsl bool `koanf:"insecure-ssl"`
EnableHelm bool `koanf:"enable-helm"`
EnableDynamicClusters bool `koanf:"enable-dynamic-clusters"`
ListPlugins bool `koanf:"list-plugins"`
Port uint `koanf:"port"`
KubeConfigPath string `koanf:"kubeconfig"`
StaticDir string `koanf:"html-static-dir"`
Expand Down Expand Up @@ -153,6 +154,7 @@ func flagset() *flag.FlagSet {
f.Bool("dev", false, "Allow connections from other origins")
f.Bool("insecure-ssl", false, "Accept/Ignore all server SSL certificates")
f.Bool("enable-dynamic-clusters", false, "Enable dynamic clusters, which stores stateless clusters in the frontend.")
f.Bool("list-plugins", false, "List all static and user-added plugins")

f.String("kubeconfig", "", "Absolute path to the kubeconfig file")
f.String("html-static-dir", "", "Static HTML directory to serve")
Expand Down
38 changes: 35 additions & 3 deletions backend/pkg/plugins/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,30 @@ func periodicallyWatchSubfolders(watcher *fsnotify.Watcher, path string, interva
}
}

// GeneratePluginPaths takes the staticPluginDir and pluginDir and returns a list of plugin paths.
func GeneratePluginPaths(staticPluginDir string, pluginDir string) ([]string, error) {
// GenerateSeparatePluginPaths takes the staticPluginDir and pluginDir and returns separate lists of plugin paths.
func GenerateSeparatePluginPaths(staticPluginDir string, pluginDir string) ([]string, []string, error) {
var pluginListURLStatic []string

if staticPluginDir != "" {
var err error

pluginListURLStatic, err = pluginBasePathListForDir(staticPluginDir, "static-plugins")
if err != nil {
return nil, err
return nil, nil, err
}
}

pluginListURL, err := pluginBasePathListForDir(pluginDir, "plugins")
if err != nil {
return nil, nil, err
}

return pluginListURLStatic, pluginListURL, nil
}

// GeneratePluginPaths generates a concatenated list of plugin paths from the staticPluginDir and pluginDir.
func GeneratePluginPaths(staticPluginDir string, pluginDir string) ([]string, error) {
pluginListURLStatic, pluginListURL, err := GenerateSeparatePluginPaths(staticPluginDir, pluginDir)
if err != nil {
return nil, err
}
Expand All @@ -103,6 +113,28 @@ func GeneratePluginPaths(staticPluginDir string, pluginDir string) ([]string, er
return pluginListURL, nil
}

func ListPlugins(staticPluginDir, pluginDir string) error {
staticPlugins, userPlugins, err := GenerateSeparatePluginPaths(staticPluginDir, pluginDir)
if err != nil {
logger.Log(logger.LevelError, nil, err, "listing plugins")
return fmt.Errorf("error listing plugins: %w", err)
}

fmt.Println(" Static Plugins:")

for _, plugin := range staticPlugins {
fmt.Println(" -", plugin)
}

fmt.Println(" User-added Plugins:")

for _, plugin := range userPlugins {
fmt.Println(" -", plugin)
}

return nil
}

// pluginBasePathListForDir returns a list of valid plugin paths for the given directory.
func pluginBasePathListForDir(pluginDir string, baseURL string) ([]string, error) {
files, err := os.ReadDir(pluginDir)
Expand Down

0 comments on commit 2c966db

Please sign in to comment.