canvas 0.16.0__py3-none-any.whl → 0.18.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of canvas might be problematic. Click here for more details.
- {canvas-0.16.0.dist-info → canvas-0.18.0.dist-info}/METADATA +25 -31
- {canvas-0.16.0.dist-info → canvas-0.18.0.dist-info}/RECORD +40 -34
- {canvas-0.16.0.dist-info → canvas-0.18.0.dist-info}/WHEEL +1 -1
- canvas-0.18.0.dist-info/entry_points.txt +2 -0
- canvas_cli/apps/plugin/plugin.py +5 -1
- canvas_generated/messages/events_pb2.py +2 -2
- canvas_generated/messages/events_pb2.pyi +88 -0
- canvas_sdk/commands/tests/protocol/tests.py +12 -2
- canvas_sdk/commands/tests/test_utils.py +4 -9
- canvas_sdk/effects/banner_alert/tests.py +5 -2
- canvas_sdk/effects/surescripts/__init__.py +11 -0
- canvas_sdk/effects/task/__init__.py +3 -0
- canvas_sdk/effects/task/task.py +3 -0
- canvas_sdk/utils/__init__.py +8 -2
- canvas_sdk/utils/http.py +113 -3
- canvas_sdk/v1/data/team.py +76 -0
- plugin_runner/plugin_installer.py +21 -13
- plugin_runner/plugin_runner.py +67 -14
- plugin_runner/tests/test_plugin_runner.py +37 -5
- protobufs/canvas_generated/messages/effects.proto +225 -0
- protobufs/canvas_generated/messages/events.proto +1057 -0
- protobufs/canvas_generated/messages/plugins.proto +9 -0
- protobufs/canvas_generated/services/plugin_runner.proto +12 -0
- settings.py +4 -1
- canvas-0.16.0.dist-info/entry_points.txt +0 -3
- plugin_runner/plugin_synchronizer.py +0 -92
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
syntax = 'proto3';
|
|
2
|
+
|
|
3
|
+
import "canvas_generated/messages/events.proto";
|
|
4
|
+
import "canvas_generated/messages/plugins.proto";
|
|
5
|
+
|
|
6
|
+
package canvas;
|
|
7
|
+
|
|
8
|
+
service PluginRunner {
|
|
9
|
+
rpc HandleEvent (Event) returns (stream EventResponse);
|
|
10
|
+
|
|
11
|
+
rpc ReloadPlugins (ReloadPluginsRequest) returns (stream ReloadPluginsResponse);
|
|
12
|
+
}
|
settings.py
CHANGED
|
@@ -12,12 +12,14 @@ ENV = os.getenv("ENV", "development")
|
|
|
12
12
|
IS_PRODUCTION = ENV == "production"
|
|
13
13
|
IS_TESTING = env_to_bool("IS_TESTING", "pytest" in sys.argv[0] or sys.argv[0] == "-c")
|
|
14
14
|
CUSTOMER_IDENTIFIER = os.getenv("CUSTOMER_IDENTIFIER", "local")
|
|
15
|
+
APP_NAME = os.getenv("APP_NAME")
|
|
15
16
|
|
|
16
17
|
INTEGRATION_TEST_URL = os.getenv("INTEGRATION_TEST_URL")
|
|
17
18
|
INTEGRATION_TEST_CLIENT_ID = os.getenv("INTEGRATION_TEST_CLIENT_ID")
|
|
18
19
|
INTEGRATION_TEST_CLIENT_SECRET = os.getenv("INTEGRATION_TEST_CLIENT_SECRET")
|
|
19
20
|
|
|
20
21
|
GRAPHQL_ENDPOINT = os.getenv("GRAPHQL_ENDPOINT", "http://localhost:8000/plugins-graphql")
|
|
22
|
+
REDIS_ENDPOINT = os.getenv("REDIS_ENDPOINT", f"redis://{APP_NAME}-redis:6379")
|
|
21
23
|
|
|
22
24
|
INSTALLED_APPS = [
|
|
23
25
|
"canvas_sdk.v1",
|
|
@@ -68,7 +70,8 @@ PLUGIN_DIRECTORY = os.getenv(
|
|
|
68
70
|
else "./custom-plugins"
|
|
69
71
|
),
|
|
70
72
|
)
|
|
71
|
-
|
|
73
|
+
PLUGINS_PUBSUB_CHANNEL = os.getenv("PLUGINS_PUBSUB_CHANNEL", default="plugins")
|
|
74
|
+
CHANNEL_NAME = f"{CUSTOMER_IDENTIFIER}:{PLUGINS_PUBSUB_CHANNEL}"
|
|
72
75
|
MANIFEST_FILE_NAME = "CANVAS_MANIFEST.json"
|
|
73
76
|
|
|
74
77
|
SECRETS_FILE_NAME = "SECRETS.json"
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
import pickle
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from subprocess import STDOUT, CalledProcessError, check_output
|
|
7
|
-
|
|
8
|
-
import redis
|
|
9
|
-
|
|
10
|
-
from plugin_runner.plugin_installer import install_plugins
|
|
11
|
-
|
|
12
|
-
APP_NAME = os.getenv("APP_NAME")
|
|
13
|
-
|
|
14
|
-
CUSTOMER_IDENTIFIER = os.getenv("CUSTOMER_IDENTIFIER")
|
|
15
|
-
PLUGINS_PUBSUB_CHANNEL = os.getenv("PLUGINS_PUBSUB_CHANNEL", default="plugins")
|
|
16
|
-
|
|
17
|
-
CHANNEL_NAME = f"{CUSTOMER_IDENTIFIER}:{PLUGINS_PUBSUB_CHANNEL}"
|
|
18
|
-
|
|
19
|
-
REDIS_ENDPOINT = os.getenv("REDIS_ENDPOINT", f"redis://{APP_NAME}-redis:6379")
|
|
20
|
-
|
|
21
|
-
try:
|
|
22
|
-
CLIENT_ID = Path("/app/container-unique-id.txt").read_text()
|
|
23
|
-
except FileNotFoundError:
|
|
24
|
-
CLIENT_ID = "non-unique"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def get_client() -> tuple[redis.Redis, redis.client.PubSub]:
|
|
28
|
-
"""Return a Redis client and pubsub object."""
|
|
29
|
-
client = redis.Redis.from_url(REDIS_ENDPOINT)
|
|
30
|
-
pubsub = client.pubsub()
|
|
31
|
-
|
|
32
|
-
return client, pubsub
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def publish_message(message: dict) -> None:
|
|
36
|
-
"""Publish a message to the pubsub channel."""
|
|
37
|
-
client, _ = get_client()
|
|
38
|
-
|
|
39
|
-
message_with_id = {**message, "client_id": CLIENT_ID}
|
|
40
|
-
|
|
41
|
-
client.publish(CHANNEL_NAME, pickle.dumps(message_with_id))
|
|
42
|
-
client.close()
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def main() -> None:
|
|
46
|
-
"""Listen for messages on the pubsub channel and restart the plugin-runner."""
|
|
47
|
-
print("plugin-synchronizer: starting")
|
|
48
|
-
try:
|
|
49
|
-
print("plugin-synchronizer: installing plugins after web container start")
|
|
50
|
-
install_plugins()
|
|
51
|
-
print("plugin-synchronizer: sending SIGHUP to plugin-runner")
|
|
52
|
-
check_output(["circusctl", "signal", "plugin-runner", "1"], cwd="/app", stderr=STDOUT)
|
|
53
|
-
except CalledProcessError as e:
|
|
54
|
-
print("plugin-synchronizer: `install_plugins` failed:", e)
|
|
55
|
-
|
|
56
|
-
_, pubsub = get_client()
|
|
57
|
-
|
|
58
|
-
pubsub.psubscribe(CHANNEL_NAME)
|
|
59
|
-
|
|
60
|
-
for message in pubsub.listen():
|
|
61
|
-
if not message:
|
|
62
|
-
continue
|
|
63
|
-
|
|
64
|
-
message_type = message.get("type", "")
|
|
65
|
-
|
|
66
|
-
if message_type != "pmessage":
|
|
67
|
-
continue
|
|
68
|
-
|
|
69
|
-
data = pickle.loads(message.get("data", pickle.dumps({})))
|
|
70
|
-
|
|
71
|
-
if "action" not in data or "client_id" not in data:
|
|
72
|
-
continue
|
|
73
|
-
|
|
74
|
-
if data["action"] == "restart":
|
|
75
|
-
# Run the plugin installer process
|
|
76
|
-
try:
|
|
77
|
-
print("plugin-synchronizer: installing plugins after receiving restart message")
|
|
78
|
-
install_plugins()
|
|
79
|
-
except CalledProcessError as e:
|
|
80
|
-
print("plugin-synchronizer: `install_plugins` failed:", e)
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
print("plugin-synchronizer: sending SIGHUP to plugin-runner")
|
|
84
|
-
check_output(
|
|
85
|
-
["circusctl", "signal", "plugin-runner", "1"], cwd="/app", stderr=STDOUT
|
|
86
|
-
)
|
|
87
|
-
except CalledProcessError as e:
|
|
88
|
-
print("plugin-synchronizer: `circusctl signal plugin-runner 1` failed:", e)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if __name__ == "__main__":
|
|
92
|
-
main()
|