Coverage for mfplugin/command.py: 47%

81 statements  

« 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 

5 

6__pdoc__ = { 

7 "coerce_log_split_stdout_sterr": False, 

8 "coerce_log_split_multiple_workers": False 

9} 

10 

11 

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) 

17 

18 

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) 

24 

25 

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} 

54 

55 

56class Command(object): 

57 

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" 

66 

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)) 

73 

74 @property 

75 def cmd_and_args(self): 

76 return self._doc_fragment["_cmd_and_args"] 

77 

78 @property 

79 def numprocesses(self): 

80 return self._doc_fragment["numprocesses"] 

81 

82 @property 

83 def log_split_stdout_stderr(self): 

84 return self._doc_fragment["log_split_stdout_stderr"] 

85 

86 @property 

87 def log_split_multiple_workers(self): 

88 return self._doc_fragment["log_split_multiple_workers"] 

89 

90 @property 

91 def graceful_timeout(self): 

92 return self._doc_fragment["graceful_timeout"] 

93 

94 @property 

95 def max_age(self): 

96 return self._doc_fragment["max_age"] 

97 

98 @property 

99 def rlimit_as(self): 

100 return self._doc_fragment["rlimit_as"] 

101 

102 @property 

103 def rlimit_nofile(self): 

104 return self._doc_fragment["rlimit_nofile"] 

105 

106 @property 

107 def rlimit_stack(self): 

108 return self._doc_fragment["rlimit_stack"] 

109 

110 @property 

111 def rlimit_fsize(self): 

112 return self._doc_fragment["rlimit_fsize"] 

113 

114 @property 

115 def debug(self): 

116 return self._doc_fragment["debug"] 

117 

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 

137 

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 

148 

149 @property 

150 def type(self): 

151 return self._type