Main module execution¶
At this point in the module’s development, the module is largely complete. In this section, we’ll
cover one of the boilerplate methods that ships with all the modules; the main
function.
It is not necessary that you implement this function. We cover it here so that you are able to combine the knowledge of how the module executes, with where its execution actually begins.
The main function¶
In the module used for this tutorial, the main
function is defined at the bottom of the
source code.
The implementation of it is almost entirely boilerplate. Here it is.
def main():
spec = ArgumentSpec()
module = AnsibleModule(
argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode
)
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module()
cleanup_tokens(client)
module.exit_json(**results)
except F5ModuleError as ex:
cleanup_tokens(client)
module.fail_json(msg=str(ex))
The operation of this function is as follows.
First, the ArgumentSpec
and the AnsibleModule
classes are initialized. You have seen both
of these in the past, so you should know their purpose.
ArgumentSpec
defines what the module can doAnsibleModule
uses theArgumentSpec
to validate user input
Next, a series of validations are made on the available libraries used in this module. The series above only includes one check, but others can be added as necessary. See the section later in this document that discusses under what circumstances you would want to do this.
Next is the main try...except
block. This exception handling is in place to catch all of the
known F5 generated errors. It very specifically does not catch the general Python Exception
class. This is done this way because module developers want bugs reported that are not known to
them already. Handling Exception
though, would prevent those bugs from raising.
The internals of the try
block include the instantiation of the F5Client
object. This
object will be used later for all communication with the F5 product.
Note
When the F5Client
class is instantiated, a connection is not immediately made to the
remote F5 product. This is intentional, because some modules (like bigip_wait
) require that this does not
happen.
The ModuleManager
class is also instantiated here and is given the AnsibleModule
object
as well as the F5Client
object. These will be necessary later when the manager is busy
executing.
Execution of the manager is next using the exec_module
method call. The return value of this
call is what will be returned to the user.
Before that return can take place, however, a function is called to clean up the authentication tokens on the F5 device.
Note
The cleanup_tokens
method is not put in the ModuleManager
because the manager
can fail in a variety of places due to F5ModuleException
’s being raised by error checking
code. This function must be run after manager execution.
Finally, the module cleanly exits with the exit_json
method if everything has gone well.
If failure occurred at any time, the except
block is invoked and a cleanup of authentication
tokens is done. The failing module reports back to Ansible with the fail_json
method of
the AnsibleModule
class.
When to change the main function¶
The only time it would be necessary to change the main
function is if you included other
module dependencies that needed to be checked for at runtime.
Note the two lines above, shown here.
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
This series of conditionals would need to be changed if you were, for example, to include the
Python netaddr
module in your work. Any dependencies of the module need to be checked for here
(and fail the module if they are not found) to ensure that the module runs correctly.
Executing main¶
The final two lines in your module inform Python to execute the module’s code if the script itself is executable.
if __name__ == '__main__':
main()
Because of how Ansible works, when the main
function contacts the remote device (or runs
locally), it is not called if you import the module.
You would import the module if you were using it outside of Ansible, or in some sort of test environment where you do not want the module to actually run.
Conclusion¶
This concludes the entirety of the core module development tutorial. If you followed along and copied code correctly, you should have a functioning module.
In the remaining sections, we’ll cover the business of testing: a requirement for F5 module development.