Skip to content

Commit

Permalink
Standardize cliconf get_capabilities (ansible#51147)
Browse files Browse the repository at this point in the history
* Standardize cliconf get_capabilities

* Check for capabilities before querying them

* Try to be more helpful when unexpected things are found in get_capabilities

* Add flags param to get_config for compatibility
  • Loading branch information
Qalthos authored Jan 28, 2019
1 parent bd44db1 commit 9336281
Show file tree
Hide file tree
Showing 26 changed files with 85 additions and 146 deletions.
65 changes: 26 additions & 39 deletions lib/ansible/modules/network/cli/cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,43 +195,27 @@
from ansible.module_utils._text import to_text


def validate_args(module, capabilities):
def validate_args(module, device_operations):
"""validate param if it is supported on the platform
"""
if (module.params['replace'] and
not capabilities['device_operations']['supports_replace']):
module.fail_json(msg='replace is not supported on this platform')

if (module.params['rollback'] is not None and
not capabilities['device_operations']['supports_rollback']):
module.fail_json(msg='rollback is not supported on this platform')

if (module.params['commit_comment'] and
not capabilities['device_operations']['supports_commit_comment']):
module.fail_json(msg='commit_comment is not supported on this platform')

if (module.params['defaults'] and
not capabilities['device_operations']['supports_defaults']):
module.fail_json(msg='defaults is not supported on this platform')

if (module.params['multiline_delimiter'] and
not capabilities['device_operations']['supports_multiline_delimiter']):
module.fail_json(msg='multiline_delimiter is not supported on this platform')

if (module.params['diff_replace'] and
not capabilities['device_operations']['supports_diff_replace']):
module.fail_json(msg='diff_replace is not supported on this platform')

if (module.params['diff_match'] and
not capabilities['device_operations']['supports_diff_match']):
module.fail_json(msg='diff_match is not supported on this platform')

if (module.params['diff_ignore_lines'] and
not capabilities['device_operations']['supports_diff_ignore_lines']):
module.fail_json(msg='diff_ignore_lines is not supported on this platform')


def run(module, capabilities, connection, candidate, running, rollback_id):
feature_list = [
'replace', 'rollback', 'commit_comment', 'defaults', 'multiline_delimiter',
'diff_replace', 'diff_match', 'diff_ignore_lines',
]

for feature in feature_list:
if module.params[feature]:
supports_feature = device_operations.get('supports_%s' % feature)
if supports_feature is None:
module.fail_json(
"This platform does not specify whether %s is supported or not. "
"Please report an issue against this platform's cliconf plugin." % feature
)
elif not supports_feature:
module.fail_json(msg='Option %s is not supported on this platform' % feature)


def run(module, device_operations, connection, candidate, running, rollback_id):
result = {}
resp = {}
config_diff = []
Expand All @@ -256,7 +240,7 @@ def run(module, capabilities, connection, candidate, running, rollback_id):
if 'diff' in resp:
result['changed'] = True

elif capabilities['device_operations']['supports_onbox_diff']:
elif device_operations.get('supports_onbox_diff'):
if diff_replace:
module.warn('diff_replace is ignored as the device supports onbox diff')
if diff_match:
Expand All @@ -274,7 +258,7 @@ def run(module, capabilities, connection, candidate, running, rollback_id):
if 'diff' in resp:
result['changed'] = True

elif capabilities['device_operations']['supports_generate_diff']:
elif device_operations.get('supports_generate_diff'):
kwargs = {'candidate': candidate, 'running': running}
if diff_match:
kwargs.update({'diff_match': diff_match})
Expand Down Expand Up @@ -361,7 +345,10 @@ def main():
capabilities = module.from_json(connection.get_capabilities())

if capabilities:
validate_args(module, capabilities)
device_operations = capabilities.get('device_operations', dict())
validate_args(module, device_operations)
else:
device_operations = dict()

if module.params['defaults']:
if 'get_default_flag' in capabilities.get('rpc'):
Expand All @@ -381,7 +368,7 @@ def main():

if candidate or rollback_id:
try:
result.update(run(module, capabilities, connection, candidate, running, rollback_id))
result.update(run(module, device_operations, connection, candidate, running, rollback_id))
except Exception as exc:
module.fail_json(msg=to_text(exc))

Expand Down
16 changes: 16 additions & 0 deletions lib/ansible/plugins/cliconf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,22 @@ def get_capabilities(self):
}
:return: capability as json string
"""
result = {}
result['rpc'] = self.get_base_rpc()
result['device_info'] = self.get_device_info()
result['network_api'] = 'cliconf'
return result

@abstractmethod
def get_device_info(self):
"""Returns basic information about the network device.
This method will provide basic information about the device such as OS version and model
name. This data is expected to be used to fill the 'device_info' key in get_capabilities()
above.
:return: dictionary of device information
"""
pass

def commit(self, comment=None):
Expand Down
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/aireos.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
if source == 'running':
Expand All @@ -73,8 +73,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/aruba.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
if source == 'running':
Expand All @@ -74,8 +74,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/asa.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
if source == 'running':
Expand All @@ -71,8 +71,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
5 changes: 1 addition & 4 deletions lib/ansible/plugins/cliconf/ce.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/cnos.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def parse_model(self, data):
return "NA"

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
msg = "fetching configuration from %s is not supported"
return self.invalid_params(msg % source)
Expand All @@ -84,8 +84,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/dellos10.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
if source == 'running':
Expand All @@ -75,8 +75,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/dellos6.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
# if source == 'running':
Expand All @@ -75,8 +75,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/dellos9.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
return self.invalid_params("fetching configuration from %s is not supported" % source)
# if source == 'running':
Expand All @@ -75,8 +75,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
8 changes: 3 additions & 5 deletions lib/ansible/plugins/cliconf/edgeos.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def get_device_info(self):

return device_info

def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
return self.send_command('show configuration commands')

def edit_config(self, candidate=None, commit=True, replace=False, comment=None):
Expand All @@ -59,8 +59,6 @@ def discard_changes(self, *args, **kwargs):
self.send_command('discard')

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc() + ['commit', 'discard_changes']
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['commit', 'discard_changes']
return json.dumps(result)
6 changes: 2 additions & 4 deletions lib/ansible/plugins/cliconf/edgeswitch.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,8 @@ def get(self, command=None, prompt=None, answer=None, sendonly=False, output=Non
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = dict()
result['rpc'] = self.get_base_rpc() + ['run_commands']
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['run_commands']
return json.dumps(result)

def run_commands(self, commands=None, check_rc=True):
Expand Down
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/enos.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def get_device_info(self):
return device_info

@enable_mode
def get_config(self, source='running', format='text'):
def get_config(self, source='running', format='text', flags=None):
if source not in ('running', 'startup'):
msg = "fetching configuration from %s is not supported"
return self.invalid_params(msg % source)
Expand All @@ -71,8 +71,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
7 changes: 2 additions & 5 deletions lib/ansible/plugins/cliconf/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,10 @@ def get_option_values(self):
}

def get_capabilities(self):
result = {}
rpc_list = ['commit', 'discard_changes', 'get_diff', 'run_commands', 'supports_sessions']
result['rpc'] = self.get_base_rpc() + rpc_list
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['commit', 'discard_changes', 'get_diff', 'run_commands', 'supports_sessions']
result['device_operations'] = self.get_device_operations()
result.update(self.get_option_values())
result['network_api'] = 'cliconf'

return json.dumps(result)

Expand Down
5 changes: 1 addition & 4 deletions lib/ansible/plugins/cliconf/exos.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,7 @@ def get_option_values(self):
}

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['device_operations'] = self.get_device_operations()
result.update(self.get_option_values())
return json.dumps(result)
6 changes: 2 additions & 4 deletions lib/ansible/plugins/cliconf/ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,8 @@ def get_option_values(self):
}

def get_capabilities(self):
result = dict()
result['rpc'] = self.get_base_rpc() + ['edit_banner', 'get_diff', 'run_commands', 'get_defaults_flag']
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['edit_banner', 'get_diff', 'run_commands', 'get_defaults_flag']
result['device_operations'] = self.get_device_operations()
result.update(self.get_option_values())
return json.dumps(result)
Expand Down
6 changes: 2 additions & 4 deletions lib/ansible/plugins/cliconf/iosxr.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,8 @@ def get_option_values(self):
}

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc() + ['commit', 'discard_changes', 'get_diff', 'configure', 'exit']
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['commit', 'discard_changes', 'get_diff', 'configure', 'exit']
result['device_operations'] = self.get_device_operations()
result.update(self.get_option_values())
return json.dumps(result)
5 changes: 1 addition & 4 deletions lib/ansible/plugins/cliconf/ironware.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,5 @@ def get(self, command, prompt=None, answer=None, sendonly=False, check_all=False
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, check_all=check_all)

def get_capabilities(self):
result = {}
result['rpc'] = self.get_base_rpc()
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
return json.dumps(result)
6 changes: 2 additions & 4 deletions lib/ansible/plugins/cliconf/junos.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,8 @@ def get_option_values(self):
}

def get_capabilities(self):
result = dict()
result['rpc'] = self.get_base_rpc() + ['commit', 'discard_changes', 'run_commands', 'compare_configuration', 'validate', 'get_diff']
result['network_api'] = 'cliconf'
result['device_info'] = self.get_device_info()
result = super(Cliconf, self).get_capabilities()
result['rpc'] += ['commit', 'discard_changes', 'run_commands', 'compare_configuration', 'validate', 'get_diff']
result['device_operations'] = self.get_device_operations()
result.update(self.get_option_values())
return json.dumps(result)
Expand Down
Loading

0 comments on commit 9336281

Please sign in to comment.