Follow these guidelines when developing F5 modules for Ansible.
Since Ansible 2.2, all new F5 modules must use the
Prior to 2.2, modules used
bigsuds (SOAP) or
You can continue to extend modules that use
bigsuds, in order to maintain backward compatibility of older modules.
f5-sdk can co-exist, but F5 recommends that you write all new features, and fix all bugs by using
Base the name of the module on the part of BIG-IP that the module manipulates. A good rule of thumb is to refer to the API the
Don’t further abbreviate names. If something is a well-known abbreviation because it is a major component of BIG-IP, you can use it, but don’t create new ones independently (e.g., LTM, GTM, ASM, etc. are fine).
If a module you need does not exist yet, the REST API in the
f5-sdk may not exist yet.
Refer to the following GitHub project to determine if the REST API exists:
If you want F5 to write an API, open an issue with this project.
Follow these guidelines for using the
f5-sdk in the modules you develop. Here are the most common scenarios that you will encounter.
import statements in a try block and fail the module later if the import fails.
try: from f5.bigip import ManagementRoot from f5.bigip.contexts import TransactionContextManager HAS_F5SDK = True except ImportError: HAS_F5SDK = False def main(): if not HAS_F5SDK: module.fail_json(msg='f5-sdk required for this module')
You might wonder why you are doing this.
The answer is that Ansible runs automated tests specifically against your module, and they use an environment that doesn’t include your module’s dependencies.
Therefore, without the appropriate exception handlers, your PR will fail to pass when Ansible runs these upstream tests.
Example tests include, but are not limited to:
Connecting to an F5 product is automatic. You can control which product you are communicating with by changing the appropriate value in your ArgumentSpec class.
For example, to specify that your module is one that communicates with a BIG-IP, here is the minimum viable ArgumentSpec:
class ArgumentSpec(object): def __init__(self): self.argument_spec = dict() self.f5_product_name = 'bigip'
Note the special key f5_product_name. By changing this value, you are able to change the ManagementRoot that your module uses.
The following is a list of allowed values for this key:
Inside your module, the ManagementRoot is in the ModuleManager under the self.client.api object.
Use the object in the same way that you normally use the ManagementRoot of an
For example, this code snippet illustrates a “normal” method of using the
mr = ManagementRoot("localhost", "admin", "admin", port='10443') vs = mr.tm.ltm.virtuals.virtual.load(name='asdf')
The equivalent Ansible module code is:
# Assumes you provided "bigip" in your ArgumentSpec vs = self.client.api.tm.ltm.virtuals.virtual.load(name='asdf')
If the code throws an exception, it is up to you to decide how to handle it.
For raising exceptions, use the exception class, F5ModuleError, provided with the f5-sdk, exclusively.
# Module code ... try: result = self.want.api.tm.ltm.pools.pool.create(foo='bar') except iControlUnexpectedHTTPError as ex: raise F5ModuleError(str(ex)) ... # End of module code
In all cases in which you encounter it, it is correct to catch internal exceptions and re-raise them (if necessary) with the F5ModuleError class.
The Python code underlying the Ansible modules should be compatible with both Python 2.7 and 3.
The Travis configuration contained in this repo will verify that your modules are compatible with both versions. Use the following cheat-sheet to write compatible code.
F5 recommends that you use the testing facilities paired with this repository. When you open PR’s, F5’s testing tools will run the PR against supported BIG-IP versions.
Because F5 has test harnesses, you do not need your own devices or VE instances to test (although if you do that’s fine).
F5 currently has the following devices in the test harness: