Skip to content

Commit

Permalink
Merge pull request #84 from napalm-automation/develop
Browse files Browse the repository at this point in the history
Release 0.7.0
  • Loading branch information
dbarrosop authored Aug 3, 2017
2 parents 71aa095 + ec855dd commit 3f32732
Show file tree
Hide file tree
Showing 29 changed files with 542 additions and 115 deletions.
25 changes: 14 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: python

python:
- 2.7

Expand All @@ -7,19 +8,21 @@ env:
- ANSIBLE_VERSION=2.3

install:
- pip install pylama
- pip install napalm-base
- pip install "ansible>=$ANSIBLE_VERSION.0,<$ANSIBLE_VERSION.99"

script:
- pylama
- cd tests
# Test configuration dry-run
- ansible-playbook -i napalm_install_config/hosts -l "*.dry_run.*" napalm_install_config/config.yaml -C
# Test configuration commit
- ansible-playbook -i napalm_install_config/hosts -l "*.commit.*" napalm_install_config/config.yaml
# Test configuration errrors
- ansible-playbook -i napalm_install_config/hosts -l "*.error*" napalm_install_config/config_error.yaml
# Test get_facts
- ansible-playbook -i napalm_get_facts/hosts napalm_get_facts/get_facts_ok.yaml -l multiple_facts.ok
- ansible-playbook -i napalm_get_facts/hosts napalm_get_facts/get_facts_not_implemented.yaml -l multiple_facts.not_implemented -e "ignore_notimplemented=true"
- ansible-playbook -i napalm_get_facts/hosts napalm_get_facts/get_facts_not_implemented.yaml -l multiple_facts.not_implemented -e "ignore_notimplemented=false"
- ansible-playbook -i napalm_get_facts/hosts napalm_get_facts/get_facts_error.yaml -l multiple_facts.error
- ./run_tests.sh
- ./test_changelog.sh

deploy:
provider: pypi
user: dbarroso
password:
secure: cXZNckuwEv4qQbUz1uCx3mDnylSCPFTfTrxYISkuRJz6cgNBJZ64KGvKNdF5ygUGAXHLbx3+LtBGtYTei1Rc6Mi8L64+XAH5Johs0TZTnlor0FyezlutGZSnzJEsXSditCl31Ap2kXOtRY5u5lJi+sa/WnLDH/cAIslISsys0RmtAcfO6HYR8rhFXCuTwG4dhWoxVKwcQE2PWZcGWBV1y9vCqMYSVGNYWKXfAduZZnBXXOcHTvCvobz9KvYYYKShOK5j7D1SURXr9/qBKWnnSN4e16UKPfTgj8o/r/zS/K4gb7rONY5Tv1YkzcbN7u/YEO1fB4s43mB//Hv9gSrCZ95Xc5TPaqfUDs15s0t/mxIPNtOJmcxJwm+ewQm5HouO9U0/d7t4Aw5BXVLqVJCsOuz1xvqe5gsJeCIkwDyk2qtqPTYyuBpn3fMXJfHMCLIVcGxmmNjCdAMMdqhVZ4sJlUfTxmxPqU97KRvHlGRW2Cz3QtrVealjdN7+jNWVl7ERiQoKfbF2TjEzdQ4Tr+KZinygv7pst4TT2/wfyzf2YluPyPtISCUUMzLmEogATJbizoOZPSrN1FFrq8PCmsQzYRxxaMU+auTCoJY4gUOefEuQpZgM3m46pzpRpwuZVnvEYt1ffXUNmyggo2jaSYsRQ5wEtzpf8MGjnjDe878M4yA=
on:
tags: true
branch: master
14 changes: 14 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
0.7.0
=====

