@ -27,9 +27,9 @@ DOCUMENTATION = """
module : junos_command
module : junos_command
version_added : " 2.1 "
version_added : " 2.1 "
author : " Peter Sprygada (@privateip) "
author : " Peter Sprygada (@privateip) "
short_description : Run arbitrary commands on an Juniper junos device
short_description : Run arbitrary commands on an Juniper JUNOS device
description :
description :
- Sends an arbitrary set of commands to an junos node and returns the results
- Sends an arbitrary set of commands to an JUNOS node and returns the results
read from the device . This module includes an
read from the device . This module includes an
argument that will cause the module to wait for a specific condition
argument that will cause the module to wait for a specific condition
before returning or timing out if the condition is not met .
before returning or timing out if the condition is not met .
@ -42,7 +42,16 @@ options:
is returned . If the I ( wait_for ) argument is provided , the
is returned . If the I ( wait_for ) argument is provided , the
module is not returned until the condition is satisfied or
module is not returned until the condition is satisfied or
the number of I ( retries ) has been exceeded .
the number of I ( retries ) has been exceeded .
required : true
required : false
default : null
rpcs :
description :
- The C ( rpcs ) argument accepts a list of RPCs to be executed
over a netconf session and the results from the RPC execution
is return to the playbook via the modules results dictionary .
required : false
default : null
version_added : " 2.3 "
wait_for :
wait_for :
description :
description :
- Specifies what to evaluate from the output of the command
- Specifies what to evaluate from the output of the command
@ -85,9 +94,6 @@ options:
"""
"""
EXAMPLES = """
EXAMPLES = """
# Note: examples below use the following provider dict to handle
# transport and authentication to the node.
- - -
- name : run show version on remote devices
- name : run show version on remote devices
junos_command :
junos_command :
commands : show version
commands : show version
@ -114,9 +120,13 @@ EXAMPLES = """
- name : run commands and specify the output format
- name : run commands and specify the output format
junos_command :
junos_command :
commands :
commands : show version
- command : show version
display : json
output : json
- name : run rpc on the remote device
junos_command :
rpcs : get - software - information
"""
"""
RETURN = """
RETURN = """
@ -135,7 +145,6 @@ from xml.etree import ElementTree as etree
from xml . etree . ElementTree import Element , SubElement , tostring
from xml . etree . ElementTree import Element , SubElement , tostring
from ansible . module_utils . junos import run_commands
from ansible . module_utils . junos import junos_argument_spec , check_args
from ansible . module_utils . junos import junos_argument_spec , check_args
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . basic import AnsibleModule
from ansible . module_utils . netcli import Conditional , FailedConditionalError
from ansible . module_utils . netcli import Conditional , FailedConditionalError
@ -174,42 +183,49 @@ def to_lines(stdout):
lines . append ( item )
lines . append ( item )
return lines
return lines
def r un_r pcs ( module , items ) :
def r pc( module , items ) :
responses = list ( )
responses = list ( )
for item in items :
for item in items :
name = item [ ' name ' ]
name = item [ ' name ' ]
args = item [ ' args ' ]
xattrs = item [ ' xattrs ' ]
args = item . get ( ' args ' )
text = item . get ( ' text ' )
name = str ( name ) . replace ( ' _ ' , ' - ' )
name = str ( name ) . replace ( ' _ ' , ' - ' )
if all ( ( module . check_mode , not name . startswith ( ' get ' ) ) ) :
if all ( ( module . check_mode , not name . startswith ( ' get ' ) ) ) :
module . fail_json ( msg = ' invalid rpc for running in check_mode ' )
module . fail_json ( msg = ' invalid rpc for running in check_mode ' )
xattrs = { ' format ' : item [ ' output ' ] }
element = Element ( name , xattrs )
element = Element ( name , xattrs )
for key , value in iteritems ( args ) :
if text :
key = str ( key ) . replace ( ' _ ' , ' - ' )
element . text = text
if isinstance ( value , list ) :
for item in value :
elif args :
for key , value in iteritems ( args ) :
key = str ( key ) . replace ( ' _ ' , ' - ' )
if isinstance ( value , list ) :
for item in value :
child = SubElement ( element , key )
if item is not True :
child . text = item
else :
child = SubElement ( element , key )
child = SubElement ( element , key )
if item is not True :
if value is not True :
child . text = item
child . text = value
else :
child = SubElement ( element , key )
if value is not True :
child . text = value
reply = send_request ( module , element )
reply = send_request ( module , element )
if module. params [ ' display ' ] == ' text ' :
if xattrs [ ' format ' ] == ' text ' :
data = reply . find ( ' .//output ' )
data = reply . find ( ' .//output ' )
responses . append ( data . text . strip ( ) )
responses . append ( data . text . strip ( ) )
elif module . params [ ' display ' ] == ' json ' :
elif xattrs [ ' format ' ] == ' json ' :
responses . append ( module . from_json ( reply . text . strip ( ) ) )
responses . append ( module . from_json ( reply . text . strip ( ) ) )
else :
else :
responses . append ( tostring ( reply ) )
responses . append ( tostring ( reply ) )
@ -224,7 +240,8 @@ def split(value):
def parse_rpcs ( module ) :
def parse_rpcs ( module ) :
items = list ( )
items = list ( )
for rpc in module . params [ ' rpcs ' ] :
for rpc in ( module . params [ ' rpcs ' ] or list ( ) ) :
parts = split ( rpc )
parts = split ( rpc )
name = parts . pop ( 0 )
name = parts . pop ( 0 )
@ -239,44 +256,39 @@ def parse_rpcs(module):
else :
else :
args [ key ] = str ( value )
args [ key ] = str ( value )
output = module . params [ ' display ' ] or ' xml '
display = module . params [ ' display ' ] or ' xml '
items. append ( { ' name ' : name , ' args ' : args , ' output ' : output } )
xattrs = { ' format ' : display }
return items
items . append ( { ' name ' : name , ' args ' : args , ' xattrs ' : xattrs } )
return items
def parse_commands ( module ) :
def parse_commands ( module ) :
spec = dict (
items = list ( )
command = dict ( key = True ) ,
output = dict ( default = module . params [ ' display ' ] , choices = [ ' text ' , ' json ' , ' xml ' ] ) ,
prompt = dict ( ) ,
answer = dict ( )
)
transform = ComplexList ( spec , module )
commands = transform ( module . params [ ' commands ' ] )
for index, item in enumerate ( commands ) :
for command in ( module . params [ ' commands ' ] or list ( ) ) :
if module . check_mode and not item[ ' command' ] . startswith ( ' show ' ) :
if module . check_mode and not command . startswith ( ' show ' ) :
warnings . append (
warnings . append (
' Only show commands are supported when using check_mode, not '
' Only show commands are supported when using check_mode, not '
' executing %s ' % item[ ' command' ]
' executing %s ' % command
)
)
if item [ ' command ' ] . startswith ( ' show configuration ' ) :
parts = command . split ( ' | ' )
item [ ' output ' ] = ' text '
text = parts [ 0 ]
if item [ ' output ' ] == ' json ' and ' display json ' not in item [ ' command ' ] :
item [ ' command ' ] + = ' | display json '
display = module . params [ ' display ' ] or ' text '
elif item [ ' output ' ] == ' xml ' and ' display xml ' not in item [ ' command ' ] :
xattrs = { ' format ' : display }
item [ ' command ' ] + = ' | display xml '
else :
if ' | display json ' in command :
if ' | display json ' in item [ ' command ' ] :
xattrs [ ' format ' ] = ' json '
item [ ' command ' ] = str ( item [ ' command ' ] ) . replace ( ' | display json ' , ' ' )
elif ' | display xml ' in item [ ' command ' ] :
elif ' | display xml ' in command :
item [ ' command ' ] = str ( item [ ' command ' ] ) . replace ( ' | display xml ' , ' ' )
xattrs [ ' format ' ] = ' xml '
commands [ index ] = item
items . append ( { ' name ' : ' command ' , ' xattrs ' : xattrs , ' text ' : text } )
return items
return commands
def main ( ) :
def main ( ) :
""" entry point for module execution
""" entry point for module execution
@ -296,12 +308,9 @@ def main():
argument_spec . update ( junos_argument_spec )
argument_spec . update ( junos_argument_spec )
mutually_exclusive = [ ( ' commands ' , ' rpcs ' ) ]
required_one_of = [ ( ' commands ' , ' rpcs ' ) ]
required_one_of = [ ( ' commands ' , ' rpcs ' ) ]
module = AnsibleModule ( argument_spec = argument_spec ,
module = AnsibleModule ( argument_spec = argument_spec ,
mutually_exclusive = mutually_exclusive ,
required_one_of = required_one_of ,
required_one_of = required_one_of ,
supports_check_mode = True )
supports_check_mode = True )
@ -310,11 +319,9 @@ def main():
warnings = list ( )
warnings = list ( )
check_args ( module , warnings )
check_args ( module , warnings )
if module . params [ ' commands ' ] :
items = list ( )
items = parse_commands ( module )
items . extend ( parse_commands ( module ) )
else :
items . extend ( parse_rpcs ( module ) )
items = parse_rpcs ( module )
wait_for = module . params [ ' wait_for ' ] or list ( )
wait_for = module . params [ ' wait_for ' ] or list ( )
display = module . params [ ' display ' ]
display = module . params [ ' display ' ]
@ -325,15 +332,12 @@ def main():
match = module . params [ ' match ' ]
match = module . params [ ' match ' ]
while retries > 0 :
while retries > 0 :
if module . params [ ' commands ' ] :
responses = rpc ( module , items )
responses = run_commands ( module , items )
else :
responses = run_rpcs ( module , items )
transformed = list ( )
transformed = list ( )
for item , resp in zip ( items , responses ) :
for item , resp in zip ( items , responses ) :
if item [ ' outpu t' ] == ' xml ' :
if item [ ' xattrs' ] [ ' forma t' ] == ' xml ' :
if not HAS_JXMLEASE :
if not HAS_JXMLEASE :
module . fail_json ( msg = ' jxmlease is required but does not appear to '
module . fail_json ( msg = ' jxmlease is required but does not appear to '
' be installed. It can be installed using `pip install jxmlease` ' )
' be installed. It can be installed using `pip install jxmlease` ' )