1### Plugin
2
3Plugin feature for the log collector is to load a user python functions at
4runtime by the engine and execute it.
5
6The design infrastructure allows user to extend or call their existing python
7scripts without needing to expose the implementation. This enriches the log
8collection and mechanize the work flow as per user driven as per their
9requirement,
10
11### Understanding Plugin
12
13The plugin works like any stand-alone piece of python script or library
14function.
15
16The main components in plugin infrastructure are:
17
18- plugin directory
19- plugin directive in YAML
20- plugin parser in the collector engine
21
22### Plugin Directory
23
24Python module script are added or copied to `plugins` directory and the log
25engine loads these plugins during runtime and on demand from the YAML else they
26are not invoked automatically.
27
28Example:
29
30```
31plugins/
32├── foo_func.py
33├── ssh_execution.py
34└── telnet_execution.py
35
36```
37
38### Plugin Template Example
39
40Stand-alone functions: plugins/foo_func.py
41
42```
43# Sample for documentation plugin
44
45def print_vars(var):
46    print(var)
47
48def return_vars():
49    return 1
50```
51
52Class function(s): plugins/plugin_class.py
53
54Example:
55
56```
57class  plugin_class:
58
59    def plugin_print_msg(msg):
60        print(msg)
61```
62
63In YAML plugin, you will need to pass self object as part of the arguments.
64
65Static Class function(s): plugins/plugin_class.py
66
67Example:
68
69```
70class  plugin_class:
71
72    @staticmethod
73    def plugin_print_msg(msg):
74        print(msg)
75```
76
77This is to avoid passing object self in plugin args YAML when calling the class
78function(s). However python class static method has its own limitation, do not
79use unless needed.
80
81You can add your own plugin modules to extend further.
82
83Test your plugin:
84
85```
86python3 plugins/foo_func.py
87```
88
89### YAML Syntax
90
91Plugin function without return statement.
92
93```
94    - plugin:
95        - plugin_name: plugin.foo_func.print_vars
96        - plugin_args:
97            - "Hello plugin"
98```
99
100Plugin function with return statement.
101
102```
103    - plugin:
104        - plugin_name: return_value = plugin.foo_func.return_vars
105        - plugin_args:
106```
107
108when the return directive is used by implying "=" , the `return_value` can be
109accessed within the same block by another following plugins by using the
110variable name directly.
111
112Example:
113
114```
115    - plugin:
116        - plugin_name: plugin.foo_func.print_vars
117        - plugin_args:
118            - return_value
119```
120
121To accept multiple return values by using coma "," separated statement
122
123```
124     - plugin_name:  return_value1,return_value2 = plugin.foo_func.print_vars
125```
126
127Accessing a class method:
128
129The rule remains same as other functions, however for a class object plugin
130syntax
131
132```
133        - plugin_name: plugin.<file_name>.<class_object>.<class_method>
134```
135
136Example: (from the class example previously mentioned)
137
138```
139    - plugin:
140        - plugin_name: plugin.plugin_class.plugin_class.plugin_print_msg
141        - plugin_args:
142            - self
143            - "Hello Plugin call"
144```
145
146### Plugin execution output for sample
147
148```
149        [PLUGIN-START]
150        Call func: plugin.foo_func.print_vars("Hello plugin")
151        Hello plugin
152        return: None
153        [PLUGIN-END]
154
155        [PLUGIN-START]
156        Call func: plugin.foo_func.return_vars()
157        return: 1
158        [PLUGIN-END]
159```
160
161### Plugin FILES Direcive
162
163Rules:
164
165If in the YAML with Plugin module called and corresponding file order
166
167plugin response if there is any will be written to named file, if
168
169```
170    FILES:
171        -'name_file.txt'
172```
173
174Else, plugin response will be skipped and not written to any file.
175
176```
177    FILES:
178        - None
179```
180
181### Plugin ERROR Direcive
182
183Error directive on plugin supported
184
185- exit_on_error : If there was an error in a plugin stacked, the subsequent
186  plugin would not be executed if this is declared.
187- continue_on_error : If there was an error and user declare this directive,
188  then the plugin block will continue to execute.
189
190Example:
191
192```
193    - plugin:
194        - plugin_name: plugin.foo_func.print_vars
195        - plugin_args:
196            - return_value
197        - plugin_error: exit_on_error
198```
199
200This error directive would come into force only if there is an error detected by
201the plugin during execution and not the error response returned from the plugin
202function in general.
203
204To go further, there is another directive for plugin to check if the plugin
205function returned a valid data or not.
206
207The directive statement is
208
209```
210    - plugin_expects_return: <data type>
211```
212
213Example:
214
215```
216    - plugin:
217    - plugin:
218      - plugin_name: plugin.ssh_execution.ssh_execute_cmd
219      - plugin_args:
220        - ${hostname}
221        - ${username}
222        - ${password}
223        - cat /etc/os-release
224        - 3
225      - plugin_expects_return: str
226```
227
228The above example states that, the plugin function is expecting a return data of
229type string. If the plugin function does not return data or the returned data is
230not of type string, then it would throw an error and sets the plugin_error flag
231exit_on_error as True.
232
233This directive helps in validating plugin return data to handle different plugin
234blocks stacked together which are depending on the success of the previous
235plugin execution to do further processing correctly.
236