- Minor internal improvements
- [#77] Added ``napalm_cli`` module
- Prepend 'napalm_' to NAPALM ansible facts generated by napalm_get_facts module
- Make NAPALM 'get_facts' be directly accessible Ansible facts (e.g. napalm_model)
- Change validate behavior to fail if 'complies' is False
- Create run_tests.sh script to make it easier to run the unit tests

0.6.1
=====

- First official version installable via pypi
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include requirements.txt
52 changes: 31 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,50 @@
napalm-ansible
======
# napalm-ansible

Collection of ansible modules that use [napalm](https://github.com/napalm-automation/napalm) to retrieve data or modify configuration on netwroking devices.
Collection of ansible modules that use [napalm](https://github.com/napalm-automation/napalm) to retrieve data or modify configuration on networking devices.

Modules
=======
The following modules are currenty available:
- napalm_get_facts
- napalm_install_config
- napalm_validate

The following modules are currently available:

- ``napalm_diff_yang``
- ``napalm_get_facts``
- ``napalm_install_config``
- ``napalm_parse_yang``
- ``napalm_ping``
- ``napalm_translate_yang``
- ``napalm_validate``

Install
=======
To install, clone the library directory into your ansible path.

OR
To install just run the command:

Add the following in requirements.yml
```
- src: https://github.com/napalm-automation/napalm-ansible/
version: master
name: napalm
path: roles
```
Then execute:
pip install napalm-ansible
```
ansible-galaxy install -r requirements.yml --force

Configuring ansible
===================

Once you have installed ``napalm-ansible`` run the command ``napalm-ansible`` and follow the instructions. For example::

```
$ napalm-ansible
To make sure ansible can make use of the napalm modules you will have
to add the following configurtion to your ansible configureation
file, i.e. `./ansible.cfg`:
Dependencies
=======
* [napalm](https://github.com/napalm-automation/napalm) 1.00.0 or later
[defaults]
library = /Users/dbarroso/workspace/napalm/napalm-ansible/napalm_ansible
For more details on ansible's configuration file visit:
https://docs.ansible.com/ansible/latest/intro_configuration.html
```

Examples
=======

Example to retreive facts from a device
```
- name: get facts from device
Expand Down Expand Up @@ -76,4 +86,4 @@ Example to get compliance report
hostname: "{{ inventory_hostname }}"
dev_os: "{{ dev_os }}"
validation_file: validate.yml
```
```
1 change: 1 addition & 0 deletions library
17 changes: 0 additions & 17 deletions meta/main.yml

This file was deleted.

18 changes: 18 additions & 0 deletions napalm_ansible/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os

message = """
To make sure ansible can make use of the napalm modules you will have
to add the following configurtion to your ansible configureation
file, i.e. `./ansible.cfg`:
[defaults]
library = {path}
For more details on ansible's configuration file visit:
https://docs.ansible.com/ansible/latest/intro_configuration.html
"""


def main():
path = os.path.dirname(__file__)
print(message.format(path=path).strip())
146 changes: 146 additions & 0 deletions napalm_ansible/napalm_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from ansible.module_utils.basic import AnsibleModule, return_values


DOCUMENTATION = '''
---
module: napalm_cli
author: "Charlie Allom - based on napalm_ping Jason Edelman (@jedelman8)"
version_added: "2.2"
short_description: "Executes CLI commands and returns response using NAPALM"
description:
- "This module logs into the device, issues a ping request, and returns the response"
requirements:
- napalm
options:
args:
description:
- Keyword arguments to pass to the `cli` method
required: True
'''

EXAMPLES = '''
vars:
napalm_provider:
hostname: "{{ inventory_hostname }}"
username: "napalm"
password: "napalm"
dev_os: "eos"
- napalm_cli:
provider: "{{ napalm_provider }}"
args:
commands:
- show version
- show snmp chassis
'''

RETURN = '''
changed:
description: ALWAYS RETURNS FALSE
returned: always
type: bool
sample: True
results:
description: string of command output
returned: always
type: dict
sample:
{
"show snmp chassis": "Chassis: 1234\n",
"show version": "Arista vEOS\nHardware version: \nSerial number: \nSystem MAC address: 0800.27c3.5f28\n\nSoftware image version: 4.17.5M\nArchitecture: i386\nInternal build version: 4.17.5M-4414219.4175M\nInternal build ID: d02143c6-e42b-4fc3-99b6-97063bddb6b8\n\nUptime: 1 hour and 21 minutes\nTotal memory: 1893416 kB\nFree memory: 956488 kB\n\n" # noqa
}
'''

try:
from napalm_base import get_network_driver
except ImportError:
napalm_found = False
else:
napalm_found = True


def main():
os_choices = ['eos', 'junos', 'iosxr', 'fortios',
'ios', 'mock', 'nxos', 'panos', 'vyos', 'ros']
module = AnsibleModule(
argument_spec=dict(
hostname=dict(type='str', required=False, aliases=['host']),
username=dict(type='str', required=False),
password=dict(type='str', required=False, no_log=True),
provider=dict(type='dict', required=False),
timeout=dict(type='int', required=False, default=60),
dev_os=dict(type='str', required=False, choices=os_choices),
optional_args=dict(required=False, type='dict', default=None),
args=dict(required=True, type='dict', default=None),
),
supports_check_mode=False
)

if not napalm_found:
module.fail_json(msg="the python module napalm is required")

provider = module.params['provider'] or {}

no_log = ['password', 'secret']
for param in no_log:
if provider.get(param):
module.no_log_values.update(return_values(provider[param]))
if provider.get('optional_args') and provider['optional_args'].get(param):
module.no_log_values.update(return_values(provider['optional_args'].get(param)))
if module.params.get('optional_args') and module.params['optional_args'].get(param):
module.no_log_values.update(return_values(module.params['optional_args'].get(param)))

# allow host or hostname
provider['hostname'] = provider.get('hostname', None) or provider.get('host', None)
# allow local params to override provider
for param, pvalue in provider.items():
if module.params.get(param) is not False:
module.params[param] = module.params.get(param) or pvalue

hostname = module.params['hostname']
username = module.params['username']
dev_os = module.params['dev_os']
password = module.params['password']
timeout = module.params['timeout']
args = module.params['args']

argument_check = {'hostname': hostname, 'username': username,
'dev_os': dev_os, 'password': password}
for key, val in argument_check.items():
if val is None:
module.fail_json(msg=str(key) + " is required")

# use checks outside of ansible defined checks, since params come can come from provider
if dev_os not in os_choices:
module.fail_json(msg="dev_os is not set to " + str(os_choices))

if module.params['optional_args'] is None:
optional_args = {}
else:
optional_args = module.params['optional_args']

try:
network_driver = get_network_driver(dev_os)
device = network_driver(hostname=hostname,
username=username,
password=password,
timeout=timeout,
optional_args=optional_args)
device.open()
except Exception, e:
module.fail_json(msg="cannot connect to device: " + str(e))

try:
cli_response = device.cli(**args)
except Exception as e:
module.fail_json(msg="{}".format(e))

try:
device.close()
except Exception, e:
module.fail_json(msg="cannot close device connection: " + str(e))

module.exit_json(changed=False, results=cli_response)


if __name__ == '__main__':
main()
File renamed without changes.
Loading

0 comments on commit 3f32732

Please sign in to comment.