@ -72,11 +72,6 @@ options:
description :
description :
- Device partition to manage resources on .
- Device partition to manage resources on .
default : Common
default : Common
notes :
- Requires the f5 - sdk Python package on the host . This is as easy as
pip install f5 - sdk
requirements :
- f5 - sdk
extends_documentation_fragment : f5
extends_documentation_fragment : f5
author :
author :
- Tim Rupp ( @caphrim007 )
- Tim Rupp ( @caphrim007 )
@ -166,54 +161,50 @@ rules:
type : list
type : list
sample : [ ' /Common/rule1 ' , ' /Common/rule2 ' ]
sample : [ ' /Common/rule1 ' , ' /Common/rule2 ' ]
'''
'''
import re
import re
from ansible . module_utils . f5_utils import AnsibleF5Client
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . f5_utils import AnsibleF5Parameters
from ansible . module_utils . basic import env_fallback
from ansible . module_utils . f5_utils import HAS_F5SDK
from ansible . module_utils . f5_utils import F5ModuleError
from ansible . module_utils . six import iteritems
from collections import defaultdict
from distutils . version import LooseVersion
from distutils . version import LooseVersion
HAS_DEVEL_IMPORTS = False
try :
# Sideband repository used for dev
from library . module_utils . network . f5 . bigip import HAS_F5SDK
from library . module_utils . network . f5 . bigip import F5Client
from library . module_utils . network . f5 . common import F5ModuleError
from library . module_utils . network . f5 . common import AnsibleF5Parameters
from library . module_utils . network . f5 . common import cleanup_tokens
from library . module_utils . network . f5 . common import fqdn_name
from library . module_utils . network . f5 . common import f5_argument_spec
try :
from library . module_utils . network . f5 . common import iControlUnexpectedHTTPError
except ImportError :
HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError :
# Upstream Ansible
from ansible . module_utils . network . f5 . bigip import HAS_F5SDK
from ansible . module_utils . network . f5 . bigip import F5Client
from ansible . module_utils . network . f5 . common import F5ModuleError
from ansible . module_utils . network . f5 . common import AnsibleF5Parameters
from ansible . module_utils . network . f5 . common import cleanup_tokens
from ansible . module_utils . network . f5 . common import fqdn_name
from ansible . module_utils . network . f5 . common import f5_argument_spec
try :
from ansible . module_utils . network . f5 . common import iControlUnexpectedHTTPError
except ImportError :
HAS_F5SDK = False
try :
try :
from ansible . module_utils . f5_utils import iControlUnexpectedHTTPError
from f5 . sdk_exception import NonExtantPolicyRule
from f5 . sdk_exception import NonExtantPolicyRule
except ImportError :
except ImportError :
HAS_F5SDK = False
HAS_F5SDK = False
class Parameters ( AnsibleF5Parameters ) :
class Parameters ( AnsibleF5Parameters ) :
def __init__ ( self , params = None ) :
self . _values = defaultdict ( lambda : None )
if params :
self . update ( params = params )
self . _values [ ' __warning ' ] = [ ]
self . _values [ ' __deprecated ' ] = [ ]
def update ( self , params = None ) :
if params :
for k , v in iteritems ( params ) :
if self . api_map is not None and k in self . api_map :
map_key = self . api_map [ k ]
else :
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr ( type ( self ) , map_key , None )
if isinstance ( class_attr , property ) :
# There is a mapped value for the api_map key
if class_attr . fset is None :
# If the mapped value does not have an associated setter
self . _values [ map_key ] = v
else :
# The mapped value has a setter
setattr ( self , map_key , v )
else :
# If the mapped value is not a @property
self . _values [ map_key ] = v
def to_return ( self ) :
def to_return ( self ) :
result = { }
result = { }
for returnable in self . returnables :
for returnable in self . returnables :
@ -221,16 +212,6 @@ class Parameters(AnsibleF5Parameters):
result = self . _filter_params ( result )
result = self . _filter_params ( result )
return result
return result
def api_params ( self ) :
result = { }
for api_attribute in self . api_attributes :
if self . api_map is not None and api_attribute in self . api_map :
result [ api_attribute ] = getattr ( self , self . api_map [ api_attribute ] )
else :
result [ api_attribute ] = getattr ( self , api_attribute )
result = self . _filter_params ( result )
return result
@property
@property
def strategy ( self ) :
def strategy ( self ) :
if self . _values [ ' strategy ' ] is None :
if self . _values [ ' strategy ' ] is None :
@ -261,9 +242,7 @@ class Parameters(AnsibleF5Parameters):
return self . _get_custom_strategy_name ( )
return self . _get_custom_strategy_name ( )
def _get_builtin_strategy ( self , strategy ) :
def _get_builtin_strategy ( self , strategy ) :
return ' / {0} / {1} -match ' . format (
return ' /Common/ {0} -match ' . format ( strategy )
self . partition , strategy
)
def _get_custom_strategy_name ( self ) :
def _get_custom_strategy_name ( self ) :
strategy = self . _values [ ' strategy ' ]
strategy = self . _values [ ' strategy ' ]
@ -314,9 +293,11 @@ class ComplexParameters(Parameters):
class BaseManager ( object ) :
class BaseManager ( object ) :
def __init__ ( self , client ) :
def __init__ ( self , * args , * * kwargs ) :
self . client = client
self . module = kwargs . get ( ' module ' , None )
self . client = kwargs . get ( ' client ' , None )
self . have = None
self . have = None
self . want = Parameters ( params = self . module . params )
def _announce_deprecations ( self ) :
def _announce_deprecations ( self ) :
warnings = [ ]
warnings = [ ]
@ -325,7 +306,7 @@ class BaseManager(object):
if self . have :
if self . have :
warnings + = self . have . _values . get ( ' __deprecated ' , [ ] )
warnings + = self . have . _values . get ( ' __deprecated ' , [ ] )
for warning in warnings :
for warning in warnings :
self . client. module. deprecate (
self . module. deprecate (
msg = warning [ ' msg ' ] ,
msg = warning [ ' msg ' ] ,
version = warning [ ' version ' ]
version = warning [ ' version ' ]
)
)
@ -337,7 +318,7 @@ class BaseManager(object):
if self . have :
if self . have :
warnings + = self . have . _values . get ( ' __warning ' , [ ] )
warnings + = self . have . _values . get ( ' __warning ' , [ ] )
for warning in warnings :
for warning in warnings :
self . client. module. warn ( warning [ ' msg ' ] )
self . module. warn ( warning [ ' msg ' ] )
def present ( self ) :
def present ( self ) :
if self . exists ( ) :
if self . exists ( ) :
@ -386,9 +367,9 @@ class BaseManager(object):
class SimpleManager ( BaseManager ) :
class SimpleManager ( BaseManager ) :
def __init__ ( self , client ) :
def __init__ ( self , * args , * * kwargs ) :
super ( SimpleManager , self ) . __init__ ( client )
super ( SimpleManager , self ) . __init__ ( * * kwargs )
self . want = SimpleParameters ( self . client . module . params )
self . want = SimpleParameters ( params = self . module . params )
self . have = SimpleParameters ( )
self . have = SimpleParameters ( )
self . changes = SimpleChanges ( )
self . changes = SimpleChanges ( )
@ -398,7 +379,7 @@ class SimpleManager(BaseManager):
if getattr ( self . want , key ) is not None :
if getattr ( self . want , key ) is not None :
changed [ key ] = getattr ( self . want , key )
changed [ key ] = getattr ( self . want , key )
if changed :
if changed :
self . changes = SimpleChanges ( changed)
self . changes = SimpleChanges ( params= changed)
def _update_changed_options ( self ) :
def _update_changed_options ( self ) :
diff = Difference ( self . want , self . have )
diff = Difference ( self . want , self . have )
@ -411,7 +392,7 @@ class SimpleManager(BaseManager):
else :
else :
changed [ k ] = change
changed [ k ] = change
if changed :
if changed :
self . changes = SimpleChanges ( changed)
self . changes = SimpleChanges ( params= changed)
return True
return True
return False
return False
@ -445,7 +426,7 @@ class SimpleManager(BaseManager):
partition = self . want . partition
partition = self . want . partition
)
)
rules = self . _get_rule_names ( resource )
rules = self . _get_rule_names ( resource )
result = SimpleParameters ( resource. attrs )
result = SimpleParameters ( params= resource. attrs )
result . update ( dict ( rules = rules ) )
result . update ( dict ( rules = rules ) )
return result
return result
@ -470,7 +451,7 @@ class SimpleManager(BaseManager):
def create ( self ) :
def create ( self ) :
self . _validate_creation_parameters ( )
self . _validate_creation_parameters ( )
self . _set_changed_options ( )
self . _set_changed_options ( )
if self . client . check_mode :
if self . module . check_mode :
return True
return True
self . create_on_device ( )
self . create_on_device ( )
return True
return True
@ -491,7 +472,7 @@ class SimpleManager(BaseManager):
self . have = self . read_current_from_device ( )
self . have = self . read_current_from_device ( )
if not self . should_update ( ) :
if not self . should_update ( ) :
return False
return False
if self . client . check_mode :
if self . module . check_mode :
return True
return True
self . update_on_device ( )
self . update_on_device ( )
return True
return True
@ -503,7 +484,7 @@ class SimpleManager(BaseManager):
return changed
return changed
def remove ( self ) :
def remove ( self ) :
if self . client . check_mode :
if self . module . check_mode :
return True
return True
self . remove_from_device ( )
self . remove_from_device ( )
if self . exists ( ) :
if self . exists ( ) :
@ -519,9 +500,9 @@ class SimpleManager(BaseManager):
class ComplexManager ( BaseManager ) :
class ComplexManager ( BaseManager ) :
def __init__ ( self , client ) :
def __init__ ( self , * args , * * kwargs ) :
super ( ComplexManager , self ) . __init__ ( client )
super ( ComplexManager , self ) . __init__ ( * * kwargs )
self . want = ComplexParameters ( self . client . module . params )
self . want = ComplexParameters ( params = self . module . params )
self . have = ComplexParameters ( )
self . have = ComplexParameters ( )
self . changes = ComplexChanges ( )
self . changes = ComplexChanges ( )
@ -531,7 +512,7 @@ class ComplexManager(BaseManager):
if getattr ( self . want , key ) is not None :
if getattr ( self . want , key ) is not None :
changed [ key ] = getattr ( self . want , key )
changed [ key ] = getattr ( self . want , key )
if changed :
if changed :
self . changes = ComplexChanges ( changed)
self . changes = ComplexChanges ( params= changed)
def _update_changed_options ( self ) :
def _update_changed_options ( self ) :
diff = Difference ( self . want , self . have )
diff = Difference ( self . want , self . have )
@ -544,7 +525,7 @@ class ComplexManager(BaseManager):
else :
else :
changed [ k ] = change
changed [ k ] = change
if changed :
if changed :
self . changes = ComplexChanges ( changed)
self . changes = ComplexChanges ( params= changed)
return True
return True
return False
return False
@ -595,7 +576,7 @@ class ComplexManager(BaseManager):
return changed
return changed
def remove ( self ) :
def remove ( self ) :
if self . client . check_mode :
if self . module . check_mode :
return True
return True
self . remove_from_device ( )
self . remove_from_device ( )
if self . draft_exists ( ) or self . policy_exists ( ) :
if self . draft_exists ( ) or self . policy_exists ( ) :
@ -631,7 +612,7 @@ class ComplexManager(BaseManager):
)
)
rules = self . _get_rule_names ( resource )
rules = self . _get_rule_names ( resource )
result = ComplexParameters ( resource. attrs )
result = ComplexParameters ( params= resource. attrs )
result . update ( dict ( rules = rules ) )
result . update ( dict ( rules = rules ) )
return result
return result
@ -697,7 +678,7 @@ class ComplexManager(BaseManager):
self . _validate_creation_parameters ( )
self . _validate_creation_parameters ( )
self . _set_changed_options ( )
self . _set_changed_options ( )
if self . client . check_mode :
if self . module . check_mode :
return True
return True
if not self . draft_exists ( ) :
if not self . draft_exists ( ) :
@ -716,7 +697,7 @@ class ComplexManager(BaseManager):
self . have = self . read_current_from_device ( )
self . have = self . read_current_from_device ( )
if not self . should_update ( ) :
if not self . should_update ( ) :
return False
return False
if self . client . check_mode :
if self . module . check_mode :
return True
return True
if not self . draft_exists ( ) :
if not self . draft_exists ( ) :
@ -787,8 +768,10 @@ class Difference(object):
class ModuleManager ( object ) :
class ModuleManager ( object ) :
def __init__ ( self , client ) :
def __init__ ( self , * args , * * kwargs ) :
self . client = client
self . module = kwargs . get ( ' module ' , None )
self . client = kwargs . get ( ' client ' , None )
self . kwargs = kwargs
def exec_module ( self ) :
def exec_module ( self ) :
if self . version_is_less_than_12 ( ) :
if self . version_is_less_than_12 ( ) :
@ -799,9 +782,9 @@ class ModuleManager(object):
def get_manager ( self , type ) :
def get_manager ( self , type ) :
if type == ' simple ' :
if type == ' simple ' :
return SimpleManager ( self . client )
return SimpleManager ( * * self . kwargs )
elif type == ' complex ' :
elif type == ' complex ' :
return ComplexManager ( self . client )
return ComplexManager ( * * self . kwargs )
def version_is_less_than_12 ( self ) :
def version_is_less_than_12 ( self ) :
version = self . client . api . tmos_version
version = self . client . api . tmos_version
@ -814,7 +797,7 @@ class ModuleManager(object):
class ArgumentSpec ( object ) :
class ArgumentSpec ( object ) :
def __init__ ( self ) :
def __init__ ( self ) :
self . supports_check_mode = True
self . supports_check_mode = True
self . argument_spec = dict (
argument_spec = dict (
name = dict (
name = dict (
required = True
required = True
) ,
) ,
@ -824,32 +807,38 @@ class ArgumentSpec(object):
choices = [ ' first ' , ' all ' , ' best ' ]
choices = [ ' first ' , ' all ' , ' best ' ]
) ,
) ,
state = dict (
state = dict (
required = False ,
default = ' present ' ,
default = ' present ' ,
choices = [ ' absent ' , ' present ' , ' draft ' ]
choices = [ ' absent ' , ' present ' , ' draft ' ]
) ,
partition = dict (
default = ' Common ' ,
fallback = ( env_fallback , [ ' F5_PARTITION ' ] )
)
)
)
)
self . f5_product_name = ' bigip '
self . argument_spec = { }
self . argument_spec . update ( f5_argument_spec )
self . argument_spec . update ( argument_spec )
def main ( ) :
def main ( ) :
if not HAS_F5SDK :
raise F5ModuleError ( " The python f5-sdk module is required " )
spec = ArgumentSpec ( )
spec = ArgumentSpec ( )
client = AnsibleF5Client (
module = AnsibleModule (
argument_spec = spec . argument_spec ,
argument_spec = spec . argument_spec ,
supports_check_mode = spec . supports_check_mode ,
supports_check_mode = spec . supports_check_mode
f5_product_name = spec . f5_product_name
)
)
if not HAS_F5SDK :
module . fail_json ( msg = " The python f5-sdk module is required " )
try :
try :
mm = ModuleManager ( client )
client = F5Client ( * * module . params )
mm = ModuleManager ( module = module , client = client )
results = mm . exec_module ( )
results = mm . exec_module ( )
client . module . exit_json ( * * results )
cleanup_tokens ( client )
except F5ModuleError as e :
module . exit_json ( * * results )
client . module . fail_json ( msg = str ( e ) )
except F5ModuleError as ex :
cleanup_tokens ( client )
module . fail_json ( msg = str ( ex ) )
if __name__ == ' __main__ ' :
if __name__ == ' __main__ ' :