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