Skip to content

Commit a9d6f11

Browse files
author
Miłosz Skaza
authored
Plugin improvements (#122)
1. Add env variable `CTFCLI_PLUGIN_DIR` to override default plugin dir - useful for development of plugins. 2. Change plugin load print to a debug log so it's not displayed with every invocation of ctfcli 3. Move plugin loading logic from __main__ file to utils/plugins
1 parent de3dcee commit a9d6f11

File tree

4 files changed

+45
-20
lines changed

4 files changed

+45
-20
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,6 @@ dmypy.json
131131
# Miscellaneous
132132
.DS_Store
133133
.vscode/
134+
.idea/
134135

135136
.ctf/

Diff for: ctfcli/__main__.py

+4-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import configparser
2-
import importlib
3-
import os
42
import subprocess
5-
import sys
3+
64
from pathlib import Path
75

86
import click
@@ -13,7 +11,7 @@
1311
from ctfcli.cli.plugins import Plugins
1412
from ctfcli.cli.templates import Templates
1513
from ctfcli.cli.pages import Pages
16-
from ctfcli.utils.plugins import get_plugin_dir
14+
from ctfcli.utils.plugins import load_plugins
1715
from ctfcli.utils.git import check_if_dir_is_inside_git_repo
1816

1917

@@ -93,15 +91,8 @@ def templates(self):
9391

9492

9593
def main():
96-
# Load plugins
97-
plugin_dir = get_plugin_dir()
98-
sys.path.insert(0, plugin_dir)
99-
for plugin in sorted(os.listdir(plugin_dir)):
100-
plugin_path = os.path.join(plugin_dir, plugin, "__init__.py")
101-
print("Loading", plugin_path, "as", plugin)
102-
loaded = importlib.import_module(plugin)
103-
loaded.load(COMMANDS)
104-
sys.path.remove(plugin_dir)
94+
# load plugins
95+
load_plugins(COMMANDS)
10596

10697
# Load CLI
10798
fire.Fire(CTFCLI)

Diff for: ctfcli/utils/deploy.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def cloud(challenge, host, protocol):
136136
# Could not find the service. Create it using our pushed image.
137137
# Deploy the image by creating service
138138
service = s.post(
139-
"/api/v1/services", json={"name": slug, "image": location,}
139+
"/api/v1/services", json={"name": slug, "image": location,},
140140
).json()["data"]
141141

142142
# Get connection details

Diff for: ctfcli/utils/plugins.py

+39-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,49 @@
1-
import os
2-
31
import appdirs
2+
import importlib
3+
import logging
4+
import os
5+
import sys
6+
from pathlib import Path
47

58
from ctfcli import __name__ as pkg_name
69

710

11+
def load_plugins(commands: dict):
12+
plugin_dir = get_plugin_dir()
13+
sys.path.insert(0, plugin_dir)
14+
15+
for plugin in sorted(os.listdir(plugin_dir)):
16+
plugin_path = Path(plugin_dir) / plugin / "__init__.py"
17+
18+
logging.debug(f"Loading {plugin_path} as {plugin}")
19+
20+
loaded = importlib.import_module(plugin)
21+
loaded.load(commands)
22+
23+
sys.path.remove(str(plugin_dir))
24+
25+
826
def get_plugin_dir():
9-
plugins_path = os.path.join(get_data_dir(), "plugins")
10-
if not os.path.exists(plugins_path):
27+
if os.getenv("CTFCLI_PLUGIN_DIR"):
28+
plugins_path = get_custom_plugin_dir()
29+
else:
30+
plugins_path = get_data_dir() / "plugins"
31+
32+
if not plugins_path.exists():
1133
os.makedirs(plugins_path)
12-
return os.path.join(plugins_path)
34+
35+
return str(plugins_path.absolute())
36+
37+
38+
def get_custom_plugin_dir() -> Path:
39+
custom_plugins_path = Path(os.getenv("CTFCLI_PLUGIN_DIR"))
40+
41+
if custom_plugins_path.is_absolute():
42+
return custom_plugins_path
43+
44+
base_dir = Path().parent.parent
45+
return base_dir / custom_plugins_path
1346

1447

1548
def get_data_dir():
16-
return appdirs.user_data_dir(appname=pkg_name)
49+
return Path(appdirs.user_data_dir(appname=pkg_name))

0 commit comments

Comments
 (0)