Coverage for mfplugin/command.py: 47%
81 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-13 15:57 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-13 15:57 +0000
1import os
2from mfplugin.utils import NON_REQUIRED_INTEGER_DEFAULT_0, to_bool, \
3 NON_REQUIRED_STRING_DEFAULT_EMPTY, NON_REQUIRED_BOOLEAN_DEFAULT_FALSE, \
4 NON_REQUIRED_INTEGER
6__pdoc__ = {
7 "coerce_log_split_stdout_sterr": False,
8 "coerce_log_split_multiple_workers": False
9}
12def coerce_log_split_stdout_sterr(val):
13 if val == "AUTO":
14 return to_bool(
15 os.environ["%s_LOG_TRY_TO_SPLIT_STDOUT_STDERR" % MFMODULE])
16 return to_bool(val)
19def coerce_log_split_multiple_workers(val):
20 if val == "AUTO":
21 return to_bool(
22 os.environ["%s_LOG_TRY_TO_SPLIT_MULTIPLE_WORKERS" % MFMODULE])
23 return to_bool(val)
26MFMODULE = os.environ.get("MFMODULE", "GENERIC")
27MFMODULE_RUNTIME_HOME = os.environ.get("MFMODULE_RUNTIME_HOME", "/tmp")
28COMMAND_SCHEMA = {
29 "log_split_stdout_stderr": {
30 "required": False,
31 "type": "boolean",
32 "default": "AUTO",
33 "coerce": (str, coerce_log_split_stdout_sterr),
34 },
35 "log_split_multiple_workers": {
36 "required": False,
37 "type": "boolean",
38 "default": "AUTO",
39 "coerce": (str, coerce_log_split_multiple_workers),
40 },
41 "numprocesses": NON_REQUIRED_INTEGER_DEFAULT_0,
42 "_cmd_and_args": NON_REQUIRED_STRING_DEFAULT_EMPTY,
43 "graceful_timeout": {
44 **NON_REQUIRED_INTEGER,
45 "default": 10
46 },
47 "max_age": NON_REQUIRED_INTEGER_DEFAULT_0,
48 "rlimit_as": NON_REQUIRED_INTEGER_DEFAULT_0,
49 "rlimit_nofile": NON_REQUIRED_INTEGER_DEFAULT_0,
50 "rlimit_stack": NON_REQUIRED_INTEGER_DEFAULT_0,
51 "rlimit_fsize": NON_REQUIRED_INTEGER_DEFAULT_0,
52 "debug": NON_REQUIRED_BOOLEAN_DEFAULT_FALSE
53}
56class Command(object):
58 def __init__(self, plugin_home, plugin_name, name, doc_fragment,
59 custom_fragment):
60 self.plugin_name = plugin_name
61 self.plugin_home = plugin_home
62 self._doc_fragment = doc_fragment
63 self._custom_fragment = custom_fragment
64 self.name = name
65 self._type = "command"
67 def duplicate(self, new_name=None):
68 c = self.__class__
69 if new_name is None:
70 new_name = self.name
71 return c(self.plugin_home, self.plugin_name, new_name,
72 dict(self._doc_fragment), dict(self._custom_fragment))
74 @property
75 def cmd_and_args(self):
76 return self._doc_fragment["_cmd_and_args"]
78 @property
79 def numprocesses(self):
80 return self._doc_fragment["numprocesses"]
82 @property
83 def log_split_stdout_stderr(self):
84 return self._doc_fragment["log_split_stdout_stderr"]
86 @property
87 def log_split_multiple_workers(self):
88 return self._doc_fragment["log_split_multiple_workers"]
90 @property
91 def graceful_timeout(self):
92 return self._doc_fragment["graceful_timeout"]
94 @property
95 def max_age(self):
96 return self._doc_fragment["max_age"]
98 @property
99 def rlimit_as(self):
100 return self._doc_fragment["rlimit_as"]
102 @property
103 def rlimit_nofile(self):
104 return self._doc_fragment["rlimit_nofile"]
106 @property
107 def rlimit_stack(self):
108 return self._doc_fragment["rlimit_stack"]
110 @property
111 def rlimit_fsize(self):
112 return self._doc_fragment["rlimit_fsize"]
114 @property
115 def debug(self):
116 return self._doc_fragment["debug"]
118 def _get_log_proxy_args(self):
119 if self.log_split_multiple_workers and self.numprocesses > 1:
120 std_prefix = f"{MFMODULE_RUNTIME_HOME}/log/" \
121 f"{self._type}_{self.plugin_name}_{self.name}_" \
122 "worker$(circus.wid)"
123 else:
124 std_prefix = f"{MFMODULE_RUNTIME_HOME}/log/" \
125 f"{self._type}_{self.plugin_name}_{self.name}"
126 if self.numprocesses <= 1:
127 use_locks = ""
128 else:
129 use_locks = "--use-locks"
130 if self.log_split_stdout_stderr:
131 res = "%s --stdout %s.stdout " \
132 "--stderr %s.stderr" % (use_locks, std_prefix, std_prefix)
133 else:
134 res = "%s --stdout %s.log " \
135 "--stderr STDOUT" % (use_locks, std_prefix)
136 return res
138 @property
139 def circus_cmd_and_args(self):
140 res = "%s -- plugin_wrapper %s -- %s" % \
141 (self._get_log_proxy_args(),
142 self.plugin_name,
143 self.cmd_and_args)
144 res = res.replace("{plugin_name}", self.plugin_name)
145 res = res.replace("{plugin_dir}", self.plugin_home)
146 res = res.replace("{%s_name}" % self._type, self.name)
147 return res
149 @property
150 def type(self):
151 return self._type